Silverfrost Forums

Welcome to our forums

Saving %og screen to PNG

2 Aug 2018 1:16 #22426

I have two codes where main window has always open graphics screens - some have %gr open other %pl open. Then I open additional window with %og (OpenGL) and try to save OpenGL plot into PNG file.

The code with %gr saves content of OpenGL %og screen OK but the one with %pl does not - it produces just black region. Pressing shortcut set via accelerator %ac might also save content of %pl graphics screen depending on currently active window.

Here is the code which i use to save content of %og screen. I also tried different approach with i = export_image@(PNGfilename) but it does not work with %og completely.

	integer function SaveOpengl_Bitmap() 
      include <clearwin.ins>,nolist 
      include <opengl.ins>,nolist 

      integer wOpGL,hOpGL 
      common /OpenGL_image_size/wOpGL,hOpGL 
        wOpGL=clearwin_info@('OPENGL_WIDTH')
        hOpGL=clearwin_info@('OPENGL_DEPTH')
        call do_bitmap(wOpGL,hOpGL) 
      SaveOpengl_Bitmap=2 
      end 

      subroutine do_bitmap(wOpGL,hOpGL) 
      include <clearwin.ins>,nolist 
      include <opengl.ins>,nolist 
      integer wOpGL,hOpGL,ierr,koff,kount,i,j,k 
      CHARACTER*1 ImageData(3*(wOpGL+3)*hOpGL), ImageDib(3,wOpGL,hOpGL) 
      CHARACTER*128 file_name 
      logical exst 

      ImageData=' ' 
      ImageDib =' ' 

      call glReadPixels(0,0,wOpGL,hOpGL, GL_RGB,GL_UNSIGNED_BYTE,ImageData) 

      koff=mod(wOpGL,4) 

      kount=0 

        do j=1,hOpGL 
            do i=1,wOpGL 
              do k=1,3 
                kount=kount+1 
                ImageDib(k,i,hOpGL-j+1)=ImageData(kount) 
              end do 
            end do 
          kount=kount+koff 
        end do 

      file_name='Opengl   .png' 

      k=0 
5     k=k+1 

      write(file_name(7:9),'(I3.3)')k 


      INQUIRE(FILE=file_name,EXIST=EXST) 
      IF (EXST) go to 5 

      call put_dib_block@(file_name,ImageDib,wOpGL,hOpGL, 0,0,wOpGL,hOpGL,24,ierr) 

	if(ierr.eq.0) then
!          CALL POP('Screen Saved in OpenGLxxxx.png current Dir')
           print*,'Screen Saved in OpenGLxxxx.png current Dir'
	endif


      return 
      end
3 Aug 2018 7:20 #22433

My guess would be that, if it is possible then it would be by using routines provided in the OpenGL library rather than by ClearWin+ library routines.

8 Aug 2018 12:25 (Edited: 8 Aug 2018 9:39) #22451

Has anyone succeeded to save %og screen to type of graphics files? Post your solution, plz. Bad day today... Exactly the same function to save to graphics file works in one program, does not in another and all totally refuses to work in small demo. That is my typical love-hate relationship with Clearwin+. Even this does not work giving zero sizes of bitmap

        wOpGL=clearwin_info@('OPENGL_WIDTH') 
        hOpGL=clearwin_info@('OPENGL_DEPTH') 
        call do_bitmap(wOpGL,hOpGL) 
8 Aug 2018 6:04 #22454

OPENGL_WIDTH and OPENGL_DEPTH are for use within a %^og callback function but only when resizing the window. Otherwise the size could be found using the hwnd from %lc and a call to GET_WINDOW_LOCATION@.

8 Aug 2018 3:08 #22457

Thanks, Paul. I have to note though that the requirement of OPENGL_WIDTH to be used only at resizing is very unexpected, confusing and inconvenient. It will cause a lot of lost hairs of Clearwin+ users...

If the problem with finding image size are somehow solved and they are of correct value next problem is saving image to file. Program posted above may show image but not save it (all black screen), or save image but not show it.

I suspect that the glReadPixels reads the wrong buffer out of two.

What options %og[options] has? I found few, 'static, double,depth16', the documentation (which was not yet corrected that it now works under 64bits) shows nothing.

With 'static' i can save generated image OK when i do not see it after it was created (i see black %og screen). As soon as i hover mouse over %og screen the image appears on it but trying to save it after that produces the file with black screen.

The option 'double,depth16' (the only i always used all these years and it was working OK and saving OK) shows the OpenGL generated picture from start but does save to file totally black image. Funny it works OK with the other 64bit program like it always worked all decades with absolutely no hiccups.

