Silverfrost Forums

Welcome to our forums

Problem Displaying JPG File

3 Oct 2007 7:33 #2297

My understanding reading the documentation for GET_DIB_SIZE@, GET_DIB_BLOCK@, and DISPLAY_DIB_BLOCK@ is that these should work identically for both .bmp and .jpg files. I have used these functions just fine for quite some time for .bmp files, but in an attempt to extend this to include .jpg files have found that the DIB display doesn't seem to work for .jpg.

Using a simple .bmp and .jpg file for the same picture (~300x300), when I run the following program for the .bmp file it works fine, but it displays a garbled image when I swap the data statement to open the .jpg file. Is there something else different about processing .bmp and .jpg files that I should be aware of?

Thanks, Dennis

  WINAPP 300000,500000
  PROGRAM JPG

  INTEGER*1    IBFFER(3,200000)
  CHARACTER*30 JPGFIL
  INCLUDE <WINDOWS.INS>

C DATA JPGFIL/'C:\DEV\SYSLB\JPG.BMP'/ DATA JPGFIL/'C:\DEV\SYSLB\JPG.JPG'/

  I=WINIO@('%GR%LW',400,400,IHANDL)

  PRINT *,JPGFIL
  CALL GET_DIB_SIZE@(JPGFIL,IWID,IHIT,INBP,IERR)
  PRINT *,IWID,IHIT,INBP,IERR

  CALL GET_DIB_BLOCK@(JPGFIL,IBFFER,400,400,0,0,
 &amp;                                  400,400,0,0,IERR)
  PRINT *,IERR

  CALL DISPLAY_DIB_BLOCK@(0,0,IBFFER ,
 &amp;                            400,400,
 &amp;                            0,0,
 &amp;                            400,400,
 &amp;                            0,0,IERR)

  STOP
  END
4 Oct 2007 6:46 #2299

The following, with different arguments, works OK.

      WINAPP 
      PROGRAM JPG 
      CHARACTER IBFFER(3,400,400) 
      CHARACTER*80 JPGFIL 
      INCLUDE <WINDOWS.INS> 
      DATA JPGFIL/'C:\\I386\\connected_data.jpg'/ 
      I=WINIO@('%GR%LW',400,400,IHANDL) 
      PRINT *,JPGFIL 
      CALL GET_DIB_SIZE@(JPGFIL,IWID,IHIT,INBP,IERR) 
      PRINT *,IWID,IHIT,INBP,IERR 
      CALL GET_DIB_BLOCK@(JPGFIL,IBFFER,400,400,0,0,IWID,IHIT,0,0,IERR) 
      PRINT *,IERR 
      CALL DISPLAY_DIB_BLOCK@(0,0,IBFFER,400,400,0,0,IWID,IHIT,0,0,IERR) 
      END
4 Oct 2007 6:41 #2307

Paul,

Many thanks for your wisdom. I've been able to get things working for .jpg with the changes you suggested. Now I can see that .jpg processing is more sensitive to trying to read past the actual limits of the image than .bmp processing is - thus setting the input parameters to match the image size is now more critical. Thanks.

4 Oct 2007 10:49 (Edited: 4 Oct 2007 10:53) #2309

After a good number of experiments, I have determined that (in my opinion) GET_DIB_BLOCK@ is behaving very differently when processing jpg images than when processing bmp images, and that the way it is being done for bmp images is the preferred (correct) way. Here's what I've discovered, referring to the FTN code listed below.

When processing a bmp file, the 7th & 8th parameters of GET_DIB_BLOCK@ (W & H in the doc) define the size of the block of image to be extracted from the file to the buffer variable, not the size of the image itself. This is important when the 9th & 10th parameters (DX & DY in the doc) are used to define the offset in the image to start the block so that a smaller block of memory is needed to read one piece of many from a large bmp file. Also, if the requested block size from the starting offset extends beyond the actual image, the function returns nothing for areas beyond the image. All of these behaviors can be seen with the code below exactly as it is shown. It's easier to see with a larger BMP file than the one you suggested earlier, and then reading larger blocks - I can provide such a file if you give me a place to email it - otherwise you'll have to create a bmp file from the jpg you suggested, or use another file that you have or can create in both formats.

Now, if the data statement (only) is modified to open the same image stored in a jpg format, as you noted earlier, the displayed image is completely garbled because it is apparent that the 7th & 8th parameters must be the size of the image itself, not the size of the desired block to be extracted. This can be verified by changing the 2nd line of the GET_DIB_BLOCK@ statement so IWID,IHIT is used instead of 25,25. This change uncovers, however, the problem of supplying the image dimensions instead of the size of the block to extract, on two fronts -- 1) if the jpg image is very large and these dimensions are passed, it appears that the function implicitly extracts the entire image and requires an enormous amount of memory to do it, possibly even creating buffer overflow problems, and 2) if an offset into the image is provided, then the implied block size is too big and the function returns a 'wrapped' image instead of one truncated at the limits of the actual image. Again, making the change above illustrates this 'wrapping' action immediately in the program below.

