Code: Select all
;////////////////////////////////////////////////////////////////////////////////////
;
; Library: GIF image loader/saver
;
; Author: Lloyd Gallant (netmaestro)
;
; Date: October 14, 2013
;
; Compiler version: PureBasic 5.10 and later (EncodeImage)
;
; License: Usage is unrestricted
; No Warranty expressed Or implied
;
;////////////////////////////////////////////////////////////////////////////////////
Declare ConvertTo8Bit(hImageIn, dither=1)
Declare LoadGIF(imagenumber, *hImageIn, inpath$)
Declare SaveGIF(hImageIn, outpath$)
UsePNGImageDecoder()
UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UseTIFFImageDecoder()
UsePNGImageEncoder()
pattern$ = "PNG, BMP, JPEG, TIFF|*.png;*.bmp;*.jpg;*.jpeg;*.tiff|PNG (*.png)|*.png|BMP (*.bmp)|*.bmp|JPEG (*.jpg)|*.jpg|TIFF (*.tif)|*.tif"
inpath$ = OpenFileRequester("Choose an image to convert to GIF:","",pattern$, 0)
prompt$ = RemoveString(GetFilePart(inpath$),"."+GetExtensionPart(inpath$))
prompt$ +".gif"
If FileSize(inpath$) < 1
MessageRequester("Info:","No file selected. Ending...",#MB_ICONINFORMATION)
End
EndIf
If inpath$
hImage = LoadImage(#PB_Any, inpath$)
Else
End
EndIf
*hImage8 = ConvertTo8bit(hImage)
If *hImage8
pattern$ = "GIF (*.gif)|*.gif;"
outpath$ = SaveFileRequester("Choose a path to save the .gif file:",prompt$,pattern$, 0)
outpath$ = RemoveString(outpath$, ".gif")
If outpath$
outpath$ + ".gif"
result = SaveGIF(*hImage8, outpath$)
Else
MessageRequester("","No save location chosen... ending.")
EndIf
Else
MessageRequester("Error:","Problem encoding image... ending.")
EndIf
If result
If MessageRequester("Success!","Image successfully converted and saved as "+outpath$+" Would you like to view it now?", #PB_MessageRequester_YesNo)
ReadFile(0, outpath$)
*this = AllocateMemory(Lof(0))
If *this
ReadData(0, *this, Lof(0))
imagefromgif = LoadGIF(#PB_Any, *this, outpath$)
If imagefromgif
OpenWindow(0,0,0,ImageWidth(imagefromgif), ImageHeight(imagefromgif),"GIF Viewer - "+outpath$, #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ImageGadget(0,0,0,0,0,ImageID(imagefromgif))
Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
EndIf
EndIf
Else
MessageRequester("Error:","Problem saving image... ending.")
EndIf
Procedure ConvertTo8Bit(hImageIn, dither=1)
*result = EncodeImage(hImageIn, #PB_ImagePlugin_PNG, #PB_Image_FloydSteinberg, 8)
ProcedureReturn *result
EndProcedure
;=============================================================
;{ Gdiplus GIFstuff Section
;=============================================================
Prototype GdiplusStartup( *token, *input, mode )
Prototype GdipCreateBitmapFromStream(stream.ISTREAM, *image)
Prototype GdipSetImagePalette(*image, *palette)
Prototype GdipSaveImageToFile(*image, *path, *clsid, *enc)
Prototype GdipGetImageWidth(*image, *width)
Prototype GdipGetImageHeight(*image, *height)
Prototype GdipCreateFromHDC( hdc, *gfx)
Prototype GdipDrawImageRectI( *gfx, *image, x, y, Width, Height )
Prototype GdipDeleteGraphics( *gfx )
Prototype GdipDisposeImage( *image )
Prototype GdiplusShutdown( *token )
CompilerIf Defined(GdiplusStartupInput, #PB_Structure) = 0
Structure GdiplusStartupInput
GdiPlusVersion.l
*DebugEventCallback.Debug_Event
SuppressBackgroundThread.l
SuppressExternalCodecs.l
EndStructure
CompilerEndIf
Structure StreamObject
block.l
*bits
stream.ISTREAM
EndStructure
Procedure LoadGIF(imagenumber, *hImageIn, inpath$)
Protected *token, lib.i, width.i, height.i, *gfx
Protected Stream.StreamObject
Protected input.GdiplusStartupInput
input\GdiPlusVersion = 1
lib = OpenLibrary(#PB_Any, "gdiplus.dll")
If Not lib
MessageRequester("Error","Required component gdiplus.dll is not found. Please install it and retry ", #MB_ICONERROR)
ProcedureReturn
EndIf
GdiplusStartup.GdiplusStartup = GetFunction( lib, "GdiplusStartup" )
GdipCreateBitmapFromStream.GdipCreateBitmapFromStream = GetFunction( lib, "GdipCreateBitmapFromStream")
GdipGetImageWidth.GdipGetImageWidth = GetFunction( lib, "GdipGetImageWidth")
GdipGetImageHeight.GdipGetImageHeight = GetFunction( lib, "GdipGetImageHeight")
GdipCreateFromHDC.GdipCreateFromHDC = GetFunction( lib, "GdipCreateFromHDC" )
GdipDrawImageRectI.GdipDrawImageRectI = GetFunction( lib, "GdipDrawImageRectI" )
GdipDeleteGraphics.GdipDeleteGraphics = GetFunction( lib, "GdipDeleteGraphics" )
GdipDisposeImage.GdipDisposeImage = GetFunction( lib, "GdipDisposeImage" )
GdiplusShutdown.GdiplusShutdown = GetFunction( lib, "GdiplusShutdown" )
GdiplusStartup( @*token, @input, #Null)
Length = MemorySize(*hImageIn)
Stream\block = GlobalAlloc_(#GHND, Length)
Stream\bits = GlobalLock_(Stream\block)
CopyMemory(*hImageIn, stream\bits, Length)
If CreateStreamOnHGlobal_(stream\bits, 0, @Stream\stream) = #S_OK
GdipCreateBitmapFromStream(Stream\stream , @*gifcandidate)
Else
GdiplusShutdown(*token)
CloseLibrary(lib)
ProcedureReturn 0
EndIf
GdipGetImageWidth(*gifcandidate, @width)
GdipGetImageHeight(*gifcandidate, @height)
If imagenumber = #PB_Any
result = CreateImage(#PB_Any, width, height, 24)
Else
CreateImage(imagenumber, width, height, 24)
result = imagenumber
EndIf
hdc=StartDrawing(ImageOutput(result))
GdipCreateFromHDC( hdc, @*gfx)
GdipDrawImageRectI(*gfx, *gifcandidate, 0, 0, width, height)
StopDrawing()
Stream\stream\Release()
GlobalUnlock_(Stream\bits)
GlobalFree_(Stream\block)
GdipDeleteGraphics(*gfx)
GdipDisposeImage(*gifcandidate)
GdiplusShutdown(*token)
CloseLibrary(lib)
ProcedureReturn result
EndProcedure
Procedure SaveGIF(*hImageIn, outpath$)
Protected *token, lib
Protected Stream.StreamObject
Protected input.GdiplusStartupInput
input\GdiPlusVersion = 1
lib = OpenLibrary(#PB_Any, "gdiplus.dll")
If Not lib
MessageRequester("Error","Required component gdiplus.dll is not found. Please install it and retry ", #MB_ICONERROR)
ProcedureReturn
EndIf
GdiplusStartup.GdiplusStartup = GetFunction( lib, "GdiplusStartup" )
GdipCreateBitmapFromStream.GdipCreateBitmapFromStream = GetFunction( lib, "GdipCreateBitmapFromStream")
GdipSaveImageToFile.GdipSaveImageToFile = GetFunction( lib, "GdipSaveImageToFile" )
GdipDisposeImage.GdipDisposeImage = GetFunction( lib, "GdipDisposeImage" )
GdiplusShutdown.GdiplusShutdown = GetFunction( lib, "GdiplusShutdown" )
GdiplusStartup( @*token, @input, #Null)
Length = MemorySize(*hImageIn)
Stream\block = GlobalAlloc_(#GHND, Length)
Stream\bits = GlobalLock_(Stream\block)
CopyMemory(*hImageIn, stream\bits, Length)
If CreateStreamOnHGlobal_(stream\bits, 0, @Stream\stream) = #S_OK
GdipCreateBitmapFromStream(Stream\stream , @*gifcandidate)
Else
GdiplusShutdown(*token)
CloseLibrary(lib)
ProcedureReturn 0
EndIf
CompilerIf #PB_Compiler_Unicode = 0
Unicode$=Space(Len(outpath$)*2+2)
PokeS(@Unicode$, outpath$, -1, #PB_Unicode)
*outpath = SysAllocString_(@Unicode$)
CompilerElse
*outpath = @outpath$
CompilerEndIf
If GdipSaveImageToFile( *gifcandidate, *outpath, ?clsid_gif, 0) = #S_OK
result = #True
Else
result = #False
EndIf
Stream\stream\Release()
GlobalUnlock_(Stream\bits)
GlobalFree_(Stream\block)
GdipDisposeImage(*gifcandidate)
GdiplusShutdown(*token)
CloseLibrary(lib)
ProcedureReturn result
EndProcedure
DataSection
clsid_gif: ; clsid for gif image format
Data.l $557cf402
Data.w $1a04
Data.w $11d3
Data.b $9a,$73,$00,$00,$f8,$1e,$f3,$2e
EndDataSection