Flippin' Images

Just starting out? Need help? Post your questions and find answers here.
User avatar
blueb
Addict
Addict
Posts: 1116
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Flippin' Images

Post by blueb »

There have been a great deal of changes in the image libs, etc.

I found some code in CodeArchiv that did what I wanted (I believe it was by Freak), except that the images are now upside down in 4.40.

Code: Select all

Procedure GetShellThumbnail(FileName$, Image, Width, Height, Depth = #PB_Image_DisplayFormat) 
  Protected Result = 0, ImageResult 
  Protected Desktop.IShellFolder, Folder.IShellFolder 
  Protected Extract.IExtractImage 
  Protected *pidlFolder.ITEMIDLIST, *pidlFile.ITEMIDLIST  
  Protected Priority, Flags, Bitmap = 0, size.SIZE 

  If SHGetDesktopFolder_(@Desktop) >= 0 
    If Desktop\ParseDisplayName(#Null, #Null, GetPathPart(FileName$), #Null, @*pidlFolder, #Null) = #S_OK 
      If Desktop\BindToObject(*pidlFolder, #Null, ?IID_IShellFolder, @Folder) = #S_OK 
        If Folder\ParseDisplayName(#Null, #Null, GetFilePart(FileName$) , #Null, @*pidlFile, #Null) = #S_OK 
          If Folder\GetUIObjectOf(#Null, 1, @*pidlFile, ?IID_IExtractImage, 0, @Extract) = #S_OK 

            ImageResult = CreateImage(Image, Width, Height, Depth) 
            If ImageResult 
              If Image = #PB_Any 
                Image = ImageResult 
              EndIf    
              If Depth = #PB_Image_DisplayFormat 
                Depth = ImageDepth(Image) 
              EndIf 
                                  
              size\cx = Width 
              size\cy = Height 
              
              If Extract\GetLocation(Space(#MAX_PATH), #MAX_PATH, @Priority, @size, Depth, @Flags) >= 0                
                If Extract\Extract(@Bitmap) >= 0 And Bitmap 
                                  
                  If StartDrawing(ImageOutput(Image)) 
                    DrawImage(Bitmap, 0, 0) 
                    StopDrawing()                    
                    Result = ImageResult 
                  EndIf 
                  
                  DeleteObject_(Bitmap) 
                EndIf 
              EndIf                
              Extract\Release() 
            EndIf 
            
            If Result = 0 
              FreeImage(Image) 
            EndIf            
          EndIf 
                    
          CoTaskMemFree_(*pidlFile) 
        EndIf                        
        Folder\Release() 
      EndIf      
      CoTaskMemFree_(*pidlFolder)      
    EndIf    
    Desktop\Release() 
  EndIf 

  ProcedureReturn Result 
  
  DataSection  
    IID_IShellFolder: ; {000214E6-0000-0000-C000-000000000046} 
      Data.l $000214E6 
      Data.w $0000, $0000 
      Data.b $C0, $00, $00, $00, $00, $00, $00, $46 
  
    IID_IExtractImage: ; {BB2E617C-0920-11D1-9A0B-00C04FC2D6C1} 
      Data.l $BB2E617C 
      Data.w $0920, $11D1 
      Data.b $9A, $0B, $00, $C0, $4F, $C2, $D6, $C1 
  EndDataSection  
EndProcedure

#ExplorerGadget = 0 
#ImageGadget    = 1 
#Image = 0 

If OpenWindow(0, 0, 0, 500, 400, "Shell Thumbnails", #PB_Window_SystemMenu|#PB_Window_ScreenCentered) 

  ExplorerTreeGadget(#ExplorerGadget, 5, 5, 190, 390, "C:\") 
  ImageGadget(#ImageGadget, 225, 100, 250, 200, 0, #PB_Image_Border) 

  Repeat 
    Event = WaitWindowEvent() 
    
    If Event = #PB_Event_Gadget And EventGadget() = #ExplorerGadget And EventType() = #PB_EventType_Change      
    
      If GetShellThumbnail(GetGadgetText(#ExplorerGadget), #Image, 250, 200) 
        SetGadgetState(#ImageGadget, ImageID(#Image)) 
      Else 
        SetGadgetState(#ImageGadget, 0) 
      EndIf 
      
    EndIf 
    
  Until Event = #PB_Event_CloseWindow 
EndIf 
End 
How can I flip the images and is there a better way with the new image commands?

--blueb
- It was too lonely at the top.

System : PB 6.21(x64) and Win 11 Pro (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Flippin' Images

Post by srod »

That code doesn't work for me at all on Vista with PB 4.31 or 4.4.

I usually use SHGetFileInfo_() in order to get the default icons.
I may look like a mule, but I'm not a complete ass.
User avatar
blueb
Addict
Addict
Posts: 1116
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: Flippin' Images

Post by blueb »

I've just tried the program on my work computer, which is running XP Pro with Pure 4.40b4.

Everything appears to work fine. I'mable to open BMP, JPG AND GIF with no trouble and the pictures are oriented properly.


My home unit with the problem is running Vista Ultimate and Pure 4.40b5

--blueb
- It was too lonely at the top.

System : PB 6.21(x64) and Win 11 Pro (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Flippin' Images

Post by srod »

Ah yes, I see... confirmed. BitBlt_() shows the images correctly, but then you lose the alpha-channel of course.

Might be linked to this : http://www.purebasic.fr/english/viewtop ... =4&t=39524
I may look like a mule, but I'm not a complete ass.
freak
PureBasic Team
PureBasic Team
Posts: 5941
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Flippin' Images

Post by freak »

Yes, BitBlt_() is the way to go here. This works:

Code: Select all

Procedure GetShellThumbnail(FileName$, Image, Width, Height, Depth = 24)
  Protected Result = 0, ImageResult
  Protected Desktop.IShellFolder, Folder.IShellFolder
  Protected Extract.IExtractImage
  Protected *pidlFolder.ITEMIDLIST, *pidlFile.ITEMIDLIST 
  Protected Priority, Flags, Bitmap = 0, size.SIZE
  Protected DC, SourceDC, BitmapInfo.BITMAP

  If SHGetDesktopFolder_(@Desktop) >= 0
    If Desktop\ParseDisplayName(#Null, #Null, GetPathPart(FileName$), #Null, @*pidlFolder, #Null) = #S_OK
      If Desktop\BindToObject(*pidlFolder, #Null, ?IID_IShellFolder, @Folder) = #S_OK
        If Folder\ParseDisplayName(#Null, #Null, GetFilePart(FileName$) , #Null, @*pidlFile, #Null) = #S_OK
          If Folder\GetUIObjectOf(#Null, 1, @*pidlFile, ?IID_IExtractImage, 0, @Extract) = #S_OK

            ImageResult = CreateImage(Image, Width, Height, Depth)
            If ImageResult
              If Image = #PB_Any
                Image = ImageResult
              EndIf   
                                 
              size\cx = Width
              size\cy = Height
             
              If Extract\GetLocation(Space(#MAX_PATH), #MAX_PATH, @Priority, @size, Depth, @Flags) >= 0               
                If Extract\Extract(@Bitmap) >= 0 And Bitmap
                                 
                  DC = StartDrawing(ImageOutput(Image))
                  If DC
                    SourceDC = CreateCompatibleDC_(DC)
                    If SourceDC
                      GetObject_(Bitmap, SizeOf(BITMAP), @BitmapInfo)
                      SelectObject_(SourceDC, Bitmap)
                      BitBlt_(DC, 0, 0, BitmapInfo\bmWidth, BitmapInfo\bmHeight, SourceDC, 0, 0, #SRCCOPY)
                      DeleteDC_(SourceDC)
                    EndIf
                    StopDrawing()                   
                    Result = ImageResult
                  EndIf
                 
                  DeleteObject_(Bitmap)
                EndIf
              EndIf               
              Extract\Release()
            EndIf
           
            If Result = 0
              FreeImage(Image)
            EndIf           
          EndIf
                   
          CoTaskMemFree_(*pidlFile)
        EndIf                       
        Folder\Release()
      EndIf     
      CoTaskMemFree_(*pidlFolder)     
    EndIf   
    Desktop\Release()
  EndIf

  ProcedureReturn Result
 
  DataSection 
    IID_IShellFolder: ; {000214E6-0000-0000-C000-000000000046}
      Data.l $000214E6
      Data.w $0000, $0000
      Data.b $C0, $00, $00, $00, $00, $00, $00, $46
 
    IID_IExtractImage: ; {BB2E617C-0920-11D1-9A0B-00C04FC2D6C1}
      Data.l $BB2E617C
      Data.w $0920, $11D1
      Data.b $9A, $0B, $00, $C0, $4F, $C2, $D6, $C1
  EndDataSection 
EndProcedure

#ExplorerGadget = 0
#ImageGadget    = 1
#Image = 0

If OpenWindow(0, 0, 0, 500, 400, "Shell Thumbnails", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

  ExplorerTreeGadget(#ExplorerGadget, 5, 5, 190, 390, "C:\")
  ImageGadget(#ImageGadget, 225, 100, 250, 200, 0, #PB_Image_Border)

  Repeat
    Event = WaitWindowEvent()
   
    If Event = #PB_Event_Gadget And EventGadget() = #ExplorerGadget And EventType() = #PB_EventType_Change     
   
      If GetShellThumbnail(GetGadgetText(#ExplorerGadget), #Image, 250, 200)
        SetGadgetState(#ImageGadget, ImageID(#Image))
      Else
        SetGadgetState(#ImageGadget, 0)
      EndIf
     
    EndIf
   
  Until Event = #PB_Event_CloseWindow
EndIf
End 
Here is the reason for all this:
DrawImage() in ImageOutput() no longer uses API. To support the new drawing modes it operates on the pixel data directly. Now, Windows allows you to create a Bitmap that either stores its pixel rows top-down in memory, or bottom-up (the default). But there is no way to find out this orientation when all you have is a HBITMAP as it is here. So DrawImage() cannot know the orientation of the input image and so it assumes bottom-up because this is the more common orientation and also the way all PB images are stored.

Long story short: If you are dealing with top-down images or images of unknown memory orientation, BitBlt_() is your only choice because through MS some magic, it knows the image orientation and can draw the image accordingly.

Did i mention that GDI is a mess? :P
quidquid Latine dictum sit altum videtur
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Flippin' Images

Post by srod »

GetDIBits_(), if used to query the bitmap, should tell you if the bitmap is top-down or bottom-up.
I may look like a mule, but I'm not a complete ass.
freak
PureBasic Team
PureBasic Team
Posts: 5941
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Flippin' Images

Post by freak »

srod wrote:GetDIBits_(), if used to query the bitmap, should tell you if the bitmap is top-down or bottom-up.
Nope. It returns a positive height value no matter what was used in the bitmap creation. Its the same for GetObject_().
quidquid Latine dictum sit altum videtur
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Flippin' Images

Post by srod »

Ahh.... teach me not to test my own assertion! I knew GetObject_() always returned a positive value but just assumed that GetDIBits_(), when you set the relevant parameters to zero, would report the height correctly. A quick test and I can confirm that you are correct there. :) Strange that GDI does not allow us to accurately recover the original BITMAPINFOHEADER structure from a DIB.
I may look like a mule, but I'm not a complete ass.
Fred
Administrator
Administrator
Posts: 18247
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Flippin' Images

Post by Fred »

Timo spent about 1 day on the subject, so i bet he is correct :twisted:
User avatar
blueb
Addict
Addict
Posts: 1116
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: Flippin' Images

Post by blueb »

Thanks for getting to the bottom of this Freak.

It works on Vista Ultimate.

--blueb
- It was too lonely at the top.

System : PB 6.21(x64) and Win 11 Pro (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Flippin' Images

Post by srod »

Fred wrote:Timo spent about 1 day on the subject, so i bet he is correct :twisted:
Nope, no doubts at all there! :) Just a case of me not testing out my own assertion - and not for the first time either! :wink:
I may look like a mule, but I'm not a complete ass.
Thalius
Enthusiast
Enthusiast
Posts: 711
Joined: Thu Jul 17, 2003 4:15 pm
Contact:

Re: Flippin' Images

Post by Thalius »

Fred wrote:Timo spent about 1 day on the subject, so i bet he is correct :twisted:
does he still have his hair ? :mrgreen:
"In 3D there is never enough Time to do Things right,
but there's always enough Time to make them *look* right."
"psssst! i steal signatures... don't tell anyone! ;)"
Fred
Administrator
Administrator
Posts: 18247
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Flippin' Images

Post by Fred »

AFAIK, yes ;)
Post Reply