Page 1 of 1

Snippet for Saving Multipage TIF with GDI+

Posted: Fri Oct 30, 2009 7:14 pm
by Xombie
This uses PB images for the files. Just a snippet on how to save multiple pages to a TIF.

Code: Select all

      input\GdiPlusVersion = 1
      GdiplusStartup(@token, @input, #Null)
      If token
         ;
         GdipGetImageEncodersSize(@Number, @Size)
         *Memory = AllocateMemory(Size)
         *pImageCodecInfo = *Memory
         GdipGetImageEncoders(Number, Size, *pImageCodecInfo) 
         For i = 1 To Number
            If "image/tiff" = PeekS(*pImageCodecInfo\MimeType, -1, #PB_Unicode)
               ;
               EncoderParameters\Count = 1
               ; EncoderParameters\Parameter[0]\Guid = ?EncoderSaveFlag
               CopyMemory(?EncoderSaveFlag, @EncoderParameters\Parameter[0]\Guid, SizeOf(GUID))
               EncoderParameters\Parameter[0]\type = 4
               EncoderParameters\Parameter[0]\NumberOfValues = 1
               EncoderParameters\Parameter[0]\Value = @ParameterValue
               ;
               ParameterValue = 18 ; EncoderValueMultiFrame
               GdipCreateBitmapFromHBITMAP(ImageID(0), 0, @gdipPlusImage)
               lResult = GdipSaveImageToFile(gdipPlusImage, "c:\temp\z2.tif", *pImageCodecInfo\clsid, EncoderParameters)
               Debug lResult
               ;
               ParameterValue = 23 ; EncoderValueFrameDimensionPage
               lResult = GdipCreateBitmapFromHBITMAP(ImageID(0), 0, @gdipPlusImage02)
               lResult = GdipSaveAddImage(gdipPlusImage, gdipPlusImage02, EncoderParameters)
               Debug lResult
               ;
               ParameterValue = 20 ; EncoderValueFlush
               lResult = GdipSaveAdd(gdipPlusImage, EncoderParameters)
               Debug lResult
               ;
               GdipDisposeImage(gdipPlusImage)
               GdipDisposeImage(gdipPlusImage02)
               ;
               Break
               ;
            EndIf
            *pImageCodecInfo + SizeOf(ImageCodecInfo)
         Next i
         FreeMemory(*Memory)
         ;
         GdiplusShutdown(token)
      EndIf

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Fri Oct 30, 2009 7:23 pm
by srod
Uhm... no imports, no structure declarations, missing labels with encoder parameter GUIDs...

It's not really going to be a great deal of use without these things!

Come on lad, pull yourself together! :wink:

:)

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Fri Oct 30, 2009 8:35 pm
by Xombie
What?! But I'm too laaaaazy to put together a full example!

Fair enough. When I get a break at work I'll put together a simple example.

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Fri Oct 30, 2009 8:37 pm
by srod
Xombie wrote:What?! But I'm too laaaaazy to put together a full example!

Fair enough. When I get a break at work I'll put together a simple example.
:D

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Wed Nov 04, 2009 6:51 pm
by Xombie
Totally forget to do this.

Code: Select all

;-
EnableExplicit
;-
#GDIPLUS_OK = 0
#PixelFormat32bppARGB = $26200A
#EncoderValueMultiFrame = 18
#EncoderValueFlush = 20
#EncoderValueFrameDimensionPage = 23
;-
Structure GdiplusStartupInput
   GdiPlusVersion.i
   *DebugEventCallback.DebugEventProc
   SuppressBackgroundThread.i 
   SuppressExternalCodecs.i 
EndStructure
Structure EncoderParameter
   Guid.GUID
   NumberOfValues.i
   type.i
   *Value
EndStructure
Structure EncoderParameters
   Count.l
   Parameter.EncoderParameter[1]
EndStructure
Structure ImageCodecInfo
   clsid.CLSID
   formatID.GUID
   *codecName.i
   *dllName.i
   *formatDescription.i
   *filenameExtension.i
   *mimeType.i
   flags.l
   version.l
   sigCount.l
   sigSize.l
   *sigPattern.Byte
   *sigMask.Byte
EndStructure 
;-
Import "gdiplus.lib"
   GdiplusStartup(token, *input.GdiplusStartupInput, output) 
   GdiplusShutdown(token)
   GdipGetImageEncodersSize(*numEncoders, *size)
   GdipGetImageEncoders(numEncoders, Size, *encoders)
   GdipCreateBitmapFromFile(FileName, *image)
   GdipCreateBitmapFromHBITMAP(hbm, hpal, *image)
   GdipCreateBitmapFromScan0(Width, Height, stride, format, *scan0, *image)
   GdipGetImageWidth(*image, *Width)
   GdipGetImageHeight(*image, *Height)
   GdipGetImagePixelFormat(*image, *Format)
   GdipCreateFromHDC(hdc, *gfx)
   GdipDrawImageRectI(*gfx, *image, X, y, Width, Height)
   GdipSaveImageToFile(image, FileName.p-unicode, *clsidEncoder.CLSID, *encoderParams)
   GdipSaveAddImage(image, newImage, *encoderParams.EncoderParameters)
   GdipSaveAdd(image, *encoderParams.EncoderParameters)
   GdipDeleteGraphics(*gfx)
   GdipDisposeImage(image)
EndImport
;-
Procedure StringToBStr (string$) ; By Zapman Inspired by Fr34k 
  Protected Unicode$ = Space(Len(string$)* 2 + 2) 
  Protected bstr_string.l 
  PokeS(@Unicode$, string$, -1, #PB_Unicode) 
  bstr_string = SysAllocString_(@Unicode$) 
  ProcedureReturn bstr_string 
EndProcedure 
;-
Procedure CreateMultiPageTIF()
   ;
   Protected hdc.i
   ;
   Protected Result, input.GdiplusStartupInput, mimeType$
   Protected numEncoders, Size, *pImageCodecInfo.ImageCodecInfo, mem, i, *Memory, gdipPlusImage, gdipPlusImage02, gdipPlusImage03
   Protected bmap.BITMAP
   Protected DC, SourceDC, imghDC
   Protected token
   Protected EncoderParameters.EncoderParameters
   Protected ParameterValue.i
   Protected Number
   ;
   Protected lResult.i
   ;
   Protected encoderCLSID.CLSID
   ;
   input\GdiPlusVersion = 1
   ;
   GdiplusStartup(@token, @input, #Null)
   ;
   If token
      ;
      GdipGetImageEncodersSize(@Number, @Size)
      *Memory = AllocateMemory(Size)
      *pImageCodecInfo = *Memory
      GdipGetImageEncoders(Number, Size, *pImageCodecInfo)
      ;
      EncoderParameters\Count = 1
      CopyMemory(?EncoderSaveFlag, @EncoderParameters\Parameter[0]\Guid, SizeOf(GUID))
      EncoderParameters\Parameter[0]\type = 4
      EncoderParameters\Parameter[0]\NumberOfValues = 1
      EncoderParameters\Parameter[0]\Value = @ParameterValue
      ;
      For i = 1 To Number
         ;
         If "image/tiff" = PeekS(*pImageCodecInfo\MimeType, -1, #PB_Unicode)
            ;
            ParameterValue = #EncoderValueMultiFrame
            GdipCreateBitmapFromFile(StringToBStr("c:\test01.tif"), @gdipPlusImage)
            lResult = GdipSaveImageToFile(gdipPlusImage, "c:\multi.tif", *pImageCodecInfo\clsid, EncoderParameters)
            ;
            ParameterValue = #EncoderValueFrameDimensionPage
            GdipCreateBitmapFromFile(StringToBStr("c:\test02.tif"), @gdipPlusImage02)
            lResult = GdipSaveAddImage(gdipPlusImage, gdipPlusImage02, EncoderParameters)
            ;
            ParameterValue = #EncoderValueFrameDimensionPage
            GdipCreateBitmapFromFile(StringToBStr("c:\test03.tif"), @gdipPlusImage03)
            lResult = GdipSaveAddImage(gdipPlusImage, gdipPlusImage03, EncoderParameters)
            ;
            ParameterValue = #EncoderValueFlush
            lResult = GdipSaveAdd(gdipPlusImage, EncoderParameters)
            ;
            GdipDisposeImage(gdipPlusImage02) : gdipPlusImage02 = 0
            GdipDisposeImage(gdipPlusImage) : gdipPlusImage = 0
            ;
            Break
            ;
         EndIf
         ;
         *pImageCodecInfo + SizeOf(ImageCodecInfo)
         ;
      Next i
      ;
      FreeMemory(*Memory)
      ;
      GdiplusShutdown(token)
      ;
   EndIf
   ;
EndProcedure
;-
CreateMultiPageTIF()
;-
End
;-
DataSection
EncoderSaveFlag:
  Data.l $292266FC
  Data.w $AC40, $47BF
  Data.b $8C, $FC, $A8, $5B, $89, $A6, $55, $DE
EndDataSection
;-

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Wed Nov 04, 2009 10:36 pm
by Edwin Knoppert
What is a multi page tif?
Like gif?
Can i animate it?

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Thu Nov 05, 2009 7:20 am
by Little John
No animation. Just multiple images in one file rather than one file for each image. Is used for instance when receiving faxes with a PC.

Regards, Little John

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Thu Nov 05, 2009 5:38 pm
by ankachen
What a great code for using GDI+
uhh...but just can read the first page of multipage TIF.
any suggestion "GdipCreateBitmapFromFile()" or other command in GDI+ library can read
not only first page but more pages I need.

any help will be very appreciation!!

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Thu Nov 05, 2009 6:11 pm
by srod
Xombie, you can get rid of the BSTR stuff if you use more p-unicode pseudotypes in the Import/EndImport section.

Thanks for sharing.

Re: Snippet for Saving Multipage TIF with GDI+

Posted: Thu Nov 05, 2009 7:33 pm
by Denis
Here is an example to show all frames from tiff file using GDI+

It opens the tiff and display each frame during a time (with a timer). Used Image is with GDI+ documentation.
It's extracted from my GDI+ documentation (the new version for PB 4.40 will come as soon as PB do the final version :mrgreen: ), chm help file only in french but almost one example for each GDI+ function.

You must use the wrapper from my doc (or adapt it for you), dowload it from my first post here
http://www.purebasic.fr/english/viewtop ... us&start=0

For some reasons, some examples doesn't work anymore with PB 4.40 beta ../4/5/6
It 's already corrected but i'm wainting for PB 4.40 final version.

Code: Select all

XIncludeFile "..\..\gdiplus.pbi"

EnableExplicit

#MainWindow = 0
#TexteGadget = 0
#Timer = 10
#Police = 0

Define .i
Global *token, *Image, *dimensionID.GUID, dimensionsCount = 0, dimension.s = ""
Global count, Erreur = 0, OldProc, quit, Titre.s, timer = 800, Operation = -1


Procedure GDIpCallback(window, message, wParam, lParam)
     Protected dc, ps.PAINTSTRUCT
     Protected *Localtoken, *Localgfx
     Protected color = ARGB(#White)
     
     Select message
               
          Case #WM_CLOSE
               Gdiplus_DelImage(*image)
               Gdiplus_Del(*token)
               RemoveWindowTimer(#MainWindow, #Timer)
               OldProc = SetWindowLong_(WindowID(#MainWindow), #GWL_WNDPROC, OldProc)
               quit + 1
               ProcedureReturn 0
               
          Case #WM_PAINT
               dc = BeginPaint_(window, @ps)
               If dc
                    ; initialisation de Gdi+
                    *Localtoken = Gdiplus_New()
                    ; on vérifie que l'initialisation est Ok
                    If *Localtoken
                         ; création du graphique source associé au DC de la fenêtre principale
                         If GdipCreateFromHDC(dc, @*Localgfx) = #Ok
                              If Operation> = count
                                   Operation = 0
                              EndIf
                              GdipGraphicsClear(*Localgfx, color)
                              GdipImageSelectActiveFrame(*image, ?FrameDimensionPage, Operation)
                              GdipDrawImageI(*Localgfx, *image, 50, 50)
                              
                              ; supprime l'objet graphique principal
                              Gdiplus_DelGraphics(*Localgfx)
                         EndIf
                         Gdiplus_Del(*Localtoken)
                    EndIf
                    EndPaint_(window, @ps)
               EndIf
               ProcedureReturn 0
     EndSelect
     ProcedureReturn CallWindowProc_(OldProc, window, message, wParam, lParam)
EndProcedure


If OpenWindow(#MainWindow, 10, 10, 610, 540, "GdiPlus 1.0 - GdipImageGetFrameCount", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
     AddWindowTimer(#MainWindow, #Timer, timer)
     TextGadget(#TexteGadget, 60, 460, WindowWidth(#MainWindow)-60, 90, "")
     LoadFont(#Police, "Arial", 12)
     SetGadgetFontEx(#TexteGadget, #Police)
     SetGadgetColor(#TexteGadget, #PB_Gadget_BackColor, #White)
     
     ; initialisation de Gdi+
     *token = Gdiplus_New()
     ; on vérifie que l'initialisation est Ok
     If *token
          If GdipLoadImageFromFile("..\..\GdiPlusDatas\MultiFrame.tif", @*Image) = #Ok
               ; retrouve le nombre de dimensions de l'image tif
               If GdipImageGetFrameDimensionsCount(*image, @dimensionsCount) = #Ok
                    If dimensionsCount
                         ; allocation de mémoire pour stocker le/les idendifiants dimensionnel de l'image tif
                         *dimensionID = AllocateMemory(SizeOf(GUID)*dimensionsCount)
                         If *dimensionID
                              ; retrouve la liste des dimensions de l'image tif
                              GdipImageGetFrameDimensionsList(*image, *dimensionID, dimensionsCount)
                              ; teste le type dimensions de l'image tif (une seule dimension)
                              If CompareMemory(*dimensionID, ?FrameDimensionTime, SizeOf(GUID))
                                   dimension = "FrameDimensionTime"
                              ElseIf CompareMemory(*dimensionID, ?FrameDimensionResolution, SizeOf(GUID))
                                   dimension = "FrameDimensionResolution"
                              ElseIf CompareMemory(*dimensionID, ?FrameDimensionPage, SizeOf(GUID))
                                   dimension = "FrameDimensionPage"
                              Else
                                   dimension = "inconnue"
                              EndIf
                              ; retrouve le nombre d'image de l'image tif
                              If GdipImageGetFrameCount(*image, ?FrameDimensionPage, @count) = #Ok
                                   Titre = "Nombre de dimensions de l'image : " + Str(dimensionsCount) + Chr(10)
                                   Titre + "Type de la dimension de l'image : " + dimension + Chr(10)
                                   Titre + "Nombre d'images contenu dans le tif : " + Str(count)
                                   ; affiche les données
                                   SetGadgetText(#TexteGadget, Titre)
                              EndIf
                              FreeMemory(*dimensionID)
                         EndIf
                    EndIf
               EndIf
               
               OldProc = SetWindowLong_(WindowID(#MainWindow), #GWL_WNDPROC, @GDIpCallback())
          Else
               Erreur + 1
          EndIf
     EndIf
     
     ; boucle
     Repeat
          If Erreur
               MessageRequester("Erreur", "Impossible de charger l'image", 16)
               Break
          EndIf
          
          Select WaitWindowEvent()
          
               Case #PB_Event_Timer
                    Operation + 1
                    RedrawWindow_(WindowID(#MainWindow), 0, 0, 7)
                    
               Case #PB_Event_CloseWindow
                    quit + 1
                    Break
          EndSelect
          
     Until quit
EndIf
End