As one more side effect when saving %og to the file: code above may save the image from the other open graphics window of the same running code (what is totally unexpected - with %pl stuff plotted on it!). How come glReadPixels reads native %pl ???

9 Aug 2018 4:05 #22458

Here we clearly miss John Horspool. That was his trick we discuss right now..

9 Aug 2018 4:59 #22459

Yes, John, thanks, I'm aware of this very much. And played with this too at different combinations of potential workarounds using for example Paul's suggestion with winio@('%lc', ihw), finding handle and making page active with, for example, select_graphics_object@(ihw). OpenGL also has buffers which it switching to get smooth picture change without flicker. That i suspect may somehow be involved: i see plot in one buffer but the glReadPixels is trying to process from another when saving to bitmap.

I also made one more demo which does not need that but it works OK. Have no clue what's wrong as all worked OK for 20 years and abruptly 5 years ago in some places of code broke. There were other broken places with saving and loading graphics during last 5 years. Some are partially fixed (for example BMP loads but PNG not), some wait for their time to find what's wrong because it is hard to extract this from larger codes (would be great if Silverfrost made such automatic demo extractor as compiler knows all the dependencies and easily can strip down all not related stuff)

Using method of tries and falls face into the mud i temporally made a workaround by moving to static option in %og[static], will see how this will work over longer time.

10 Aug 2018 5:14 (Edited: 10 Aug 2018 10:51) #22461

John, Yes, exporting image must be in one single line like this i = export_image@(PNGfilename), or no one will use Fortran.

Meantime anyone can try to find why saving to PNG does not work in this demo with the option which worked for years, i.e. with 'double,depth16'. Compile as usual 'FTN95 AAA.f95 /link /debug >z'. With 'static' it works but impression is that when you rotate more complex images they flicker instead of being silky smooth. This code is not one line though

INCLUDE <clearwin.ins>
INCLUDE <opengl.ins>
integer, external :: GUIofOprnGLWin, SaveOpenglBitmap
common /OpenGL_image_size_/iwOpGL,ihOpGL 
INTEGER i,x 
INTEGER,PARAMETER::n=1000 
DOUBLE PRECISION p1,p2,p3,y(n) 
INTEGER,EXTERNAL::cb 

iwid01=500; ihgt01=400

p1=1.5d0 
p2=150.0d0 
p3=15d0 
x=0 
DO i=1,n 
  y(i)=p1*sin(x/p3)*exp(-x/p2) 
  x=x+1 
ENDDO 

i=winio@('%ww[no_border]%ca[Damped wave]%pv&') 
i=winio@('%fn[Tahoma]&') 
i=winio@('%ts&', 1.1d0) 
i=winio@('%tc&',rgb@(0,0,80)) 
i=winio@('%it&') 
i=winio@('%`bg&',rgb@(230,255,225)) 
call winop@('%pl[native]') 
call winop@('%pl[width=2]') 
call winop@('%pl[title='Sample plot']') 
call winop@('%pl[x_axis=Time(Milliseconds)]') 
call winop@('%pl[y_axis=Amplitude@(-8.0)]') ! 
!call winop@('%pl[style=2]') ! curve joins points 
call winop@('%pl[smoothing=4]') ! anti-aliasing 
i=winio@('%^pl[colour=red,n_graphs=1]%ff&',500,400,n,0.0d0,1.0d0,y,cb) 

i=winio@('%cn%^tt[main OprnGL Window]&', GUIofOprnGLWin)
!  i=winio@('%^tt[Save PNG]&', SaveOpenglBitmap)
i=winio@('%ac[esc]', 'exit')

END 

!................................

INTEGER FUNCTION cb() 
INCLUDE <clearwin.ins> 
call draw_characters@('Legend:..', 300, 100, 0) 
call draw_line_between@(300,120,360,120,rgb@(0,0,255)) 
cb = 2 
END 

!.......................................
   integer function GUIofOprnGLWin()
   INCLUDE <clearwin.ins>
   INCLUDE <opengl.ins>
   integer, external :: SaveOpenglBitmap, PlottingOG
   common /OpenGL_image_size_/iwOpGL,ihOpGL 
   integer(7) iLW

    iwOpGL=600; ihOpGL =500
    i=winio@('%ww[no_border]%ca[OpengGL Sample]&') 
