Back to index

radiance  4R0+20100331
Defines | Functions | Variables
bmpfile.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bmpfile.h"

Go to the source code of this file.

Defines

#define getScanSiz(h)   ( ((((h)->bpp*(h)->width+7) >>3) + 3) & ~03 )
#define rdbyte(c, br)   ((br)->fpos += (c=(*(br)->cget)((br)->c_data))!=EOF, c)
#define wrbyte(c, bw)

Functions

const char * BMPerrorMessage (int ec)
static int BMPheaderOK (const BMPHeader *hdr)
static int rdbytes (char *bp, uint32 n, BMPReader *br)
static int32 rdint32 (BMPReader *br)
static int rduint16 (BMPReader *br)
static int rdseek (uint32 pos, BMPReader *br)
BMPReaderBMPopenReader (int(*cget)(void *), int(*seek)(uint32, void *), void *c_data)
int BMPisGrayscale (const BMPHeader *hdr)
int BMPreadScanline (BMPReader *br)
int BMPseekScanline (int y, BMPReader *br)
RGBquad BMPdecodePixel (int i, const BMPReader *br)
void BMPfreeReader (BMPReader *br)
int stdio_getc (void *p)
void stdio_putc (int c, void *p)
int stdio_fseek (uint32 pos, void *p)
BMPHeaderBMPtruecolorHeader (int xr, int yr, int infolen)
BMPHeaderBMPmappedHeader (int xr, int yr, int infolen, int ncolors)
static void wrbytes (char *bp, uint32 n, BMPWriter *bw)
static void wrint32 (int32 i, BMPWriter *bw)
static void wruint16 (uint16 ui, BMPWriter *bw)
static int wrseek (uint32 pos, BMPWriter *bw)
BMPWriterBMPopenWriter (void(*cput)(int, void *), int(*seek)(uint32, void *), void *c_data, BMPHeader *hdr)
static int findNextRun (const int8 *bp, int len)
int BMPwriteScanline (BMPWriter *bw)
void BMPfreeWriter (BMPWriter *bw)

Variables

static const char RCSid [] = "$Id: bmpfile.c,v 2.15 2005/05/10 01:08:43 greg Exp $"

Define Documentation

#define getScanSiz (   h)    ( ((((h)->bpp*(h)->width+7) >>3) + 3) & ~03 )

Definition at line 87 of file bmpfile.c.

#define rdbyte (   c,
  br 
)    ((br)->fpos += (c=(*(br)->cget)((br)->c_data))!=EOF, c)

Definition at line 90 of file bmpfile.c.

#define wrbyte (   c,
  bw 
)
Value:
( (*(bw)->cput)(c,(bw)->c_data), \
                            ++(bw)->fpos > (bw)->flen ? \
                                   ((bw)->flen = (bw)->fpos) : \
                                   (bw)->fpos )

Definition at line 574 of file bmpfile.c.


Function Documentation

RGBquad BMPdecodePixel ( int  i,
const BMPReader br 
)

Definition at line 412 of file bmpfile.c.

