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.3 by greg, Fri Mar 26 22:58:21 2004 UTC vs.
Revision 2.10 by greg, Fri Apr 30 17:00:29 2004 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 + #define getc    getc_unlocked
15 + #define putc    putc_unlocked
16 + #endif
17 +
18   /* get corresponding error message */
19   const char *
20   BMPerrorMessage(int ec)
# Line 37 | Line 42 | BMPheaderOK(const BMPHeader *hdr)
42   {
43          if (!hdr)
44                  return 0;
45 <        if ((hdr->width <= 0 | hdr->height <= 0))
45 >        if ((hdr->width <= 0) | (hdr->height <= 0))
46                  return 0;
47          switch (hdr->bpp) {             /* check compression */
48          case 1:
# Line 47 | Line 52 | BMPheaderOK(const BMPHeader *hdr)
52                  break;
53          case 16:
54          case 32:
55 <                if ((hdr->compr != BI_UNCOMPR & hdr->compr != BI_BITFIELDS))
55 >                if ((hdr->compr != BI_UNCOMPR) & (hdr->compr != BI_BITFIELDS))
56                          return 0;
57                  break;
58          case 4:
59 <                if ((hdr->compr != BI_UNCOMPR & hdr->compr != BI_RLE4))
59 >                if ((hdr->compr != BI_UNCOMPR) & (hdr->compr != BI_RLE4))
60                          return 0;
61                  break;
62          case 8:
63 <                if ((hdr->compr != BI_UNCOMPR & hdr->compr != BI_RLE8))
63 >                if ((hdr->compr != BI_UNCOMPR) & (hdr->compr != BI_RLE8))
64                          return 0;
65                  break;
66          default:
# Line 64 | Line 69 | BMPheaderOK(const BMPHeader *hdr)
69          if (hdr->compr == BI_BITFIELDS && (BMPbitField(hdr)[0] &
70                                  BMPbitField(hdr)[1] & BMPbitField(hdr)[2]))
71                  return 0;
72 <        if ((hdr->nColors < 0 | hdr->impColors < 0))
72 >        if ((hdr->nColors < 0) | (hdr->impColors < 0))
73                  return 0;
74          if (hdr->impColors > hdr->nColors)
75                  return 0;
# Line 74 | Line 79 | BMPheaderOK(const BMPHeader *hdr)
79   }
80  
81                                          /* compute uncompressed scan size */
82 < #define getScanSiz(h)   ( (((h)->bpp*(h)->width+7 >>3) + 3) & ~03 )
82 > #define getScanSiz(h)   ( ((((h)->bpp*(h)->width+7) >>3) + 3) & ~03 )
83  
84                                          /* get next byte from reader */
85   #define rdbyte(c,br)    ((br)->fpos += (c=(*(br)->cget)((br)->c_data))!=EOF, c)
# Line 219 | Line 224 | BMPopenReader(int (*cget)(void *), int (*seek)(uint32,
224          if (br->scanline == NULL)
225                  goto err;
226          br->yscan = -1;
227 <        if (seek != NULL && (br->hdr->compr == BI_RLE8 |
228 <                                        br->hdr->compr == BI_RLE4)) {
227 >        if (seek != NULL && ((br->hdr->compr == BI_RLE8) |
228 >                                        (br->hdr->compr == BI_RLE4))) {
229                  BMPReader       *newbr = (BMPReader *)realloc((void *)br,
230                                                  sizeof(BMPReader) +
231                                                  sizeof(br->scanpos[0]) *
# 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 255 | Line 259 | BMPisGrayscale(const BMPHeader *hdr)
259                  return -1;
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++)
262 >        for (rgbp = hdr->palette, n = hdr->nColors; n-- > 0; rgbp++)
263                  if (((rgbp->r != rgbp->g) | (rgbp->g != rgbp->b)))
264                          return 0;
265          return 1;                       /* all colors neutral in map */
# 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;
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 444 | Line 453 | BMPdecodePixel(int i, const BMPReader *br)
453          case 8:
454                  return br->hdr->palette[br->scanline[i]];
455          case 1:
456 <                return br->hdr->palette[br->scanline[i>>3]>>(7-i&7) & 1];
456 >                return br->hdr->palette[br->scanline[i>>3]>>((7-i)&7) & 1];
457          case 4:
458                  return br->hdr->palette[br->scanline[i>>1]>>(i&1?4:0) & 0xf];
459          case 16:
# Line 522 | Line 531 | BMPtruecolorHeader(int xr, int yr, int infolen)
531          return hdr;
532   }
533  
534 < /* allocate color-mapped header (defaults minimal grayscale) */
534 > /* allocate color-mapped header (defaults to minimal grayscale) */
535   BMPHeader *
536   BMPmappedHeader(int xr, int yr, int infolen, int ncolors)
537   {
# Line 549 | Line 558 | BMPmappedHeader(int xr, int yr, int infolen, int ncolo
558          hdr->height = yr;
559          hdr->yIsDown = 0;                       /* default to upwards order */
560          hdr->bpp = n;
561 <        hdr->compr = BI_UNCOMPR;
561 >        hdr->compr = BI_UNCOMPR;                /* compression needs seek */
562          hdr->hRes = hdr->vRes = 2835;           /* default to 72 ppi */
563          hdr->nColors = ncolors;
564          hdr->impColors = 0;                     /* says all colors important */
# 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 626 | Line 630 | BMPopenWriter(void (*cput)(int, void *), int (*seek)(u
630                  return NULL;
631          if (!BMPheaderOK(hdr))
632                  return NULL;
633 <        if ((hdr->bpp == 16 | hdr->compr == BI_RLE4))
633 >        if ((hdr->bpp == 16) | (hdr->compr == BI_RLE4))
634                  return NULL;                    /* unsupported */
635 <        if (seek == NULL && (hdr->compr == BI_RLE8 | hdr->compr == BI_RLE4))
635 > /* no seek means we may have the wrong file length, but most app's don't care
636 >        if (seek == NULL && ((hdr->compr == BI_RLE8) | (hdr->compr == BI_RLE4)))
637                  return NULL;
638 + */
639                                                  /* compute sizes */
640          hdrSiz = 2 + 6*4 + 2*2 + 6*4;
641          if (hdr->compr == BI_BITFIELDS)
# Line 691 | Line 697 | findNextRun(const int8 *bp, int len)
697   {
698          int     pos, cnt;
699                                                  /* look for run */
700 <        for (pos = 0; len > 0 & pos < 255; pos++, bp++, len--) {
700 >        for (pos = 0; (len > 0) & (pos < 255); pos++, bp++, len--) {
701                  if (len < 5)                    /* no hope left? */
702                          continue;
703                  cnt = 1;                        /* else let's try it */
704                  while (bp[cnt] == bp[0])
705 <                        if (++cnt >= 5)         /* long enough */
706 <                                return pos;
705 >                        if (++cnt >= 5)
706 >                                return pos;     /* long enough */
707          }
708          return pos;                             /* didn't find any */
709   }
# Line 734 | Line 740 | BMPwriteScanline(BMPWriter *bw)
740          n = bw->hdr->width;
741          while (n > 0) {
742                  int     cnt, val;
737
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 749 | Line 754 | BMPwriteScanline(BMPWriter *bw)
754                  if (n <= 0)                     /* was that it? */
755                          break;
756                  val = *sp;                      /* output run */
757 <                for (cnt = 1; --n > 0 & *++sp == val; cnt++)
758 <                        ;
757 >                for (cnt = 1; --n && cnt < 255; cnt++)
758 >                        if (*++sp != val)
759 >                                break;
760                  wrbyte(cnt, bw);
761                  wrbyte(val, bw);
762          }
763 <        bw->yscan++;                            /* write file length at end */
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)
767 <                        return BIR_SEEKERR;
768 <                bw->fpos = 2;
769 <                wrint32(bw->flen, bw);          /* corrected file length */
766 >                if (wrseek(2, bw) != BIR_OK)
767 >                        return BIR_OK;          /* no one may care */
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