November 28, 2020, 01:54:20 AM

Author Topic: [bmx] HOT.IFFILBMloader by Hotcakes [ 1+ years ago ]  (Read 681 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] HOT.IFFILBMloader by Hotcakes [ 1+ years ago ]
« on: June 29, 2017, 12:28:42 AM »
Title : HOT.IFFILBMloader
Author : Hotcakes
Posted : 1+ years ago

Description : 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).

<a href="http://members.dodo.com.au/~tzuyd/hotmods.rar" target="_blank">http://members.dodo.com.au/~tzuyd/hotmods.rar[/url]


Code :
Code: BlitzMax
  1. Strict
  2.  
  3. Rem
  4. bbdoc: IFF ILBM loader
  5. End Rem
  6. Module HOT.IFFILBMLoader
  7.  
  8. ModuleInfo "Version: 1.00"
  9. ModuleInfo "Author: Toby Zuijdveld"
  10. ModuleInfo "License: Blitz Shared Source Code"
  11. ModuleInfo "Copyright: Jerry Morrison, Electronic Arts (public domain)"
  12. ModuleInfo "Modserver: n/a"
  13.  
  14. ModuleInfo "History: 1.00 Release"
  15.  
  16. Import BRL.Pixmap
  17. Import BRL.EndianStream
  18.  
  19. Private
  20.  
  21. Function ReadTag$( stream:TStream )
  22.         Local tag:Byte[4]
  23.         If stream.ReadBytes( tag,4 )<>4 Return
  24.         Return Chr(tag[0])+Chr(tag[1])+Chr(tag[2])+Chr(tag[3])
  25. End Function
  26.  
  27. Function UStoSI%(a:Short)
  28.         If a>$7FFF Then Return -($8000-(a-$8000)) Else Return a
  29. End Function    ' unsigned short to signed integer
  30.  
  31. Rem
  32.         "cmpByteRun1" is the byte run encoding
  33. End Rem ' End Rem
  34. Const   cmpNone         = 0
  35. Const   cmpByteRun1     = 1
  36.  
  37. Global  ColourMapRed[]  = Null
  38. Global  ColourMapGreen[]
  39. Global  ColourMapBlue[] ' dodginess!
  40.  
  41. Public
  42.  
  43. Rem
  44. bbdoc: Preload a Colour Map for use when loading future ILBM images
  45. about:
  46. #IFFCMAP loads CMAP information from the given @url file.<br>
  47. <br>
  48. Every subsequent ILBM image will be loaded using this palette.<br>
  49. <br>
  50. By default, the CMAP information stored with an ILBM picture would be used.  To restore that behaviour, use #IFFCMAP without a @url specified.<br>
  51. If the Colour Map cannot be loaded, 0 is returned and this function's default behaviour will apply.<br>
  52. End Rem
  53. Function IFFCMAP( url:Object="" )
  54.         If url=""
  55.                 ColourMapRed    = Null
  56.                 ColourMapGreen  = Null
  57.                 ColourMapBlue   = Null
  58.                 Return 1
  59.         EndIf
  60.         Local stream:TStream=ReadStream( url )
  61.         If Not stream
  62.                 ColourMapRed    = Null
  63.                 ColourMapGreen  = Null
  64.                 ColourMapBlue   = Null
  65.                 Return 0
  66.         EndIf
  67.         stream  = BigEndianStream(stream)
  68.         If ReadTag( stream )<>"FORM" Return
  69.         Local   dud%    = stream.Readint()      ' length of file after ILBM header
  70.         If ReadTag( stream )<>"ILBM" Return
  71.         Local   cmap%   = 0
  72.         Local   i%              = 0
  73.         Local   n%              = 0
  74.         While Not stream.Eof()
  75.                 Local blahblah$=ReadTag$(stream)
  76.                 Select  blahblah$'Readtag$(stream)
  77.                         Case    "CMAP"  ' ColorMap
  78.                                 dud             = stream.ReadInt()      ' length of ColourMap chunk
  79.                                 cmap    = dud/3
  80.                                 ColourMapRed    = ColourMapRed[..cmap+1]
  81.                                 ColourMapGreen  = ColourMapGreen[..cmap+1]
  82.                                 ColourMapBlue   = ColourMapBlue[..cmap+1]
  83.                                 For i=1 To cmap
  84.                                         ColourMapRed[i]         = stream.ReadByte()
  85.                                         ColourMapGreen[i]       = stream.ReadByte()
  86.                                         ColourMapBlue[i]        = stream.ReadByte()
  87.                                 Next    ' i=1 To cmap
  88.                                 n=1
  89.                                 Exit
  90.                         Default                 ' unsupported chunks
  91.                                 stream.SkipBytes(stream.ReadInt())      ' skip chunk
  92.                 End Select      ' ReadTag$(stream)
  93.                 If n=0 Then Exit
  94.         Wend    ' Not stream.EOF()
  95.         stream.Close
  96.         Return n
  97. End Function
  98.  
  99. Private
  100.  
  101. Type TPixmapLoaderILBM Extends TPixmapLoader
  102.         Method LoadPixmap:TPixmap(stream:TStream)
  103.                 stream=BigEndianStream( stream )
  104.                
  105.                 If ReadTag( stream )<>"FORM" Return
  106.  
  107.                 Local   dud%                                    = stream.Readint()      ' length of file after ILBM header
  108.  
  109.                 If ReadTag( stream )<>"ILBM" Return
  110.  
  111.                 Local   cmap%                                   = 0
  112.                 Local   w:Short                                 = 0
  113.                 Local   h:Short                                 = 0
  114.                 Local   x%                                              = 0
  115.                 Local   y%                                              = 0
  116.                 Local   nPlanes:Byte                    = 0
  117.                 Local   masking:Byte                    = 0
  118.                 Local   compression:Byte                = 0
  119.                 Local   transparentColour:Short = 0
  120.                 Local   xAspect:Byte                    = 0
  121.                 Local   yAspect:Byte                    = 0
  122.                 Local   pageWidth%                              = 0
  123.                 Local   pageHeight%                             = 0
  124.                 Local   plane%                                  = 0
  125.                 Local   scanline%                               = 1
  126.                 Local   i%                                              = 0
  127.                 Local   n%                                              = 0
  128.                 Local   nn%                                             = 0
  129.                 Local   pixmap:TPixmap                  = Null
  130.                 Local   buffer2:Byte[]
  131.                
  132.                 While Not stream.Eof()
  133.                         Local blahblah$=ReadTag$(stream)
  134.                         Select  blahblah$'Readtag$(stream)
  135.                                 Case    "BMHD"  ' BitMapHeader
  136.                                         dud                                     = stream.ReadInt()                              ' length of BitMapHeader chunk
  137.                                         w                                       = stream.ReadShort()
  138.                                         h                                       = stream.ReadShort()                    ' raster width & height in pixels
  139.                                         x                                       = UStoSI(stream.ReadShort())
  140.                                         y                                       = UStoSI(stream.ReadShort())    ' pixel position for this image
  141.                                         nPlanes                         = stream.ReadByte()                             ' # source bitplanes
  142.                                         masking                         = stream.ReadByte()                             ' Choice of masking technique.
  143.                                         compression                     = stream.ReadByte()                             ' Choice of compression algorithm applied to the rows of all source and mask planes.
  144.                                         Local   dud2%           = stream.ReadByte()                             ' unused; for consistency, put 0 here
  145.                                         transparentColour       = stream.ReadShort()                    ' transparent "colour number" (sort of)
  146.                                         xAspect                         = stream.ReadByte()
  147.                                         yAspect                         = stream.ReadByte()                             ' pixel aspect, a ratio width : height
  148.                                         pageWidth                       = UStoSI(stream.ReadShort())
  149.                                         pageHeight                      = UStoSI(stream.ReadShort())    ' source "page" size in pixels
  150.                                         stream.SkipBytes(dud-20)                                                        ' extended chunk compatibility
  151.                                 Case    "CMAP"  ' ColorMap
  152.                                                         dud                     = stream.ReadInt()                              ' length of ColourMap chunk
  153.                                         If Not ColourMapRed
  154.                                                 cmap            = dud/3
  155.                                                 ColourMapRed    = ColourMapRed[..cmap+1]
  156.                                                 ColourMapGreen  = ColourMapGreen[..cmap+1]
  157.                                                 ColourMapBlue   = ColourMapBlue[..cmap+1]
  158.                                                 For i=1 To cmap
  159.                                                         ColourMapRed[i]         = stream.ReadByte()
  160.                                                         ColourMapGreen[i]       = stream.ReadByte()
  161.                                                         ColourMapBlue[i]        = stream.ReadByte()
  162.                                                 Next    ' i=1 To cmap
  163.                                                 If dud & 1 Then stream.SkipBytes(1)                             ' padded chunk compatibility
  164.                                         Else
  165.                                                 stream.SkipBytes(dud)                                                   ' skip chunk
  166.                                                 If dud & 1 Then stream.SkipBytes(1)                             ' padded chunk compatibility
  167.                                         EndIf   ' ColourMap=Null
  168.                                 Case    "BODY"  '
  169.                                                         dud                             = stream.ReadInt()                      ' length of BODY chunk
  170.                                         Local   row[]
  171.                                         Local   buffer%[17]
  172.                                                         pixmap                  = TPixmap.Create(w,h,PF_RGB888)
  173.                                         If 2^nPlanes>cmap
  174.                                                 ColourMapRed=ColourMapRed[..(2^nPlanes)+1]
  175.                                                 ColourMapGreen=ColourMapGreen[..(2^nPlanes)+1]
  176.                                                 ColourMapBlue=ColourMapBlue[..(2^nPlanes)+1]
  177.                                         EndIf   ' 2^nPlanes>cmap
  178.                                         For Local column%=1 To h
  179.                                                 row                     = New Int[w+17]
  180.                                                 Select  compression
  181.                                                         Case    cmpNone
  182.                                                                 For plane=1 To nPlanes
  183.                                                                         For scanline=1 To w Step 16
  184.                                                                                 buffer[1]       = stream.ReadShort()
  185.                                                                                 For dud=2 To 16
  186.                                                                                         buffer[dud]                             = (buffer[1] Shr (dud-1)) & 1
  187.                                                                                 Next    ' dud=2 To 16
  188.                                                                                 buffer[1]       = buffer[1] & 1
  189.                                                                                 For dud=1 To 16
  190.                                                                                         row[scanline+(16-dud)]  = row[scanline+(16-dud)]+(buffer[dud] Shl (plane-1))
  191.                                                                                 Next    ' dud=1 To 16
  192.                                                                         Next    ' scanline=1 To w Step 8
  193.                                                                 Next    ' plane=1 To nPlanes
  194.                                                         Case    cmpByteRun1
  195.                                                                 Local   dud2    = 1
  196.                                                                                 nn              = 1
  197.                                                                 Local   ii
  198.                                                                 If Not buffer2
  199.                                                                         buffer2 = New Byte[w*h*(nPlanes+1)]
  200.                                                                         Repeat
  201.                                                                                 n=stream.ReadByte();dud2:+1
  202.                                                                                 If n>127 Then n:-256    ' unsigned to signed conversion
  203.                                                                                 If n<>-128      ' noop
  204.                                                                                         If n<0  ' replicate the next byte -n+1 times
  205.                                                                                                 n       = Abs(n)+1
  206.                                                                                                 ii      = stream.ReadByte();dud2:+1
  207.                                                                                                 For i=1 To n
  208.                                                                                                         buffer2[nn]=ii;nn:+1
  209.                                                                                                 Next    ' i=1 To n
  210.                                                                                         Else    ' copy the next n+1 bytes literally
  211.                                                                                                 For i=0 To n
  212.                                                                                                         buffer2[nn]=stream.ReadByte();dud2:+1;nn:+1
  213.                                                                                                 Next    ' i=0 To n
  214.                                                                                         EndIf   ' n<0
  215.                                                                                 EndIf   ' n<>-128
  216.                                                                         Until dud2>dud
  217.                                                                 EndIf   ' Not buffer2
  218.                                                                 For plane=1 To nPlanes
  219.                                                                         For i=1 To w Step 16
  220.                                                                                 buffer[1]       = buffer2[scanline+1]+(buffer2[scanline] Shl 8);scanline:+2
  221.                                                                                 For dud=2 To 16
  222.                                                                                         buffer[dud]                             = (buffer[1] Shr (dud-1)) & 1
  223.                                                                                 Next    ' dud=2 To 16
  224.                                                                                 buffer[1]       = buffer[1] & 1
  225.                                                                                 For dud=1 To 16
  226.                                                                                         row[i+(16-dud)] = row[i+(16-dud)]+(buffer[dud] Shl (plane-1))
  227.                                                                                 Next    ' dud=1 To 16
  228.                                                                         Next    ' i=1 To w Step 16
  229.                                                                 Next    ' plane=1 To nPlanes
  230.                                                         Default ' unsupported compression algorithm
  231.                                                                 dud     = 0
  232.                                                                 Exit
  233.                                                 End Select      ' compression
  234.                                                 If dud=0 Then pixmap                    = Null;Exit
  235.                                                 For dud=1 To w
  236.                                                         pixmap.WritePixel dud-1,column-1,(ColourMapRed[row[dud]+1] Shl 16)+(ColourMapGreen[row[dud]+1] Shl 8)+ColourMapBlue[row[dud]+1]
  237.                                                 Next    ' row=1 To w
  238.                                         Next    ' column=1 To h
  239.                                         If cmap Then ColourMapRed       = Null
  240.                                         Exit
  241.                                 Default                 ' unsupported chunks
  242.                                         stream.SkipBytes(stream.ReadInt())                                                                      ' skip chunk
  243.                         End Select      ' ReadTag$(stream)
  244.                        
  245.                         If pixmap Then Exit
  246.                 Wend    ' Not stream.EOF()
  247.                
  248.                 Return pixmap
  249.         End Method
  250.  
  251. End Type
  252.  
  253. New TPixmapLoaderILBM


Comments :


ozak(Posted 1+ years ago)

 Sweet!


skidracer(Posted 1+ years ago)

 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: [Select]
' 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
DebugLog "IFF ILBM Unsupported compression "+compression
dud = 0
Exit
End Select ' compression
If dud=0 Then pixmap = Null;Exit

If nPlanes=24
For dud=1 To w
pixmap.WritePixel dud-1,column-1,row[dud]
Next ' row=1 To w

Else
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
EndIf



 

SimplePortal 2.3.6 © 2008-2014, SimplePortal