Code archives/File Utilities/HOT.IFFILBMloader
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Used exactly like the png/jpg/bmp loaders, this module attaches itself to LoadPixmap (and LoadImage) to provide support for IFF ILBM images (of Amiga days). An extra function allows the loading of images with alternate Colour Maps (palettes). http://members.dodo.com.au/~tzuyd/hotmods.rar | |||||
Strict Rem bbdoc: IFF ILBM loader End Rem Module HOT.IFFILBMLoader ModuleInfo "Version: 1.00" ModuleInfo "Author: Toby Zuijdveld" ModuleInfo "License: Blitz Shared Source Code" ModuleInfo "Copyright: Jerry Morrison, Electronic Arts (public domain)" ModuleInfo "Modserver: n/a" ModuleInfo "History: 1.00 Release" Import BRL.Pixmap Import BRL.EndianStream Private Function ReadTag$( stream:TStream ) Local tag:Byte[4] If stream.ReadBytes( tag,4 )<>4 Return Return Chr(tag[0])+Chr(tag[1])+Chr(tag[2])+Chr(tag[3]) End Function Function UStoSI%(a:Short) If a>$7FFF Then Return -($8000-(a-$8000)) Else Return a End Function ' unsigned short to signed integer Rem "cmpByteRun1" is the byte run encoding End Rem ' End Rem Const cmpNone = 0 Const cmpByteRun1 = 1 Global ColourMapRed[] = Null Global ColourMapGreen[] Global ColourMapBlue[] ' dodginess! Public Rem bbdoc: Preload a Colour Map for use when loading future ILBM images about: #IFFCMAP loads CMAP information from the given @url file.<br> <br> Every subsequent ILBM image will be loaded using this palette.<br> <br> By default, the CMAP information stored with an ILBM picture would be used. To restore that behaviour, use #IFFCMAP without a @url specified.<br> If the Colour Map cannot be loaded, 0 is returned and this function's default behaviour will apply.<br> End Rem Function IFFCMAP( url:Object="" ) If url="" ColourMapRed = Null ColourMapGreen = Null ColourMapBlue = Null Return 1 EndIf Local stream:TStream=ReadStream( url ) If Not stream ColourMapRed = Null ColourMapGreen = Null ColourMapBlue = Null Return 0 EndIf stream = BigEndianStream(stream) If ReadTag( stream )<>"FORM" Return Local dud% = stream.Readint() ' length of file after ILBM header If ReadTag( stream )<>"ILBM" Return Local cmap% = 0 Local i% = 0 Local n% = 0 While Not stream.Eof() Local blahblah$=ReadTag$(stream) Select blahblah$'Readtag$(stream) Case "CMAP" ' ColorMap dud = stream.ReadInt() ' length of ColourMap chunk cmap = dud/3 ColourMapRed = ColourMapRed[..cmap+1] ColourMapGreen = ColourMapGreen[..cmap+1] ColourMapBlue = ColourMapBlue[..cmap+1] For i=1 To cmap ColourMapRed[i] = stream.ReadByte() ColourMapGreen[i] = stream.ReadByte() ColourMapBlue[i] = stream.ReadByte() Next ' i=1 To cmap n=1 Exit Default ' unsupported chunks stream.SkipBytes(stream.ReadInt()) ' skip chunk End Select ' ReadTag$(stream) If n=0 Then Exit Wend ' Not stream.EOF() stream.Close Return n End Function Private Type TPixmapLoaderILBM Extends TPixmapLoader Method LoadPixmap:TPixmap(stream:TStream) stream=BigEndianStream( stream ) If ReadTag( stream )<>"FORM" Return Local dud% = stream.Readint() ' length of file after ILBM header If ReadTag( stream )<>"ILBM" Return Local cmap% = 0 Local w:Short = 0 Local h:Short = 0 Local x% = 0 Local y% = 0 Local nPlanes:Byte = 0 Local masking:Byte = 0 Local compression:Byte = 0 Local transparentColour:Short = 0 Local xAspect:Byte = 0 Local yAspect:Byte = 0 Local pageWidth% = 0 Local pageHeight% = 0 Local plane% = 0 Local scanline% = 1 Local i% = 0 Local n% = 0 Local nn% = 0 Local pixmap:TPixmap = Null Local buffer2:Byte[] While Not stream.Eof() Local blahblah$=ReadTag$(stream) Select blahblah$'Readtag$(stream) Case "BMHD" ' BitMapHeader dud = stream.ReadInt() ' length of BitMapHeader chunk w = stream.ReadShort() h = stream.ReadShort() ' raster width & height in pixels x = UStoSI(stream.ReadShort()) y = UStoSI(stream.ReadShort()) ' pixel position for this image nPlanes = stream.ReadByte() ' # source bitplanes masking = stream.ReadByte() ' Choice of masking technique. compression = stream.ReadByte() ' Choice of compression algorithm applied to the rows of all source and mask planes. Local dud2% = stream.ReadByte() ' unused; for consistency, put 0 here transparentColour = stream.ReadShort() ' transparent "colour number" (sort of) xAspect = stream.ReadByte() yAspect = stream.ReadByte() ' pixel aspect, a ratio width : height pageWidth = UStoSI(stream.ReadShort()) pageHeight = UStoSI(stream.ReadShort()) ' source "page" size in pixels stream.SkipBytes(dud-20) ' extended chunk compatibility Case "CMAP" ' ColorMap dud = stream.ReadInt() ' length of ColourMap chunk If Not ColourMapRed cmap = dud/3 ColourMapRed = ColourMapRed[..cmap+1] ColourMapGreen = ColourMapGreen[..cmap+1] ColourMapBlue = ColourMapBlue[..cmap+1] For i=1 To cmap ColourMapRed[i] = stream.ReadByte() ColourMapGreen[i] = stream.ReadByte() ColourMapBlue[i] = stream.ReadByte() Next ' i=1 To cmap If dud & 1 Then stream.SkipBytes(1) ' padded chunk compatibility Else stream.SkipBytes(dud) ' skip chunk If dud & 1 Then stream.SkipBytes(1) ' padded chunk compatibility EndIf ' ColourMap=Null Case "BODY" ' dud = stream.ReadInt() ' length of BODY chunk Local row[] Local buffer%[17] pixmap = TPixmap.Create(w,h,PF_RGB888) If 2^nPlanes>cmap ColourMapRed=ColourMapRed[..(2^nPlanes)+1] ColourMapGreen=ColourMapGreen[..(2^nPlanes)+1] ColourMapBlue=ColourMapBlue[..(2^nPlanes)+1] EndIf ' 2^nPlanes>cmap For Local column%=1 To h row = New Int[w+17] Select compression Case cmpNone For plane=1 To nPlanes For scanline=1 To w Step 16 buffer[1] = stream.ReadShort() For dud=2 To 16 buffer[dud] = (buffer[1] Shr (dud-1)) & 1 Next ' dud=2 To 16 buffer[1] = buffer[1] & 1 For dud=1 To 16 row[scanline+(16-dud)] = row[scanline+(16-dud)]+(buffer[dud] Shl (plane-1)) Next ' dud=1 To 16 Next ' scanline=1 To w Step 8 Next ' plane=1 To nPlanes Case cmpByteRun1 Local dud2 = 1 nn = 1 Local ii If Not buffer2 buffer2 = New Byte[w*h*(nPlanes+1)] Repeat n=stream.ReadByte();dud2:+1 If n>127 Then n:-256 ' unsigned to signed conversion If n<>-128 ' noop If n<0 ' replicate the next byte -n+1 times n = Abs(n)+1 ii = stream.ReadByte();dud2:+1 For i=1 To n buffer2[nn]=ii;nn:+1 Next ' i=1 To n Else ' copy the next n+1 bytes literally For i=0 To n buffer2[nn]=stream.ReadByte();dud2:+1;nn:+1 Next ' i=0 To n EndIf ' n<0 EndIf ' n<>-128 Until dud2>dud EndIf ' Not buffer2 For plane=1 To nPlanes For i=1 To w Step 16 buffer[1] = buffer2[scanline+1]+(buffer2[scanline] Shl 8);scanline:+2 For dud=2 To 16 buffer[dud] = (buffer[1] Shr (dud-1)) & 1 Next ' dud=2 To 16 buffer[1] = buffer[1] & 1 For dud=1 To 16 row[i+(16-dud)] = row[i+(16-dud)]+(buffer[dud] Shl (plane-1)) Next ' dud=1 To 16 Next ' i=1 To w Step 16 Next ' plane=1 To nPlanes Default ' unsupported compression algorithm dud = 0 Exit End Select ' compression If dud=0 Then pixmap = Null;Exit For dud=1 To w pixmap.WritePixel dud-1,column-1,(ColourMapRed[row[dud]+1] Shl 16)+(ColourMapGreen[row[dud]+1] Shl 8)+ColourMapBlue[row[dud]+1] Next ' row=1 To w Next ' column=1 To h If cmap Then ColourMapRed = Null Exit Default ' unsupported chunks stream.SkipBytes(stream.ReadInt()) ' skip chunk End Select ' ReadTag$(stream) If pixmap Then Exit Wend ' Not stream.EOF() Return pixmap End Method End Type New TPixmapLoaderILBM |
Comments
| ||
Sweet! |
| ||
When nPlanes is 24 there is no palette so the code should not be using a lookup. This change seems to work for me: |
Code Archives Forum