#PB_ImagePlugin_GIF for OSX.
Currently original image depth is always set to 8 bits.
SaveImage / EncodeImage unfortunately ignore setting for requested bit depth (I couldn't find a way to tell OSX to write 1 bit or 4 bit images).
Code: Select all
; *** #PB_ImagePlugin_GIF ***
#PB_ImagePlugin_GIF = $464947
XIncludeFile "ImagePlugin.pbi"
ImportC ""
CFDataCreate(allocator, *bytes, length)
CFRelease(cf)
CGBitmapContextCreate(*data, width, height, bitsPerComponent, bytesPerRow, colorspace, bitmapInfo)
CGColorSpaceCreateDeviceRGB()
CGColorSpaceRelease(colorspace)
CGContextDrawImage(c, xf.f, yf.f, wf.f, hf.f, image, d0.f, d1.f, d2.f, d3.f, xd.d, yd.d, wd.d, hd.d)
CGContextRelease(context)
CGDataProviderCreateWithCFData(cfdata)
CGDataProviderCreateWithData(*info, *data, size, releaseData)
CGDataProviderRelease(provider)
CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, space, bitmapInfo, provider, *decode, shouldInterpolate, intent)
CGImageGetBitsPerPixel(image)
CGImageRelease(image)
CGImageSourceCreateImageAtIndex(isrc, index, options)
CGImageSourceCreateWithDataProvider(provider, options)
EndImport
; *** Decoder procedures ***
ProcedureC _GIFCleanup_(*Globals.PB_ImageDecoderGlobals)
If *Globals\Mode = #PB_ImageDecoder_File And *Globals\Buffer
FreeMemory(*Globals\Buffer) : *Globals\Buffer = #Null : *Globals\Length = 0
EndIf
EndProcedure
ProcedureC.i _GIFCheck_(*Globals.PB_ImageDecoderGlobals)
If *Globals\Mode = #PB_ImageDecoder_File
; File Mode
Protected.i GIFFile = ReadFile(#PB_Any, PeekS(*Globals\Filename, -1, #PB_UTF8))
If GIFFile And Lof(GIFFile) >= 12
*Globals\Length = Lof(GIFFile)
*Globals\Buffer = AllocateMemory(*Globals\Length, #PB_Memory_NoClear)
If *Globals\Buffer
ReadData(GIFFile, *Globals\Buffer, 12)
If PeekL(*Globals\Buffer) = $38464947 ; 'GIF8'
*Globals\Width = PeekU(*Globals\Buffer + 6)
*Globals\Height = PeekU(*Globals\Buffer + 8)
If *Globals\Width And *Globals\Height
ReadData(GIFFile, *Globals\Buffer + 12, *Globals\Length - 12)
Else
_GIFCleanup_(*Globals)
EndIf
EndIf
EndIf
CloseFile(GIFFile)
EndIf
ElseIf *Globals\Length >= 12
; Memory mode
If PeekL(*Globals\Buffer) = $38464947 ; 'GIF8'
*Globals\Width = PeekU(*Globals\Buffer + 6)
*Globals\Height = PeekU(*Globals\Buffer + 8)
EndIf
EndIf
If *Globals\Width And *Globals\Height
*Globals\Depth = 32
*Globals\OriginalDepth = 8
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
ProcedureC.i _GIFDecode_(*Globals.PB_ImageDecoderGlobals, *Buffer, Pitch, Flags)
Protected.i ColorSpace, Context, Image, Provider, Source
Provider = CGDataProviderCreateWithData(#Null, *Globals\Buffer, *Globals\Length, #Null)
Source = CGImageSourceCreateWithDataProvider(Provider, #Null)
Image = CGImageSourceCreateImageAtIndex(Source, 0, #Null)
ColorSpace = CGColorSpaceCreateDeviceRGB()
Context = CGBitmapContextCreate(*Buffer, *Globals\Width, *Globals\Height, 8, Pitch, ColorSpace, 1)
CGContextDrawImage(Context, 0, 0, *Globals\Width, *Globals\Height, image, 0,0,0,0, 0, 0, *Globals\Width, *Globals\Height)
CGContextRelease(Context)
CGColorSpaceRelease(ColorSpace)
CGImageRelease(Image)
CFRelease(Source)
CGDataProviderRelease(Provider)
_GIFCleanup_(*Globals)
ProcedureReturn #True
EndProcedure
Procedure UseGIFImageDecoder()
Static GIFDecoder.PB_ImageDecoder, Registered
If Not Registered
GIFDecoder\ID = #PB_ImagePlugin_GIF
GIFDecoder\Check = @_GIFCheck_()
GIFDecoder\Cleanup = @_GIFCleanup_()
GIFDecoder\Decode = @_GIFDecode_()
PB_ImageDecoder_Register(GIFDecoder)
Registered = #True
EndIf
ProcedureReturn Registered
EndProcedure
; *** Encoder procedures ***
ProcedureC.i _GIFEncode_(*Filename, *Buffer, Width, Height, LinePitch, Flags, EncoderFlags, RequestedDepth)
Protected.i CFData, ColorSpace, Image, ImageData, ImageRep, Length, Pool, Provider, Result
Protected.s FileName
; Convert to NSBitmapImageRep
CFData = CFDataCreate(#Null, *Buffer, Height * LinePitch)
Provider = CGDataProviderCreateWithCFData(CFData)
ColorSpace = CGColorSpaceCreateDeviceRGB()
If RequestedDepth = 32
Image = CGImageCreate(Width, Height, 8, 32, LinePitch, ColorSpace, 1, Provider, #Null, #False, 0)
Else
Image = CGImageCreate(Width, Height, 8, 24, LinePitch, ColorSpace, 0, Provider, #Null, #False, 0)
EndIf
ImageRep = CocoaMessage(0, CocoaMessage(0, 0, "NSBitmapImageRep alloc"), "initWithCGImage:", Image)
CGImageRelease(Image)
CGColorSpaceRelease(ColorSpace)
CGDataProviderRelease(Provider)
CFRelease(CFData)
; Convert NSBitmapImageRep to GIF
If ImageRep
Pool = CocoaMessage(0, 0, "NSAutoreleasePool new")
ImageData = CocoaMessage(0, ImageRep, "representationUsingType:", 2, "properties:", #Null)
If *Filename
; File Mode
FileName = PeekS(*Filename, -1, #PB_UTF8)
Result = CocoaMessage(0, ImageData, "writeToFile:$", @FileName, "atomically:", #NO)
Else
; Memory Mode
Length = CocoaMessage(0, ImageData, "length")
Result = AllocateMemory(Length, #PB_Memory_NoClear)
CocoaMessage(0, ImageData, "getBytes:", Result, "length:", Length)
EndIf
CocoaMessage(0, Pool, "release")
CocoaMessage(0, ImageRep, "release")
EndIf
ProcedureReturn Result
EndProcedure
Procedure UseGIFImageEncoder()
Static GIFEncoder.PB_ImageEncoder, Registered
If Not Registered
GIFEncoder\ID = #PB_ImagePlugin_GIF
GIFEncoder\Encode24 = @_GIFEncode_()
GIFEncoder\Encode32 = @_GIFEncode_()
PB_ImageEncoder_Register(GIFEncoder)
Registered = #True
EndIf
ProcedureReturn Registered
EndProcedure