Silverfrost Forums

Welcome to our forums

How to create a png file from array data?

25 Aug 2014 4:19 #14500

Hello all, for long time I'm creating fine jpg files from computed pixel arrays using CALL put_dib_block@(dibfile,a2,a2hres,a2vres,0,0,iCxdim,jCydim,24,ier) (dibfile has extension .jpg).

Now I want to create an additional png file based on same array a2, but don't know how to create them. I did this experiment.

i= IMPORT_IMAGE@('{'//dibfile//'}',0,0)      ! import jpg in curly brackets
   print *,'IMPORT return flag=',i
 i= EXPORT_IMAGE@( TRIM(pathmod)//'test.png')       !export png
   print *,'EXPORT', TRIM(pathmod)//'test.png     return flag=',i   

The result is IMPORT returns i=1 (good) EXPORT returns i=0 (bad). the file has 0 bytes.

I am sure there is a better way of doing. Should work without any user interaction, either directly from array a2 or using the intermediate jpg. best regards, johannes

26 Aug 2014 5:54 #14501

I don't think there is a direct way to export to a png file from the array.

Your method should work. Are you using a recent salflibc.dll?

26 Aug 2014 12:48 #14503

I find that EXPORT_IMAGE@ works successfully for .png format files. This exports the currently selected drawing surface, which can be either: the %gr window or a virtual window created by the calls: i = create_graphics_region@ (hd_handle, w_width, w_depth) i = select_graphics_object@ (hd_handle)

If you want to export a DIB array, you may need to copy it to an appropriate graphics region (drawing surface). DIB arrays appear to be different from the drawing surface or direct addressing of the %gr graphics region. The restrictions on moving between the different types of surfaces can be difficult. If I recall correctly, my experimenting with direct addressing of the graphics region shows it only worked with the %gr surface and not selected graphics regions. You have to work with what is available.

Over the years I have moved from .pcx to .gif and now .png. I tried .jpg, but found it to be unsuitable for the colour shaded surfaces I am using. .pcx was dropped by MS Word (2003?) so became unuseable. .gif is by far the most compact, but I had problems with the limited colour palette, which was solved by using .png

John

26 Aug 2014 1:26 #14504

Hello Paul, I tried with 7.10 but same response as 7.00. *.png is not created.

Hello John, could you please write down the complete set of calls? Given I have an array a2, which I store into a jpg by now using CALL put_dib_block@(dibfile,a2,a2hres,a2vres,0,0,iCxdim,jCydim,24,ier)

What to do with a2 until EXPORT_IMAGE@?

Thanks, johannes

27 Aug 2014 1:13 #14508

Johannes,

The process I would go through is:

  1. determine the size of the DIB graphics area
  2. create a graphics area of the appropriate size i = create_graphics_region@ (hd_handle, w_width, w_depth) i = select_graphics_object@ (hd_handle)
  3. copy the DIB array using DISPLAY_DIB_BLOCK@
  4. export the graphics object using EXPORT_IMAGE@ and the appropriate file name extension .png

I am not sure of the history of DIB, but one of the problems with this array is that it is stored as BGR, while %gr graphics region direct addressing is RGB (or the other way round).

There are 3 ways of manipulating graphics that I looked at: DIB - drawing device independent bitmaps %gr - direct manipulation of the graphics surface Off-screen graphics

I use Off-screen graphics as I want to have a graphics image that is not limited by the %gr size. Both DIB or Create_graphics_region@ provide this.

I was looking for direct addressing of the graphics region to improve paint times. I found that 'Direct manipulation of the graphics surface' only worked on the %gr region. I considered DIB but unfortunately there are only a few routines to address a DIB array.

I found it easier to work between the %gr, clearwin+ off-screen graphics and my own virtual screen definition. Export_Image@ works with both clearwin surfaces. To improve the speed of setting pixels, rather than use draw_point@, I scanned lines of my own virtual screen definition and draw_line_between@ as typically I have areas of similar colour.

My own drawing surface is a 3D surface to do simple hidden line removal on a larger window and the performance is acceptable. DIB did not show much performance improvement and a few show stoppers, so I did not persist. Others may be more proficient with DIB but I'd recommend the alternative.

There are lots of ways to do this and the above is what I know that works best.

John

28 Aug 2014 9:34 #14529

Hello John, I have to admit that I have little experience with %gr and DIB.

Meanwhile I tried: i=create_graphics_region@(ihandle,a2hres,a2vres) → i=1 i=select_graphics_object@(ihandle) → i=1 call DISPLAY_DIB_BLOCK@( 0,0 ,a2,a2hres,a2vres,0,0,a2hres,a2vres,0,0,ier ) → ier=0 i= EXPORT_IMAGE@( TRIM(pathmod)//'test.png') !export png → i=0 File test.png is not created at all. I would have been lucky if it were empty. What's wrong? BR, johannes

28 Aug 2014 12:14 #14531

Johannes, I made a few tests and it seems that the png export doesn't work but all others do (???). Here is my code:

      winapp 
      program test 
      implicit none
      include <windows.ins> 

      integer*4      i,j,A,lins,cols
      real*8         r
      character*1    image(120000)

c     create 24-bit test image (replace by your own)

      lins = 200
      cols = 200
      image = char(255)

      do i = 1,lins
        A = 3*(i-1)*cols
        do j = 1,3*cols,3
          if (mod(i,50) .eq. 0 .or. mod(j,50) .eq. 0) then
            image(A+j  ) = char(1)
            image(A+j+1) = char(1)
            image(A+j+2) = char(1)
          end if
        end do
      end do

c     off-screen graphics & export

      j = create_graphics_region@(4L,cols,lins)
      j = select_graphics_object@(4L)
      call display_dib_block@(1,1,image,cols,lins,1,1,cols,lins,0,0,i)
      r = set_jpeg_quality@(1.D0)
      j = export_image@('c:\\temp\\test.jpg')  ! works
      j = export_image@('c:\\temp\\test.bmp')  ! works
      j = export_image@('c:\\temp\\test.gif')  ! works
      j = export_image@('c:\\temp\\test.png')  ! does not work !!
      j = delete_graphics_region@(4L)
      end

Funny... Wilfried

28 Aug 2014 12:20 #14532

Johannes,

.png wasn't supported until FTN95 6.35

The documentation for DISPLAY_DIB_BLOCK@ indicates it transfers to the current graphics device (e.g. a %gr window or a printer). I never know if this includes the selected drawing surface, which makes it all a bit more difficult. It has been a few years since I tried DIB and went back to the old ways.

I don't have a DIB array handy, but you could try the following adaptations to your code; ! ! all arguments are I4 and must be supplied ihandle = 11 write (,) 'create_graphics_region@ inputs :',ihandle,a2hres,a2vres i = create_graphics_region@ (ihandle,a2hres,a2vres) write (,) 'create_graphics_region@ >',i,' (=1)' ! i = select_graphics_object@ (ihandle) write (,) 'select_graphics_object@ >',i,' (=1)' ! call DISPLAY_DIB_BLOCK@( 0,0, a2,a2hres,a2vres, 0,0,a2hres,a2vres,0,0,ier ) write (,) 'DISPLAY_DIB_BLOCK@ >',ier,' (=0)' ! ! You could try this but I don't think it is necessary i = select_graphics_object@ (ihandle) write (,) 'select_graphics_object@ >',i,' (=1)' ! ! .png requires FTN95 version 6.35. i = EXPORT_IMAGE@ ( 'test.png' ) !export png write (,) 'EXPORT_IMAGE@ .png >',i,' (/=0)' ! ! export .jpg to confirm image is ok i = EXPORT_IMAGE@ ( 'test.jpg' ) !export jpg to check write (,*) 'EXPORT_IMAGE@ .jpg >',i,' (/=0)'

Wilfred,

Hopefully you are using FTN95 prior to Ver 6.35. I am still creating .png files with Ver 7.0. Why didn't you use rank 3 character or integer1 array ? integer4, parameter :: horz = 1900 integer*4, parameter :: vert = 1100 character image(3,horz,vert)*1 ! I think that is the order

My earlier comment about direct manipulation of drawing surface should have said that the colour order is BGR, while the DIB array is RGB. Just something more to create some doubt.

John

28 Aug 2014 1:06 #14533

Wilfred,

You have provided a very useful example, which I have expanded to show a few more features that can be confusing. Moving to a rank 3 allocatable array makes it easier to import a graphics file of general size, using GET_DIB_BLOCK@. Again I don't know what graphics formats are now supported, but if others aren't then we need to transfer via a graphics region.

You need to be careful with the start coordinates. I think they should be 0,0. You can blame a C programmer for this. The following will work, but if you use 1,1 it will not.

It is also useful to compare the different sizes of the resulting graphics files. In this case .png has the best compression.

      winapp 
       program test3
       implicit none 
       include <windows.ins> 

       integer*4      i,j,A,lins,cols 
       integer*4      x,y, HANDLE
       real*8         r 
       character*1, dimension(:,:,:), allocatable :: image
       character*1 :: red(3), blue(3), black(3)

!    create 24-bit test image (replace by your own) 

       handle = 4
       lins   = 250 
       cols   = 550 
       allocate ( image(3,cols,lins) )
!
       red   = char(1) ; red(1)  = char(255)
       blue  = char(1) ; blue(3) = char(255)
       black = char(1)
!       
       image  = char(255) ! white
       do y = 1,lins
         image(:,1,y)    = red
         image(:,cols,y) = red
       end do
       do x = 1,cols
         image(:,x,1)    = blue
         image(:,x,lins) = blue
       end do
!
       do y = 2,lins-1
         do x = 2,cols-1
           if (mod(y,50) .eq. 0 .or. mod(x,50) .eq. 0) image(:,x,y) = black
         end do 
       end do 

!     off-screen graphics & export 

       j = create_graphics_region@ (handle,cols,lins) 
       j = select_graphics_object@ (handle) 
!
       call display_dib_block@ (0,0,image,cols,lins,0,0,cols,lins,0,0,i) 
!
       r = set_jpeg_quality@ (1.D0) 
       j = export_image@ ('c:\\temp\\test3.jpg')  ! works 
       j = export_image@ ('c:\\temp\\test3.bmp')  ! works 
       j = export_image@ ('c:\\temp\\test3.gif')  ! works 
       j = export_image@ ('c:\\temp\\test3.png')  ! does not work !! 
       j = delete_graphics_region@ (handle) 
!
       end
28 Aug 2014 1:37 #14534

John, I just saw that I use FTN95 version 5.50 on my laptop. I hope that png export works on newer versions. Sorry for the confusion. I have to update my compiler 😉

I always use character1 for 8- or 24-bits images and integer2 for 16-bits surface models. What do you think are the advantages using 3D character*1 values?

Wilfried

28 Aug 2014 2:35 #14535

Wilfred,

It is a couple of years since I tried to look at DIB, but I was trying to use TYPE structures to make the addressing of the graphics images, especially when trying to manipulate 3-byte RGB or BGR colours. The Rank 3 array does simplify the 3byte|X|Y addressing. I also found the use of allocatable arrays helpful when using DIB. I also tried it with direct addressing, but I recall this only worked with the %gr drawing surface and was no good for create_graphics_region@ images. It might be good to have direct addressing for create_graphics_region@ images, by obtaining the memory address, but the use of the CORE routines is not very friendly. The aim of my test was to improve paint times, but I found that when I tried to paint by lines, rather than points the paint times were then less significant than compared to other graphics functions I was doing, such as generating the image and even allocating and initialising the arrays.

John

28 Aug 2014 2:39 #14536

Hi John, Paul, Wilfried, I adapted Wilfried's code and tried with latest 7.10 and 6.30. Both create the jpg file but none of them the .png (i=0).

I compiled john's code from below and confirm that no .png is created with 6.30 and 7.10.

Now I am also confused about the version discussion.

28 Aug 2014 3:07 #14537

I am using FTN95/Win32 Ver. 7.00.0. Perhaps Paul could test the latest version I posted, as it works with my .dll dated 18-Dec-2013.

I have not yet tried Ver 7.1, so would be interested to find out if this is a regression.

John

PS: Well I just installed version 7.10.0 dated 27-Apr-14 over Ver 7.00 and it produces a .png file. I am not sure what is different. ( my OS is Windows 7 Home Premium. The latest version I tested is: winapp program test3 implicit none include <windows.ins>

       integer*4      i,j,A,lins,cols 
       integer*4      x,y, HANDLE
       real*8         r 
       character*1, dimension(:,:,:), allocatable :: image
       character*1 :: red(3), blue(3), black(3)

!    create 24-bit test image (replace by your own) 

       handle = 4
       lins   = 250 
       cols   = 550 
       allocate ( image(3,cols,lins) )
!
       red   = char(1) ; red(1)  = char(255)
       blue  = char(1) ; blue(3) = char(255)
       black = char(1)
!       
       image  = char(255) ! white
       do y = 1,lins
         image(:,1,y)    = red
         image(:,cols,y) = red
       end do
       do x = 1,cols
         image(:,x,1)    = blue
         image(:,x,lins) = blue
       end do
!
       do y = 2,lins-1
         do x = 2,cols-1
           if (mod(y,50) .eq. 0 .or. mod(x,50) .eq. 0) image(:,x,y) = black
         end do 
       end do 

!     off-screen graphics & export 

       j = create_graphics_region@ (handle,cols,lins) 
       j = select_graphics_object@ (handle) 
!
       call display_dib_block@ (0,0,image,cols,lins,0,0,cols,lins,0,0,i) 
!
       r = set_jpeg_quality@ (1.D0) 
       j = export_image@ ('c:\\temp\\test_71.jpg')  ! works 
       j = export_image@ ('c:\\temp\\test_71.bmp')  ! works 
       j = export_image@ ('c:\\temp\\test_71.gif')  ! works 
       j = export_image@ ('c:\\temp\\test_71.png')  ! does not work !! 
       j = delete_graphics_region@ (handle) 
!
       end
28 Aug 2014 4:06 #14538

Wilfried's program runs OK for me.

28 Aug 2014 6:29 #14541

Hi Paul, I compiled Wilfried's original code ( Thu Aug 28, 2014 1:14 pm ) using version 7.10 and as well my own application according to Wilfried's receipe. .png is created ! ... before I copied the new salflibc.dll into my exe directory. Perhaps the initial bug was using a wrong dll.

Thanks a lot to all contributors! Helped a lot. johannes

29 Aug 2014 7:02 #14547

Additional question: Can we somehow set parameters to modify the .png output, like setting an alpha value (Transparency) or b/w vs. color output? BR Johannes

29 Aug 2014 1:35 #14551

No. ClearWin+ does not have a facility to adjust the png output.

29 Aug 2014 9:16 #14553

By the way, when you read the graphics file into DIB block say like this

call get_dib_block@(BitmapFile, A, imdim,imdim,0,0,hres,vres,0,0,ier)

how original RGB of the BitmapFile are coded inside the array A(3,imdim,imdim) ?

Is it RGB_inside_A = Real_RGB - 128 or something like that?

30 Aug 2014 5:29 #14554

There is sample program in ftn95.chm under

Win32 Platform->ClearWin+->Graphics->Drawing Device Independent Bitmaps

30 Aug 2014 7:48 #14556

I think the FTN95 help is still missing that detail. Or I miss it as usually. After DIB is loaded into array A(3,ixsize,iysize) all the values in A are 'distorted' and lie not in 0 to 255 range but in -127 to +127 one (why? It's the same 1 byte size...). If you look into array with the debugger it is full of -1 numbers. I did conversion to normal 256 range before but forgot details and couldn't quickly find anything. So DIB pushes me to switch on my rusty brain to get shadowy reasoning behind all that kitchen. By common sense one of variants is that the actual normal human RGB value 'RGB_256' in the scale 0-255 and loaded RGB_127 which is in -127 -- +127 range RGB_256 = RGB_127 if number is positive and
RGB_256 = 255 - RGB_127 if RGB_127 is negative ...or 256-RGB_127...

Please login to reply.