ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/bmpfile.c
(Generate patch)

Comparing ray/src/common/bmpfile.c (file contents):
Revision 2.5 by greg, Sat Mar 27 05:43:37 2004 UTC vs.
Revision 2.15 by greg, Tue May 10 01:08:43 2005 UTC

# Line 10 | Line 10 | static const char RCSid[] = "$Id$";
10   #include <string.h>
11   #include "bmpfile.h"
12  
13 + #ifdef getc_unlocked            /* avoid horrendous overhead of flockfile */
14 + #undef getc
15 + #undef putc
16 + #define getc    getc_unlocked
17 + #define putc    putc_unlocked
18 + #endif
19 +
20   /* get corresponding error message */
21   const char *
22   BMPerrorMessage(int ec)
# Line 64 | Line 71 | BMPheaderOK(const BMPHeader *hdr)
71          if (hdr->compr == BI_BITFIELDS && (BMPbitField(hdr)[0] &
72                                  BMPbitField(hdr)[1] & BMPbitField(hdr)[2]))
73                  return 0;
74 <        if ((hdr->nColors < 0) | (hdr->impColors < 0))
75 <                return 0;
76 <        if (hdr->impColors > hdr->nColors)
77 <                return 0;
78 <        if (hdr->nColors > BMPpalLen(hdr))
79 <                return 0;
74 >        if (hdr->bpp > 8) {
75 >                if (hdr->nColors != 0)
76 >                        return 0;
77 >        } else {
78 >                if ((hdr->nColors < 0) | (hdr->nColors > 1<<hdr->bpp))
79 >                        return 0;
80 >                if ((hdr->impColors < 0) | (hdr->impColors > hdr->nColors))
81 >                        return 0;
82 >        }
83          return 1;
84   }
85  
# Line 136 | Line 146 | BMPReader *
146   BMPopenReader(int (*cget)(void *), int (*seek)(uint32, void *), void *c_data)
147   {
148          BMPReader       *br;
149 <        uint32          bmPos, hdrSiz;
150 <        int             palLen;
149 >        uint32          bmPos, hdrSiz, palSiz;
150 >        int             magic[2];               /* check magic number */
151  
152          if (cget == NULL)
153                  return NULL;
144        int     magic[2];               /* check magic number */
154          magic[0] = (*cget)(c_data);
155          if (magic[0] != 'B')
156                  return NULL;
# Line 179 | Line 188 | BMPopenReader(int (*cget)(void *), int (*seek)(uint32,
188          br->hdr->hRes = rdint32(br);            /* horizontal resolution */
189          br->hdr->vRes = rdint32(br);            /* vertical resolution */
190          br->hdr->nColors = rdint32(br);         /* # colors used */
191 +        if (!br->hdr->nColors && br->hdr->bpp <= 8)
192 +                br->hdr->nColors = 1<<br->hdr->bpp;
193          br->hdr->impColors = rdint32(br);       /* # important colors */
194          if (br->hdr->impColors < 0)
195                  goto err;                       /* catch premature EOF */
196          if (!BMPheaderOK(br->hdr))
197                  goto err;
198 <        palLen = BMPpalLen(br->hdr);
199 <        if (br->hdr->bpp <= 8) {                /* normalize color counts */
200 <                if (br->hdr->nColors <= 0)
190 <                        br->hdr->nColors = palLen;
191 <                if (br->hdr->impColors <= 0)
192 <                        br->hdr->impColors = br->hdr->nColors;
193 <        }
198 >        palSiz = sizeof(RGBquad)*br->hdr->nColors;
199 >        if (br->hdr->impColors <= 0)
200 >                br->hdr->impColors = br->hdr->nColors;
201                                                  /* extend header */
202 <        if (bmPos < hdrSiz + sizeof(RGBquad)*palLen)
202 >        if (bmPos < hdrSiz + palSiz)
203                  goto err;
204 <        br->hdr->infoSiz = bmPos - (hdrSiz + sizeof(RGBquad)*palLen);
205 <        if (palLen > 0 || br->hdr->infoSiz > 0) {
204 >        br->hdr->infoSiz = bmPos - (hdrSiz + palSiz);
205 >        if (br->hdr->nColors > 0 || br->hdr->infoSiz > 0) {
206                  br->hdr = (BMPHeader *)realloc((void *)br->hdr,
207                                          sizeof(BMPHeader) +
208 <                                        sizeof(RGBquad)*palLen +
202 <                                        br->hdr->infoSiz);
208 >                                        palSiz + br->hdr->infoSiz);
209                  if (br->hdr == NULL)
210                          goto err;
211          }
# Line 208 | Line 214 | BMPopenReader(int (*cget)(void *), int (*seek)(uint32,
214                  BMPbitField(br->hdr)[0] = (uint32)rdint32(br);
215                  BMPbitField(br->hdr)[1] = (uint32)rdint32(br);
216                  BMPbitField(br->hdr)[2] = (uint32)rdint32(br);
217 <        } else if (rdbytes((char *)br->hdr->palette,
212 <                        sizeof(RGBquad)*palLen, br) != BIR_OK)
217 >        } else if (rdbytes((char *)br->hdr->palette, palSiz, br) != BIR_OK)
218                  goto err;
219                                                  /* read add'l information */
220          if (rdbytes(BMPinfo(br->hdr), br->hdr->infoSiz, br) != BIR_OK)
# Line 232 | Line 237 | BMPopenReader(int (*cget)(void *), int (*seek)(uint32,
237                                  sizeof(br->scanpos[0])*br->hdr->height);
238          }
239          br->scanpos[0] = br->fpos;
240 <        if (BMPreadScanline(br) != BIR_OK)
241 <                goto err;
237 <        return br;
240 >        if (BMPreadScanline(br) == BIR_OK)
241 >                return br;
242   err:
243          if (br->hdr != NULL)
244                  free((void *)br->hdr);
# Line 256 | Line 260 | BMPisGrayscale(const BMPHeader *hdr)
260          if (hdr->bpp > 8)               /* assume they had a reason for it */
261                  return 0;
262          for (rgbp = hdr->palette, n = hdr->impColors; n-- > 0; rgbp++)
263 <                if (((rgbp->r != rgbp->g) | (rgbp->g != rgbp->b)))
263 >                if ((rgbp->r != rgbp->g) | (rgbp->g != rgbp->b))
264                          return 0;
265          return 1;                       /* all colors neutral in map */
266   }
# Line 275 | Line 279 | BMPreadScanline(BMPReader *br)
279          if (br->hdr->compr == BI_UNCOMPR || br->hdr->compr == BI_BITFIELDS)
280                  return rdbytes((char *)br->scanline, n, br);
281          /*
282 <         * RLE/RLE8 Decoding
282 >         * RLE4/RLE8 Decoding
283           *
284           * Certain aspects of this scheme are completely insane, so
285           * we don't support them.  Fortunately, they rarely appear.
286 <         * One is the mid-file EOD (0x0001) and another is the insane
286 >         * One is the mid-file EOD (0x0001) and another is the ill-conceived
287           * "delta" (0x0002), which is like a "goto" statement for bitmaps.
288 <         * Whoever thought this up should be shot, then told why
289 <         * it's impossible to support in any reasonable way.
288 >         * Whoever thought this up should be wrestled to the ground and told
289 >         * why it's impossible to support such a scheme in any reasonable way.
290           * Also, RLE4 mode allows runs to stop halfway through a byte,
291           * which is likewise uncodeable, so we don't even try.
292           * Finally, the scanline break is ambiguous -- we assume here that
# Line 291 | Line 295 | BMPreadScanline(BMPReader *br)
295           * the end of the scanline, assuming the next bit of data belongs
296           * the following scan.  If a break follows the last pixel, as it
297           * seems to in the files I've tested out of Photoshop, you end up
298 <         * painting every other line black.  BTW, I assume any skipped
298 >         * painting every other line black.  Also, I assume any skipped
299           * pixels are painted with color 0, which is often black.  Nowhere
300           * is it specified what we should assume for missing pixels.  This
301           * is undoubtedly the most brain-dead format I've ever encountered.
302           */
303 <        sp = br->scanline;
303 >        sp = (int8 *)br->scanline;
304 >        n = br->hdr->width;
305 >        if (br->hdr->compr == BI_RLE4)
306 >                n = (n + 1) >> 1;
307          while (n > 0) {
308                  int     skipOdd, len, val;
309  
# Line 317 | Line 324 | BMPreadScanline(BMPReader *br)
324                                  *sp++ = val;
325                          continue;
326                  }
327 +                                        /* check for escape */
328                  switch (rdbyte(len, br)) {
329                  case EOF:
330                          return BIR_TRUNCATED;
331                  case 0:                 /* end of line */
332                          while (n--)
333                                  *sp++ = 0;
334 +                        /* leaves n == -1 as flag for test after loop */
335                          continue;
336                  case 1:                 /* end of bitmap */
337                  case 2:                 /* delta */
# Line 347 | Line 356 | BMPreadScanline(BMPReader *br)
356                          return BIR_TRUNCATED;
357          }
358                                          /* verify break at end of line */
359 <        if (rdbyte(n, br) != 0 || (rdbyte(n, br) != 0 &&
360 <                                (n != 1 || br->yscan != br->hdr->height-1)))
359 >        if (!n && (rdbyte(n, br) != 0 || (rdbyte(n, br) != 0 &&
360 >                                (n != 1 || br->yscan != br->hdr->height-1))))
361                  return BIR_RLERROR;
362          if (br->seek != NULL)           /* record next scanline position */
363                  br->scanpos[br->yscan + 1] = br->fpos;
# Line 599 | Line 608 | wrseek(uint32 pos, BMPWriter *bw)
608   {
609          if (pos == bw->fpos)
610                  return BIR_OK;
611 <        if (bw->seek == NULL) {
612 <                if (pos < bw->fpos)
604 <                        return BIR_SEEKERR;
605 <                while (bw->fpos < pos)
606 <                        wrbyte(0, bw);
607 <                return BIR_OK;
608 <        }
611 >        if (bw->seek == NULL)
612 >                return BIR_SEEKERR;
613          if ((*bw->seek)(pos, bw->c_data) != 0)
614                  return BIR_SEEKERR;
615          bw->fpos = pos;
# Line 636 | Line 640 | BMPopenWriter(void (*cput)(int, void *), int (*seek)(u
640          hdrSiz = 2 + 6*4 + 2*2 + 6*4;
641          if (hdr->compr == BI_BITFIELDS)
642                  hdrSiz += sizeof(uint32)*3;
643 <        palSiz = sizeof(RGBquad)*BMPpalLen(hdr);
643 >        palSiz = sizeof(RGBquad)*hdr->nColors;
644          scanSiz = getScanSiz(hdr);
645          bmSiz = hdr->height*scanSiz;            /* wrong if compressed */
646                                                  /* initialize writer */
# Line 732 | Line 736 | BMPwriteScanline(BMPWriter *bw)
736           * (0x0000) except for the last, which ends in a bitmap break
737           * (0x0001).  We don't support RLE4 at all; it's too awkward.
738           */
739 <        sp = bw->scanline;
739 >        sp = (const int8 *)bw->scanline;
740          n = bw->hdr->width;
741          while (n > 0) {
742                  int     cnt, val;
739
743                  cnt = findNextRun(sp, n);       /* 0-255 < n */
744 <                if (cnt >= 3) {                 /* output non-run */
744 >                if (cnt >= 3) {                 /* output absolute */
745                          int     skipOdd = cnt & 1;
746                          wrbyte(0, bw);
747                          wrbyte(cnt, bw);
# Line 751 | Line 754 | BMPwriteScanline(BMPWriter *bw)
754                  if (n <= 0)                     /* was that it? */
755                          break;
756                  val = *sp;                      /* output run */
757 <                for (cnt = 1; cnt < 255; cnt++)
758 <                        if (!--n | *++sp != val)
757 >                for (cnt = 1; --n && cnt < 255; cnt++)
758 >                        if (*++sp != val)
759                                  break;
760                  wrbyte(cnt, bw);
761                  wrbyte(val, bw);
# Line 760 | Line 763 | BMPwriteScanline(BMPWriter *bw)
763          bw->yscan++;                            /* write line break or EOD */
764          if (bw->yscan == bw->hdr->height) {
765                  wrbyte(0, bw); wrbyte(1, bw);   /* end of bitmap marker */
766 <                if (bw->seek == NULL || (*bw->seek)(2, bw->c_data) != 0)
766 >                if (wrseek(2, bw) != BIR_OK)
767                          return BIR_OK;          /* no one may care */
768 <                bw->fpos = 2;
769 <                wrint32(bw->flen-bw->fbmp, bw); /* output correct bitmap length */
768 >                wrint32(bw->flen, bw);          /* correct file length */
769 >                if (wrseek(34, bw) != BIR_OK)
770 >                        return BIR_OK;
771 >                wrint32(bw->flen-bw->fbmp, bw); /* correct bitmap length */
772          } else {
773                  wrbyte(0, bw); wrbyte(0, bw);   /* end of line marker */
774          }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines