Some compiler warnings removed.
[cake.git] / workbench / classes / datatypes / bmp / bmpclass.c
blobda80bb8aaee6a782d5a1563bc628a1acf92053cc
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /**********************************************************************/
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
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>
36 #include "debug.h"
38 #include "methods.h"
40 /* Open superclass */
41 ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);
43 /**************************************************************************************************/
45 #define FILEBUFSIZE 65536
46 #define MAXCOLORS 256
48 typedef struct {
49 struct IFFHandle *filehandle;
51 UBYTE *filebuf;
52 UBYTE *filebufpos;
53 long filebufbytes;
54 long filebufsize;
55 UBYTE *linebuf;
56 UBYTE *linebufpos;
57 long linebufbytes;
58 long linebufsize;
60 APTR codecvars;
61 } BmpHandleType;
64 typedef struct
66 WORD bfType; // 0 ASCII "BM"
67 ULONG bfSize; // 2 Size in bytes of the file
68 WORD bfReserved1; // 6 Zero
69 WORD bfReserved2; // 8 Zero
70 ULONG bfOffBits; // 10 Byte offset in files where image begins
71 } FileBitMapHeader __attribute__((packed)); // 14
73 typedef struct
75 ULONG biSize; // 0 Size of this header, 40 bytes
76 LONG biWidth; // 4 Image width in pixels
77 LONG biHeight; // 8 Image height in pixels
78 WORD biPlanes; // 12 Number of image planes, must be 1
79 WORD biBitCount; // 14 Bits per pixel, 1, 4, 8, 24, or 32
80 ULONG biCompression; // 16 Compression type, below
81 ULONG biSizeImage; // 20 Size in bytes of compressed image, or zero
82 LONG biXPelsPerMeter; // 24 Horizontal resolution, in pixels/meter
83 LONG biYPelsPerMeter; // 28 Vertical resolution, in pixels/meter
84 ULONG biClrUsed; // 32 Number of colors used, below
85 ULONG biClrImportant; // 36 Number of "important" colors
86 } BitmapInfoHeader __attribute__((packed)); // 40
88 /* "BM" backwards, due to LE byte order */
89 #define BITMAP_ID "MB"
91 /**************************************************************************************************/
93 static void BMP_Exit(BmpHandleType *bmphandle, LONG errorcode)
95 D(if (errorcode) bug("bmp.datatype/BMP_Exit() --- IoErr %ld\n", errorcode));
96 if (bmphandle->filebuf)
98 FreeMem(bmphandle->filebuf, bmphandle->filebufsize);
100 if (bmphandle->linebuf)
102 FreeMem(bmphandle->linebuf, bmphandle->linebufsize);
104 if (bmphandle->codecvars)
106 FreeVec(bmphandle->codecvars);
108 SetIoErr(errorcode);
111 /**************************************************************************************************/
113 /* buffered file access, useful for RLE */
114 BOOL SaveBMP_EmptyBuf(BmpHandleType *bmphandle, long minbytes)
116 long bytes, bytestowrite;
118 bytestowrite = bmphandle->filebufsize - (bmphandle->filebufbytes + minbytes);
119 D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- minimum %ld bytes, %ld bytes to write\n", (long)minbytes, (long)bytestowrite));
120 bytes = Write(bmphandle->filehandle, bmphandle->filebuf, bytestowrite);
121 if ( bytes < bytestowrite )
123 D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- writing failed, wrote %ld bytes\n", (long)bytes));
124 return FALSE;
126 bmphandle->filebufpos = bmphandle->filebuf;
127 bmphandle->filebufbytes = bmphandle->filebufsize - minbytes;
128 D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- wrote %ld bytes\n", (long)bytes));
129 return TRUE;
132 /* buffered file access, useful for RLE */
133 BOOL LoadBMP_FillBuf(BmpHandleType *bmphandle, long minbytes)
135 long i, bytes;
137 //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)) ));
138 if ( bmphandle->filebufbytes >= 0 )
139 return TRUE;
140 bytes = bmphandle->filebufbytes + minbytes;
141 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- %ld bytes requested, %ld bytes left\n", (long)minbytes, (long)bytes));
142 if (bytes > 0)
144 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- existing %ld old bytes\n", (long)bytes));
145 for (i=0; i<bytes; i++) /* copy existing bytes to start of buffer */
146 bmphandle->filebuf[i] = bmphandle->filebufpos[i];
148 bmphandle->filebufpos = bmphandle->filebuf;
149 bytes = Read(bmphandle->filehandle, bmphandle->filebuf + bytes, bmphandle->filebufsize - bytes);
150 if (bytes < 0 ) bytes = 0;
151 bmphandle->filebufbytes += bytes;
152 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- read %ld bytes, remaining new %ld bytes\n", (long)bytes, (long)bmphandle->filebufbytes));
153 //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)) ));
154 if (bmphandle->filebufbytes >= 0)
155 return TRUE;
156 return FALSE;
159 static BOOL LoadBMP_Colormap(BmpHandleType *bmphandle, int numcolors,
160 struct ColorRegister *colormap, ULONG *colregs)
162 unsigned int i, j;
164 if (numcolors && numcolors <= MAXCOLORS)
166 j = 0;
167 for (i = 0; i < numcolors; i++)
169 if ( (bmphandle->filebufbytes -= 4) < 0 && !LoadBMP_FillBuf(bmphandle, 4) )
171 D(bug("bmp.datatype/LoadBMP_Colormap() --- colormap loading failed\n"));
172 return FALSE;
174 /* BGR0 format for MS Win files, BGR format for OS/2 files */
175 colormap[i].blue = *(bmphandle->filebufpos)++;
176 colormap[i].green = *(bmphandle->filebufpos)++;
177 colormap[i].red = *(bmphandle->filebufpos)++;
178 bmphandle->filebufpos++;
179 colregs[j++] = ((ULONG)colormap[i].red)<<24;
180 colregs[j++] = ((ULONG)colormap[i].green)<<24;
181 colregs[j++] = ((ULONG)colormap[i].blue)<<24;
182 // D(if (i<5) bug("gif r %02lx g %02lx b %02lx\n", colormap[i].red, colormap[i].green, colormap[i].blue));
184 D(bug("bmp.datatype/LoadBMP_Colormap() --- %d colors loaded\n", numcolors));
186 return TRUE;
189 /**************************************************************************************************/
190 static BOOL LoadBMP(struct IClass *cl, Object *o)
192 BmpHandleType *bmphandle;
193 UBYTE *filebuf;
194 IPTR sourcetype;
195 ULONG bfSize, bfOffBits;
196 ULONG biSize, biWidth, biHeight, biCompression;
197 ULONG biClrUsed, biClrImportant;
198 UWORD biPlanes, biBitCount;
199 ULONG alignwidth, alignbytes, pixelfmt;
200 long x, y;
201 int cont, byte;
202 struct BitMapHeader *bmhd;
203 struct ColorRegister *colormap;
204 ULONG *colorregs;
205 STRPTR name;
207 D(bug("bmp.datatype/LoadBMP()\n"));
209 if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
211 SetIoErr(ERROR_NO_FREE_STORE);
212 return FALSE;
214 bmphandle->filebuf = NULL;
215 bmphandle->linebuf = NULL;
216 bmphandle->codecvars = NULL;
219 if( GetDTAttrs(o, DTA_SourceType , (IPTR)&sourcetype ,
220 DTA_Handle , (IPTR)&(bmphandle->filehandle),
221 PDTA_BitMapHeader , (IPTR)&bmhd,
222 TAG_DONE) != 3 )
224 BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
225 return FALSE;
228 if ( sourcetype == DTST_RAM && bmphandle->filehandle == NULL && bmhd )
230 D(bug("bmp.datatype/LoadBMP() --- Creating an empty object\n"));
231 BMP_Exit(bmphandle, 0);
232 return TRUE;
234 if ( sourcetype != DTST_FILE || !bmphandle->filehandle || !bmhd )
236 D(bug("bmp.datatype/LoadBMP() --- unsupported mode\n"));
237 BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
238 return FALSE;
241 /* initialize buffered file reads */
242 bmphandle->filebufbytes = 0;
243 bmphandle->filebufsize = FILEBUFSIZE;
244 if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
246 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
247 return FALSE;
250 /* load FileBitmapHeader from file, make sure, there are at least 14 bytes in buffer */
251 if ( (bmphandle->filebufbytes -= 14) < 0 && !LoadBMP_FillBuf(bmphandle, 14) )
253 D(bug("bmp.datatype/LoadBMP() --- filling buffer with header failed\n"));
254 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
255 return FALSE;
257 filebuf = bmphandle->filebufpos; /* this makes things easier */
258 bmphandle->filebufpos += 14;
259 if( filebuf[0] != 'B' && filebuf[1] != 'M' )
261 D(bug("bmp.datatype/LoadBMP() --- header type mismatch\n"));
262 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
263 return FALSE;
265 /* byte-wise access isn't elegant, but it is endianess-safe */
266 bfSize = (filebuf[5]<<24) | (filebuf[4]<<16) | (filebuf[3]<<8) | filebuf[2];
267 bfOffBits = (filebuf[13]<<24) | (filebuf[12]<<16) | (filebuf[11]<<8) | filebuf[10];
268 D(bug("bmp.datatype/LoadBMP() --- bfSize %ld bfOffBits %ld\n", bfSize, bfOffBits));
270 /* load BitmapInfoHeader from file, make sure, there are at least 40 bytes in buffer */
271 if ( (bmphandle->filebufbytes -= 40) < 0 && !LoadBMP_FillBuf(bmphandle, 40) )
273 D(bug("bmp.datatype/LoadBMP() --- filling buffer with header 2 failed\n"));
274 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
275 return FALSE;
277 filebuf = bmphandle->filebufpos; /* this makes things easier */
278 bmphandle->filebufpos += 40;
280 /* get image size attributes */
281 biSize = (filebuf[3]<<24) | (filebuf[2]<<16) | (filebuf[1]<<8) | filebuf[0];
282 biWidth = (filebuf[7]<<24) | (filebuf[6]<<16) | (filebuf[5]<<8) | filebuf[4];
283 biHeight = (filebuf[11]<<24) | (filebuf[10]<<16) | (filebuf[9]<<8) | filebuf[8];
284 biPlanes = (filebuf[13]<<8) | filebuf[12];
285 biBitCount = (filebuf[15]<<8) | filebuf[14];
286 biCompression = (filebuf[19]<<24) | (filebuf[18]<<16) | (filebuf[17]<<8) | filebuf[16];
287 biClrUsed = (filebuf[35]<<24) | (filebuf[34]<<16) | (filebuf[33]<<8) | filebuf[32];
288 biClrImportant = (filebuf[39]<<24) | (filebuf[38]<<16) | (filebuf[37]<<8) | filebuf[36];
289 D(bug("bmp.datatype/LoadBMP() --- BMP-Screen %ld x %ld x %ld, %ld (%ld) colors, compression %ld, type %ld\n",
290 biWidth, biHeight, (long)biBitCount, biClrUsed, biClrImportant, biCompression, biSize));
291 if (biSize != 40 || biPlanes != 1 || biCompression != 0)
293 D(bug("bmp.datatype/LoadBMP() --- Image format not supported\n"));
294 BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
295 return FALSE;
298 /* check color mode */
299 pixelfmt = PBPAFMT_LUT8;
300 switch (biBitCount)
302 case 1:
303 alignwidth = (biWidth + 31) & ~31UL;
304 alignbytes = alignwidth / 8;
305 break;
306 case 4:
307 alignwidth = (biWidth + 7) & ~7UL;
308 alignbytes = alignwidth / 2;
309 break;
310 case 8:
311 alignwidth = (biWidth + 3) & ~3UL;
312 alignbytes = alignwidth;
313 break;
314 case 24:
315 alignbytes = (biWidth + 3) & ~3UL;
316 alignwidth = alignbytes * 3;
317 pixelfmt = PBPAFMT_RGB;
318 break;
319 default:
320 D(bug("bmp.datatype/LoadBMP() --- unsupported color depth\n"));
321 BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
322 return FALSE;
324 D(bug("bmp.datatype/LoadBMP() --- align: pixels %ld bytes %ld\n", alignwidth, alignbytes));
326 /* set BitMapHeader with image size */
327 bmhd->bmh_Width = bmhd->bmh_PageWidth = biWidth;
328 bmhd->bmh_Height = bmhd->bmh_PageHeight = biHeight;
329 bmhd->bmh_Depth = biBitCount;
331 /* get empty colormap, then fill in colormap to use*/
332 if (biBitCount != 24)
334 if( !(GetDTAttrs(o, PDTA_ColorRegisters, (IPTR)&colormap,
335 PDTA_CRegs, (IPTR)&colorregs,
336 TAG_DONE ) == 2) ||
337 !(colormap && colorregs) )
339 D(bug("bmp.datatype/LoadBMP() --- got no colormap\n"));
340 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
341 return FALSE;
343 if( !LoadBMP_Colormap(bmphandle, biClrUsed, colormap, colorregs) )
345 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
346 return FALSE;
349 /* skip offset */
350 bfOffBits = bfOffBits - 14 - 40 - biClrUsed*4;
351 D(bug("bmp.datatype/LoadBMP() --- remaining offset %ld\n", bfOffBits));
352 if ( bfOffBits < 0 ||
353 ( (bmphandle->filebufbytes -= bfOffBits ) < 0 && !LoadBMP_FillBuf(bmphandle, bfOffBits) ) )
355 D(bug("bmp.datatype/LoadBMP() --- cannot skip offset\n"));
356 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
357 return FALSE;
359 bmphandle->filebufpos += bfOffBits;
361 /* Pass attributes to picture.datatype */
362 GetDTAttrs( o, DTA_Name, (IPTR)&name, TAG_DONE );
363 SetDTAttrs(o, NULL, NULL, PDTA_NumColors, biClrUsed,
364 DTA_NominalHoriz, biWidth,
365 DTA_NominalVert , biHeight,
366 DTA_ObjName , (IPTR)name,
367 TAG_DONE);
369 /* Now decode the picture data into a chunky buffer; and pass it to Bitmap line-by-line */
370 bmphandle->linebufsize = bmphandle->linebufbytes = alignwidth;
371 if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
373 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
374 return FALSE;
377 //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
378 cont = 1;
379 for (y=biHeight-1; y>=0 && cont; y--)
381 int r, g, b;
383 bmphandle->linebufpos = bmphandle->linebuf;
384 if (biBitCount == 24)
386 if ( (bmphandle->filebufbytes -= alignwidth) < 0 && !LoadBMP_FillBuf(bmphandle, alignwidth) )
388 D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
389 //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
390 //return FALSE;
391 cont = 0;
393 for (x=0; x<alignbytes; x++)
395 b = *(bmphandle->filebufpos)++;
396 g = *(bmphandle->filebufpos)++;
397 r = *(bmphandle->filebufpos)++;
398 *(bmphandle->linebufpos)++ = r;
399 *(bmphandle->linebufpos)++ = g;
400 *(bmphandle->linebufpos)++ = b;
403 else
405 for (x=0; x<alignbytes; x++)
407 if ( (bmphandle->filebufbytes -= 1) < 0 && !LoadBMP_FillBuf(bmphandle, 1) )
409 D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
410 //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
411 //return FALSE;
412 cont = 0;
413 break;
415 byte = *(bmphandle->filebufpos)++;
416 switch (biBitCount)
418 case 1:
419 for (b=0; b<8; b++)
421 *(bmphandle->linebufpos)++ = (byte & 0x80) ? 1 : 0;
422 byte <<= 1;
424 break;
425 case 4:
426 *(bmphandle->linebufpos)++ = (byte & 0xf0) >> 4;
427 *(bmphandle->linebufpos)++ = (byte & 0x0f);
428 break;
429 case 8:
430 *(bmphandle->linebufpos)++ = byte;
431 break;
432 case 24:
433 *(bmphandle->linebufpos)++ = byte;
434 break;
440 !DoSuperMethod(cl, o,
441 PDTM_WRITEPIXELARRAY, /* Method_ID */
442 (IPTR)bmphandle->linebuf, /* PixelData */
443 pixelfmt, /* PixelFormat */
444 alignwidth, /* PixelArrayMod (number of bytes per row) */
445 0, /* Left edge */
446 y, /* Top edge */
447 biWidth, /* Width */
448 1 /* Height (here: one line) */
452 D(bug("bmp.datatype/LoadBMP() --- WRITEPIXELARRAY failed !\n"));
453 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
454 return FALSE;
457 //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
459 D(bug("bmp.datatype/LoadBMP() --- Normal Exit\n"));
460 BMP_Exit(bmphandle, 0);
461 return TRUE;
464 /**************************************************************************************************/
466 static BOOL SaveBMP(struct IClass *cl, Object *o, struct dtWrite *dtw )
468 BmpHandleType *bmphandle;
469 UBYTE *filebuf;
470 unsigned int width, height, widthxheight, numplanes, numcolors;
471 struct BitMapHeader *bmhd;
472 struct BitMap *bm;
473 struct RastPort rp;
474 long *colorregs;
475 int i, j, ret;
477 D(bug("bmp.datatype/SaveBMP()\n"));
479 if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
481 SetIoErr(ERROR_NO_FREE_STORE);
482 return FALSE;
484 bmphandle->filebuf = NULL;
485 bmphandle->linebuf = NULL;
486 bmphandle->codecvars = NULL;
488 /* A NULL file handle is a NOP */
489 if( !dtw->dtw_FileHandle )
491 D(bug("bmp.datatype/SaveBMP() --- empty Filehandle - just testing\n"));
492 BMP_Exit(bmphandle, 0);
493 return TRUE;
495 bmphandle->filehandle = dtw->dtw_FileHandle;
497 /* Get BitMap and color palette */
498 if( GetDTAttrs( o, PDTA_BitMapHeader, (IPTR)&bmhd,
499 PDTA_BitMap, (IPTR)&bm,
500 PDTA_CRegs, (IPTR)&colorregs,
501 PDTA_NumColors, (IPTR)&numcolors,
502 TAG_DONE ) != 4UL ||
503 !bmhd || !bm || !colorregs || !numcolors)
505 D(bug("bmp.datatype/SaveBMP() --- missing attributes\n"));
506 BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
507 return FALSE;
509 #if 0
510 /* Check if this is a standard BitMap */
511 if( !( GetBitMapAttr(bm, BMA_FLAGS) & BMF_STANDARD ) )
513 D(bug("bmp.datatype/SaveBMP() --- wrong BitMap type\n"));
514 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
515 return FALSE;
517 #endif
518 /* initialize buffered file reads */
519 bmphandle->filebufsize = FILEBUFSIZE;
520 bmphandle->filebufbytes = bmphandle->filebufsize;
521 if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
523 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
524 return FALSE;
527 /* write BMP 87a header to file, make sure, there are at least 13 bytes in buffer */
528 if ( (bmphandle->filebufbytes -= 13) < 0 && !SaveBMP_EmptyBuf(bmphandle, 13) )
530 D(bug("bmp.datatype/SaveBMP() --- filling buffer with header failed\n"));
531 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
532 return FALSE;
534 filebuf = bmphandle->filebufpos; /* this makes things easier */
535 bmphandle->filebufpos += 13;
537 /* set screen descriptor attributes (from BitMapHeader) */
538 width = bmhd->bmh_PageWidth;
539 height = bmhd->bmh_PageHeight;
540 numplanes = bmhd->bmh_Depth - 1;
541 numcolors = 1 << (numplanes + 1);
542 D(bug("bmp.datatype/SaveBMP() --- BMP-Image %d x %d x %d, cols %d\n", width, height, numplanes+1, numcolors));
543 filebuf[6] = width & 0xff;
544 filebuf[7] = width >> 8;
545 filebuf[8] = height & 0xff;
546 filebuf[9] = height >> 8;
547 filebuf[10] = 0x80 | ((numplanes & 0x07) << 4) | (numplanes & 0x07) ; /* set numplanes, havecolmap=1 */
548 filebuf[11] = 0; /* this is fillcolor */
549 filebuf[12] = 0; /* this is pixel aspect ratio, 0 means unused */
551 /* write screen colormap, we don't use an image colormap */
552 for (i = 0; i < numcolors*3; i += 3)
554 if ( (bmphandle->filebufbytes -= 3) < 0 && !SaveBMP_EmptyBuf(bmphandle, 3) )
556 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
557 return FALSE;
559 *(bmphandle->filebufpos)++ = colorregs[i] >> 24;
560 *(bmphandle->filebufpos)++ = colorregs[i+1] >> 24;
561 *(bmphandle->filebufpos)++ = colorregs[i+2] >> 24;
564 /* write image header, image has same size as screen */
565 if ( (bmphandle->filebufbytes -= 10) < 0 && !SaveBMP_EmptyBuf(bmphandle, 10) )
567 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
568 return FALSE;
570 filebuf = bmphandle->filebufpos; /* this makes things easier */
571 bmphandle->filebufpos += 10;
572 filebuf[0] = ','; /* header ID */
573 filebuf[1] = filebuf[2] = 0; /* no left edge */
574 filebuf[3] = filebuf[4] = 0; /* no top edge */
575 filebuf[5] = width & 0xff;
576 filebuf[6] = width >> 8;
577 filebuf[7] = height & 0xff;
578 filebuf[8] = height >> 8;
579 filebuf[9] = numplanes & 0x07; /* set numplanes, havecolmap=0, interlaced=0 */
581 /* Now read the picture data from the bitplanes and write it to a chunky buffer */
582 /* For now, we use a full picture pixel buffer, not a single line */
583 widthxheight = width*height;
584 bmphandle->linebufsize = bmphandle->linebufbytes = widthxheight;
585 if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
587 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
588 return FALSE;
590 InitRastPort(&rp);
591 rp.BitMap=bm;
592 for (j=0; j<height; j++)
594 for (i=0; i<width; i++)
596 ret = (UBYTE)ReadPixel(&rp, i, j); /* very slow, to be changed */
597 *(bmphandle->linebufpos)++ = ret;
600 bmphandle->linebufpos = bmphandle->linebuf;
602 /* write the chunky buffer to file, after encoding */
604 /* write end-of-BMP marker */
605 if ( !bmphandle->filebufbytes-- && !SaveBMP_EmptyBuf(bmphandle, 1) )
607 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
608 return FALSE;
610 *(bmphandle->filebufpos)++ = ';';
612 /* flush write buffer to file and exit */
613 SaveBMP_EmptyBuf(bmphandle, 0);
614 D(bug("bmp.datatype/SaveBMP() --- Normal Exit\n"));
615 BMP_Exit(bmphandle, 0);
616 return TRUE;
621 /**************************************************************************************************/
623 IPTR BMP__OM_NEW(Class *cl, Object *o, Msg msg)
625 Object *newobj;
627 D(bug("bmp.datatype/DT_Dispatcher: Method OM_NEW\n"));
629 newobj = (Object *)DoSuperMethodA(cl, o, msg);
630 if (newobj)
632 if (!LoadBMP(cl, newobj))
634 CoerceMethod(cl, newobj, OM_DISPOSE);
635 newobj = NULL;
639 return (IPTR)newobj;
642 /**************************************************************************************************/
644 IPTR BMP__DTM_WRITE(Class *cl, Object *o, struct dtWrite *dtw)
646 D(bug("bmp.datatype/DT_Dispatcher: Method DTM_WRITE\n"));
647 if( (dtw -> dtw_Mode) == DTWM_RAW )
649 /* Local data format requested */
650 return SaveBMP(cl, o, dtw );
652 else
654 /* Pass msg to superclass (which writes an IFF ILBM picture)... */
655 return DoSuperMethodA( cl, o, (Msg)dtw );