!    i=winio@('%pv%^og[double,depth16]%ff&', iwOpGL,ihOpGL, PlottingOG )  ! DOES NOT WORK HERE, but works in other my code
    i=winio@('%pv%^og[static]%ff&', iwOpGL,ihOpGL, PlottingOG )  ! static works OK
    i=winio@('%ac[esc]&', 'exit')
    i=winio@('%cn&')
    i=winio@('%^tt[Save PNG]', SaveOpenglBitmap)
    GUIofOprnGLWin = 2
    END function
!...................................
    integer function PlottingOG ()
    INCLUDE <clearwin.ins>
    INCLUDE <opengl.ins>
    common /OpenGL_image_size_/iwOpGL,ihOpGL 
    character*256 reasonMousePie01old 
    character*256 reasonMousePie01

    call get_opengl_mouse_state@ (ix_mousePie01,iy_mousePie01,iflag_mousePie01)

    reasonMousePie01=clearwin_string@('CALL_BACK_REASON')

      if(reasonMousePie01.EQ.'RESIZE')then
        iwOpGL = clearwin_info@('OPENGL_WIDTH')
        ihOpGL = clearwin_info@('OPENGL_DEPTH')
      else if(reasonMousePie01.EQ.'SETUP')then
      endif

     CALL glClearColor (0.0, 0.0, 0.0, 0.0) 
     CALL glClear(GL_COLOR_BUFFER_BIT) 
10 Aug 2018 5:16 #22462
     CALL glColor3f(1.0, 1.0, 1.0) 
     CALL glMatrixMode(GL_PROJECTION) 
     CALL glLoadIdentity() 
     CALL glOrtho(-1d0, 1d0, -1d0, 1d0, -1d0, 1d0) 

     CALL glBegin(GL_POLYGON)      
! Setting polygon points counterclockwise. 
! Doing this will make color interpolated 
! (this will be specifically nice if multiple adjacent polygons are plotted)

     CALL glColor3f(1.0,0.0,0.0) 
     CALL glVertex2f(-0.5, -0.5) 
     
     CALL glColor3f(0.0,1.0,0.0) 
     CALL glVertex2f(-0.5, 0.5) 

     CALL glColor3f(0.0,0.0,1.0)      
     CALL glVertex2f( 0.5, 0.5) 

     CALL glColor3f(1.0,0.0,0.0)      
     CALL glVertex2f( 0.5, -0.5) 

!...end setting polygon

     CALL glEnd() 
     CALL glFlush() 

     call swap_opengl_buffers()
     call temporary_yield@()

     PlottingOG=2
     end function

!...................................
      integer function SaveOpenglBitmap() 
      include <clearwin.ins>
      include <opengl.ins>
      integer iwOpGL,ihOpGL 
      common /OpenGL_image_size_/iwOpGL,ihOpGL 

!  This way of setting iwOpGL,ihOpGL does not work now
!        iwOpGL=clearwin_info@('OPENGL_WIDTH') 
!        ihOpGL=clearwin_info@('OPENGL_DEPTH') 

        call do_bitmap(iwOpGL,ihOpGL) 
      SaveOpenglBitmap=2 
      end 

!..........................................................
! This way of saving to file was suggested by John Horspool 
!
      subroutine do_bitmap(iwOpGL,ihOpGL) 
      include <clearwin.ins> 
      include <opengl.ins>

      CHARACTER*1 ImageData(3*(iwOpGL+3)*ihOpGL), ImageDib(3,iwOpGL,ihOpGL) 
      CHARACTER*128 file_name 
      logical exst 

      ImageData=' ' 
      ImageDib =' ' 

      call glReadPixels(0,0,iwOpGL,ihOpGL, GL_RGB,GL_UNSIGNED_BYTE,ImageData) 

      koff=mod(iwOpGL,4) 

      kount=0 

        do j=1,ihOpGL 
            do i=1,iwOpGL 
              do k=1,3 
                kount=kount+1 
                ImageDib(k,i,ihOpGL-j+1)=ImageData(kount) 
              end do 
            end do 
          kount=kount+koff 
        end do 

      file_name='Opengl   .png' 

      k=0 
5     k=k+1 

      write(file_name(7:9),'(I3.3)')k 

      INQUIRE(FILE=file_name,EXIST=EXST) 
      IF (EXST) go to 5 

      call put_dib_block@(file_name,ImageDib,iwOpGL,ihOpGL, 0,0,iwOpGL,ihOpGL,24,ierr) 

   if(ierr.ne.0) then 
           print*,'Problems saving in OpenGLxxxx.png in current Dir' 
   endif 


   return 
   end subroutine
Please login to reply.