47static int GetByte (istream * fp);
48static short GetShort (istream * fp);
49static long GetLong (istream * fp);
50static void readto (istream *fp,
unsigned long *ppos,
unsigned long dst);
51static void BMPreadfileheader (istream *fp,
unsigned long *ppos,
52 unsigned long *poffBits);
53static void BMPreadinfoheader (istream *fp,
unsigned long *ppos,
54 unsigned long *pcx,
unsigned long *pcy,
unsigned short *pcBitCount,
56static int BMPreadrgbtable (istream *fp,
unsigned long *ppos,
57 unsigned short cBitCount,
int classv, pixval *R, pixval *G, pixval *B);
59static const char *ifname =
"BMP";
60static char er_read[] =
"%s: read error";
68 if ((v = fp->get()) == EOF)
81 if (pm_readlittleshort(fp, &v) == -1)
94 if (pm_readlittlelong(fp, &v) == -1)
120 pm_error(
"%s: internal error in readto()", ifname);
122 for(; pos < dst; pos++)
124 if (fp->get() == EOF)
142 unsigned long *poffBits)
149 unsigned long offBits;
166 offBits = GetLong(fp);
179 unsigned short *pcBitCount,
180 unsigned short *pcCompression,
184 unsigned short cPlanes = 0;
186 unsigned long cx = 0;
187 unsigned long cy = 0;
188 unsigned short cBitCount = 0;
189 unsigned long cCompression = 0;
215 pm_error(
"%s: unknown cbFix: %d", ifname, cbFix);
219 if (classv == C_OS2) {
226 cPlanes = GetShort(fp);
227 cBitCount = GetShort(fp);
233 if (classv != C_OS2) {
234 cCompression = GetLong(fp);
236 for (
int i = 0; i < (int)cbFix - 20; i += 4) {
243 pm_error(
"%s: don't know how to handle cPlanes = %d"
261 ,(classv - C_WINV2 + 2)
285 *pcBitCount = cBitCount;
286 *pcCompression = cCompression;
299 unsigned short cBitCount,
308 long ncolors = (1 << cBitCount);
310 for (i = 0; i < ncolors; i++)
312 B[i] = (pixval) GetByte(fp);
313 G[i] = (pixval) GetByte(fp);
314 R[i] = (pixval) GetByte(fp);
338 unsigned short cBitCount,
344 BITSTREAM b =
nullptr;
350 if ((b = pm_bitinit(fp,
"r")) ==
nullptr)
356 for (x = 0; x < cx; x++, row++)
365 if (cBitCount > 24) {
366 *(alpha_row++) = GetByte(fp);
370 PPM_ASSIGN(*row, r, g, b);
372 if ((rc = pm_bitread(b, cBitCount, &v)) == -1)
378 PPM_ASSIGN(*row, R[v], G[v], B[v]);
383 if ((rc = pm_bitfini(b)) != 0)
403BMPreadbits(
xel *array, xelval *alpha_array,
406 unsigned long offBits,
409 unsigned short cBitCount,
410 unsigned long cCompression,
418 readto(fp, ppos, offBits);
420 if (cBitCount > 24 && cBitCount != 32) {
421 pm_error(
"%s: cannot handle cBitCount: %d", ifname, cBitCount);
424 if (cCompression == 1) {
426 xel *row = array + (cy - 1) * cx;
428 unsigned long nbyte = 0;
430 int first = GetByte(fp);
431 int second = GetByte(fp);
436 for (
int i = 0; i < first; ++i) {
437 PPM_ASSIGN(*p, R[second], G[second], B[second]);
441 else if (second == 0) {
446 else if (second == 1) {
450 else if (second == 2) {
452 int xoffset = GetByte(fp);
453 int yoffset = GetByte(fp);
456 p += xoffset - cx * yoffset;
460 for (
int i = 0; i < second; ++i) {
463 PPM_ASSIGN(*p, R[v], G[v], B[v]);
478 for (y = (
long)cy - 1; y >= 0; y--) {
479 int rc = BMPreadrow(fp, ppos, array + y*cx, alpha_array + y*cx, cx, cBitCount, indexed, R, G, B);
481 pm_error(
"%s: couldn't read row %d", ifname, y);
484 pm_error(
"%s: row had bad number of bytes: %d", ifname, rc);
493PNMFileTypeBMP::Reader::
494Reader(
PNMFileType *type, istream *file,
bool owns_file,
string magic_number) :
497 if (!read_magic_number(_file, magic_number, 2)) {
499 if (pnmimage_bmp_cat.is_debug()) {
500 pnmimage_bmp_cat.debug()
501 <<
"BMP image file appears to be empty.\n";
507 if (magic_number !=
string(
"BM")) {
508 pnmimage_bmp_cat.error()
509 <<
"File is not a valid BMP file.\n";
521 BMPreadfileheader(file, &pos, &offBits);
522 BMPreadinfoheader(file, &pos, &cx, &cy, &cBitCount, &cCompression, &classv);
524 if (offBits != BMPoffbits(classv, cBitCount)) {
525 pnmimage_bmp_cat.warning()
526 <<
"offBits is " << offBits <<
", expected "
527 << BMPoffbits(classv, cBitCount) <<
"\n";
532 if (cBitCount <= 8) {
534 rc = BMPreadrgbtable(file, &pos, cBitCount, classv, R, G, B);
536 if (rc != (
int)BMPlenrgbtable(classv, cBitCount)) {
537 pnmimage_bmp_cat.warning()
538 << rc <<
"-byte RGB table, expected "
539 << BMPlenrgbtable(classv, cBitCount) <<
" bytes\n";
543 if (cBitCount > 24) {
552 if (pnmimage_bmp_cat.is_debug()) {
553 pnmimage_bmp_cat.debug()
554 <<
"Reading BMP " << *
this <<
"\n";
568int PNMFileTypeBMP::Reader::
569read_data(
xel *array, xelval *alpha_array) {
570 BMPreadbits(array, alpha_array, _file, &pos, offBits, _x_size, _y_size,
571 cBitCount, cCompression, indexed, R, G, B);
573 if (cCompression != 1 &&
574 pos != BMPlenfile(classv, cBitCount, _x_size, _y_size)) {
575 pnmimage_bmp_cat.warning()
576 <<
"Read " << pos <<
" bytes, expected to read "
577 << BMPlenfile(classv, cBitCount, _x_size, _y_size) <<
" bytes\n";
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the base class of a family of classes that represent particular image file types that PNMImag...
This is an abstract base class that defines the interface for reading image files of various types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void pm_error(const char *format,...)
Outputs the given printf-style message to the user and terminates messily.
void pm_message(const char *format,...)
Outputs the given printf-style message to the user and returns.