15 #include "pnmFileTypeBMP.h"
19 #include "config_pnmimagetypes.h"
22 #include "pnmWriter.h"
53 static char er_write[] =
"stdout: write error";
56 static void PutByte (ostream *fp,
char v);
57 static void PutShort (ostream *fp,
short v);
58 static void PutLong (ostream *fp,
long v);
59 static int BMPwritefileheader (ostream *fp,
int classv,
unsigned long bitcount,
60 unsigned long x,
unsigned long y);
61 static int BMPwriteinfoheader (ostream *fp,
int classv,
unsigned long bitcount,
62 unsigned long x,
unsigned long y);
63 static int BMPwritergb (ostream *fp,
int classv, pixval R, pixval G, pixval B);
64 static int BMPwritergbtable (ostream *fp,
int classv,
int bpp,
int colors,
65 pixval *R, pixval *G, pixval *B);
66 static int colorstobpp (
int colors);
67 static void BMPEncode (ostream *fp,
int classv,
int x,
int y,
pixel **pixels,
85 if (pm_writelittleshort(fp, v) == -1)
96 if (pm_writelittlelong(fp, v) == -1)
113 unsigned long bitcount,
121 PutLong(fp, (
long)BMPlenfile(classv, bitcount, x, y));
130 PutLong(fp, (
long)BMPoffbits(classv, bitcount));
142 unsigned long bitcount,
156 PutLong(fp, (
long)x);
158 PutLong(fp, (
long)y);
162 PutShort(fp, (
short)bitcount);
183 PutShort(fp, (
short)x);
185 PutShort(fp, (
short)y);
189 PutShort(fp, (
short)bitcount);
193 pm_error(er_internal,
"BMPwriteinfoheader");
224 pm_error(er_internal,
"BMPwritergb");
246 for (i = 0; i < colors; i++)
248 nbyte += BMPwritergb(fp,classv,R[i],G[i],B[i]);
251 ncolors = (1 << bpp);
253 for (; i < ncolors; i++)
255 nbyte += BMPwritergb(fp,classv,0,0,0);
280 if ((b = pm_bitinit(fp,
"w")) == (
BITSTREAM) 0)
285 for (x = 0; x < cx; x++, row++)
287 if ((rc = pm_bitwrite(b, bpp, ppm_lookupcolor(cht, row))) == -1)
294 if ((rc = pm_bitfini(b)) == -1)
301 for (x = 0; x < cx; x++, row++)
303 PutByte(fp, PPM_GETB(*row) * 255 / maxval);
304 PutByte(fp, PPM_GETG(*row) * 255 / maxval);
305 PutByte(fp, PPM_GETR(*row) * 255 / maxval);
330 unsigned short cBitCount,
341 pm_error(
"cannot handle cBitCount: %d"
349 for (y = (
long)cy - 1; y >= 0; y--)
352 rc = BMPwriterow(fp, pixels[y], cx, cBitCount, indexed, cht,
357 pm_error(
"couldn't write row %d"
362 pm_error(
"row had bad number of bytes: %d"
377 colorstobpp(
int colors)
383 pm_error(
"can't have less than one color");
386 if ((bpp = pm_maxvaltobits(colors - 1)) > 8)
388 pm_error(
"can't happen");
415 unsigned long nbyte = 0;
418 int needs_bpp = colorstobpp(colors);
419 if (bpp != 0 && bpp < needs_bpp) {
420 pnmimage_bmp_cat.info()
421 <<
"too many colors for " << bmp_bpp <<
"-bit image.\n";
452 pnmimage_bmp_cat.info()
453 <<
"Using " << bpp <<
" bits per pixel.\n";
455 nbyte += BMPwritefileheader(fp, classv, bpp, x, y);
456 nbyte += BMPwriteinfoheader(fp, classv, bpp, x, y);
457 nbyte += BMPwritergbtable(fp, classv, bpp, colors, R, G, B);
459 if(nbyte != ( BMPlenfileheader(classv)
460 + BMPleninfoheader(classv)
461 + BMPlenrgbtable(classv, bpp)))
463 pm_error(er_internal,
"BMPEncode");
466 nbyte += BMPwritebits(fp, x, y, bpp, pixels,
true, cht, 255);
467 if(nbyte != BMPlenfile(classv, bpp, x, y))
469 pm_error(er_internal,
"BMPEncode");
485 unsigned long nbyte = 0;
488 pnmimage_bmp_cat.info()
489 <<
"Using " << bpp <<
" bits per pixel.\n";
491 nbyte += BMPwritefileheader(fp, classv, bpp, x, y);
492 nbyte += BMPwriteinfoheader(fp, classv, bpp, x, y);
494 if(nbyte != ( BMPlenfileheader(classv)
495 + BMPleninfoheader(classv)))
497 pm_error(er_internal,
"BMPEncode24");
502 if(nbyte != BMPlenfile(classv, bpp, x, y))
504 pm_error(er_internal,
"BMPEncode24");
514 PNMFileTypeBMP::Writer::
515 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
543 int PNMFileTypeBMP::Writer::
544 write_data(
xel *array, xelval *) {
545 if (_y_size<=0 || _x_size<=0) {
554 pixval Red[MAXCOLORS];
555 pixval Green[MAXCOLORS];
556 pixval Blue[MAXCOLORS];
573 pm_error(er_internal,
"report");
576 pm_message(
"generating %s BMP file", name);
581 pixels = (
pixel **)alloca(
sizeof(
pixel *) * _y_size);
582 for (i = 0; i < _y_size; i++) {
583 pixels[i] = (
pixel *)(array + i * _x_size);
587 chv = ppm_computecolorhist(pixels, _x_size, _y_size, MAXCOLORS, &colors);
590 BMPEncode24(_file, classv, _x_size, _y_size, pixels, _maxval);
595 pnmimage_bmp_cat.info()
596 <<
"too many colors for " << bmp_bpp <<
"-bit image.\n";
599 BMPEncode24(_file, classv, _x_size, _y_size, pixels, _maxval);
602 pnmimage_bmp_cat.debug()
603 << colors <<
" colors found\n";
609 pnmimage_bmp_cat.debug()
610 <<
"maxval is not 255 - automatically rescaling colors\n";
613 for (i = 0; i < colors; ++i) {
614 if (_maxval == 255) {
615 Red[i] = PPM_GETR(chv[i].
color);
616 Green[i] = PPM_GETG(chv[i].
color);
617 Blue[i] = PPM_GETB(chv[i].
color);
619 Red[i] = (pixval) PPM_GETR(chv[i].
color) * 255 / _maxval;
620 Green[i] = (pixval) PPM_GETG(chv[i].color) * 255 / _maxval;
621 Blue[i] = (pixval) PPM_GETB(chv[i].color) * 255 / _maxval;
626 cht = ppm_colorhisttocolorhash(chv, colors);
627 ppm_freecolorhist(chv);
629 BMPEncode(_file, classv, _x_size, _y_size, pixels, colors, cht,
647 bool PNMFileTypeBMP::Writer::
648 supports_grayscale()
const {
This is the base class of a family of classes that represent particular image file types that PNMImag...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
This is an abstract base class that defines the interface for writing image files of various types...