Pour réussir à afficher une image IFF, il faut un peu d'huile de coude

Pour afficher la plupart des images IFF, il faut bien se gratter la tête, et de bonnes docs

Le minimum syndical pour être raisonnablement compatible est de traiter tout çà :
- Données stockées en BigEndian.
- Format de l'image : Planar (Entrelacé) ou Chunky (Normal).
- Compression : Aucune ou algorithme ByteRun1.
- Palette de couleurs : Aucune, Indexée, Normal.
- Mode spécifique du hardware Amiga (Normal, EHB, HAM5/6).
- Dimension de l'image * Ratio d'affichage.
Ça explique donc les +500 lignes de ce module

pour qu'il soit plus facile à partager sur le forum. J'en ai un autre beaucoup plus complet.
Quelques images dans l'esprit PixelArt de l'Amiga

http://amiga.lychesis.net/
http://amiga.lychesis.net/amiga/Cougar/ ... gonSun.iff
http://amiga.lychesis.net/amiga/Cougar/ ... matron.iff
http://amiga.lychesis.net/amiga/Danny/D ... velock.iff
http://amiga.lychesis.net/amiga/Danny/D ... ceTits.iff
http://amiga.lychesis.net/amiga/JimSach ... Lagoon.iff
Une petite compilation - 3.4Mo :
https://www.filepicker.io/api/file/9TWib84jTZCM82hwZeET



