Disabled debug output.
[AROS.git] / workbench / classes / datatypes / bmp / bmpclass.c
blob88f9e0fa2d65f7b33cce6e1d2c66123d811c7008
1 /*
2 Copyright © 1995-2015, 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 union {
50 struct IFFHandle *iff;
51 BPTR bptr;
52 } filehandle;
54 UBYTE *filebuf;
55 UBYTE *filebufpos;
56 long filebufbytes;
57 long filebufsize;
58 UBYTE *linebuf;
59 UBYTE *linebufpos;
60 long linebufsize;
62 APTR codecvars;
63 } BmpHandleType;
66 typedef struct
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
75 typedef struct
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);
110 SetIoErr(errorcode);
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));
126 return FALSE;
128 bmphandle->filebufpos = bmphandle->filebuf;
129 bmphandle->filebufbytes = bmphandle->filebufsize - minbytes;
130 D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- wrote %ld bytes\n", (long)bytes));
131 return TRUE;
134 /* buffered file access, useful for RLE */
135 BOOL LoadBMP_FillBuf(BmpHandleType *bmphandle, long minbytes)
137 long i, bytes;
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 )
141 return TRUE;
142 bytes = bmphandle->filebufbytes + minbytes;
143 //D(bug("bmp.datatype/LoadBMP_FillBuf() --- %ld bytes requested, %ld bytes left\n", (long)minbytes, (long)bytes));
144 if (bytes > 0)
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)
157 return TRUE;
158 return FALSE;
161 static BOOL LoadBMP_Colormap(BmpHandleType *bmphandle, int numcolors,
162 struct ColorRegister *colormap, ULONG *colregs)
164 unsigned int i, j;
166 if (numcolors && numcolors <= MAXCOLORS)
168 j = 0;
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"));
174 return FALSE;
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));
188 return TRUE;
191 /**************************************************************************************************/
192 static BOOL LoadBMP(struct IClass *cl, Object *o)
194 BmpHandleType *bmphandle;
195 UBYTE *filebuf;
196 IPTR sourcetype;
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;
202 long x = 0, y;
203 int cont, byte;
204 struct BitMapHeader *bmhd;
205 struct ColorRegister *colormap;
206 ULONG *colorregs;
207 STRPTR name;
209 D(bug("bmp.datatype/LoadBMP()\n"));
211 if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
213 SetIoErr(ERROR_NO_FREE_STORE);
214 return FALSE;
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,
224 TAG_DONE) != 3 )
226 BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
227 return FALSE;
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);
234 return TRUE;
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);
240 return FALSE;
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);
249 return FALSE;
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);
257 return FALSE;
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);
265 return FALSE;
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);
277 return FALSE;
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);
297 return FALSE;
300 /* check color mode */
301 pixelfmt = PBPAFMT_LUT8;
302 switch (biBitCount)
304 case 1:
305 alignwidth = (biWidth + 31) & ~31UL;
306 alignbytes = alignwidth / 8;
307 break;
308 case 4:
309 alignwidth = (biWidth + 7) & ~7UL;
310 alignbytes = alignwidth / 2;
311 break;
312 case 8:
313 alignwidth = (biWidth + 3) & ~3UL;
314 alignbytes = alignwidth;
315 break;
316 case 24:
317 alignbytes = ((biBitCount * biWidth + 31) / 32) * 4;
318 alignwidth = alignbytes / 3;
319 pixelfmt = PBPAFMT_RGB;
320 break;
321 default:
322 D(bug("bmp.datatype/LoadBMP() --- unsupported color depth\n"));
323 BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
324 return FALSE;
326 D(bug("bmp.datatype/LoadBMP() --- align: pixels %ld bytes %ld\n", alignwidth, alignbytes));
328 /* set BitMapHeader with image size */
329 bmhd->bmh_Width = bmhd->bmh_PageWidth = biWidth;
330 bmhd->bmh_Height = bmhd->bmh_PageHeight = biHeight;
331 bmhd->bmh_Depth = biBitCount;
333 /* get empty colormap, then fill in colormap to use*/
334 if (biBitCount != 24)
336 if( !(GetDTAttrs(o, PDTA_ColorRegisters, (IPTR)&colormap,
337 PDTA_CRegs, (IPTR)&colorregs,
338 TAG_DONE ) == 2) ||
339 !(colormap && colorregs) )
341 D(bug("bmp.datatype/LoadBMP() --- got no colormap\n"));
342 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
343 return FALSE;
346 /* Zero in the color count field means calculate it based on bits */
347 if (biClrUsed == 0)
348 biClrUsed = 1 << biBitCount;
350 if( !LoadBMP_Colormap(bmphandle, biClrUsed, colormap, colorregs) )
352 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
353 return FALSE;
356 /* skip offset */
357 bfOffBits = bfOffBits - 14 - 40 - biClrUsed*4;
358 D(bug("bmp.datatype/LoadBMP() --- remaining offset %ld\n", bfOffBits));
359 if ( bfOffBits < 0 ||
360 ( (bmphandle->filebufbytes -= bfOffBits ) < 0 && !LoadBMP_FillBuf(bmphandle, bfOffBits) ) )
362 D(bug("bmp.datatype/LoadBMP() --- cannot skip offset\n"));
363 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
364 return FALSE;
366 bmphandle->filebufpos += bfOffBits;
368 /* Pass attributes to picture.datatype */
369 GetDTAttrs( o, DTA_Name, (IPTR)&name, TAG_DONE );
370 SetDTAttrs(o, NULL, NULL, PDTA_NumColors, biClrUsed,
371 DTA_NominalHoriz, biWidth,
372 DTA_NominalVert , biHeight,
373 DTA_ObjName , (IPTR)name,
374 TAG_DONE);
376 /* Now decode the picture data into a chunky buffer; and pass it to Bitmap line-by-line */
377 if (biBitCount == 24)
378 bmphandle->linebufsize = alignbytes;
379 else
380 bmphandle->linebufsize = alignwidth;
381 if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
383 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
384 return FALSE;
387 //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
388 cont = 1;
389 for (y=biHeight-1; y>=0 && cont; y--)
391 int r, g, b;
392 UBYTE *p;
394 bmphandle->linebufpos = bmphandle->linebuf;
395 if (biBitCount == 24)
397 if ( (bmphandle->filebufbytes -= alignbytes) < 0 && !LoadBMP_FillBuf(bmphandle, alignbytes) )
399 D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
400 //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
401 //return FALSE;
402 cont = 0;
404 for (x=0, p = bmphandle->filebufpos; x<alignwidth; x++)
406 b = *p++;
407 g = *p++;
408 r = *p++;
409 *(bmphandle->linebufpos)++ = r;
410 *(bmphandle->linebufpos)++ = g;
411 *(bmphandle->linebufpos)++ = b;
413 bmphandle->filebufpos += alignbytes;
415 else
417 for (x=0; x<alignbytes; x++)
419 if ( (bmphandle->filebufbytes -= 1) < 0 && !LoadBMP_FillBuf(bmphandle, 1) )
421 D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
422 //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
423 //return FALSE;
424 cont = 0;
425 break;
427 byte = *(bmphandle->filebufpos)++;
428 switch (biBitCount)
430 case 1:
431 for (b=0; b<8; b++)
433 *(bmphandle->linebufpos)++ = (byte & 0x80) ? 1 : 0;
434 byte <<= 1;
436 break;
437 case 4:
438 *(bmphandle->linebufpos)++ = (byte & 0xf0) >> 4;
439 *(bmphandle->linebufpos)++ = (byte & 0x0f);
440 break;
441 case 8:
442 *(bmphandle->linebufpos)++ = byte;
443 break;
444 case 24:
445 *(bmphandle->linebufpos)++ = byte;
446 break;
452 !DoSuperMethod(cl, o,
453 PDTM_WRITEPIXELARRAY, /* Method_ID */
454 (IPTR)bmphandle->linebuf, /* PixelData */
455 pixelfmt, /* PixelFormat */
456 alignbytes, /* PixelArrayMod (number of bytes per row) */
457 0, /* Left edge */
458 y, /* Top edge */
459 biWidth, /* Width */
460 1 /* Height (here: one line) */
464 D(bug("bmp.datatype/LoadBMP() --- WRITEPIXELARRAY failed !\n"));
465 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
466 return FALSE;
469 //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
471 D(bug("bmp.datatype/LoadBMP() --- Normal Exit\n"));
472 BMP_Exit(bmphandle, 0);
473 return TRUE;
476 /**************************************************************************************************/
478 static BOOL SaveBMP(struct IClass *cl, Object *o, struct dtWrite *dtw )
480 BmpHandleType *bmphandle;
481 UBYTE *filebuf;
482 unsigned int width, height, widthxheight, numplanes, numcolors;
483 struct BitMapHeader *bmhd;
484 struct BitMap *bm;
485 struct RastPort rp;
486 long *colorregs;
487 int i, j, ret;
489 D(bug("bmp.datatype/SaveBMP()\n"));
491 if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
493 SetIoErr(ERROR_NO_FREE_STORE);
494 return FALSE;
496 bmphandle->filebuf = NULL;
497 bmphandle->linebuf = NULL;
498 bmphandle->codecvars = NULL;
500 /* A NULL file handle is a NOP */
501 if( !dtw->dtw_FileHandle )
503 D(bug("bmp.datatype/SaveBMP() --- empty Filehandle - just testing\n"));
504 BMP_Exit(bmphandle, 0);
505 return TRUE;
507 bmphandle->filehandle.bptr = dtw->dtw_FileHandle;
509 /* Get BitMap and color palette */
510 if( GetDTAttrs( o, PDTA_BitMapHeader, (IPTR)&bmhd,
511 PDTA_BitMap, (IPTR)&bm,
512 PDTA_CRegs, (IPTR)&colorregs,
513 PDTA_NumColors, (IPTR)&numcolors,
514 TAG_DONE ) != 4UL ||
515 !bmhd || !bm || !colorregs || !numcolors)
517 D(bug("bmp.datatype/SaveBMP() --- missing attributes\n"));
518 BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
519 return FALSE;
521 #if 0
522 /* Check if this is a standard BitMap */
523 if( !( GetBitMapAttr(bm, BMA_FLAGS) & BMF_STANDARD ) )
525 D(bug("bmp.datatype/SaveBMP() --- wrong BitMap type\n"));
526 BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
527 return FALSE;
529 #endif
530 /* initialize buffered file reads */
531 bmphandle->filebufsize = FILEBUFSIZE;
532 bmphandle->filebufbytes = bmphandle->filebufsize;
533 if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
535 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
536 return FALSE;
539 /* write BMP 87a header to file, make sure, there are at least 13 bytes in buffer */
540 if ( (bmphandle->filebufbytes -= 13) < 0 && !SaveBMP_EmptyBuf(bmphandle, 13) )
542 D(bug("bmp.datatype/SaveBMP() --- filling buffer with header failed\n"));
543 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
544 return FALSE;
546 filebuf = bmphandle->filebufpos; /* this makes things easier */
547 bmphandle->filebufpos += 13;
549 /* set screen descriptor attributes (from BitMapHeader) */
550 width = bmhd->bmh_PageWidth;
551 height = bmhd->bmh_PageHeight;
552 numplanes = bmhd->bmh_Depth - 1;
553 numcolors = 1 << (numplanes + 1);
554 D(bug("bmp.datatype/SaveBMP() --- BMP-Image %d x %d x %d, cols %d\n", width, height, numplanes+1, numcolors));
555 filebuf[6] = width & 0xff;
556 filebuf[7] = width >> 8;
557 filebuf[8] = height & 0xff;
558 filebuf[9] = height >> 8;
559 filebuf[10] = 0x80 | ((numplanes & 0x07) << 4) | (numplanes & 0x07) ; /* set numplanes, havecolmap=1 */
560 filebuf[11] = 0; /* this is fillcolor */
561 filebuf[12] = 0; /* this is pixel aspect ratio, 0 means unused */
563 /* write screen colormap, we don't use an image colormap */
564 for (i = 0; i < numcolors*3; i += 3)
566 if ( (bmphandle->filebufbytes -= 3) < 0 && !SaveBMP_EmptyBuf(bmphandle, 3) )
568 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
569 return FALSE;
571 *(bmphandle->filebufpos)++ = colorregs[i] >> 24;
572 *(bmphandle->filebufpos)++ = colorregs[i+1] >> 24;
573 *(bmphandle->filebufpos)++ = colorregs[i+2] >> 24;
576 /* write image header, image has same size as screen */
577 if ( (bmphandle->filebufbytes -= 10) < 0 && !SaveBMP_EmptyBuf(bmphandle, 10) )
579 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
580 return FALSE;
582 filebuf = bmphandle->filebufpos; /* this makes things easier */
583 bmphandle->filebufpos += 10;
584 filebuf[0] = ','; /* header ID */
585 filebuf[1] = filebuf[2] = 0; /* no left edge */
586 filebuf[3] = filebuf[4] = 0; /* no top edge */
587 filebuf[5] = width & 0xff;
588 filebuf[6] = width >> 8;
589 filebuf[7] = height & 0xff;
590 filebuf[8] = height >> 8;
591 filebuf[9] = numplanes & 0x07; /* set numplanes, havecolmap=0, interlaced=0 */
593 /* Now read the picture data from the bitplanes and write it to a chunky buffer */
594 /* For now, we use a full picture pixel buffer, not a single line */
595 widthxheight = width*height;
596 bmphandle->linebufsize = widthxheight;
597 if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
599 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
600 return FALSE;
602 InitRastPort(&rp);
603 rp.BitMap=bm;
604 for (j=0; j<height; j++)
606 for (i=0; i<width; i++)
608 ret = (UBYTE)ReadPixel(&rp, i, j); /* very slow, to be changed */
609 *(bmphandle->linebufpos)++ = ret;
612 bmphandle->linebufpos = bmphandle->linebuf;
614 /* write the chunky buffer to file, after encoding */
616 /* write end-of-BMP marker */
617 if ( !bmphandle->filebufbytes-- && !SaveBMP_EmptyBuf(bmphandle, 1) )
619 BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
620 return FALSE;
622 *(bmphandle->filebufpos)++ = ';';
624 /* flush write buffer to file and exit */
625 SaveBMP_EmptyBuf(bmphandle, 0);
626 D(bug("bmp.datatype/SaveBMP() --- Normal Exit\n"));
627 BMP_Exit(bmphandle, 0);
628 return TRUE;
633 /**************************************************************************************************/
635 IPTR BMP__OM_NEW(Class *cl, Object *o, Msg msg)
637 Object *newobj;
639 D(bug("bmp.datatype/DT_Dispatcher: Method OM_NEW\n"));
641 newobj = (Object *)DoSuperMethodA(cl, o, msg);
642 if (newobj)
644 if (!LoadBMP(cl, newobj))
646 CoerceMethod(cl, newobj, OM_DISPOSE);
647 newobj = NULL;
651 return (IPTR)newobj;
654 /**************************************************************************************************/
656 IPTR BMP__DTM_WRITE(Class *cl, Object *o, struct dtWrite *dtw)
658 D(bug("bmp.datatype/DT_Dispatcher: Method DTM_WRITE\n"));
659 if( (dtw -> dtw_Mode) == DTWM_RAW )
661 /* Local data format requested */
662 return SaveBMP(cl, o, dtw );
664 else
666 /* Pass msg to superclass (which writes an IFF ILBM picture)... */
667 return DoSuperMethodA( cl, o, (Msg)dtw );