{
       static const uint32     std16mask[3] = {0x7c00, 0x3e0, 0x1f};
       static const RGBquad    black = {0, 0, 0, 0};
       const uint32         *mask;
       const uint8          *pp;
       uint32               pval, v;
       RGBquad                     cval;
       
       if (((br == NULL) | (i < 0)) || i >= br->hdr->width)
              return black;

       cval.padding = 0;

       switch (br->hdr->bpp) {
       case 24:
              pp = br->scanline + 3*i;
              cval.b = *pp++;
              cval.g = *pp++;
              cval.r = *pp;
              return cval;
       case 32:
              if (br->hdr->compr == BI_UNCOMPR)
                     return ((RGBquad *)br->scanline)[i];
                                          /* convert bit fields */
              pp = br->scanline + 4*i;
              pval = *pp++;
              pval |= *pp++ << 8;
              pval |= *pp++ << 16;
              pval |= *pp << 24;
              mask = BMPbitField(br->hdr);
              v = pval & mask[0];
              while (v & ~0xff) v >>= 8;
              cval.r = v;
              v = pval & mask[1];
              while (v & ~0xff) v >>= 8;
              cval.g = v;
              v = pval & mask[2];
              while (v & ~0xff) v >>= 8;
              cval.b = v;
              return cval;
       case 8:
              return br->hdr->palette[br->scanline[i]];
       case 1:
              return br->hdr->palette[br->scanline[i>>3]>>((7-i)&7) & 1];
       case 4:
              return br->hdr->palette[br->scanline[i>>1]>>(i&1?4:0) & 0xf];
       case 16:
              pp = br->scanline + 2*i;
              pval = *pp++;
              pval |= *pp++ << 8;
              mask = std16mask;
              if (br->hdr->compr == BI_BITFIELDS)
                     mask = BMPbitField(br->hdr);
              cval.r = ((pval & mask[0]) << 8) / (mask[0] + 1);
              cval.g = ((pval & mask[1]) << 8) / (mask[1] + 1);
              cval.b = ((pval & mask[2]) << 8) / (mask[2] + 1);
              return cval;
       }
       return black;                      /* should never happen */
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* BMPerrorMessage ( int  ec)

Definition at line 22 of file bmpfile.c.

{
       switch (ec) {
       case BIR_OK:
              return "No error";
       case BIR_EOF:
              return "End of BMP image";
       case BIR_TRUNCATED:
              return "Truncated BMP image";
       case BIR_UNSUPPORTED:
              return "Unsupported BMP feature";
       case BIR_RLERROR:
              return "BMP runlength encoding error";
       case BIR_SEEKERR:
              return "BMP seek error";
       }
       return "Unknown BMP error";
}

Here is the caller graph for this function:

void BMPfreeReader ( BMPReader br)

Definition at line 476 of file bmpfile.c.

{
       if (br == NULL)
              return;
       free((void *)br->hdr);
       free((void *)br->scanline);
       free((void *)br);
}
void BMPfreeWriter ( BMPWriter bw)

Definition at line 780 of file bmpfile.c.

{
       if (bw == NULL)
              return;
       free((void *)bw->hdr);
       free((void *)bw->scanline);
       free((void *)bw);
}
static int BMPheaderOK ( const BMPHeader hdr) [static]

Definition at line 43 of file bmpfile.c.

{
       if (!hdr)
              return 0;
       if ((hdr->width <= 0) | (hdr->height <= 0))
              return 0;
       switch (hdr->bpp) {         /* check compression */
       case 1:
       case 24:
              if (hdr->compr != BI_UNCOMPR)
                     return 0;
              break;
       case 16:
       case 32:
              if ((hdr->compr != BI_UNCOMPR) & (hdr->compr != BI_BITFIELDS))
                     return 0;
              break;
       case 4:
              if ((hdr->compr != BI_UNCOMPR) & (hdr->compr != BI_RLE4))
                     return 0;
              break;
       case 8:
              if ((hdr->compr != BI_UNCOMPR) & (hdr->compr != BI_RLE8))
                     return 0;
              break;
       default:
              return 0;
       }
       if (hdr->compr == BI_BITFIELDS && (BMPbitField(hdr)[0] &
                            BMPbitField(hdr)[1] & BMPbitField(hdr)[2]))
              return 0;
       if (hdr->bpp > 8) {
              if (hdr->nColors != 0)
                     return 0;
       } else {
              if ((hdr->nColors < 0) | (hdr->nColors > 1<<hdr->bpp))
                     return 0;
              if ((hdr->impColors < 0) | (hdr->impColors > hdr->nColors))
                     return 0;
       }
       return 1;
}

Here is the caller graph for this function:

int BMPisGrayscale ( const BMPHeader hdr)

Definition at line 253 of file bmpfile.c.

{
       const RGBquad   *rgbp;
       int           n;

       if (hdr == NULL)
              return -1;
       if (hdr->bpp > 8)           /* assume they had a reason for it */
              return 0;
       for (rgbp = hdr->palette, n = hdr->impColors; n-- > 0; rgbp++)
              if ((rgbp->r != rgbp->g) | (rgbp->g != rgbp->b))
                     return 0;
       return 1;                   /* all colors neutral in map */
}
BMPHeader* BMPmappedHeader ( int  xr,
int  yr,
int  infolen,
int  ncolors 
)

Definition at line 536 of file bmpfile.c.

{
       int           n;
       BMPHeader       *hdr;
       
       if (xr <= 0 || yr <= 0 || infolen < 0 || ncolors < 2)
              return NULL;
       if (ncolors <= 2)
              n = 1;
       else if (ncolors <= 16)
              n = 4;
       else if (ncolors <= 256)
              n = 8;
       else
              return NULL;
       hdr = (BMPHeader *)malloc(sizeof(BMPHeader) +
                                   sizeof(RGBquad)*(1<<n) -
                                   sizeof(hdr->palette) +
                                   infolen);
       if (hdr == NULL)
              return NULL;
       hdr->width = xr;
       hdr->height = yr;
       hdr->yIsDown = 0;                  /* default to upwards order */
       hdr->bpp = n;
       hdr->compr = BI_UNCOMPR;           /* compression needs seek */
       hdr->hRes = hdr->vRes = 2835;             /* default to 72 ppi */
       hdr->nColors = ncolors;
       hdr->impColors = 0;                /* says all colors important */
       hdr->infoSiz = infolen;
       memset((void *)hdr->palette, 0, sizeof(RGBquad)*(1<<n) + infolen);
       for (n = ncolors; n--; )
              hdr->palette[n].r = hdr->palette[n].g =
                     hdr->palette[n].b = n*255/(ncolors-1);
       return hdr;
}

Here is the caller graph for this function:

BMPReader* BMPopenReader ( int(*)(void *)  cget,
int(*)(uint32, void *)  seek,
void *  c_data 
)

Definition at line 146 of file bmpfile.c.

{
       BMPReader       *br;
       uint32        bmPos, hdrSiz, palSiz;
       int           magic[2];            /* check magic number */

       if (cget == NULL)
              return NULL;
       magic[0] = (*cget)(c_data);
       if (magic[0] != 'B')
              return NULL;
       magic[1] = (*cget)(c_data);
       if (magic[1] != 'M' && magic[1] != 'A')
              return NULL;
       br = (BMPReader *)calloc(1, sizeof(BMPReader));
       if (br == NULL)
              return NULL;
       br->cget = cget;
       br->seek = seek;
       br->c_data = c_data;
       br->hdr = (BMPHeader *)malloc(sizeof(BMPHeader));
       if (br->hdr == NULL)
              goto err;
       br->fpos = 2;
                                   /* read & verify file header */
       (void)rdint32(br);                 /* file size */
       (void)rdint32(br);                 /* reserved word */
       bmPos = rdint32(br);               /* offset to bitmap */
       hdrSiz = 2 + 3*4 + rdint32(br);           /* header size */
       if (hdrSiz < 2 + 6*4 + 2*2 + 6*4)
              goto err;
       br->hdr->width = rdint32(br);             /* bitmap width */
       br->hdr->height = rdint32(br);            /* bitmap height */
       if (((br->hdr->width <= 0) | (br->hdr->height == 0)))
              goto err;
       if ((br->hdr->yIsDown = br->hdr->height < 0))
              br->hdr->height = -br->hdr->height;
       if (rduint16(br) != 1)                    /* number of planes */
              goto err;
       br->hdr->bpp = rduint16(br);              /* bits per pixel */
       br->hdr->compr = rdint32(br);             /* compression mode */
       (void)rdint32(br);                 /* bitmap size */
       br->hdr->hRes = rdint32(br);              /* horizontal resolution */
       br->hdr->vRes = rdint32(br);              /* vertical resolution */
       br->hdr->nColors = rdint32(br);           /* # colors used */
       if (!br->hdr->nColors && br->hdr->bpp <= 8)
              br->hdr->nColors = 1<<br->hdr->bpp;
       br->hdr->impColors = rdint32(br);       /* # important colors */
       if (br->hdr->impColors < 0)
              goto err;                   /* catch premature EOF */
       if (!BMPheaderOK(br->hdr))
              goto err;
       palSiz = sizeof(RGBquad)*br->hdr->nColors;
       if (br->hdr->impColors <= 0)
              br->hdr->impColors = br->hdr->nColors;
                                          /* extend header */
       if (bmPos < hdrSiz + palSiz)
              goto err;
       br->hdr->infoSiz = bmPos - (hdrSiz + palSiz);
       if (br->hdr->nColors > 0 || br->hdr->infoSiz > 0) {
              br->hdr = (BMPHeader *)realloc((void *)br->hdr,
                                   sizeof(BMPHeader) +
                                   palSiz + br->hdr->infoSiz);
              if (br->hdr == NULL)
                     goto err;
       }
                                          /* read colors or fields */
       if (br->hdr->compr == BI_BITFIELDS) {
              BMPbitField(br->hdr)[0] = (uint32)rdint32(br);
              BMPbitField(br->hdr)[1] = (uint32)rdint32(br);
              BMPbitField(br->hdr)[2] = (uint32)rdint32(br);
       } else if (rdbytes((char *)br->hdr->palette, palSiz, br) != BIR_OK)
              goto err;
                                          /* read add'l information */
       if (rdbytes(BMPinfo(br->hdr), br->hdr->infoSiz, br) != BIR_OK)
              goto err;
                                          /* read first scanline */
       br->scanline = (uint8 *)calloc(getScanSiz(br->hdr), sizeof(uint8));
       if (br->scanline == NULL)
              goto err;
       br->yscan = -1;
       if (seek != NULL && ((br->hdr->compr == BI_RLE8) |
                                   (br->hdr->compr == BI_RLE4))) {
              BMPReader       *newbr = (BMPReader *)realloc((void *)br,
                                          sizeof(BMPReader) +
                                          sizeof(br->scanpos[0]) *
                                                 br->hdr->height);
              if (newbr == NULL)
                     goto err;
              br = newbr;
              memset((void *)(br->scanpos + 1), 0,
                            sizeof(br->scanpos[0])*br->hdr->height);
       }
       br->scanpos[0] = br->fpos;
       if (BMPreadScanline(br) == BIR_OK)
              return br;
err:
       if (br->hdr != NULL)
              free((void *)br->hdr);
       if (br->scanline != NULL)
              free((void *)br->scanline);
       free((void *)br);
       return NULL;
}

Here is the call graph for this function:

BMPWriter* BMPopenWriter ( void(*)(int, void *)  cput,
int(*)(uint32, void *)  seek,
void *  c_data,
BMPHeader hdr 
)

Definition at line 623 of file bmpfile.c.

{
       BMPWriter       *bw;
       uint32        hdrSiz, palSiz, scanSiz, bmSiz;
                                          /* check arguments */
       if (cput == NULL)
              return NULL;
       if (!BMPheaderOK(hdr))
              return NULL;
       if ((hdr->bpp == 16) | (hdr->compr == BI_RLE4))
              return NULL;                /* unsupported */
/* no seek means we may have the wrong file length, but most app's don't care
       if (seek == NULL && ((hdr->compr == BI_RLE8) | (hdr->compr == BI_RLE4)))
              return NULL;
*/
                                          /* compute sizes */
       hdrSiz = 2 + 6*4 + 2*2 + 6*4;
       if (hdr->compr == BI_BITFIELDS)
              hdrSiz += sizeof(uint32)*3;
       palSiz = sizeof(RGBquad)*hdr->nColors;
       scanSiz = getScanSiz(hdr);
       bmSiz = hdr->height*scanSiz;              /* wrong if compressed */
                                          /* initialize writer */
       bw = (BMPWriter *)malloc(sizeof(BMPWriter));
       if (bw == NULL)
              return NULL;
       bw->hdr = hdr;
       bw->yscan = 0;
       bw->scanline = (uint8 *)calloc(scanSiz, sizeof(uint8));
       if (bw->scanline == NULL) {
              free((void *)bw);
              return NULL;
       }
       bw->fbmp = hdrSiz + palSiz + hdr->infoSiz;
       bw->fpos = bw->flen = 0;
       bw->cput = cput;
       bw->seek = seek;
       bw->c_data = c_data;
                                          /* write out header */
       wrbyte('B', bw); wrbyte('M', bw);       /* magic number */
       wrint32(bw->fbmp + bmSiz, bw);            /* file size */
       wrint32(0, bw);                           /* reserved word */
       wrint32(bw->fbmp, bw);                    /* offset to bitmap */
       wrint32(hdrSiz - bw->fpos, bw);           /* info header size */
       wrint32(hdr->width, bw);           /* bitmap width */
       if (hdr->yIsDown)                  /* bitmap height */
              wrint32(-hdr->height, bw);
       else
              wrint32(hdr->height, bw);
       wruint16(1, bw);                   /* number of planes */
       wruint16(hdr->bpp, bw);                   /* bits per pixel */
       wrint32(hdr->compr, bw);           /* compression mode */
       wrint32(bmSiz, bw);                /* bitmap size */
       wrint32(hdr->hRes, bw);                   /* horizontal resolution */
       wrint32(hdr->vRes, bw);                   /* vertical resolution */
       wrint32(hdr->nColors, bw);         /* # colors used */
       wrint32(hdr->impColors, bw);              /* # important colors */
                                          /* write out color palette */
       wrbytes((char *)hdr->palette, palSiz, bw);
                                          /* write add'l information */
       wrbytes(BMPinfo(hdr), hdr->infoSiz, bw);
#ifndef NDEBUG
       if (bw->fpos != bw->fbmp) {
              fputs("Coding error 1 in BMPopenWriter\n", stderr);
              exit(1);
       }
#endif
       return bw;
}

Here is the call graph for this function:

int BMPreadScanline ( BMPReader br)

Definition at line 270 of file bmpfile.c.

{
       int     n;
       int8    *sp;

       if (br->yscan + 1 >= br->hdr->height)
              return BIR_EOF;
       br->yscan++;                /* prepare to read */
       n = getScanSiz(br->hdr);    /* reading uncompressed data? */
       if (br->hdr->compr == BI_UNCOMPR || br->hdr->compr == BI_BITFIELDS)
              return rdbytes((char *)br->scanline, n, br);
       /*
        * RLE4/RLE8 Decoding
        *
        * Certain aspects of this scheme are completely insane, so
        * we don't support them.  Fortunately, they rarely appear.
        * One is the mid-file EOD (0x0001) and another is the ill-conceived
        * "delta" (0x0002), which is like a "goto" statement for bitmaps.
        * Whoever thought this up should be wrestled to the ground and told
        * why it's impossible to support such a scheme in any reasonable way.
        * Also, RLE4 mode allows runs to stop halfway through a byte,
        * which is likewise uncodeable, so we don't even try.
        * Finally, the scanline break is ambiguous -- we assume here that
        * it is required at the end of each scanline, though I haven't
        * found anywhere this is written.  Otherwise, we would read to
        * the end of the scanline, assuming the next bit of data belongs
        * the following scan.  If a break follows the last pixel, as it
        * seems to in the files I've tested out of Photoshop, you end up
        * painting every other line black.  Also, I assume any skipped
        * pixels are painted with color 0, which is often black.  Nowhere
        * is it specified what we should assume for missing pixels.  This
        * is undoubtedly the most brain-dead format I've ever encountered.
        */
       sp = (int8 *)br->scanline;
       n = br->hdr->width;
       if (br->hdr->compr == BI_RLE4)
              n = (n + 1) >> 1;
       while (n > 0) {
              int     skipOdd, len, val;

              if (rdbyte(len, br) == EOF)
                     return BIR_TRUNCATED;
              if (len > 0) {              /* got a run */
                     if (br->hdr->compr == BI_RLE4) {
                            if (len & 1)
                                   return BIR_UNSUPPORTED;
                            len >>= 1;
                     }
                     if (len > n)
                            return BIR_RLERROR;
                     if (rdbyte(val, br) == EOF)
                            return BIR_TRUNCATED;
                     n -= len;
                     while (len--)
                            *sp++ = val;
                     continue;
              }
                                   /* check for escape */
              switch (rdbyte(len, br)) {
              case EOF:
                     return BIR_TRUNCATED;
              case 0:                     /* end of line */
                     while (n--)
                            *sp++ = 0;
                     /* leaves n == -1 as flag for test after loop */
                     continue;
              case 1:                     /* end of bitmap */
              case 2:                     /* delta */
                     return BIR_UNSUPPORTED;
              }
                                   /* absolute mode */
              if (br->hdr->compr == BI_RLE4) {
                     if (len & 1)
                            return BIR_UNSUPPORTED;
                     len >>= 1;
              }
              skipOdd = len & 1;
              if (len > n)
                     return BIR_RLERROR;
              n -= len;
              while (len--) {
                     if (rdbyte(val, br) == EOF)
                            return BIR_TRUNCATED;
                     *sp++ = val;
              }
              if (skipOdd && rdbyte(val, br) == EOF)
                     return BIR_TRUNCATED;
       }
                                   /* verify break at end of line */
       if (!n && (rdbyte(n, br) != 0 || (rdbyte(n, br) != 0 &&
                            (n != 1 || br->yscan != br->hdr->height-1))))
              return BIR_RLERROR;
       if (br->seek != NULL)              /* record next scanline position */
              br->scanpos[br->yscan + 1] = br->fpos;
       return BIR_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int BMPseekScanline ( int  y,
BMPReader br 
)

Definition at line 369 of file bmpfile.c.

{
       int     rv;
                                   /* check arguments */
       if (br == NULL)
              return BIR_EOF;
       if (y < 0)
              return BIR_SEEKERR;
       if (y >= br->hdr->height)
              return BIR_EOF;
                                   /* already read? */
       if (y == br->yscan)
              return BIR_OK;
                                   /* shall we seek? */
       if (y != br->yscan + 1 && br->seek != NULL) {
              int     yseek;
              uint32  seekp;
              if (br->hdr->compr == BI_UNCOMPR ||
                                   br->hdr->compr == BI_BITFIELDS) {
                     yseek = y;
                     seekp = br->scanpos[0] + y*getScanSiz(br->hdr);
              } else {
                     yseek = br->yscan + 1;
                     while (yseek < y && br->scanpos[yseek+1] != 0)
                            ++yseek;
                     if (y < yseek && br->scanpos[yseek=y] == 0)
                            return BIR_SEEKERR;
                     seekp = br->scanpos[yseek];
              }
              if ((rv = rdseek(seekp, br)) != BIR_OK)
                     return rv;
              br->yscan = yseek - 1;
       } else if (y < br->yscan)       /* else we can't back up */
              return BIR_SEEKERR;
                                   /* read until we get there */
       while (br->yscan < y)
              if ((rv = BMPreadScanline(br)) != BIR_OK)
                     return rv;
       return BIR_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

BMPHeader* BMPtruecolorHeader ( int  xr,
int  yr,
int  infolen 
)

Definition at line 513 of file bmpfile.c.

{
       BMPHeader       *hdr;
       
       if (xr <= 0 || yr <= 0 || infolen < 0)
              return NULL;
       hdr = (BMPHeader *)malloc(sizeof(BMPHeader) - sizeof(hdr->palette) +
                                   infolen);
       if (hdr == NULL)
              return NULL;
       hdr->width = xr;
       hdr->height = yr;
       hdr->yIsDown = 0;                  /* default to upwards order */
       hdr->bpp = 24;
       hdr->compr = BI_UNCOMPR;
       hdr->hRes = hdr->vRes = 2835;             /* default to 72 ppi */
       hdr->nColors = hdr->impColors = 0;
       hdr->infoSiz = infolen;
       return hdr;
}

Here is the caller graph for this function:

int BMPwriteScanline ( BMPWriter bw)

Definition at line 713 of file bmpfile.c.

{
       const int8      *sp;
       int           n;

       if (bw->yscan >= bw->hdr->height)
              return BIR_EOF;
                                          /* writing uncompressed? */
       if (bw->hdr->compr == BI_UNCOMPR || bw->hdr->compr == BI_BITFIELDS) {
              uint32  scanSiz = getScanSiz(bw->hdr);
              uint32  slpos = bw->fbmp + bw->yscan*scanSiz;
              if (wrseek(slpos, bw) != BIR_OK)
                     return BIR_SEEKERR;
              wrbytes((char *)bw->scanline, scanSiz, bw);
              bw->yscan++;
              return BIR_OK;
       }
       /*
        * RLE8 Encoding
        *
        * See the notes in BMPreadScanline() on this encoding.  Needless
        * to say, we avoid the nuttier aspects of this specification.
        * We also assume that every scanline ends in a line break
        * (0x0000) except for the last, which ends in a bitmap break
        * (0x0001).  We don't support RLE4 at all; it's too awkward.
        */
       sp = (const int8 *)bw->scanline;
       n = bw->hdr->width;
       while (n > 0) {
              int     cnt, val;
              cnt = findNextRun(sp, n);       /* 0-255 < n */
              if (cnt >= 3) {                    /* output absolute */
                     int     skipOdd = cnt & 1;
                     wrbyte(0, bw);
                     wrbyte(cnt, bw);
                     n -= cnt;
                     while (cnt--)
                            wrbyte(*sp++, bw);
                     if (skipOdd)
                            wrbyte(0, bw);
              }
              if (n <= 0)                 /* was that it? */
                     break;
              val = *sp;                  /* output run */
              for (cnt = 1; --n && cnt < 255; cnt++)
                     if (*++sp != val)
                            break;
              wrbyte(cnt, bw);
              wrbyte(val, bw);
       }
       bw->yscan++;                       /* write line break or EOD */
       if (bw->yscan == bw->hdr->height) {
              wrbyte(0, bw); wrbyte(1, bw);   /* end of bitmap marker */
              if (wrseek(2, bw) != BIR_OK)
                     return BIR_OK;              /* no one may care */
              wrint32(bw->flen, bw);             /* correct file length */
              if (wrseek(34, bw) != BIR_OK)
                     return BIR_OK;
              wrint32(bw->flen-bw->fbmp, bw); /* correct bitmap length */
       } else {
              wrbyte(0, bw); wrbyte(0, bw);   /* end of line marker */
       }
       return BIR_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int findNextRun ( const int8 *  bp,
int  len 
) [static]

Definition at line 696 of file bmpfile.c.

{
       int     pos, cnt;
                                          /* look for run */
       for (pos = 0; (len > 0) & (pos < 255); pos++, bp++, len--) {
              if (len < 5)                /* no hope left? */
                     continue;
              cnt = 1;                    /* else let's try it */
              while (bp[cnt] == bp[0])
                     if (++cnt >= 5)
                            return pos;     /* long enough */
       }
       return pos;                        /* didn't find any */
}

Here is the caller graph for this function:

static int rdbytes ( char *  bp,
uint32  n,
BMPReader br 
) [static]

Definition at line 94 of file bmpfile.c.

{
       int     c;

       while (n--) {
              if (rdbyte(c, br) == EOF)
                     return BIR_TRUNCATED;
              *bp++ = c;
       }
       return BIR_OK;
}

Here is the caller graph for this function:

static int32 rdint32 ( BMPReader br) [static]

Definition at line 108 of file bmpfile.c.

{
       int32   i;
       int     c;

       i = rdbyte(c, br);
       i |= rdbyte(c, br) << 8;
       i |= rdbyte(c, br) << 16;
       i |= rdbyte(c, br) << 24;
       return i;                   /* -1 on EOF */
}

Here is the caller graph for this function:

static int rdseek ( uint32  pos,
BMPReader br 
) [static]

Definition at line 134 of file bmpfile.c.

{
       if (pos == br->fpos)
              return BIR_OK;
       if (br->seek == NULL || (*br->seek)(pos, br->c_data) != 0)
              return BIR_SEEKERR;
       br->fpos = pos;
       return BIR_OK;
}

Here is the caller graph for this function:

static int rduint16 ( BMPReader br) [static]

Definition at line 122 of file bmpfile.c.

{
       int     i;
       int     c;
       
       i = rdbyte(c, br);
       i |= rdbyte(c, br) << 8;
       return i;                   /* -1 on EOF */
}

Here is the caller graph for this function:

int stdio_fseek ( uint32  pos,
void *  p 
)

Definition at line 504 of file bmpfile.c.

{
       if (!p)
              return -1;
       return fseek((FILE *)p, (long)pos, 0);
}
int stdio_getc ( void *  p)

Definition at line 487 of file bmpfile.c.

{
       if (!p)
              return EOF;
       return getc((FILE *)p);
}
void stdio_putc ( int  c,
void *  p 
)

Definition at line 496 of file bmpfile.c.

{
       if (p)
              putc(c, (FILE *)p);
}
static void wrbytes ( char *  bp,
uint32  n,
BMPWriter bw 
) [static]

Definition at line 581 of file bmpfile.c.

{
       while (n--)
              wrbyte(*bp++, bw);
}

Here is the caller graph for this function:

static void wrint32 ( int32  i,
BMPWriter bw 
) [static]

Definition at line 589 of file bmpfile.c.

{
       wrbyte(i& 0xff, bw);
       wrbyte(i>>8 & 0xff, bw);
       wrbyte(i>>16 & 0xff, bw);
       wrbyte(i>>24 & 0xff, bw);
}

Here is the caller graph for this function:

static int wrseek ( uint32  pos,
BMPWriter bw 
) [static]

Definition at line 607 of file bmpfile.c.

{
       if (pos == bw->fpos)
              return BIR_OK;
       if (bw->seek == NULL)
              return BIR_SEEKERR;
       if ((*bw->seek)(pos, bw->c_data) != 0)
              return BIR_SEEKERR;
       bw->fpos = pos;
       if (pos > bw->flen)
              bw->flen = pos;
       return BIR_OK;
}

Here is the caller graph for this function:

static void wruint16 ( uint16  ui,
BMPWriter bw 
) [static]

Definition at line 599 of file bmpfile.c.

{
       wrbyte(ui & 0xff, bw);
       wrbyte(ui>>8 & 0xff, bw);
}

Here is the caller graph for this function:


Variable Documentation

const char RCSid[] = "$Id: bmpfile.c,v 2.15 2005/05/10 01:08:43 greg Exp $" [static]

Definition at line 2 of file bmpfile.c.