This is my take on the problems I'm having with the function. I don't know if it is exactly correct, but the program provided illustrates the problems it is causing me. It seems to me that the function can be repaired in an upwards compatible way for anyone currently using it for jpg images -- that is, the only possible way they can be using it now is by supplying the image dimensions as parameters 7 & 8, and my suggested fix is to allow any block size to be requested and determine the image size internally (as in or with GET_DIB_SIZE@). This would work the same way for current jpg users, but make it consistent with the way it works for bmp files and at the same time extending its funtionality. Also, making it truncate at the end of the image instead of the current overflow/wrap-around result should be upwards compatible for current users. From what I can tell, it would also (hopefully) significantly reduce the amount of memory required to extract small blocks of a large image individually instead of (apparently) forcing the function to process the entire image. (I'm deducing the memory issue by looking at memory usage in Task Manager.)

Your thoughts would be greatly appreciated. I'd be happy to discuss further via email or within the forum, and to provide any testing of changes which you might create.

<< see the following message for the example program code >>

4 Oct 2007 10:52 #2310

Apparently my message was too long and the program was truncated - here is the complete program in * CODE * format.

      WINAPP 300000,500000
      PROGRAM JPG
C
      INTEGER*1    IBFFER(3,200000)
      CHARACTER*80 JPGFIL
      INCLUDE <WINDOWS.INS>

C--TOGGLE THE COMMENTS BELOW TO SELECT EITHER THE BMP OR JPG VERSION OF THE SAME IMAGE.

CX      DATA JPGFIL/'C:\\DEV\\SYSLB\\JPG.BMP'/     ! 372 X 304 PIXELS
CX      DATA JPGFIL/'C:\\DEV\\SYSLB\\JPG.JPG'/
      DATA JPGFIL/'C:\\I386\\CONNECTED_DATA.BMP'/ ! 60 X 70 PIXELS
CX      DATA JPGFIL/'C:\\I386\\CONNECTED_DATA.JPG'/

      I=WINIO@('%GR%LW',400,400,IHANDL)

      PRINT *,JPGFIL
      CALL GET_DIB_SIZE@(JPGFIL,IWID,IHIT,INBP,IERR)
      PRINT *,IWID,IHIT,INBP,IERR

      I=0
C--EITHER OF THESE CAN BE COMMENTED TO PREVENT EITHER VERT OR HORIZ PANNING.
      IPANX=0
      IPANY=0

C--INIT ENTIRE BUFFER TO GREY EACH TIME THRU SO RESULT OF GET_DIB_BLOCK@ IS VISIBLE.
  100 DO J=1,200000
         DO K=1,3
            IBFFER(K,J)=-63
            ENDDO
         ENDDO

      IPANX=I
      IPANY=I

C--SELECT ANY ONE OF THE CONTINUATION LINES FOR GET_DIB_BLOCK@ BELOW
C--  TO SEE DIFFERENT PERFORMANCE OF FUNCTION FOR BMP & JPG FILES.
      CALL GET_DIB_BLOCK@(JPGFIL,IBFFER,400,400,0,0,
CX     &                                  400, 400,IPANX,IPANY,IERR)
     &                                     25,  25,IPANX,IPANY,IERR)
CX     &                                 IWID,IHIT,IPANX,IPANY,IERR)

      PRINT *,IPANX,IPANY,IERR
      PAUSE

      CALL DISPLAY_DIB_BLOCK@(0,0,                ! %GR POS
     &                        IBFFER,400,400,     ! ARRAY & DIMS
     &                        0,0,                ! ARRAY POS
     &                        400,400,            ! BLOCK SIZE
CX     &                        IWID,IHIT,          ! BLOCK SIZE
     &                        0,0,IERR)           ! FLAGS
      I=I+1
      GOTO 100

C
C======END OF JPG.
      STOP
      END
5 Oct 2007 7:14 #2315

Processing jpeg files requires a lengthy process of decompression. The internal working of this routine is necessarily very different for the two kinds of files.

5 Oct 2007 1:53 #2318

Paul,

Agreed and understood, but shouldn't the call parameters for GET_DIB_BLOCK@ have the same meaning for both file types, and by doing an internal call to GET_DIB_SIZE@ for jpg files, wouldn't it be pretty straightforward to create this consistency?

5 Oct 2007 3:57 #2319

Dennis

OK I agree with you but I am not sure it is worth providing a new routine.

5 Oct 2007 4:13 #2320

Paul,

