2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
6 /**********************************************************************/
12 #include <exec/types.h>
13 #include <exec/memory.h>
14 #include <dos/dostags.h>
15 #include <graphics/gfxbase.h>
16 #include <graphics/rpattr.h>
17 #include <graphics/modeid.h>
18 #include <intuition/imageclass.h>
19 #include <intuition/icclass.h>
20 #include <intuition/gadgetclass.h>
21 #include <intuition/cghooks.h>
22 #include <datatypes/datatypesclass.h>
23 #include <datatypes/pictureclass.h>
25 #include <clib/alib_protos.h>
26 #include <proto/exec.h>
27 #include <proto/dos.h>
28 #include <proto/intuition.h>
29 #include <proto/graphics.h>
30 #include <proto/utility.h>
31 #include <proto/iffparse.h>
32 #include <proto/datatypes.h>
35 #include <aros/symbolsets.h>
36 ADD2LIBS("datatypes/picture.datatype", 0, struct Library
*, PictureBase
);
38 #include "compilerspecific.h"
46 /**************************************************************************************************/
48 struct FileBitMapHeader
56 UBYTE bmh_Compression
;
58 UBYTE bmh_Transparent
[2];
61 UBYTE bmh_PageWidth
[2];
62 UBYTE bmh_PageHeight
[2];
65 /**************************************************************************************************/
67 static LONG propchunks
[] =
74 /**************************************************************************************************/
76 static UBYTE
*UnpackByteRun1(UBYTE
*source
, UBYTE
*dest
, LONG unpackedsize
)
83 c
= (BYTE
)(*source
++);
89 if (--unpackedsize
<= 0) return source
;
100 if (--unpackedsize
<= 0) return source
;
106 /**************************************************************************************************/
108 static BOOL
ReadBitMapPic(Class
*cl
, Object
*o
, struct IFFHandle
*handle
, struct BitMapHeader
*bmhd
,
109 struct FileBitMapHeader
*file_bmhd
, struct ContextNode
*body_cn
)
112 UBYTE
*src
, *body
, *uncompress_buf
;
113 LONG y
, p
, w16
, bm_bpr
, body_bpr
, copy_bpr
, totdepth
;
115 totdepth
= bmhd
->bmh_Depth
;
116 if (file_bmhd
->bmh_Masking
== mskHasMask
) totdepth
++;
118 w16
= (bmhd
->bmh_Width
+ 15) & ~15;
121 p
= body_cn
->cn_Size
;
122 if ((file_bmhd
->bmh_Compression
== cmpByteRun1
))
124 p
+= body_bpr
* totdepth
;
127 body
= AllocVec(p
, MEMF_ANY
);
130 SetIoErr(ERROR_NO_FREE_STORE
);
134 if (ReadChunkBytes(handle
, body
, body_cn
->cn_Size
) != body_cn
->cn_Size
)
137 SetIoErr(ERROR_UNKNOWN
);
141 bm
= AllocBitMap(bmhd
->bmh_Width
, bmhd
->bmh_Height
, bmhd
->bmh_Depth
, BMF_CLEAR
, NULL
);
145 SetIoErr(ERROR_NO_FREE_STORE
);
149 bm_bpr
= bm
->BytesPerRow
;
150 copy_bpr
= (body_bpr
< bm_bpr
) ? body_bpr
: bm_bpr
;
152 switch(file_bmhd
->bmh_Compression
)
156 for(y
= 0; y
< bmhd
->bmh_Height
; y
++)
158 for(p
= 0; p
< bmhd
->bmh_Depth
; p
++)
162 dest
= bm
->Planes
[p
] + y
* bm_bpr
;
164 CopyMem(src
, dest
, copy_bpr
);
168 if (file_bmhd
->bmh_Masking
== mskHasMask
) src
+= body_bpr
;
173 uncompress_buf
= body
+ body_cn
->cn_Size
;
176 for(y
= 0; y
< bmhd
->bmh_Height
; y
++)
178 UBYTE
*copysrc
= uncompress_buf
;
180 src
= UnpackByteRun1(src
, uncompress_buf
, body_bpr
* totdepth
);
182 for(p
= 0; p
< bmhd
->bmh_Depth
; p
++)
186 dest
= bm
->Planes
[p
] + y
* bm_bpr
;
188 CopyMem(copysrc
, dest
, copy_bpr
);
195 } /* switch(file_bmhd->bmh_Compression) */
197 SetDTAttrs(o
, NULL
, NULL
, PDTA_BitMap
, (IPTR
)bm
, TAG_DONE
);
205 /**************************************************************************************************/
207 const UBYTE bitmask
[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0 };
209 static BOOL
ReadRGBPic(Class
*cl
, Object
*o
, struct IFFHandle
*handle
, struct BitMapHeader
*bmhd
,
210 struct FileBitMapHeader
*file_bmhd
, struct ContextNode
*body_cn
, UBYTE
*coltab
)
212 UBYTE
*src
, *srcline
, *srclinestart
, *chunkystart
, *chunky
, *body
, *compressed
=0, *uncompressed
=0, *maskptr
;
213 int width
, height
, numplanes
, mask
, hamrot1
, hamrot2
;
214 LONG x
, y
, p
, w16
, body_bpr
, bodysize
;
216 UBYTE r
, g
, b
, hmask
, mmask
;
219 width
= bmhd
->bmh_Width
;
220 height
= bmhd
->bmh_Height
;
221 numplanes
= bmhd
->bmh_Depth
;
222 w16
= (width
+ 15) & ~15;
224 bodysize
= body_cn
->cn_Size
;
226 p
= bodysize
+ width
* 3;
227 if ((file_bmhd
->bmh_Compression
== cmpByteRun1
))
229 p
+= body_bpr
* numplanes
;
232 body
= AllocVec(p
, MEMF_ANY
);
235 SetIoErr(ERROR_NO_FREE_STORE
);
239 // D(bug("ilbm.datatype/ReadRGB: Width %d Height %d Depth %d body_bpr %ld bodysize %ld p %ld body %lx\n", width, height, numplanes, body_bpr, bodysize, p, body));
241 if (ReadChunkBytes(handle
, body
, bodysize
) != bodysize
)
244 SetIoErr(ERROR_UNKNOWN
);
248 hamrot1
= 10 - numplanes
;
249 hamrot2
= numplanes
- 2;
250 mmask
= 0xff << (numplanes
- 6);
253 switch( file_bmhd
->bmh_Compression
)
257 uncompressed
= body
+ bodysize
+ width
* 3;
261 chunkystart
= body
+ bodysize
;
262 for(y
= 0; y
< height
; y
++)
264 chunky
= chunkystart
;
268 compressed
= UnpackByteRun1(compressed
, uncompressed
, body_bpr
* numplanes
);
269 srclinestart
= uncompressed
;
272 maskptr
= (UBYTE
*) bitmask
;
273 for(x
= 0; x
< width
; x
++)
278 maskptr
= (UBYTE
*) bitmask
;
282 srcline
= srclinestart
;
284 for(p
= 0; p
< numplanes
; p
++)
286 rgb
= (rgb
>> 1) | (*srcline
& mask
? 0x800000 : 0);
289 // D(bug("ilbm.datatype/ReadRGB: RGB %06lx mask %02x srcline %lx chunky %lx\n", rgb, mask, srcline, chunky));
291 /* Process HAM or RGB data (a color table implies HAM) */
295 rgb
|= (rgb
& 0xff) >> hamrot2
;
296 switch( rgb
& 0x300 )
301 *chunky
++ = r
= coltab
[rgb
++];
302 *chunky
++ = g
= coltab
[rgb
++];
303 *chunky
++ = b
= coltab
[rgb
];
308 *chunky
++ = b
= rgb
& mmask
| b
& hmask
;
311 *chunky
++ = r
= rgb
& mmask
| r
& hmask
;
317 *chunky
++ = g
= rgb
& mmask
| g
& hmask
;
324 *chunky
++ = rgb
& 0xff;
325 *chunky
++ = (rgb
>> 8) & 0xff;
326 *chunky
++ = (rgb
>> 16) & 0xff;
330 if( !DoSuperMethod(cl
, o
,
331 PDTM_WRITEPIXELARRAY
, /* Method_ID */
332 (IPTR
) chunkystart
, /* PixelData */
333 PBPAFMT_RGB
, /* PixelFormat */
334 width
*3, /* PixelArrayMod (number of bytes per row) */
338 1)) /* Height (here: one line) */
340 D(bug("ilbm.datatype/ReadRGB: WRITEPIXELARRAY failed\n"));
342 SetIoErr(ERROR_UNKNOWN
);
346 src
+= body_bpr
* numplanes
;
349 } /* switch(file_bmhd->bmh_Compression) */
357 /**************************************************************************************************/
359 static void FixColRegs(ULONG numcolors
, UBYTE
*srcstart
)
364 /* Check if all color elements have an empty lower nibble */
366 for (i
= 0; i
< numcolors
* 3; i
++)
370 /* If so, scale all color elements */
373 for (i
= 0; i
< numcolors
* 3; i
++)
382 /**************************************************************************************************/
384 static void CopyColRegs(Object
*o
, ULONG numcolors
, UBYTE
*srcstart
, BOOL ehb
)
386 struct ColorRegister
*colorregs
;
389 SetDTAttrs(o
, NULL
, NULL
, PDTA_NumColors
, numcolors
, TAG_DONE
);
391 if (GetDTAttrs(o
, PDTA_ColorRegisters
, (IPTR
)&colorregs
,
392 PDTA_CRegs
, (IPTR
)&cregs
,
395 if (colorregs
&& cregs
)
406 for(j
= 0; j
<= cnt
; j
++)
409 for(i
= 0; i
< numcolors
; i
++)
415 /* Halve the brightness on the second (EHB) round */
424 colorregs
->green
= g
;
428 *cregs
++ = (ULONG
)r
* 0x01010101;
429 *cregs
++ = (ULONG
)g
* 0x01010101;
430 *cregs
++ = (ULONG
)b
* 0x01010101;
437 /**************************************************************************************************/
438 /**************************************************************************************************/
440 static BOOL
ReadILBM(Class
*cl
, Object
*o
)
442 struct FileBitMapHeader
*file_bmhd
;
443 struct BitMapHeader
*bmhd
;
444 struct IFFHandle
*handle
;
445 struct StoredProperty
*bmhd_prop
, *cmap_prop
, *camg_prop
;
446 struct ContextNode
*cn
;
451 D(bug("ilbm.datatype/ReadILBM()\n"));
453 if (GetDTAttrs(o
, DTA_SourceType
, (IPTR
)&sourcetype
,
454 DTA_Handle
, (IPTR
)&handle
,
455 PDTA_BitMapHeader
, (IPTR
)&bmhd
,
458 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
462 if ((sourcetype
!= DTST_FILE
) && (sourcetype
!= DTST_CLIPBOARD
))
464 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
468 if (!handle
|| !bmhd
)
470 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
474 if (PropChunks(handle
, propchunks
, 3) != 0)
476 SetIoErr(ERROR_NO_FREE_STORE
);
477 D(bug("ilbm.datatype error propchunks\n"));
481 if (StopChunk(handle
, ID_ILBM
, ID_BODY
) != 0)
483 SetIoErr(ERROR_NO_FREE_STORE
);
484 D(bug("ilbm.datatype error stopchunks\n"));
488 error
= ParseIFF(handle
, IFFPARSE_SCAN
);
491 SetIoErr(ERROR_OBJECT_WRONG_TYPE
);
492 D(bug("ilbm.datatype error parseiff\n"));
496 bmhd_prop
= FindProp(handle
, ID_ILBM
, ID_BMHD
);
497 cmap_prop
= FindProp(handle
, ID_ILBM
, ID_CMAP
);
498 camg_prop
= FindProp(handle
, ID_ILBM
, ID_CAMG
);
500 cn
= CurrentChunk(handle
);
501 if ((cn
->cn_Type
!= ID_ILBM
) ||
502 (cn
->cn_ID
!= ID_BODY
) ||
505 SetIoErr(ERROR_REQUIRED_ARG_MISSING
);
506 D(bug("ilbm.datatype error currentchunk\n"));
510 file_bmhd
= (struct FileBitMapHeader
*)bmhd_prop
->sp_Data
;
511 bmhd
->bmh_Width
= bmhd
->bmh_PageWidth
= file_bmhd
->bmh_Width
[0] * 256 + file_bmhd
->bmh_Width
[1];
512 bmhd
->bmh_Height
= bmhd
->bmh_PageHeight
= file_bmhd
->bmh_Height
[0] * 256 + file_bmhd
->bmh_Height
[1];
513 bmhd
->bmh_Depth
= file_bmhd
->bmh_Depth
;
514 bmhd
->bmh_Masking
= file_bmhd
->bmh_Masking
;
515 bmhd
->bmh_Transparent
= file_bmhd
->bmh_Transparent
[0] * 256 + file_bmhd
->bmh_Transparent
[1];
518 IPTR name
= (IPTR
) NULL
;
520 GetDTAttrs(o
, DTA_Name
, (IPTR
)&name
, TAG_DONE
);
522 SetDTAttrs(o
, NULL
, NULL
, DTA_ObjName
, name
,
523 DTA_NominalHoriz
, bmhd
->bmh_Width
,
524 DTA_NominalVert
, bmhd
->bmh_Height
,
528 if ((file_bmhd
->bmh_Depth
== 24) && (file_bmhd
->bmh_Compression
<= 1))
530 D(bug("ilbm.datatype/ReadILBM: 24 bit\n"));
531 if( !ReadRGBPic(cl
, o
, handle
, bmhd
, file_bmhd
, cn
, NULL
) )
533 D(bug("ilbm.datatype error readrgbpic\n"));
537 else if ( (file_bmhd
->bmh_Depth
<= 8) && (file_bmhd
->bmh_Compression
<= 1) && cmap_prop
)
543 if ( camg_prop
&& (camg_prop
->sp_Size
== 4) )
547 data
= (UBYTE
*)camg_prop
->sp_Data
;
548 mode
= (data
[0]<<24) | (data
[1]<<16) | (data
[2]<<8) | data
[3];
553 if (mode
& EXTRAHALFBRITE_KEY
)
557 D(bug("ilbm.datatype/ReadILBM: modeid %08lx%s%s\n", mode
, ham
? " HAM" : "", ehb
? " EHB" : ""));
560 numcolors
= cmap_prop
->sp_Size
/ 3;
561 D(bug("ilbm.datatype/ReadILBM: %d bit %d colors\n", (int)file_bmhd
->bmh_Depth
, numcolors
));
562 data
= (UBYTE
*)cmap_prop
->sp_Data
;
563 FixColRegs(numcolors
, data
);
564 CopyColRegs(o
, numcolors
, data
, ehb
);
568 /* picture.datatype can't cope with a transparent colour when we
569 * convert a HAM image to an RGB image */
570 if (bmhd
->bmh_Masking
== mskHasTransparentColor
)
571 bmhd
->bmh_Masking
= mskNone
;
573 if( !ReadRGBPic(cl
, o
, handle
, bmhd
, file_bmhd
, cn
, (UBYTE
*)cmap_prop
->sp_Data
) )
575 D(bug("ilbm.datatype error readrgbpic\n"));
578 bmhd
->bmh_Depth
= 24;
582 if( !ReadBitMapPic(cl
, o
, handle
, bmhd
, file_bmhd
, cn
) )
584 D(bug("ilbm.datatype error readbitmappic\n"));
591 D(bug("ilbm.datatype unknown\n"));
592 SetIoErr(ERROR_NOT_IMPLEMENTED
);
599 /**************************************************************************************************/
601 IPTR
ILBM__OM_NEW(Class
*cl
, Object
*o
, struct opSet
*msg
)
605 retval
= DoSuperMethodA(cl
, o
, (Msg
)msg
);
608 if (!ReadILBM(cl
, (Object
*)retval
))
610 CoerceMethod(cl
, (Object
*)retval
, OM_DISPOSE
);
618 /**************************************************************************************************/