ATARI-ST : PI1,PI2,PI3,PC1,PC2,PC3,NEO
AMIGA : IFF ILBM (incomplet manque HAM & HALFBRIGHT)
PC : PCX
Code : Tout sélectionner
; +----------------------------+
; | GRAPHIC FILE FORMATS |
; +----------------------------+
; | ATARI ST FILE FORMATS |
; | |
; | Degas Elite PI1,2,3 LOADER |
; | Pc1,2,3 |
; | Neochrome .NEO |
; +----------------------------+
; | COMODORE AMIGA FILE FORMATS|
; | |
; | IFF (beta implementation) | manque le mode HAM & Halfbright
; +----------------------------+
; | PC FILE FORMATS |
; | |
; | PCX (PAINTBRUSH) | pcx V.5.00
; | |
; +----------------------------+
; | © Case @ purebasic forums |
; | Domaine public |
; +----------------------------+
; ------- declaration des procedures principales ------
Declare pi1(file$,x=0,y=0)
Declare iff(file$,x=0,y=0)
Declare pcx(file$,x=0,y=0)
; ------------- procedures utilitaires -----------------
Declare BE_peekw(*adr)
Declare BE_peekl(*adr)
Declare.S getchunkid(*adr)
Declare unpack(*source,*unpack,off,planes,w,h,noplane=0)
Declare draw(x,y,*buffer,off,BIT_PLANES,w,h,square,Array rvb(1),option=0,LinePaddingSize=0)
Declare unpack_pcx(*source,*unpack,w,h,off,planes,nbytes)
;********************************************************
; exemple d'utilisation
;********************************************************
InitSprite()
main=OpenWindow(#PB_Any,0,0,1024,768,"test")
screen=OpenWindowedScreen(WindowID(main),0,0,1024,768,0,0,0)
;
Repeat
ClearScreen($101010)
file$=OpenFileRequester("charge image P(C)i 123","c:\","*.pcx;*.pi1;*.pi2;*.pi3;*.pc1;*.pc2;*.pc3;*.neo",1);"D:\AMINET\pix\tp96\NOT!FINL.PCX";
StartDrawing(ScreenOutput())
If FileSize(file$)>0
Select LCase(GetExtensionPart(file$))
Case "pi1","pc1","pi2","pi3","pc2","pc3","neo"
PI1(file$,100,0)
Case"iff","" ; charge l'image sur l'ecran
iff(file$,100,0)
Case "pcx"
pcx(file$,100,0)
EndSelect
EndIf
StopDrawing() ; arette de dessiner
FlipBuffers() ; affiche l'ecran
; boucle d'affichage
Repeat
ev=WaitWindowEvent(1)
FlipBuffers()
Select ev
Case #PB_Event_CloseWindow
Break 2
Case #WM_LBUTTONDOWN
Break
EndSelect
ForEver
ForEver
End
;********************************************************
;********************************************************
;
;
;
; procedures principales
Procedure PI1(file$,x=0,y=0) ; (PI1,PI2,PI3,PC1,PC2,PC3,NEO)
If FileSize(file$)>0
*sourcebuffer=AllocateMemory(FileSize(file$)) ; cree le tampon memoire pour charger les données
READ_BYTE=0 ; position dans le buffer source
Dim plane(4) ; stocker les bitplans
Dim RVB(15) ; palette de couleur
rd=OpenFile(#PB_Any,file$) ; ouverture fichier
If rd ; Succes !!
ReadData(rd,*sourcebuffer,FileSize(file$))
CloseFile(rd)
EndIf
If (LCase(GetExtensionPart(file$)))="neo" ; neochrome
ALWAY0=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
flag=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2 ;
Else ; degas flag : 0=320*200*16 couleurs : 1=640*200*4 couleurs : 2=640*400*2 couleurs
flag=PeekB(*sourcebuffer+READ_BYTE+1) &$ff ; format d'image(Pi1,Pi2,pi3)
packed= PeekB(*sourcebuffer+READ_BYTE) &$ff ; packed (pc1,pc2,pc3)
READ_BYTE+2
EndIf ;
Select flag ; QUEL FORMAT D'IMAGE
Case 0 ; PI1 16 colors, 320x200 pixels
BIT_PLANES=4 ; 4 PB =16 couleurs
x_bound=320 ; resolution horizontale
y_bound=200 ; resolution Verticale
square=1
offset=6 ; bytes offset
nbytes=160 ; bytes par lignes
Case 1 ; PI2 4 colors, 640x200 pixels
BIT_PLANES=2 ; 2 PB =4 couleurs
x_bound=640 ; resolution horizontale
y_bound=200 ; resolution Verticale
square=0 ; pixels non carres multiplie par 2 pour conserver le raport original
offset=2
nbytes=160
Case 2 ; PI3 2 colors, 640x400 pixels
BIT_PLANES=1 ; 1 PB =16 couleurs
x_bound=640 ; resolution horizontale
y_bound=400 ; resolution Verticale
square=1
offset=0
nbytes=80
EndSelect
; +--------------------------+
; | lecture de la palette |
; +--------------------------+
For b=0 To 15 ; on repete 16 fois la boucle suivante
val.w=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
bl=(val & %1111 )*36 ; BLEU
vl=((val >> 4) & %1111 )*36; VERT
rl=((val >>8) & %1111)*36 ; ROUGE
RVB(b)=RGB(rl,vl,bl) ; stoque la valeur RVB de la couleur actuelle
Next
; neochrome
If (LCase(GetExtensionPart(file$)))="neo"
For a =1 To 12
filename$=filename$+Chr(PeekB(*sourcebuffer+READ_BYTE)&$ff):READ_BYTE +1;semble ne pas etre implementé
Next
limits=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
speed=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
steps=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
xoffset=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
yoffset=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
img_w=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
img_h=BE_peekw(*sourcebuffer+READ_BYTE):READ_BYTE+2
; les 33 mots suivants sont reserves, on saute 66 bytes
read_byte +66
EndIf
If packed<>0 ; packed degas elite file rle decoder
*unpackbuffer=AllocateMemory(32000)
unpack(*sourcebuffer,*unpackbuffer,READ_BYTE,BIT_PLANES,x_bound,y_bound)
draw(X,Y,*unpackbuffer,0,BIT_PLANES,x_bound,y_bound,square,rvb())
Else
draw(X,Y,*sourcebuffer,READ_BYTE,BIT_PLANES,x_bound,y_bound,square,rvb())
EndIf
EndIf
FreeMemory(*sourcebuffer)
If packed<>0
FreeMemory(*unpackbuffer)
EndIf
EndProcedure
Procedure IFF(file$,x=0,y=0) ; IFF ilbm
*sourcebuffer=AllocateMemory(FileSize(file$))
READ_BYTE=0
rd=OpenFile(#PB_Any,file$)
If rd
ReadData(rd,*sourcebuffer,FileSize(file$))
CloseFile(rd)
EndIf
chunk.s
Repeat
chunk=getchunkid(*sourcebuffer+READ_BYTE):read_byte+4
Select chunk
Case "FORM"
SIZE= BE_peekl(*sourcebuffer+READ_BYTE):read_byte+4
TYPE.s= getchunkid(*sourcebuffer+READ_BYTE):read_byte+4
Select type
Case "PBM " ; not implemented
Repeat
chunk=getchunkid(*sourcebuffer+READ_BYTE):read_byte+4
Select chunk
Case"CASE"
Default
SIZE= BE_peekl(*sourcebuffer+READ_BYTE):read_byte+4
read_byte+size
If size % 2 =1
read_byte +1
EndIf
EndSelect
Until read_byte=FileSize(file$)
Case "ILBM" ; standard images ok, HAM et HALFbright manque
Repeat
chunk=getchunkid(*sourcebuffer+READ_BYTE):read_byte+4
Select chunk
Case "BMHD"
SIZE= BE_peekl(*sourcebuffer+READ_BYTE):read_byte+4
W=BE_peekw(*sourcebuffer+READ_BYTE):read_byte+2
H=BE_peekw(*sourcebuffer+READ_BYTE):read_byte+2
Xs=BE_peekw(*sourcebuffer+READ_BYTE):read_byte+2
Ys=BE_peekw(*sourcebuffer+READ_BYTE):read_byte+2
BIT_PLANES=PeekB(*sourcebuffer+READ_BYTE):read_byte+1
masking=PeekB(*sourcebuffer+READ_BYTE):read_byte+1
packed=PeekB(*sourcebuffer+READ_BYTE):read_byte+1
pad1=PeekB(*sourcebuffer+READ_BYTE):read_byte+1
transp_col=BE_peekw(*sourcebuffer+READ_BYTE):read_byte+2
xaspect=PeekB(*sourcebuffer+READ_BYTE):read_byte+1
yaspect=PeekB(*sourcebuffer+READ_BYTE):read_byte+1
pagew=BE_peekw(*sourcebuffer+READ_BYTE):read_byte+2
pageh=BE_peekw(*sourcebuffer+READ_BYTE):read_byte+2
If read_byte % 2 =1
read_byte +1
EndIf
Case "CMAP"
SIZE= BE_peekl(*sourcebuffer+READ_BYTE):read_byte+4
Dim color(size/3)
For a=1 To size/3
r=PeekB(*sourcebuffer+READ_BYTE)&$ff:read_byte+1
g=PeekB(*sourcebuffer+READ_BYTE)&$ff:read_byte+1
b=PeekB(*sourcebuffer+READ_BYTE)&$ff:read_byte+1
color(a-1)=RGB(r,g,b)
Next
If read_byte % 2 =1
read_byte +1
EndIf
Case "BODY"
SIZE= BE_peekl(*sourcebuffer+READ_BYTE):read_byte+4
start=READ_BYTE
offset=(BIT_PLANES*2)-2
x_bound=w
y_bound=h
nbytes=(w/8)*BIT_PLANES
If hires=0 ; lowres
pix_siz=1
If laced=1 ; interlaced
pix_siz=2
EndIf
Else ; hires
pix_siz=0
If laced=1 ; interlaced
pix_siz=1
EndIf
EndIf
If packed=1
unpacksize=(w*h*BIT_PLANES)/8
*unpackbuffer=AllocateMemory(unpacksize)
unpack(*sourcebuffer,*unpackbuffer,READ_BYTE,BIT_PLANES,w,h)
draw(X,Y,*unpackbuffer,0,BIT_PLANES,w,h,pix_siz,color())
Else
draw(X,Y,*sourcebuffer,READ_BYTE,BIT_PLANES,w,h,pix_siz,color(),option)
EndIf
read_byte=start+size
If read_byte % 2 =1
read_byte +1
EndIf
Case"CAMG"
SIZE= BE_peekl(*sourcebuffer+READ_BYTE):read_byte+4
v=BE_peekL(*sourcebuffer+READ_BYTE)
hires=(v & $8000) >>15
ham=(v & $800) >> 11
hb=(v & $80) >> 7
laced=(v & $4) >>2
;
read_byte+size
If read_byte % 2 =1
read_byte +1
EndIf
If ham=1 And BIT_PLANES=6
option=1
EndIf
Default
SIZE= BE_peekl(*sourcebuffer+READ_BYTE):read_byte+4
read_byte+size
If size % 2 =1
read_byte +1
EndIf
EndSelect
Until read_byte>=FileSize(file$)
If *sourcebuffer<>0
If MemorySize(*sourcebuffer)
FreeMemory(*sourcebuffer)
*sourcebuffer=0
EndIf
EndIf
If *unpackbuffer<>0
If MemorySize(*unpackbuffer)
FreeMemory(*unpackbuffer)
*unpackbuffer=0
EndIf
EndIf
Break
EndSelect
Default
Break
EndSelect
ForEver
EndProcedure
Procedure pcx(file$,x=0,y=0) ; PCX (version 5)
*sourcebuffer=AllocateMemory(FileSize(file$))
rd=OpenFile(#PB_Any,file$) ; ouverture fichier
If rd ; Succes !!
ReadData(rd,*sourcebuffer,FileSize(file$))
CloseFile(rd)
EndIf
off=0
manufacturer =PeekB(*sourcebuffer+off):off+1
version_info =PeekB(*sourcebuffer+off):off+1
encode_sheme =PeekB(*sourcebuffer+off):off+1
bit_per_pixel =PeekB(*sourcebuffer+off):off+1
left_margin =PeekW(*sourcebuffer+off):off+2
upper_margin =PeekW(*sourcebuffer+off):off+2
right_margin =PeekW(*sourcebuffer+off):off+2
lower_margin =PeekW(*sourcebuffer+off):off+2
horizontal_dpi =PeekW(*sourcebuffer+off):off+2
vertical_dpi =PeekW(*sourcebuffer+off):off+2
; indexed palette ?
Dim color(256)
For a= 0 To 15
color(a)=RGB(PeekB(*sourcebuffer+off),PeekB(*sourcebuffer+off+1),PeekB(*sourcebuffer+off+2)):off+3
Next
off+1 ;reserved byte
planes =PeekB(*sourcebuffer+off):off+1
nbytes =PeekW(*sourcebuffer+off):off+2
palette_information =PeekW(*sourcebuffer+off):off+2
horizontal_screen_size =PeekW(*sourcebuffer+off):off+2
vertical_screen_size =PeekW(*sourcebuffer+off):off+2
off+54; reserved
Width=right_margin-left_margin+1
height=lower_margin-upper_margin+1
unpacksize=(Width*height)*bit_per_pixel*planes
*unpackbuffer=AllocateMemory(unpacksize)
off=unpack_pcx(*sourcebuffer,*unpackbuffer,Width,height,off,planes,nbytes)
LinePaddingSize = (nbytes * planes) * (8 / bit_per_pixel) - ((right_margin - left_margin) + 1)
off=MemorySize(*sourcebuffer)-769
vga_palette_id =PeekB(*sourcebuffer+off):off+1
If vga_palette_id=12
For a=0 To 255
color(a)=RGB(PeekB(*sourcebuffer+off)&$ff,PeekB(*sourcebuffer+off+1)&$ff,PeekB(*sourcebuffer+off+2)&$ff):off+3
Next
EndIf
draw(X,Y,*unpackbuffer,0,planes*bit_per_pixel,Width,height,1,color(),2,LinePaddingSize)
If *sourcebuffer<>0
If MemorySize(*sourcebuffer)<>0
FreeMemory(*sourcebuffer)
EndIf
EndIf
EndProcedure
;
;
;
;========================================================
; procedures utilitaires
; iff chunk ID
Procedure.S getchunkid(*adr)
For a=0 To 3
t$+Chr(PeekB(*adr+a))
Next
ProcedureReturn t$
EndProcedure
; PeekW en BIG ENDIAN
Procedure BE_peekw(*adr)
ret.w
PokeB(@ret+1,PeekB(*adr)&$ff)
PokeB(@ret,PeekB(*adr+1)&$ff)
ProcedureReturn ret
EndProcedure
; PeekL en BIG ENDIAN
Procedure BE_peekL(*adr)
ret.l
PokeB(@ret+3,PeekB(*adr)&$ff)
PokeB(@ret+2,PeekB(*adr+1)&$ff)
PokeB(@ret+1,PeekB(*adr+2)&$ff)
PokeB(@ret,PeekB(*adr+3)&$ff)
ProcedureReturn ret
EndProcedure
; RLE decompression
Procedure unpack(*source,*unpack,off,planes,w,h,noplane=0)
offset=(planes*2)-2
x_bound=w
y_bound=h
nbytes=(w/8)*planes
off2=0
ligne=0
Repeat
ZZ=0
Plane=0
Repeat
Repeat
X=PeekB(*source+off) & $ff
off +1
If off>MemorySize(*source)
Break 3
EndIf
If X<128
I=0
Repeat
PokeB(*unpack+off2+ZZ,PeekB(*source+off)&$ff)
off+1
ZZ +1
If off>MemorySize(*source)
Break 4
EndIf
If off2+zz>MemorySize(*unpack)
Break 4
EndIf
If ZZ % 2 = 0
ZZ + Offset
EndIf
I +1
Until I>X
Else
If X>128
X=256-X
S=PeekB(*source+off)&$ff
off +1
I=0
Repeat
PokeB(*unpack+off2+ZZ,s)
ZZ + 1
If ZZ % 2 = 0
ZZ + Offset
EndIf
I+1
Until I>X
EndIf
EndIf
Until ZZ>=Nbytes
ZZ=ZZ-Nbytes+2
Plane +1
Until Plane=planes
off2=off2+Nbytes
ligne+1
Until ligne=y_bound
ProcedureReturn(off)
EndProcedure
; affiche les images decompressees
Procedure draw(x,y,*buffer,off,BIT_PLANES,w,h,square,Array rvb(1),option=0,LinePaddingSize=0)
Dim plane(BIT_PLANES) ; stocker les bitplans
x_bound=w
y_bound=h
; +--------------------------+
; | lecture de l'image |
; +--------------------------+
; PCX
If option=2 ; pcx 8 bpp 1 bp
For dy = 0 To h-1
For dx=0 To w-1
If (off)<=MemorySize(*buffer)
If BIT_PLANES=24
If x+dx>=0 And x+dx<OutputWidth() And y+dy>=0 And y+dy<OutputHeight()
Plot(x+dx,y+dy,RGB(PeekB(*buffer+off) &$ff,PeekB(*buffer+off+(w)) &$ff,PeekB(*buffer+off+(w*2)) &$ff)):
EndIf
off+1
Else
If x+dx>=0 And x+dx<OutputWidth() And y+dy>=0 And y+dy<OutputHeight()
Plot(x+dx,y+dy,rvb(PeekB(*buffer+off) &$ff)):off+1
EndIf
EndIf
EndIf
Next
If BIT_PLANES=24
off+LinePaddingSize
EndIf
Next
Else
Repeat
For a=1 To BIT_PLANES ; on repete pour chaque bitplane
plane(a)=BE_peekw(*buffer+off):off+2
Next
For b=1 To 16 ;
rot=15-(b-1) ; nombre de bit de decalage le premier pixel est a gauche du mot,
mask=1 << rot ; on decale donc le masque de 15 pas pour le premier pixel puis 14 13 ---> 0 pour le dernier pixel
;
; la ligne suivante lis le bit correspondant de chaque bitplan a l'aide du masque
; et additione chaque bit en les decalant de facon a avoir un nombre sur 4 bit pour le registre de couleur
c=0
For planes=1 To BIT_PLANES
c + ((plane(planes) & mask) >> rot) << (planes-1)
Next
; palette
Select option
Case 0
If BIT_PLANES<>24
col=rvb(c)
Else
col=c
EndIf
Case 1 ;hamm je m'en sors pas ici :p
Select (c & %110000) >>4
Case %00
col=rvb(c)
;
red=Red(rvb(c & %1111))
green=Green(rvb(c & %1111))
blue=Blue(rvb(c & %1111))
Case %01
blue=((Blue <<4)>>4)+((c & %1111)<<4)
Case %10
red=((red <<4)>>4)+((c & %1111)<<4)
Case%11
green=((green <<4)>>4)+((c & %1111)<<4)
EndSelect
EndSelect
; aspet des pixels
Select square
Case 0 ; double vertical
XC1=x+nx*1
YC1=y+ny*2
;
XC2=x+nx*1
YC2=y+ny*2+1
Case 1 ; pixel carres
XC1=x+nx*1
YC1=y+ny*1
Case 2 ; double horizontal
XC1=x+nx*2
YC1=y+ny*1
;
XC2=x+nx*2+1
YC2=y+ny*1
EndSelect
If XC1<OutputWidth() And YC1<OutputHeight() And XC1>-1 And YC1>-1
Plot(xc1,yc1,col) ; affichage du point sur la surface utilisée pour le dessin aux coordonées choisies
EndIf
If square<>1
If XC2<OutputWidth() And YC2<OutputHeight() And XC2>-1 And YC2>-1
Plot(xc2,yc2,col) ; affichage du point sur la surface utilisée pour le dessin aux coordonées choisies
EndIf
EndIf
nx+1 ; point suivant
If nx=x_bound ; arrivée a 320 pixels
nx=0 ; retour en debut de ligne
ny+1 ; retour a la ligne
EndIf
Next ; fin du mot
Until ny=y_bound ; si la ligne de fin est atteinte on sort de la boucle
EndIf
EndProcedure
; PCX RLE decompression
Procedure unpack_pcx(*source,*unpack,w,h,off,planes,nbytes)
x_bound=w
y_bound=h
;
nbytes *planes
off2=0
ligne=0
Repeat
Repeat
X=PeekB(*source+off) & $ff
off +1
;
If off>MemorySize(*source)
Break 2
EndIf
;
If X & %11000000 = %11000000
R=(x & %00111111) &$ff
V=PeekB(*source+off) & $ff
off+1
Else
r=1
V=X &$ff
EndIf
I=0
Repeat
PokeB(*unpack+off2+ZZ,v &$ff)
ZZ +1
I +1
If off2+zz>MemorySize(*unpack)
Break 3
EndIf
Until I=r
Until ZZ=Nbytes
ZZ=0
ligne+1
off2=off2+Nbytes
Until ligne=y_bound
ProcedureReturn(off)
EndProcedure
;========================================================