I argue that it is well worth it because as it now stands I don't think the routine can be used for jpg files to retrieve a block size smaller than the whole image and/or a block that starts anywhere accept at offset 0,0. This then vastly limits the ability to use the routine for very large images without allocating a huge amount of memory. In my civil engineering world we are frequently working with large aerial photographs with the need to zoom in to specific sections. Your consideration of 'fixing' this problem would be very much appreciated.

6 Oct 2007 7:28 #2322

I can add this to the list of things to look at. In the mean time it will be necessary to convert the file from jpeg to bmp. I think Microsoft Paint can do this.

8 Oct 2007 4:34 #2332

That would be great. Is there a way I can be notified if/when a change is made to this function? I'm also willing to be a beta tester for any changes made. In the meantime I'll keep using the larger bmp files. Thanks, Dennis

16 Oct 2007 3:13 #2365

I hope this reply ends up in the right place. This is the first time I've used this forum since relocating.

I use paint to make the conversion from .bmp to .jpg all the time. The thing that paint doesn't do is make .jpg images smaller. If you get your film processed at walgreens and get a cd to accompany, the filesizes are huge. I used to have good rendering software, but that was back when I had a digital camcorder, which got stolen in the great state of Michigan. (Crackheads.)

Now, to make images of a manageable size, I send them to myself using OE, which pares them down to reasonable size. I've got a lot of things i want to do with fortran, in particular clearwin, with images.

wade ward

7 May 2008 9:39 #3169

Paul,

Has there been any progress on this issue?

19 May 2008 11:15 #3214

No progress so far and this is item is way down the list, sorry.

Just got back from 10 days at the Lakeland revival in Florida so it will take me a little while to catch up with routine things anyway.

Paul

21 May 2008 2:20 #3232

Paul,

Good to see you do take some time off. I hope it was a good holiday.

John

21 Jul 2008 9:28 #3506

I don't know if this helps, but I was having difficulty placing an image on the printer. The solution was to put it to a separate intermediate graphics region and then copy that region to the printer. In your case, you could copy a section of this graphics region.

      program print_test
      include <windows.ins>,nolist
      integer*4 iwidth,iheight,dx,dy
      external idraw_image
      call GET_DIB_SIZE@( 'cball7.jpg', iWIDTH, iHEIGHT, NBBP,  iERCODE )
      print *,'iWIDTH, iHEIGHT, NBBP,  iERCODE'
      print *,iWIDTH, iHEIGHT, NBBP,  iERCODE


      iwid=500
      ihgt=300
      i=winio@('%ca[image in window]%ww&')
      i=winio@('%rj%im[{cball7.jpg}]%ff&')
      i=winio@('%`gr[white,RGB_COLOURS]&', iwid, ihgt, ihandle)
      i=winio@('%sc',idraw_image)
      call set_clearwin_string@('printer_document','Print image')
      ihandle2 = 2
      i=CREATE_GRAPHICS_REGION@( iHANDLE2, iWIDTH, iHEIGHT )
      i=USE_RGB_COLOURS@( iHANDLE2, .true.)
      ihandle3 = 3
      jwidth  = iwidth*4
      jHEIGHT = iHEIGHT*4
      i=CREATE_GRAPHICS_REGION@( iHANDLE3, jwidth, jHEIGHT )
      i=USE_RGB_COLOURS@( iHANDLE3, .true.)
      i=SELECT_GRAPHICS_OBJECT@( iHANDLE2 )
      i=IMPORT_IMAGE@('{cball7.jpg}', 0, 0 )

      ihandl = 1
      itest = open_printer@(ihandl)
      if(itest .ne. 0)then
        call use_rgb_colours@(1,1)
        i=SELECT_GRAPHICS_OBJECT@( ihandl )
        call get_graphical_resolution@( ix, iy )
        dx = ix/8
        dy = iy/8
        i = COPY_GRAPHICS_REGION@(ihandl , DX, DY, iWIDTH, iHEIGHT, &
                                  iHANDLE2, 0,0, iWIDTH, iHEIGHT, SRCCOPY)
        i = COPY_GRAPHICS_REGION@(ihandle3, 0,0, jwidth, jHEIGHT, &
                                  iHANDLE2, 0,0, iWIDTH, iHEIGHT, SRCCOPY)
        dx = ix/4
        dy = iy/4
        i = COPY_GRAPHICS_REGION@(ihandl ,  DX,DY, jwidth, jHEIGHT, &
                                  iHANDLE3, 0,  0, jWIDTH, jHEIGHT, SRCCOPY)


!c now close the printer, sending the output to the printer
        itest = close_printer@(ihandl)
      endif
      i=DELETE_GRAPHICS_REGION@( iHANDLE2 )
      i=DELETE_GRAPHICS_REGION@( iHANDLE3 )

      end

      integer*4 function idraw_image()
      include <windows.ins>,nolist
      idraw_image= 1
      i=IMPORT_IMAGE@('{cball7.jpg}', 100,50 )
      end
Please login to reply.