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 <cybergraphx/cybergraphics.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>
34 #include <aros/symbolsets.h>
41 ADD2LIBS("datatypes/picture.datatype", 0, struct Library
*, PictureBase
);
43 /**************************************************************************************************/
45 #define FILEBUFSIZE 65536
50 struct IFFHandle
*iff
;
68 WORD bfType
; // 0 ASCII "BM"
69 ULONG bfSize
; // 2 Size in bytes of the file
70 WORD bfReserved1
; // 6 Zero
71 WORD bfReserved2
; // 8 Zero
72 ULONG bfOffBits
; // 10 Byte offset in files where image begins
73 } __attribute__((packed
)) FileBitMapHeader
; // 14
77 ULONG biSize
; // 0 Size of this header, 40 bytes
78 LONG biWidth
; // 4 Image width in pixels
79 LONG biHeight
; // 8 Image height in pixels
80 WORD biPlanes
; // 12 Number of image planes, must be 1
81 WORD biBitCount
; // 14 Bits per pixel, 1, 4, 8, 24, or 32
82 ULONG biCompression
; // 16 Compression type, below
83 ULONG biSizeImage
; // 20 Size in bytes of compressed image, or zero
84 LONG biXPelsPerMeter
; // 24 Horizontal resolution, in pixels/meter
85 LONG biYPelsPerMeter
; // 28 Vertical resolution, in pixels/meter
86 ULONG biClrUsed
; // 32 Number of colors used, below
87 ULONG biClrImportant
; // 36 Number of "important" colors
88 } __attribute__((packed
)) BitmapInfoHeader
; // 40
90 /* "BM" backwards, due to LE byte order */
91 #define BITMAP_ID "MB"
93 /**************************************************************************************************/
95 static void BMP_Exit(BmpHandleType
*bmphandle
, LONG errorcode
)
97 D(if (errorcode
) bug("bmp.datatype/BMP_Exit() --- IoErr %ld\n", errorcode
));
98 if (bmphandle
->filebuf
)
100 FreeMem(bmphandle
->filebuf
, bmphandle
->filebufsize
);
102 if (bmphandle
->linebuf
)
104 FreeMem(bmphandle
->linebuf
, bmphandle
->linebufsize
);
106 if (bmphandle
->codecvars
)
108 FreeVec(bmphandle
->codecvars
);
113 /**************************************************************************************************/
115 /* buffered file access, useful for RLE */
116 BOOL
SaveBMP_EmptyBuf(BmpHandleType
*bmphandle
, long minbytes
)
118 long bytes
, bytestowrite
;
120 bytestowrite
= bmphandle
->filebufsize
- (bmphandle
->filebufbytes
+ minbytes
);
121 D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- minimum %ld bytes, %ld bytes to write\n", (long)minbytes
, (long)bytestowrite
));
122 bytes
= Write(bmphandle
->filehandle
.bptr
, bmphandle
->filebuf
, bytestowrite
);
123 if ( bytes
< bytestowrite
)
125 D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- writing failed, wrote %ld bytes\n", (long)bytes
));
128 bmphandle
->filebufpos
= bmphandle
->filebuf
;
129 bmphandle
->filebufbytes
= bmphandle
->filebufsize
- minbytes
;
130 D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- wrote %ld bytes\n", (long)bytes
));
134 /* buffered file access, useful for RLE */
135 BOOL
LoadBMP_FillBuf(BmpHandleType
*bmphandle
, long minbytes
)
139 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
140 if ( bmphandle
->filebufbytes
>= 0 )
142 bytes
= bmphandle
->filebufbytes
+ minbytes
;
143 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- %ld bytes requested, %ld bytes left\n", (long)minbytes, (long)bytes));
146 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- existing %ld old bytes\n", (long)bytes));
147 for (i
=0; i
<bytes
; i
++) /* copy existing bytes to start of buffer */
148 bmphandle
->filebuf
[i
] = bmphandle
->filebufpos
[i
];
150 bmphandle
->filebufpos
= bmphandle
->filebuf
;
151 bytes
= Read(bmphandle
->filehandle
.bptr
, bmphandle
->filebuf
+ bytes
, bmphandle
->filebufsize
- bytes
);
152 if (bytes
< 0 ) bytes
= 0;
153 bmphandle
->filebufbytes
+= bytes
;
154 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- read %ld bytes, remaining new %ld bytes\n", (long)bytes, (long)bmphandle->filebufbytes));
155 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- >minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
156 if (bmphandle
->filebufbytes
>= 0)
161 static BOOL
LoadBMP_Colormap(BmpHandleType
*bmphandle
, int numcolors
,
162 struct ColorRegister
*colormap
, ULONG
*colregs
)
166 if (numcolors
&& numcolors
<= MAXCOLORS
)
169 for (i
= 0; i
< numcolors
; i
++)
171 if ( (bmphandle
->filebufbytes
-= 4) < 0 && !LoadBMP_FillBuf(bmphandle
, 4) )
173 D(bug("bmp.datatype/LoadBMP_Colormap() --- colormap loading failed\n"));
176 /* BGR0 format for MS Win files, BGR format for OS/2 files */
177 colormap
[i
].blue
= *(bmphandle
->filebufpos
)++;
178 colormap
[i
].green
= *(bmphandle
->filebufpos
)++;
179 colormap
[i
].red
= *(bmphandle
->filebufpos
)++;
180 bmphandle
->filebufpos
++;
181 colregs
[j
++] = ((ULONG
)colormap
[i
].red
)<<24;
182 colregs
[j
++] = ((ULONG
)colormap
[i
].green
)<<24;
183 colregs
[j
++] = ((ULONG
)colormap
[i
].blue
)<<24;
184 // D(if (i<5) bug("gif r %02lx g %02lx b %02lx\n", colormap[i].red, colormap[i].green, colormap[i].blue));
186 D(bug("bmp.datatype/LoadBMP_Colormap() --- %d colors loaded\n", numcolors
));
191 /**************************************************************************************************/
192 static BOOL
LoadBMP(struct IClass
*cl
, Object
*o
)
194 BmpHandleType
*bmphandle
;
197 ULONG
D(bfSize
,) bfOffBits
;
198 ULONG biSize
, biWidth
, biHeight
, biCompression
;
199 ULONG biClrUsed
D(, biClrImportant
);
200 UWORD biPlanes
, biBitCount
;
201 ULONG alignwidth
, alignbytes
, pixelfmt
;
204 struct BitMapHeader
*bmhd
;
205 struct ColorRegister
*colormap
;
209 D(bug("bmp.datatype/LoadBMP()\n"));
211 if( !(bmphandle
= AllocMem(sizeof(BmpHandleType
), MEMF_ANY
)) )
213 SetIoErr(ERROR_NO_FREE_STORE
);
216 bmphandle
->filebuf
= NULL
;
217 bmphandle
->linebuf
= NULL
;
218 bmphandle
->codecvars
= NULL
;
221 if( GetDTAttrs(o
, DTA_SourceType
, (IPTR
)&sourcetype
,
222 DTA_Handle
, (IPTR
)&(bmphandle
->filehandle
),
223 PDTA_BitMapHeader
, (IPTR
)&bmhd
,
226 BMP_Exit(bmphandle
, ERROR_OBJECT_NOT_FOUND
);
230 if ( sourcetype
== DTST_RAM
&& bmphandle
->filehandle
.iff
== NULL
&& bmhd
)
232 D(bug("bmp.datatype/LoadBMP() --- Creating an empty object\n"));
233 BMP_Exit(bmphandle
, 0);
236 if ( sourcetype
!= DTST_FILE
|| !bmphandle
->filehandle
.bptr
|| !bmhd
)
238 D(bug("bmp.datatype/LoadBMP() --- unsupported mode\n"));
239 BMP_Exit(bmphandle
, ERROR_NOT_IMPLEMENTED
);
243 /* initialize buffered file reads */
244 bmphandle
->filebufbytes
= 0;
245 bmphandle
->filebufsize
= FILEBUFSIZE
;
246 if( !(bmphandle
->filebuf
= bmphandle
->filebufpos
= AllocMem(bmphandle
->filebufsize
, MEMF_ANY
)) )
248 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
252 /* load FileBitmapHeader from file, make sure, there are at least 14 bytes in buffer */
253 if ( (bmphandle
->filebufbytes
-= 14) < 0 && !LoadBMP_FillBuf(bmphandle
, 14) )
255 D(bug("bmp.datatype/LoadBMP() --- filling buffer with header failed\n"));
256 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
259 filebuf
= bmphandle
->filebufpos
; /* this makes things easier */
260 bmphandle
->filebufpos
+= 14;
261 if( filebuf
[0] != 'B' && filebuf
[1] != 'M' )
263 D(bug("bmp.datatype/LoadBMP() --- header type mismatch\n"));
264 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
267 /* byte-wise access isn't elegant, but it is endianess-safe */
268 D(bfSize
= (filebuf
[5]<<24) | (filebuf
[4]<<16) | (filebuf
[3]<<8) | filebuf
[2]);
269 bfOffBits
= (filebuf
[13]<<24) | (filebuf
[12]<<16) | (filebuf
[11]<<8) | filebuf
[10];
270 D(bug("bmp.datatype/LoadBMP() --- bfSize %ld bfOffBits %ld\n", bfSize
, bfOffBits
));
272 /* load BitmapInfoHeader from file, make sure, there are at least 40 bytes in buffer */
273 if ( (bmphandle
->filebufbytes
-= 40) < 0 && !LoadBMP_FillBuf(bmphandle
, 40) )
275 D(bug("bmp.datatype/LoadBMP() --- filling buffer with header 2 failed\n"));
276 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
279 filebuf
= bmphandle
->filebufpos
; /* this makes things easier */
280 bmphandle
->filebufpos
+= 40;
282 /* get image size attributes */
283 biSize
= (filebuf
[3]<<24) | (filebuf
[2]<<16) | (filebuf
[1]<<8) | filebuf
[0];
284 biWidth
= (filebuf
[7]<<24) | (filebuf
[6]<<16) | (filebuf
[5]<<8) | filebuf
[4];
285 biHeight
= (filebuf
[11]<<24) | (filebuf
[10]<<16) | (filebuf
[9]<<8) | filebuf
[8];
286 biPlanes
= (filebuf
[13]<<8) | filebuf
[12];
287 biBitCount
= (filebuf
[15]<<8) | filebuf
[14];
288 biCompression
= (filebuf
[19]<<24) | (filebuf
[18]<<16) | (filebuf
[17]<<8) | filebuf
[16];
289 biClrUsed
= (filebuf
[35]<<24) | (filebuf
[34]<<16) | (filebuf
[33]<<8) | filebuf
[32];
290 D(biClrImportant
= (filebuf
[39]<<24) | (filebuf
[38]<<16) | (filebuf
[37]<<8) | filebuf
[36]);
291 D(bug("bmp.datatype/LoadBMP() --- BMP-Screen %ld x %ld x %ld, %ld (%ld) colors, compression %ld, type %ld\n",
292 biWidth
, biHeight
, (long)biBitCount
, biClrUsed
, biClrImportant
, biCompression
, biSize
));
293 if (biSize
!= 40 || biPlanes
!= 1 || biCompression
!= 0)
295 D(bug("bmp.datatype/LoadBMP() --- Image format not supported\n"));
296 BMP_Exit(bmphandle
, ERROR_NOT_IMPLEMENTED
);
300 /* check color mode */
301 pixelfmt
= PBPAFMT_LUT8
;
305 alignwidth
= (biWidth
+ 31) & ~31UL;
306 alignbytes
= alignwidth
/ 8;
309 alignwidth
= (biWidth
+ 7) & ~7UL;
310 alignbytes
= alignwidth
/ 2;
313 alignwidth
= (biWidth
+ 3) & ~3UL;
314 alignbytes
= alignwidth
;
317 alignbytes
= ((biBitCount
* biWidth
+ 31) / 32) * 4;
318 alignwidth
= alignbytes
/ 2;
319 pixelfmt
= PBPAFMT_RGB
;
322 alignbytes
= ((biBitCount
* biWidth
+ 31) / 32) * 4;
323 alignwidth
= alignbytes
/ 3;
324 pixelfmt
= PBPAFMT_RGB
;
327 D(bug("bmp.datatype/LoadBMP() --- unsupported color depth\n"));
328 BMP_Exit(bmphandle
, ERROR_NOT_IMPLEMENTED
);
331 D(bug("bmp.datatype/LoadBMP() --- align: pixels %ld bytes %ld\n", alignwidth
, alignbytes
));
333 /* set BitMapHeader with image size */
334 bmhd
->bmh_Width
= bmhd
->bmh_PageWidth
= biWidth
;
335 bmhd
->bmh_Height
= bmhd
->bmh_PageHeight
= biHeight
;
336 bmhd
->bmh_Depth
= biBitCount
;
338 /* get empty colormap, then fill in colormap to use*/
341 if( !(GetDTAttrs(o
, PDTA_ColorRegisters
, (IPTR
)&colormap
,
342 PDTA_CRegs
, (IPTR
)&colorregs
,
344 !(colormap
&& colorregs
) )
346 D(bug("bmp.datatype/LoadBMP() --- got no colormap\n"));
347 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
351 /* Zero in the color count field means calculate it based on bits */
353 biClrUsed
= 1 << biBitCount
;
355 if( !LoadBMP_Colormap(bmphandle
, biClrUsed
, colormap
, colorregs
) )
357 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
362 bfOffBits
= bfOffBits
- 14 - 40 - biClrUsed
*4;
363 D(bug("bmp.datatype/LoadBMP() --- remaining offset %ld\n", bfOffBits
));
364 if ( bfOffBits
< 0 ||
365 ( (bmphandle
->filebufbytes
-= bfOffBits
) < 0 && !LoadBMP_FillBuf(bmphandle
, bfOffBits
) ) )
367 D(bug("bmp.datatype/LoadBMP() --- cannot skip offset\n"));
368 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
371 bmphandle
->filebufpos
+= bfOffBits
;
373 /* Pass attributes to picture.datatype */
374 GetDTAttrs( o
, DTA_Name
, (IPTR
)&name
, TAG_DONE
);
375 SetDTAttrs(o
, NULL
, NULL
, PDTA_NumColors
, biClrUsed
,
376 DTA_NominalHoriz
, biWidth
,
377 DTA_NominalVert
, biHeight
,
378 DTA_ObjName
, (IPTR
)name
,
381 /* Now decode the picture data into a chunky buffer; and pass it to Bitmap line-by-line */
383 bmphandle
->linebufsize
= alignwidth
* 3;
385 bmphandle
->linebufsize
= alignwidth
;
386 if (! (bmphandle
->linebuf
= bmphandle
->linebufpos
= AllocMem(bmphandle
->linebufsize
, MEMF_ANY
)) )
388 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
392 //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
394 for (y
=biHeight
-1; y
>=0 && cont
; y
--)
400 bmphandle
->linebufpos
= bmphandle
->linebuf
;
401 if (biBitCount
== 24)
403 if ( (bmphandle
->filebufbytes
-= alignbytes
) < 0 && !LoadBMP_FillBuf(bmphandle
, alignbytes
) )
405 D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x
, y
));
406 //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
410 for (x
=0, p
= bmphandle
->filebufpos
; x
<alignwidth
; x
++)
415 *(bmphandle
->linebufpos
)++ = r
;
416 *(bmphandle
->linebufpos
)++ = g
;
417 *(bmphandle
->linebufpos
)++ = b
;
419 bmphandle
->filebufpos
+= alignbytes
;
421 else if (biBitCount
== 16)
423 if ( (bmphandle
->filebufbytes
-= alignbytes
) < 0 && !LoadBMP_FillBuf(bmphandle
, alignbytes
) )
425 D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x
, y
));
426 //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
430 for (x
=0, p
= bmphandle
->filebufpos
; x
<alignwidth
; x
++)
434 *(bmphandle
->linebufpos
)++ = (pixel
& 0x7c00) >> 7;
435 *(bmphandle
->linebufpos
)++ = (pixel
& 0x03e0) >> 2;
436 *(bmphandle
->linebufpos
)++ = (pixel
& 0x1f) << 3;
438 bmphandle
->filebufpos
+= alignbytes
;
442 for (x
=0; x
<alignbytes
; x
++)
444 if ( (bmphandle
->filebufbytes
-= 1) < 0 && !LoadBMP_FillBuf(bmphandle
, 1) )
446 D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x
, y
));
447 //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
452 byte
= *(bmphandle
->filebufpos
)++;
458 *(bmphandle
->linebufpos
)++ = (byte
& 0x80) ? 1 : 0;
463 *(bmphandle
->linebufpos
)++ = (byte
& 0xf0) >> 4;
464 *(bmphandle
->linebufpos
)++ = (byte
& 0x0f);
467 *(bmphandle
->linebufpos
)++ = byte
;
470 *(bmphandle
->linebufpos
)++ = byte
;
477 !DoSuperMethod(cl
, o
,
478 PDTM_WRITEPIXELARRAY
, /* Method_ID */
479 (IPTR
)bmphandle
->linebuf
, /* PixelData */
480 pixelfmt
, /* PixelFormat */
481 alignbytes
, /* PixelArrayMod (number of bytes per row) */
485 1 /* Height (here: one line) */
489 D(bug("bmp.datatype/LoadBMP() --- WRITEPIXELARRAY failed !\n"));
490 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
494 //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
496 D(bug("bmp.datatype/LoadBMP() --- Normal Exit\n"));
497 BMP_Exit(bmphandle
, 0);
501 /**************************************************************************************************/
503 static BOOL
SaveBMP(struct IClass
*cl
, Object
*o
, struct dtWrite
*dtw
)
505 BmpHandleType
*bmphandle
;
507 unsigned int width
, height
, widthxheight
, numplanes
, numcolors
;
508 struct BitMapHeader
*bmhd
;
514 D(bug("bmp.datatype/SaveBMP()\n"));
516 if( !(bmphandle
= AllocMem(sizeof(BmpHandleType
), MEMF_ANY
)) )
518 SetIoErr(ERROR_NO_FREE_STORE
);
521 bmphandle
->filebuf
= NULL
;
522 bmphandle
->linebuf
= NULL
;
523 bmphandle
->codecvars
= NULL
;
525 /* A NULL file handle is a NOP */
526 if( !dtw
->dtw_FileHandle
)
528 D(bug("bmp.datatype/SaveBMP() --- empty Filehandle - just testing\n"));
529 BMP_Exit(bmphandle
, 0);
532 bmphandle
->filehandle
.bptr
= dtw
->dtw_FileHandle
;
534 /* Get BitMap and color palette */
535 if( GetDTAttrs( o
, PDTA_BitMapHeader
, (IPTR
)&bmhd
,
536 PDTA_BitMap
, (IPTR
)&bm
,
537 PDTA_CRegs
, (IPTR
)&colorregs
,
538 PDTA_NumColors
, (IPTR
)&numcolors
,
540 !bmhd
|| !bm
|| !colorregs
|| !numcolors
)
542 D(bug("bmp.datatype/SaveBMP() --- missing attributes\n"));
543 BMP_Exit(bmphandle
, ERROR_OBJECT_NOT_FOUND
);
547 /* Check if this is a standard BitMap */
548 if( !( GetBitMapAttr(bm
, BMA_FLAGS
) & BMF_STANDARD
) )
550 D(bug("bmp.datatype/SaveBMP() --- wrong BitMap type\n"));
551 BMP_Exit(bmphandle
, ERROR_OBJECT_WRONG_TYPE
);
555 /* initialize buffered file reads */
556 bmphandle
->filebufsize
= FILEBUFSIZE
;
557 bmphandle
->filebufbytes
= bmphandle
->filebufsize
;
558 if( !(bmphandle
->filebuf
= bmphandle
->filebufpos
= AllocMem(bmphandle
->filebufsize
, MEMF_ANY
)) )
560 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
564 /* write BMP 87a header to file, make sure, there are at least 13 bytes in buffer */
565 if ( (bmphandle
->filebufbytes
-= 13) < 0 && !SaveBMP_EmptyBuf(bmphandle
, 13) )
567 D(bug("bmp.datatype/SaveBMP() --- filling buffer with header failed\n"));
568 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
571 filebuf
= bmphandle
->filebufpos
; /* this makes things easier */
572 bmphandle
->filebufpos
+= 13;
574 /* set screen descriptor attributes (from BitMapHeader) */
575 width
= bmhd
->bmh_PageWidth
;
576 height
= bmhd
->bmh_PageHeight
;
577 numplanes
= bmhd
->bmh_Depth
- 1;
578 numcolors
= 1 << (numplanes
+ 1);
579 D(bug("bmp.datatype/SaveBMP() --- BMP-Image %d x %d x %d, cols %d\n", width
, height
, numplanes
+1, numcolors
));
580 filebuf
[6] = width
& 0xff;
581 filebuf
[7] = width
>> 8;
582 filebuf
[8] = height
& 0xff;
583 filebuf
[9] = height
>> 8;
584 filebuf
[10] = 0x80 | ((numplanes
& 0x07) << 4) | (numplanes
& 0x07) ; /* set numplanes, havecolmap=1 */
585 filebuf
[11] = 0; /* this is fillcolor */
586 filebuf
[12] = 0; /* this is pixel aspect ratio, 0 means unused */
588 /* write screen colormap, we don't use an image colormap */
589 for (i
= 0; i
< numcolors
*3; i
+= 3)
591 if ( (bmphandle
->filebufbytes
-= 3) < 0 && !SaveBMP_EmptyBuf(bmphandle
, 3) )
593 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
596 *(bmphandle
->filebufpos
)++ = colorregs
[i
] >> 24;
597 *(bmphandle
->filebufpos
)++ = colorregs
[i
+1] >> 24;
598 *(bmphandle
->filebufpos
)++ = colorregs
[i
+2] >> 24;
601 /* write image header, image has same size as screen */
602 if ( (bmphandle
->filebufbytes
-= 10) < 0 && !SaveBMP_EmptyBuf(bmphandle
, 10) )
604 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
607 filebuf
= bmphandle
->filebufpos
; /* this makes things easier */
608 bmphandle
->filebufpos
+= 10;
609 filebuf
[0] = ','; /* header ID */
610 filebuf
[1] = filebuf
[2] = 0; /* no left edge */
611 filebuf
[3] = filebuf
[4] = 0; /* no top edge */
612 filebuf
[5] = width
& 0xff;
613 filebuf
[6] = width
>> 8;
614 filebuf
[7] = height
& 0xff;
615 filebuf
[8] = height
>> 8;
616 filebuf
[9] = numplanes
& 0x07; /* set numplanes, havecolmap=0, interlaced=0 */
618 /* Now read the picture data from the bitplanes and write it to a chunky buffer */
619 /* For now, we use a full picture pixel buffer, not a single line */
620 widthxheight
= width
*height
;
621 bmphandle
->linebufsize
= widthxheight
;
622 if (! (bmphandle
->linebuf
= bmphandle
->linebufpos
= AllocMem(bmphandle
->linebufsize
, MEMF_ANY
)) )
624 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
629 for (j
=0; j
<height
; j
++)
631 for (i
=0; i
<width
; i
++)
633 ret
= (UBYTE
)ReadPixel(&rp
, i
, j
); /* very slow, to be changed */
634 *(bmphandle
->linebufpos
)++ = ret
;
637 bmphandle
->linebufpos
= bmphandle
->linebuf
;
639 /* write the chunky buffer to file, after encoding */
641 /* write end-of-BMP marker */
642 if ( !bmphandle
->filebufbytes
-- && !SaveBMP_EmptyBuf(bmphandle
, 1) )
644 BMP_Exit(bmphandle
, ERROR_NO_FREE_STORE
);
647 *(bmphandle
->filebufpos
)++ = ';';
649 /* flush write buffer to file and exit */
650 SaveBMP_EmptyBuf(bmphandle
, 0);
651 D(bug("bmp.datatype/SaveBMP() --- Normal Exit\n"));
652 BMP_Exit(bmphandle
, 0);
658 /**************************************************************************************************/
660 IPTR
BMP__OM_NEW(Class
*cl
, Object
*o
, Msg msg
)
664 D(bug("bmp.datatype/DT_Dispatcher: Method OM_NEW\n"));
666 newobj
= (Object
*)DoSuperMethodA(cl
, o
, msg
);
669 if (!LoadBMP(cl
, newobj
))
671 CoerceMethod(cl
, newobj
, OM_DISPOSE
);
679 /**************************************************************************************************/
681 IPTR
BMP__DTM_WRITE(Class
*cl
, Object
*o
, struct dtWrite
*dtw
)
683 D(bug("bmp.datatype/DT_Dispatcher: Method DTM_WRITE\n"));
684 if( (dtw
-> dtw_Mode
) == DTWM_RAW
)
686 /* Local data format requested */
687 return SaveBMP(cl
, o
, dtw
);
691 /* Pass msg to superclass (which writes an IFF ILBM picture)... */
692 return DoSuperMethodA( cl
, o
, (Msg
)dtw
);