Code : Tout sélectionner
;----------------------------------------------------------
; Name: Module TinyIFF
; Description: A tiny module for loading IFF images.
; Author: flype, flype44(at)gmail(dot)com
; Revision: 1.2 (2015-09-11)
;----------------------------------------------------------
; ILBM ::= "FORM" #{ "ILBM" BMHD [CMAP] [CAMG] [BODY] }
; BMHD ::= "BMHD" #{ BitMapHeader }
; CMAP ::= "CMAP" #{ (Red Green Blue)* } [0]
; CAMG ::= "CAMG" #{ LONG }
; BODY ::= "BODY" #{ UBYTE* } [0]
;----------------------------------------------------------
; http://fileformats.archiveteam.org/wiki/ILBM
; http://wiki.amigaos.net/wiki/ILBM_IFF_Interleaved_Bitmap
; http://www.fileformat.info/format/iff/spec/7866a9f0e53c42309af667c5da3bd426/view.htm
; http://amiga.lychesis.net/knowledge/EHB.html
;----------------------------------------------------------
DeclareModule TinyIFF
Declare.i Catch(*memory, size.q = #PB_Ignore)
Declare.i Load(fileName.s)
EndDeclareModule
Module TinyIFF
;----------------------------------------------------------
; INITS
;----------------------------------------------------------
EnableExplicit
;----------------------------------------------------------
; PRIVATE MACROS
;----------------------------------------------------------
Macro MAKEID(a, b, c, d)
((a)|((b)<<8)|((c)<<16)|((d)<<24))
EndMacro
Macro GetUInt16BE(a)
((((a)<<8)&$FF00)|(((a)>>8)&$FF))
EndMacro
Macro GetUInt32BE(a)
((((a)&$FF)<<24)|(((a)&$FF00)<<8)|(((a)>>8)&$FF00)|(((a)>>24)&$FF))
EndMacro
;----------------------------------------------------------
; PRIVATE CONSTANTS
;----------------------------------------------------------
#ID_FORM = MAKEID('F','O','R','M') ; IFF file
#ID_ILBM = MAKEID('I','L','B','M') ; Interleaved Bitmap (Planar)
#ID_PBM = MAKEID('P','B','M',' ') ; Portable Bitmap (Chunky)
#ID_BMHD = MAKEID('B','M','H','D') ; Bitmap Header
#ID_CMAP = MAKEID('C','M','A','P') ; ColorMap
#ID_CAMG = MAKEID('C','A','M','G') ; ViewModes
#ID_BODY = MAKEID('B','O','D','Y') ; Bitmap Data
Enumeration BitmapHeaderCmp
#cmpNone ; No compression
#cmpByteRun1 ; ByteRun1 encoding
EndEnumeration
Enumeration BitmapHeaderMsk
#mskNone ; Opaque rectangular image
#mskHasMask ; Mask plane is interleaved with the bitplanes in the BODY chunk
#mskHasTransparentColor ; Pixels in source planes matching 'transparentColor' are "transparent"
#mskLasso ; Reader may construct a mask by lassoing the image
EndEnumeration
Enumeration ViewModes
#camgLace = $0004 ; Interlaced
#camgEHB = $0080 ; Extra Half Bright
#camgHAM = $0800 ; Hold And Modify
#camgHiRes = $8000 ; High Resolution
#camgSuperHiRes = $0020 ; Super High Resolution
EndEnumeration
;----------------------------------------------------------
; PRIVATE STRUCTURES
;----------------------------------------------------------
CompilerIf Defined(BYTES, #PB_Structure) = #False
Structure BYTES
b.b[0]
EndStructure
CompilerEndIf
CompilerIf Defined(UBYTES, #PB_Structure) = #False
Structure UBYTES
b.a[0]
EndStructure
CompilerEndIf
Structure IFF_RGB8
r.a
g.a
b.a
EndStructure
Structure IFF_CMAP
c.IFF_RGB8[0]
EndStructure
Structure IFF_BMHD
w.u ; UWORD
h.u ; UWORD
x.w ; WORD
y.w ; WORD
nPlanes.a ; UBYTE
masking.a ; UBYTE
compression.a ; UBYTE
pad.a ; UBYTE
tColor.u ; UWORD
xAspect.a ; UBYTE
yAspect.a ; UBYTE
pageWidth.w ; WORD
pageHeight.w ; WORD
EndStructure
Structure IFF_Chunk
code.l
size.l
bytes.UBYTES
EndStructure
Structure IFF_Header
code.l
size.l
format.l
chunk.UBYTES
EndStructure
;----------------------------------------------------------
; PRIVATE PROCEDURES
;----------------------------------------------------------
Procedure Log2(a)
Protected b
While a > ( 1 << b )
b + 1
Wend
ProcedureReturn b
EndProcedure
Procedure FreeMem(*mem)
If *mem
FreeMemory(*mem)
EndIf
EndProcedure
Procedure ColorMapGray(*bmhd.IFF_BMHD)
Protected i.l, numColors.l, *cmap.IFF_CMAP, *c.IFF_RGB8
numColors = 1 << *bmhd\nPlanes
If numColors > 0
*cmap = AllocateMemory(numColors * SizeOf(IFF_RGB8), #PB_Memory_NoClear)
If *cmap
For i = 0 To numColors - 1
*c = *cmap\c[i]
*c\r = i * 255 / numColors
*c\g = *c\r
*c\b = *c\r
Next
EndIf
EndIf
ProcedureReturn *cmap
EndProcedure
Procedure ColorMapEHB(*bmhd.IFF_BMHD, *cmap.IFF_CMAP, cmapSize.l)
Protected i.l, count.l, countEHB.l
Protected *cmapEHB.IFF_CMAP, *c.IFF_RGB8, *d.IFF_RGB8
count = cmapSize / SizeOf(IFF_RGB8)
If count > 0
If Log2(count) = *bmhd\nPlanes
count / 2
EndIf
If count And count < ( 1 << *bmhd\nPlanes )
countEHB = count * 2
*cmapEHB = AllocateMemory(countEHB * SizeOf(IFF_RGB8), #PB_Memory_NoClear)
If *cmap And *cmapEHB
CopyMemory(*cmap, *cmapEHB, cmapSize)
For i = count To countEHB - 1
*c = *cmap\c[i-count]
*d = *cmapEHB\c[i]
*d\r = *c\r >> 1
*d\g = *c\g >> 1
*d\b = *c\b >> 1
Next
EndIf
EndIf
EndIf
ProcedureReturn *cmapEHB
EndProcedure
Procedure UnPackBits(*bmhd.IFF_BMHD, *packedBits.BYTES, packedSize)
Protected i, j, k, n, unpackedSize, *unpackedBits.BYTES
unpackedSize = 1 + ( ( *bmhd\w * *bmhd\h * *bmhd\nPlanes ) / 8 )
If unpackedSize > 0
*unpackedBits = AllocateMemory(unpackedSize)
If *unpackedBits <> 0
While i < packedSize
n = *packedBits\b[i]
If n >= 0
For j = 0 To n
*unpackedBits\b[k] = *packedBits\b[i + 1 + j]
k + 1
Next
i + j
ElseIf n <> -128
For j = 0 To -n
*unpackedBits\b[k] = *packedBits\b[i + 1]
k + 1
Next
i + 1
EndIf
i + 1
Wend
EndIf
EndIf
ProcedureReturn *unpackedBits
EndProcedure
Procedure UnInterleaveBits(*bmhd.IFF_BMHD, *interleaveBits.UBYTES)
Protected C0, C1, C2, C3, C4, C5, C6
Protected bytesPerRow, bit, x, y, z, *unInterleaveBits.UBYTES
*unInterleaveBits = AllocateMemory(*bmhd\w * *bmhd\h * *bmhd\nPlanes)
If *unInterleaveBits
bytesPerRow = ( ( *bmhd\w + 15 ) >> 4 ) << 1
C0 = *bmhd\nPlanes * bytesPerRow
For y = 0 To *bmhd\h - 1
C1 = y * C0
C2 = y * *bmhd\w
For z = 0 To *bmhd\nPlanes - 1
C3 = 1 << z
C4 = C1 + z * bytesPerRow
For x = 0 To bytesPerRow - 1
C5 = *interleaveBits\b[ C4 + x ]
C6 = C2 + x << 3
For bit = 0 To 7
If C5 & ( 1 << ( 7 - bit ) )
*unInterleaveBits\b[ C6 + bit ] | C3
EndIf
Next
Next
Next
Next
EndIf
ProcedureReturn *unInterleaveBits
EndProcedure
Procedure GetPixelHAM(*cmap.IFF_CMAP, pixel, color, hbits, mbits, mask)
Protected r, g, b
Select pixel >> hbits
Case 0 ; rgb
r = *cmap\c[pixel & mask]\r
g = *cmap\c[pixel & mask]\g
b = *cmap\c[pixel & mask]\b
Case 1 ; rgx
r = Red(color)
g = Green(color)
b = ( pixel & mask ) << mbits
b | ( b >> mbits )
Case 2 ; xgb
r = ( pixel & mask ) << mbits
r | ( r >> mbits )
g = Green(color)
b = Blue(color)
Case 3 ; rxg
r = Red(color)
g = ( pixel & mask ) << mbits
g | ( g >> mbits )
b = Blue(color)
EndSelect
ProcedureReturn RGBA(r, g, b, 255)
EndProcedure
Procedure DrawBitmapHAM(*bmhd.IFF_BMHD, *cmap.IFF_CMAP, *bits.UBYTES, image.i)
Protected x, y, i, j, c, hbits, mbits, mask, tColor
If *bmhd\nPlanes > 6
hbits = 6
Else
hbits = 4
EndIf
mbits = ( 8 - hbits )
mask = ( 1 << hbits ) - 1
tColor = RGBA(*cmap\c[*bmhd\tColor]\r,
*cmap\c[*bmhd\tColor]\g,
*cmap\c[*bmhd\tColor]\b, 0)
If StartDrawing(ImageOutput(image))
;Box(0, 0, *bmhd\w, *bmhd\h, RGB(0, 255, 0))
For y = 0 To *bmhd\h - 1
c = RGB(0, 0, 0)
For x = 0 To *bmhd\w - 1
j = *bits\b[i]
If ( *bmhd\masking & #mskHasTransparentColor ) And ( j = *bmhd\tColor )
c = RGB(0, 0, 0)
Plot(x, y, tColor)
Else
c = GetPixelHAM(*cmap, j, c, hbits, mbits, mask)
Plot(x, y, c)
EndIf
i + 1
Next
Next
StopDrawing()
EndIf
EndProcedure
Procedure DrawBitmap(*bmhd.IFF_BMHD, *cmap.IFF_CMAP, *bits.UBYTES, image.i)
Protected x.u, y.u, i.l, j.l, *c.IFF_RGB8
If StartDrawing(ImageOutput(image))
;Box(0, 0, *bmhd\w, *bmhd\h, RGB(0, 255, 0))
For y = 0 To *bmhd\h - 1
For x = 0 To *bmhd\w - 1
j = *bits\b[i]
If ( *bmhd\masking & #mskHasTransparentColor ) And ( j = *bmhd\tColor )
; Transparent Color
Else
*c = *cmap\c[j]
Plot(x, y, RGB(*c\r, *c\g, *c\b))
EndIf
i + 1
Next
Next
StopDrawing()
EndIf
EndProcedure
;----------------------------------------------------------
; PUBLIC PROCEDURES
;----------------------------------------------------------
Procedure.i Catch(*mem.IFF_Header, size.q = #PB_Ignore)
Protected image.i, cmapSize.l, xRes.d, yRes.d
Protected *chunk.IFF_Chunk, *bmhd.IFF_BMHD
Protected *body, *bodyUnpacked, *bodyUninterleaved
Protected *eof, *cmap, *cmapEHB, *cmapGray, *camg.Long
If *mem And *mem\code = #ID_FORM And ( *mem\format = #ID_ILBM Or *mem\format = #ID_PBM )
*mem\size = GetUInt32BE(*mem\size)
If *mem\size > 0 And *mem\size < size
*chunk = *mem\chunk
*eof = *mem + size
While *chunk
*chunk\size = GetUInt32BE(*chunk\size)
If *chunk\size & 1
*chunk\size + 1
EndIf
Select *chunk\code
Case #ID_BMHD
*bmhd = *chunk\bytes
*bmhd\w = GetUInt16BE(*bmhd\w)
*bmhd\h = GetUInt16BE(*bmhd\h)
*bmhd\tColor = GetUInt16BE(*bmhd\tColor)
If *bmhd\masking & #mskNone
*bmhd\tColor = 0
EndIf
If *bmhd\masking & #mskHasMask
*bmhd\nPlanes + 1
*bmhd\tColor = 0
EndIf
Case #ID_CMAP
*cmap = *chunk\bytes
cmapSize = *chunk\size
Case #ID_CAMG
*camg = *chunk\bytes
*camg\l = GetUInt32BE(*camg\l)
Case #ID_BODY
; [PBM ] chunk\bytes => *body
; [PBM ] chunk\bytes => *bodyUnpacked => *body
; [ILBM] chunk\bytes => *bodyUninterleaved => *body
; [ILBM] chunk\bytes => *bodyUnpacked => *bodyUninterleaved => *body
Select *mem\format
Case #ID_ILBM
Select *bmhd\compression
Case #cmpNone
*bodyUninterleaved = UnInterleaveBits(*bmhd, *chunk\bytes)
If *bodyUninterleaved
*body = *bodyUninterleaved
EndIf
Case #cmpByteRun1
*bodyUnpacked = UnPackBits(*bmhd, *chunk\bytes, *chunk\size)
If *bodyUnpacked
*bodyUninterleaved = UnInterleaveBits(*bmhd, *bodyUnpacked)
If *bodyUninterleaved
*body = *bodyUninterleaved
EndIf
EndIf
EndSelect
Case #ID_PBM
Select *bmhd\compression
Case #cmpNone
*body = *chunk\bytes
Case #cmpByteRun1
*bodyUnpacked = UnPackBits(*bmhd, *chunk\bytes, *chunk\size)
If *bodyUnpacked
*body = *bodyUnpacked
EndIf
EndSelect
EndSelect
If *camg And *camg\l & #camgEHB
*cmapEHB = ColorMapEHB(*bmhd, *cmap, cmapSize)
If *cmapEHB
*cmap = *cmapEHB
EndIf
EndIf
If *cmap = #Null
*cmapGray = ColorMapGray(*bmhd)
If *cmapGray
*cmap = *cmapGray
EndIf
EndIf
If *body And *cmap And *bmhd And *bmhd\w > 0 And *bmhd\h > 0
image = CreateImage(#PB_Any, *bmhd\w, *bmhd\h, 24, RGB(0, 255, 0))
If *bmhd\xAspect = 0 Or *bmhd\yAspect = 0
*bmhd\xAspect = 10
*bmhd\yAspect = 11
EndIf
xRes = 1.0 + ( *bmhd\xAspect / *bmhd\yAspect )
yRes = 1.0 + ( *bmhd\yAspect / *bmhd\xAspect )
If *camg And *camg\l & #camgHAM
DrawBitmapHAM(*bmhd, *cmap, *body, image)
Else
DrawBitmap(*bmhd, *cmap, *body, image)
EndIf
;If *camg And *camg\l & #camgLace
; yRes / 2.0
;EndIf
ResizeImage(image, *bmhd\w * xRes, *bmhd\h * yRes, #PB_Image_Raw)
EndIf
FreeMem(*cmapEHB)
FreeMem(*cmapGray)
FreeMem(*bodyUninterleaved)
FreeMem(*bodyUnpacked)
Break
EndSelect
If *chunk < *eof
*chunk + 8 + *chunk\size
Else
*chunk = 0
EndIf
Wend
EndIf
EndIf
ProcedureReturn image
EndProcedure
Procedure.i Load(fileName.s)
Protected image.i, file.i, fileSize.q, *fileData
file = ReadFile(#PB_Any, fileName)
If file
fileSize = Lof(file)
If fileSize > 0
*fileData = AllocateMemory(fileSize, #PB_Memory_NoClear)
If *fileData
If ReadData(file, *fileData, fileSize)
image = Catch(*fileData, fileSize)
EndIf
FreeMemory(*fileData)
EndIf
EndIf
CloseFile(file)
EndIf
ProcedureReturn image
EndProcedure
EndModule