/******************************************************************************* * bmp4.c * Microsoft Windows bitmap (BMP) file reading functions. * * 1.0 04-13-92 drt. First cut. * 1.1 08-25-92 drt. Renamed bmp_header members. * 1.2 09-17-92 drt. Split into bmp4.c and bmp5.c. * * Copyright (c)1992-94, David R. Tribble. */ /* includes */ #include #include #include #include #include #include #include "bmp.h" /* debug macros */ #ifndef DEBUG #define DEBUG 0 #endif #if DEBUG-0 <= 0 #undef DEBUG #define DEBUG 0 #endif #if DEBUG #define D(expr) expr #else #define D(expr) 0 #endif /******************************************************************************* * bmp_read_eoln * Reads end of pixel line marker from BMP file `fp'. */ int bmp_read_eoln(BMP_FILE *fp) { /* skip padding bytes */ while (fp->byteno < fp->linesz) { getc(fp->fp); fp->byteno++; } /* get end of line */ switch (fp->h.biCompression) { case BMP_CMP_RLE8: fp->rep = 0x00; fp->bitno = 0; break; #ifdef is_incomplete_ case BMP_CMP_RLE4: ... break; #endif case BMP_CMP_NONE: default: fp->rep = 0x00; fp->bitno = 0; break; } fp->byteno = 0; return 0; } /******************************************************************************* * bmp_read_byte * Reads next (8-bit) byte value from BMP file `fp'. * * returns * Byte value, in range [0x00,0xFF], or -1 on error or end of file. */ int bmp_read_byte(BMP_FILE *fp) { int byte; /* check args */ if (fp == NULL) { /* invalid pointer */ errno = EINVAL; return -1; } if (fp->fp == NULL) { /* file is not open */ errno = EBADF; return -1; } #if 0 /* New */ /* skip padding bytes */ if (fp->byteno > ... fp->linesz|fp->h.width ?) bmp_read_eoln(fp); #endif /* read next byte */ switch (fp->h.biCompression) { case BMP_CMP_RLE8: while (fp->rep == 0x00) { /* read next RLE pair */ byte = getc(fp->fp); if (byte == EOF) return -1; fp->rep = byte; /* repeat count */ fp->byteno++; byte = getc(fp->fp); if (byte == EOF) return -1; fp->pix = byte; /* byte value */ fp->byteno++; } fp->rep--; byte = fp->pix; break; #ifdef is_incomplete_ case BMP_CMP_RLE4: ... break; #endif case BMP_CMP_NONE: default: byte = getc(fp->fp); if (byte == EOF) return -1; fp->pix = byte; fp->byteno++; break; } fp->byte = byte; D(printf("read %.2X\n", byte)); return byte; } /******************************************************************************* * bmp_read_rgb * Reads next RGB pixel value from BMP file `fp' into `pix'. * * returns * Zero on success, or -1 on error or end of file. * If the BMP file is 1, 2, 4, or 8 bit, the returned value is the color * table index of the pixel, otherwise it is a 24-bit file and zero is * returned. */ int bmp_read_rgb(BMP_FILE *fp, struct bmp_rgbpix *pix) { int byte; int col; /* check args */ if (fp == NULL) { /* invalid pointer */ errno = EINVAL; return -1; } if (fp->fp == NULL) { /* file is not open */ errno = EBADF; return -1; } /* write pixel value */ switch (fp->h.bits) { case 1: case 2: case 4: case 8: default: if (fp->bitno == 0) { /* get next byte's worth of pixels */ byte = bmp_read_byte(fp); if (byte < 0) return -1; fp->byte = byte; fp->bitno = 8; } /* get next pixel from current byte */ switch (fp->h.bits) { case 1: col = (fp->byte & 0x80) >> 7; fp->byte <<= 1; fp->bitno -= 1; break; case 2: col = (fp->byte & 0xC0) >> 6; fp->byte <<= 2; fp->bitno -= 2; break; case 4: col = (fp->byte & 0xF0) >> 4; fp->byte <<= 4; fp->bitno -= 4; break; case 8: default: col = fp->byte; fp->bitno = 0; break; } if (fp->map != NULL) { pix->r = fp->map[col].r; pix->g = fp->map[col].g; pix->b = fp->map[col].b; } else { pix->r = 0; pix->g = 0; pix->b = 0; } break; case 24: /* build 24-bit pixel from next 3 bytes */ byte = bmp_read_byte(fp); /* blue component */ if (byte < 0) return -1; pix->b = byte; byte = bmp_read_byte(fp); /* green component */ if (byte < 0) return -1; pix->g = byte; byte = bmp_read_byte(fp); /* red component */ if (byte < 0) return -1; pix->r = byte; col = 0; D(printf("read<%.2X:%.2X:%.2X>\n", pix->r, pix->g, pix->b)); break; } return col; } /******************************************************************************* * bmp_read_pixel * Reads next pixel value from BMP file `fp'. * * returns * Pixel value, or -1 on error or end of file. * The pixel value will be in the range [0x00,0xFF] (a color table index) * for 1, 2, 4, and 8 bit colors, and will be in the range * [0x00000000,0x00FFFFFF] for 24-bit colors. */ long bmp_read_pixel(BMP_FILE *fp) { int byte; long pix; /* check args */ if (fp == NULL) { /* invalid pointer */ errno = EINVAL; return -1; } if (fp->fp == NULL) { /* file is not open */ errno = EBADF; return -1; } /* write pixel value */ switch (fp->h.bits) { case 1: case 2: case 4: case 8: default: if (fp->bitno == 0) { /* get next byte's worth of pixels */ byte = bmp_read_byte(fp); if (byte < 0) return -1; fp->byte = byte; fp->bitno = 8; } /* get next pixel from current byte */ switch (fp->h.bits) { case 1: pix = (fp->byte & 0x80) >> 7; fp->byte <<= 1; fp->bitno -= 1; break; case 2: pix = (fp->byte & 0xC0) >> 6; fp->byte <<= 2; fp->bitno -= 2; break; case 4: pix = (fp->byte & 0xF0) >> 4; fp->byte <<= 4; fp->bitno -= 4; break; case 8: default: pix = fp->byte; fp->bitno = 0; break; } break; case 24: /* build 24-bit pixel from next 3 bytes */ byte = bmp_read_byte(fp); /* blue component */ if (byte < 0) return -1; pix = byte; byte = bmp_read_byte(fp); /* green component */ if (byte < 0) return -1; pix = pix + ((long)byte << 8); byte = bmp_read_byte(fp); /* red component */ if (byte < 0) return -1; pix = pix + ((long)byte << 16); D(printf("pix=%.6lX\n", pix)); break; } return pix; } /* end bmp4.c */