/******************************************************************************* * bmp2.c * Microsoft Windows bitmap (BMP) file functions. * * 1.0 04-13-92 drt. First cut. * 1.1 08-25-92 drt. Renamed bmp_header members. * * Copyright (c)1992-94, David R. Tribble. */ /* includes */ #include #include #include #include #include #include #include "bmp.h" /* Private variables */ static unsigned short h_id = BMP_HDR_MAGIC; /******************************************************************************* * bmp_read_hdr * Read header from BMP file `fp'. * * Returns * Zero if successful, otherwise -1. */ int bmp_read_hdr(BMP_FILE *fp) { long pos; size_t len; struct os2_bmp_header os2; /* Check args */ if (fp == NULL) { /* Invalid pointer */ errno = EINVAL; return -1; } /* Read header struct from file */ pos = ftell(fp->fp); len = fread(&fp->h, sizeof(fp->h), 1, fp->fp); if (len != 1) goto fail; /* Check for bad magic */ if (fp->h.id != h_id) goto fail; /* Header was successfully read, check for OS/2 header */ if (fp->h.infoSize == 12) { /* OS/2 BMP header */ /* Back up file pointer and reread header */ if (fseek(fp->fp, pos, SEEK_SET) != 0) goto fail; len = fread(&os2, sizeof(os2), 1, fp->fp); if (len != 1) goto fail; /* Fill in file's info with OS/2 header info */ memset(&fp->h, 0, sizeof(fp->h)); fp->flags = BMP_FILE_F_OS2 | BMP_FILE_F_RGB3; fp->h.id = os2.id; fp->h.filesize = os2.filesize; fp->h.headersize = os2.headersize; fp->h.infoSize = os2.infoSize; fp->h.width = os2.width; fp->h.depth = os2.depth; fp->h.biPlanes = os2.biPlanes; fp->h.bits = os2.bits; fp->h.biClrUsed = 0; memcpy(fp->h.r, os2.r, sizeof(fp->h.r)); } /* Adjust file info */ switch (fp->h.bits) { case 1: case 2: case 4: case 8: fp->linesz = fp->h.width / (8/fp->h.bits); /** nplanes? **/ break; case 24: fp->linesz = fp->h.width * 24/8; /** nplanes? **/ break; } fp->linesz = (fp->linesz + 4-1) / 4 * 4; /* Nearest longword */ fp->byteno = 0; fp->bitno = 0; fp->rep = 0; fp->pix = 0; fp->byte = 0; /* Read was successful */ return 0; fail: fseek(fp->fp, pos, SEEK_SET); return -1; } /******************************************************************************* * bmp_write_hdr * Write header to BMP file `fp'. * * Returns * Zero if successful, otherwise -1. */ int bmp_write_hdr(BMP_FILE *fp) { long pos; size_t len; /* Check args */ if (fp == NULL) { /* Invalid pointer */ errno = EINVAL; return -1; } #if 1 /* Fill in header members */ fp->h.id = BMP_HDR_MAGIC; fp->h.r[0] = 0; fp->h.r[1] = 0; fp->h.r[2] = 0; fp->h.r[3] = 0; #if 0 fp->h.infoSize = 40; #endif /* Adjust file info */ switch (fp->h.bits) { case 1: case 2: case 4: case 8: fp->linesz = fp->h.width / (8/fp->h.bits); /** nplanes? **/ break; case 24: fp->linesz = fp->h.width * 24/8; /** nplanes? **/ break; } fp->linesz = (fp->linesz + 4-1) / 4 * 4; /* Nearest longword */ fp->byteno = 0; fp->bitno = 0; fp->rep = 0; fp->pix = 0; fp->byte = 0; #endif /* Write header struct to file */ pos = ftell(fp->fp); len = fwrite(&fp->h, sizeof(fp->h), 1, fp->fp); if (len != 1) goto fail; /* Read was successful */ return 0; fail: fseek(fp->fp, pos, SEEK_SET); return -1; } /******************************************************************************* * bmp_read_rgbtab * Read RGB color palette table from BMP file `fp'. * * Returns * Number of colors in the palette if successful, otherwise -1. * * Notes * This function leaves the file positioned at the start of the pixel * data, whether or not the file contains a palette map. */ int bmp_read_rgbtab(BMP_FILE *fp, struct bmp_rgb tab[]) { long pos; size_t len, alen; int i; /* Check args */ if (fp == NULL) { /* Invalid pointer */ errno = EINVAL; return -1; } if (tab == NULL) { /* Invalid pointer */ errno = EINVAL; return -1; } /* Read color palette (if there is one) */ if (fp->h.bits > 0 && fp->h.bits <= 8) { /* Save current file position */ pos = ftell(fp->fp); /* Determine actual size of color palette */ len = bmp_pow2[fp->h.bits]; alen = (fp->h.biClrUsed > 0 ? fp->h.biClrUsed : len); fp->ncols = alen; /* Read palette */ if (fp->flags & BMP_FILE_F_OS2) { struct os2_bmp_rgb map3[0x100]; /* Read OS/2 BMP color map */ memset(map3, 0x00, sizeof(map3)); if (fread(map3, sizeof(map3[0]), alen, fp->fp) != alen) { /* Can't read palette */ goto fail; } /* Convert OS/2 colors into Windows colors */ for (i = 0; i < alen && i < 0x100; i++) { tab[i].r = map3[i].r; tab[i].g = map3[i].g; tab[i].b = map3[i].b; tab[i].a = 0x00; } } else { /* Read BMP color map */ memset(tab, 0x00, sizeof(tab)); if (fread(tab, sizeof(tab[0]), alen, fp->fp) != alen) { /* Can't read palette */ goto fail; } } } else { /* There is no color palette */ alen = 0; fp->ncols = alen; } /* Save current file position */ pos = ftell(fp->fp); /* Seek to start of pixel data */ if (fp->h.headersize > pos) { /* Seek to start of pixel data */ if (fseek(fp->fp, fp->h.headersize, SEEK_SET) != 0) { /* Seek failed */ goto fail; } } /* Read was successful */ return alen; fail: fseek(fp->fp, pos, SEEK_SET); return -1; } /******************************************************************************* * bmp_write_rgbtab * Write RGB color palette table `tab' of `num' colors to BMP file `fp'. * * Returns * Number of colors written to the palette if successful, otherwise -1. * * Notes * This function leaves the file positioned at the start of the pixel * data, whether or not the file contains a palette map. */ int bmp_write_rgbtab(BMP_FILE *fp, const struct bmp_rgb tab[], unsigned num) { long pos; size_t len; int i; /* Check args */ if (fp == NULL) { /* Invalid pointer */ errno = EINVAL; return -1; } if (tab == NULL) { /* Invalid pointer */ errno = EINVAL; return -1; } /* Write color palette */ if (num > 0 && fp->h.bits > 0 && fp->h.bits <= 8) { /* Save current file position */ pos = ftell(fp->fp); /* Determine actual size of color palette */ len = bmp_pow2[fp->h.bits]; fp->h.biClrUsed = (num != len ? num : 0); /* Write palette */ if (fp->flags & BMP_FILE_F_OS2) { struct os2_bmp_rgb map3[0x100]; /* Convert Windows colors into OS/2 colors */ memset(map3, 0x00, sizeof(map3)); for (i = 0; i < num && i < 0x100; i++) { map3[i].r = tab[i].r; map3[i].g = tab[i].g; map3[i].b = tab[i].b; } /* Write OS/2 BMP color map */ if (fwrite(map3, sizeof(map3[0]), num, fp->fp) != num) { /* Can't write palette */ goto fail; } } else { /* Write BMP color map */ if (fwrite(tab, sizeof(tab[0]), num, fp->fp) != num) { /* Can't write palette */ goto fail; } } } else { /* There is no color palette */ num = 0; } /* Save current file position */ pos = ftell(fp->fp); /* Seek to start of pixel data */ if (fp->h.headersize > pos) { /* Seek to start of pixel data */ if (fseek(fp->fp, fp->h.headersize, SEEK_SET) != 0) { /* Seek failed */ goto fail; } } /* Write was successful */ return num; fail: fseek(fp->fp, pos, SEEK_SET); return -1; } /* End bmp2.c */