Mise à jour du loader d'images IFF.
Réduction importante du code.
Code : Tout sélectionner
;--------------------------------------------------------------------------------------------------
; Module: TinyIFF.pbi
; Description: Module pour charger des images IFF-ILBM ou IFF-PBM.
; Auteur: flype, flype44(at)gmail(dot)com
; Révision: 1.5 (2015-09-17)
; Compilateur: PureBasic 5.40 LTS Beta 3 (x64) Linux
;--------------------------------------------------------------------------------------------------
DeclareModule TinyIFF
; @TinyIFF::Load()
; Charge une image à partir de l'emplacement disque spécifié.
; #ImageID : Le numéro d'identification de l'image à charger.
; FileName$ : Le chemin et le nom du fichier à charger.
; KeepAspect : Garde l'aspect original de l'image (Tient compte de xAspect/yAspect).
; ResizeMode : Mode de redimensionnement de l'image (avec ou sans interpolation).
Declare Load(ImageID.l, FileName$, KeepAspect.l = #True, ResizeMode.l = #PB_Image_Raw)
; @TinyIFF::Catch()
; Charge une image à partir de l'emplacement mémoire spécifié.
; #ImageID : Le numéro d'identification de l'image à charger.
; *Memory : Adresse de l'emplacement mémoire.
; MemSize.q : Taille de l'emplacement mémoire (en octets).
; KeepAspect : Garde l'aspect original de l'image (Tient compte de xAspect/yAspect).
; ResizeMode : Mode de redimensionnement de l'image (avec ou sans interpolation).
Declare Catch(ImageID.l, *Memory, MemSize.q, KeepAspect.l = #True, ResizeMode.l = #PB_Image_Raw)
; @Parameter KeepAspect
; #True : Garde l'aspect original de l'image (défaut).
; #False : Redimensionne l'image en tenant compte de xAspect/yAspect.
; @Parameter ResizeMode
; #PB_Image_Raw : Redimensionne l'image avec interpolation (défaut).
; #PB_Image_Smooth : Redimensionne l'image sans interpolation.
EndDeclareModule
;--------------------------------------------------------------------------------------------------
Module TinyIFF
;------------------------------------------------------------------------------------------------
EnableExplicit
;------------------------------------------------------------------------------------------------
Macro UINT16(a)
((((a)<<8)&$FF00)|(((a)>>8)&$FF))
EndMacro
Macro UINT32(a)
((((a)&$FF)<<24)|(((a)&$FF00)<<8)|(((a)>>8)&$FF00)|(((a)>>24)&$FF))
EndMacro
Macro MAKEID(a, b, c, d)
((a)|((b)<<8)|((c)<<16)|((d)<<24))
EndMacro
;------------------------------------------------------------------------------------------------
Enumeration ChunkIDs
#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') ; Color Map
#ID_CAMG = MAKEID('C','A','M','G') ; View Modes
#ID_BODY = MAKEID('B','O','D','Y') ; Bitmap Data
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
Enumeration BitmapHeaderCmp
#cmpNone ; No compression
#cmpByteRun1 ; ByteRun1 encoding
EndEnumeration
;------------------------------------------------------------------------------------------------
Structure BYTES
b.b[0]
EndStructure
Structure UBYTES
b.a[0]
EndStructure
Structure IFF_RGB8
r.a
g.a
b.a
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_CMAP
c.IFF_RGB8[0]
EndStructure
Structure IFF_Chunk
id.l
size.l
bytes.UBYTES
EndStructure
Structure IFF_Header
id.l
size.l
name.l
chunk.UBYTES
EndStructure
;------------------------------------------------------------------------------------------------
Procedure UnPackBits(*bh.IFF_BMHD, *packedBits.BYTES, packedSize, rowBytes)
Protected i, j, k, v, unpackedSize, *unpackedBits.BYTES
unpackedSize = 1 + ( *bh\h * rowBytes * *bh\nPlanes )
If unpackedSize
*unpackedBits = AllocateMemory(unpackedSize)
If *unpackedBits
While i < packedSize
v = *packedBits\b[i]
If v >= 0
For j = 0 To v
*unpackedBits\b[k] = *packedBits\b[i + 1 + j]
k + 1
Next
i + j
ElseIf v <> -128
For j = 0 To -v
*unpackedBits\b[k] = *packedBits\b[i + 1]
k + 1
Next
i + 1
EndIf
i + 1
Wend
EndIf
EndIf
ProcedureReturn *unpackedBits
EndProcedure
;------------------------------------------------------------------------------------------------
Procedure Catch_PBM_8(*bh.IFF_BMHD, *bp.UBYTES, Array cmap.l(1))
Protected x, y, i
For y = 0 To *bh\h - 1
For x = 0 To *bh\w - 1
Plot(x, y, cmap(*bp\b[i]))
i + 1
Next
Next
EndProcedure
Procedure Catch_PBM_24(*bh.IFF_BMHD, *bp.UBYTES)
Protected x, y, i
For y = 0 To *bh\h - 1
For x = 0 To *bh\w - 1
Plot(x, y, RGB(*bp\b[i], *bp\b[i+1], *bp\b[i+2]))
i + 3
Next
Next
EndProcedure
;------------------------------------------------------------------------------------------------
Procedure Catch_ILBM_8(*bh.IFF_BMHD, *bp.UBYTES, rowBytes.w, camg.l, cmapSize.l, Array cmap.l(1))
Protected i, x, y, c, p, plane, mbits, mask, hbits, Dim pixels(*bh\w)
If camg & #camgHAM
hbits = 4
If *bh\nPlanes > 6 : hbits + 2 : EndIf
mbits = 8 - hbits
mask = ( 1 << hbits ) - 1
EndIf
If camg & #camgEHB
For i = 0 To ( cmapSize / 3 ) - 1
cmap(i+32) = RGB(Red(cmap(i)) >> 1, Green(cmap(i)) >> 1, Blue(cmap(i)) >> 1)
Next
EndIf
For y = 0 To *bh\h - 1
For plane = 0 To *bh\nPlanes - 1
For x = 0 To *bh\w - 1
If *bp\b[x >> 3] & ( 128 >> ( x % 8 ) )
pixels(x) | ( 1 << plane )
EndIf
Next
*bp + rowBytes
Next
For x = 0 To *bh\w - 1
If camg & #camgHAM
p = pixels(x)
Select p >> hbits
Case 0: c = cmap(p & mask)
Case 1: c = RGB(Red(c), Green(c), ( p & mask ) << mbits)
Case 2: c = RGB(( p & mask ) << mbits, Green(c), Blue(c))
Case 3: c = RGB(Red(c), ( p & mask ) << mbits, Blue(c))
EndSelect
Else
c = cmap(pixels(x))
EndIf
Plot(x, y, c)
pixels(x) = 0
Next
c = 0
Next
EndProcedure
Procedure Catch_ILBM_24(*bh.IFF_BMHD, *bp.UBYTES, rowBytes.l)
Protected x, y, w, h, p, plane, p0, p1, p2
Protected Dim m(*bh\w), Dim r(*bh\w), Dim g(*bh\w), Dim b(*bh\w)
w = *bh\w - 1 : h = *bh\h - 1 : p = *bh\nPlanes - 1
For x = 0 To w : m(x) = 128 >> ( x % 8 ) : Next
For y = 0 To h
For plane = 0 To p
p0 = 1 << plane
p1 = 1 << ( plane - 8 )
p2 = 1 << ( plane - 16 )
If plane < 8
For x = 0 To w
If *bp\b[x >> 3] & m(x) : r(x) | p0 : EndIf
Next
ElseIf plane > 15
For x = 0 To w
If *bp\b[x >> 3] & m(x) : b(x) | p2 : EndIf
Next
Else
For x = 0 To w
If *bp\b[x >> 3] & m(x) : g(x) | p1 : EndIf
Next
EndIf
*bp + rowBytes
Next
For x = 0 To w
Plot(x, y, RGB(r(x), g(x), b(x)))
r(x) = 0 : g(x) = 0 : b(x) = 0
Next
Next
EndProcedure
;------------------------------------------------------------------------------------------------
Procedure Catch(ImageID.l, *m.IFF_Header, MemSize.q, KeepAspect.l = #True, ResizeMode.l = #PB_Image_Raw)
Protected i.l, image.i, rowBytes.w, camg.l, cmapSize.l, *imageOutput, *bp, *eof, *bodyUnpacked
Protected *ck.IFF_Chunk, *bh.IFF_BMHD, *cmap.IFF_CMAP, Dim cmap.l(256)
If *m And *m\id = #ID_FORM And ( *m\name = #ID_ILBM Or *m\name = #ID_PBM )
*m\size = UINT32(*m\size)
If *m\size > 0 And *m\size < MemSize
*eof = *m + MemSize
*ck = *m\chunk
While *ck
*ck\size = UINT32(*ck\size)
If *ck\size & 1
*ck\size + 1
EndIf
Select *ck\id
Case #ID_BMHD
*bh = *ck\bytes
*bh\w = UINT16(*bh\w)
*bh\h = UINT16(*bh\h)
rowBytes = ( ( ( *bh\w + 15 ) >> 4 ) << 1 )
Case #ID_CAMG
camg = UINT32(PeekL(*ck\bytes))
Debug "camg = %" + RSet(Bin(camg, #PB_Long), 32, "0")
Case #ID_CMAP
*cmap = *ck\bytes
cmapSize = *ck\size
For i = 0 To ( cmapSize / 3 ) - 1
cmap(i) = RGB(*cmap\c[i]\r, *cmap\c[i]\g, *cmap\c[i]\b)
Next
Case #ID_BODY
*bp = *ck\bytes
If *bh\compression = #cmpByteRun1
*bodyUnpacked = UnPackBits(*bh, *ck\bytes, *ck\size, rowBytes)
*bp = *bodyUnpacked
EndIf
If *bp And *bh
image = CreateImage(ImageID, *bh\w, *bh\h, 24, RGB(0, 0, 0))
If image
If ImageID = #PB_Any
*imageOutput = ImageOutput(image)
Else
*imageOutput = ImageOutput(ImageID)
EndIf
If StartDrawing(*imageOutput)
Select *m\name
Case #ID_ILBM
If *bh\nPlanes = 24
Catch_ILBM_24(*bh, *bp, rowBytes)
Else
Catch_ILBM_8(*bh, *bp, rowBytes, camg, cmapSize, cmap())
EndIf
Case #ID_PBM
If *bh\nPlanes = 24
Catch_PBM_24(*bh, *bp)
Else
Catch_PBM_8(*bh, *bp, cmap())
EndIf
EndSelect
StopDrawing()
EndIf
EndIf
If KeepAspect = #False
If *bh\xAspect = 0 Or *bh\yAspect = 0
*bh\xAspect = 10 : *bh\yAspect = 11
EndIf
Protected xRes.d = 1.0 + ( *bh\xAspect / *bh\yAspect )
Protected yRes.d = 1.0 + ( *bh\yAspect / *bh\xAspect )
If ImageID = #PB_Any
ResizeImage(image, *bh\w * xRes, *bh\h * yRes, ResizeMode)
Else
ResizeImage(ImageID, *bh\w * xRes, *bh\h * yRes, ResizeMode)
EndIf
EndIf
EndIf
If *bodyUnpacked
FreeMemory(*bodyUnpacked)
EndIf
Break
EndSelect
If *ck < *eof
*ck + 8 + *ck\size
Else
*ck = 0
EndIf
Wend
EndIf
EndIf
ProcedureReturn image
EndProcedure
Procedure Load(ImageID.l, FileName$, KeepAspect.l = #True, ResizeMode.l = #PB_Image_Raw)
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) > 0
image = Catch(ImageID, *fileData, fileSize, KeepAspect, ResizeMode)
EndIf
FreeMemory(*fileData)
EndIf
EndIf
CloseFile(file)
EndIf
ProcedureReturn image
EndProcedure
EndModule
;--------------------------------------------------------------------------------------------------