Announcement

Collapse
No announcement yet.

Some PNG Images Display Oddly

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Some PNG Images Display Oddly

    I downloaded some PNG images recently and ran across several which gave odd results when loading them into a graphic control.

    In IrfanView (image viewer) and MSPaint, all of the images display as 128x128, with the image content centered and fully covering the image boundaries.

    But when I run the code below, loading the images with GDI+ code I've for some from Jose, all of the images report the 128x128 size, but display as shown in this composite image. Some are small, some smaller, and some are offset.

    Most images I downloaded worked exactly as expected. But these few displayed incorrectly.

    Other than by looking at the result, is there a way that I might have detected whether these images would load incorrectly using the GDI+ code? And why IrfanView/MSPaint might show the image "correctly"?

    Just wondering ...



    Here's the compilable code. (download code plus images here)
    Code:
    'Compilable Example:
    #Compiler PBWin 10
    #Compile Exe
    #Dim All
    %Unicode = 1
    #Include "cwindow.inc"
    #Include "cgdiplus.inc"
    
    Enum Equates Singular
       IDC_Button
       IDC_Graphic
    End Enum
    
    Global hDlg As Dword
    
    Function PBMain() As Long
       Dialog New Pixels, 0, "Image Test",300,300,1050,400, %WS_OverlappedWindow To hDlg
       Dialog Show Modal hDlg Call DlgProc
    End Function
    
    CallBack Function DlgProc() As Long
       Local hBMP As Dword, i,w,h,x,y As Long, temp$
       Select Case Cb.Msg
          Case %WM_InitDialog
             i = -1
             temp$ = Dir$("*.png")
             While Len(temp$)
                Incr i
                x = IIf(i>6,(i-7)*150,i*150)
                y = IIf(i>6,210,40)
                Control Add Graphic, hDlg, %IDC_Graphic+i, "", x,y,150,150
                LoadImageToMemoryBitmap(temp$, hBMP, w,h)
                Graphic Attach hDlg, %IDC_Graphic+i
                Graphic Clear
                Graphic Copy hBMP, 0
                Graphic Set Pos (0,0)
                Graphic Print Str$(w) + Str$(h)
                Graphic Attach hBMP, 0
                Graphic Bitmap End
                temp$ = Dir$
             Wend
       End Select
    End Function
    
    Sub LoadImageToMemoryBitmap (ImgName As String, hWin As Dword, w As Long, h As Long)
       Local pGraphics,pImage,hDC,token As Dword, StartupInput As GdiplusStartupInput
       'initialize GDI
       StartupInput.GdiplusVersion = 1                    'initialize GDIPlus
       GdiplusStartup(token, StartupInput, ByVal %NULL)   'initialize GDIPlus
    
       GdipLoadImageFromFile((ImgName), pImage)           'load image
       GdipGetImageWidth(pImage,w)                        'get width
       GdipGetImageHeight(pImage, h)                      'get height
    
       Graphic Bitmap New w,h To hWin
       Graphic Attach hWin, 0
       Graphic Get DC To hDC
    
       GdipCreateFromHDC(hDC, pGraphics)                  ' Create the Graphic object
       GdipDrawImage(pGraphics, pImage, 0, 0)             ' Draw the image
    
       'shutdown GDI
       If pImage Then GdipDisposeImage(pImage)            'cleanup
       If pGraphics Then GdipDeleteGraphics(pGraphics)    'cleanup
       GdiplusShutdown token                              'shutdown GDI+
    End Sub
    Last edited by Gary Beene; 4 Feb 2013, 10:03 AM.

  • #2
    Here's IrfanView showing the baseball image from above. It looks as expected here.

    It displays fine in MS Paint also.

    Comment


    • #3
      The images have different resolutions.

      Use:

      Code:
      GdipDrawImageRect(pGraphics, pImage, 0, 0, w, h)             ' Draw the image
      instead of GdipDrawImage.
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        Sounds like you need to stretch the image uniformly. It doesn't look like the images are displaying incorrectly, they're just displaying the upper left 128 x 128 pixels.
        LarryC
        Website
        Sometimes life's a dream, sometimes it's a scream

        Comment


        • #5
          Jose!
          Thanks for the explanation. The change you suggest does correctly show the image.

          But, you've shown me a gap in my understanding of an image file. I didn't realize that in addition to the size of the image (128x128 in these images), that a DPI was stored in the file as well.

          I thought DPI is a measure of the display device pixel density. What does it have to do with the image itself?

          I'll have to go do some reading on this ...

          Comment


          • #6
            See: http://www.powerbasic.com/support/pb...ad.php?t=47870
            Forum: http://www.jose.it-berater.org/smfforum/index.php

            Comment


            • #7
              You can also use GdipDrawImage, but set the resolution, e.g. GdipBitmapSetResolution(pImage, 96, 96)

              Of course, instead of using 96, and if your application is High DPI aware, you should get the DPI at which your application is working and use it.
              Forum: http://www.jose.it-berater.org/smfforum/index.php

              Comment


              • #8
                Hi Larry,
                Sorry, my label may have confused things. The size of the graphic controls are 150x150, so the images are displaying more than 128x128 pixels.

                As for stretching, I thought putting the 128x128 pixels in the upper left hand corner of the graphic control was all that was needed. I don't yet understand how the DPI info in the file is needed/used. I've read that some image editors stick in default values, rather than any technically-derived value. So that further raises the question of the reason/value for DPI values in a file. I'll definitely read more on this ...

                Comment


                • #9
                  Jose!
                  Thanks for the link. I'd totally forgotten that information. Perhaps if I asked fewer questions, I'd more easily remember the answers I get!

                  I've noticed more than once in these forums, that when I type in a search term I often get dozens of my own threads! I'm sure my memory will improve the older I get!

                  Comment


                  • #10
                    Hey Jose!
                    I sometimes want a scaled up/down version of the image contained in the file.

                    Once the image is loaded into any Graphic target, I can always use Graphic commands to get to the size I want, but with the GDIPDrawImageRect command, getting a scaled version seems incredibly easy - just add a scalefactor as an argument to the function call and then add a single line modifying w/h before the memory bitmap is created and before GdipDrawImageRect is used.

                    Here's the output of images, using a 0.5 scalefactor, showing the half size images:



                    Here's the modified compilable code. Is there anything wrong with the simple modification I made to achieve the scaled images?

                    Code:
                    'Compilable Example:
                    #Compiler PBWin 10
                    #Compile Exe
                    #Dim All
                    %Unicode = 1
                    #Include "cwindow.inc"
                    #Include "cgdiplus.inc"
                    
                    Enum Equates Singular
                       IDC_Button
                       IDC_Graphic
                    End Enum
                    
                    Global hDlg As Dword
                    
                    Function PBMain() As Long
                       Dialog New Pixels, 0, "Image Test",300,300,1050,400, %WS_OverlappedWindow To hDlg
                       Dialog Show Modal hDlg Call DlgProc
                    End Function
                    
                    CallBack Function DlgProc() As Long
                       Local hBMP As Dword, i,w,h,x,y As Long, temp$
                       Select Case Cb.Msg
                          Case %WM_InitDialog
                             i = -1
                             temp$ = Dir$("*.png")
                             While Len(temp$)
                                Incr i
                                x = IIf(i>6,(i-7)*150,i*150)
                                y = IIf(i>6,210,40)
                                Control Add Graphic, hDlg, %IDC_Graphic+i, "", x,y,150,150
                                LoadImageToMemoryBitmap(temp$, hBMP, w,h, 0.5)
                                Graphic Attach hDlg, %IDC_Graphic+i
                                Graphic Clear
                                Graphic Copy hBMP, 0
                                Graphic Set Pos (0,0)
                                Graphic Print Str$(w) + Str$(h)
                                Graphic Attach hBMP, 0
                                Graphic Bitmap End
                                temp$ = Dir$
                             Wend
                       End Select
                    End Function
                    
                    Sub LoadImageToMemoryBitmap (ImgName As String, hWin As Dword, w As Long, h As Long, SF As Single) '<-- SF = scale factor
                       Local pGraphics,pImage,hDC,token As Dword, StartupInput As GdiplusStartupInput
                    
                       'initialize GDI
                       StartupInput.GdiplusVersion = 1                    'initialize GDIPlus
                       GdiplusStartup(token, StartupInput, ByVal %NULL)   'initialize GDIPlus
                    
                       GdipLoadImageFromFile((ImgName), pImage)           'load image
                       GdipGetImageWidth(pImage,w)                        'get width
                       GdipGetImageHeight(pImage, h)                      'get height
                    
                       w = SF * w : h = SF * h   '<---- the new line
                    
                       Graphic Bitmap New w,h To hWin
                       Graphic Attach hWin, 0
                       Graphic Get DC To hDC
                    
                       GdipCreateFromHDC(hDC, pGraphics)                  ' Create the Graphic object
                       GdipDrawImageRect(pGraphics, pImage, 0, 0, w, h)   ' Draw the image
                    
                       'shutdown GDI
                       If pImage Then GdipDisposeImage(pImage)            'cleanup
                       If pGraphics Then GdipDeleteGraphics(pGraphics)    'cleanup
                       GdiplusShutdown token                              'shutdown GDI+
                    End Sub
                    Last edited by Gary Beene; 4 Feb 2013, 10:06 PM.

                    Comment


                    • #11
                      Nothing wrong. There is also a function called GdipDrawImageRectRect that allows you to select the size of both the origin and the destination, that you can use to magnify a portion of the image.
                      Forum: http://www.jose.it-berater.org/smfforum/index.php

                      Comment

                      Working...
                      X