/src/freeimage-svn/FreeImage/trunk/Source/LibTIFF4/tif_next.c
Line  | Count  | Source  | 
1  |  | /*  | 
2  |  |  * Copyright (c) 1988-1997 Sam Leffler  | 
3  |  |  * Copyright (c) 1991-1997 Silicon Graphics, Inc.  | 
4  |  |  *  | 
5  |  |  * Permission to use, copy, modify, distribute, and sell this software and  | 
6  |  |  * its documentation for any purpose is hereby granted without fee, provided  | 
7  |  |  * that (i) the above copyright notices and this permission notice appear in  | 
8  |  |  * all copies of the software and related documentation, and (ii) the names of  | 
9  |  |  * Sam Leffler and Silicon Graphics may not be used in any advertising or  | 
10  |  |  * publicity relating to the software without the specific, prior written  | 
11  |  |  * permission of Sam Leffler and Silicon Graphics.  | 
12  |  |  *  | 
13  |  |  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,  | 
14  |  |  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY  | 
15  |  |  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  | 
16  |  |  *  | 
17  |  |  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR  | 
18  |  |  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,  | 
19  |  |  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,  | 
20  |  |  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF  | 
21  |  |  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE  | 
22  |  |  * OF THIS SOFTWARE.  | 
23  |  |  */  | 
24  |  |  | 
25  |  | #include "tiffiop.h"  | 
26  |  | #ifdef NEXT_SUPPORT  | 
27  |  | /*  | 
28  |  |  * TIFF Library.  | 
29  |  |  *  | 
30  |  |  * NeXT 2-bit Grey Scale Compression Algorithm Support  | 
31  |  |  */  | 
32  |  |  | 
33  |  | #define SETPIXEL(op, v)                                                        \  | 
34  | 0  |     {                                                                          \ | 
35  | 0  |         switch (npixels++ & 3)                                                 \  | 
36  | 0  |         {                                                                      \ | 
37  | 0  |             case 0:                                                            \  | 
38  | 0  |                 op[0] = (unsigned char)((v) << 6);                             \  | 
39  | 0  |                 break;                                                         \  | 
40  | 0  |             case 1:                                                            \  | 
41  | 0  |                 op[0] |= (v) << 4;                                             \  | 
42  | 0  |                 break;                                                         \  | 
43  | 0  |             case 2:                                                            \  | 
44  | 0  |                 op[0] |= (v) << 2;                                             \  | 
45  | 0  |                 break;                                                         \  | 
46  | 0  |             case 3:                                                            \  | 
47  | 0  |                 *op++ |= (v);                                                  \  | 
48  | 0  |                 op_offset++;                                                   \  | 
49  | 0  |                 break;                                                         \  | 
50  | 0  |         }                                                                      \  | 
51  | 0  |     }  | 
52  |  |  | 
53  | 0  | #define LITERALROW 0x00  | 
54  | 0  | #define LITERALSPAN 0x40  | 
55  |  | #define WHITE ((1 << 2) - 1)  | 
56  |  |  | 
57  |  | static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)  | 
58  | 0  | { | 
59  | 0  |     static const char module[] = "NeXTDecode";  | 
60  | 0  |     unsigned char *bp, *op;  | 
61  | 0  |     tmsize_t cc;  | 
62  | 0  |     uint8_t *row;  | 
63  | 0  |     tmsize_t scanline, n;  | 
64  |  | 
  | 
65  | 0  |     (void)s;  | 
66  |  |     /*  | 
67  |  |      * Each scanline is assumed to start off as all  | 
68  |  |      * white (we assume a PhotometricInterpretation  | 
69  |  |      * of ``min-is-black'').  | 
70  |  |      */  | 
71  | 0  |     for (op = (unsigned char *)buf, cc = occ; cc-- > 0;)  | 
72  | 0  |         *op++ = 0xff;  | 
73  |  | 
  | 
74  | 0  |     bp = (unsigned char *)tif->tif_rawcp;  | 
75  | 0  |     cc = tif->tif_rawcc;  | 
76  | 0  |     scanline = tif->tif_scanlinesize;  | 
77  | 0  |     if (occ % scanline)  | 
78  | 0  |     { | 
79  | 0  |         TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");  | 
80  | 0  |         return (0);  | 
81  | 0  |     }  | 
82  | 0  |     for (row = buf; cc > 0 && occ > 0; occ -= scanline, row += scanline)  | 
83  | 0  |     { | 
84  | 0  |         n = *bp++;  | 
85  | 0  |         cc--;  | 
86  | 0  |         switch (n)  | 
87  | 0  |         { | 
88  | 0  |             case LITERALROW:  | 
89  |  |                 /*  | 
90  |  |                  * The entire scanline is given as literal values.  | 
91  |  |                  */  | 
92  | 0  |                 if (cc < scanline)  | 
93  | 0  |                     goto bad;  | 
94  | 0  |                 _TIFFmemcpy(row, bp, scanline);  | 
95  | 0  |                 bp += scanline;  | 
96  | 0  |                 cc -= scanline;  | 
97  | 0  |                 break;  | 
98  | 0  |             case LITERALSPAN:  | 
99  | 0  |             { | 
100  | 0  |                 tmsize_t off;  | 
101  |  |                 /*  | 
102  |  |                  * The scanline has a literal span that begins at some  | 
103  |  |                  * offset.  | 
104  |  |                  */  | 
105  | 0  |                 if (cc < 4)  | 
106  | 0  |                     goto bad;  | 
107  | 0  |                 off = (bp[0] * 256) + bp[1];  | 
108  | 0  |                 n = (bp[2] * 256) + bp[3];  | 
109  | 0  |                 if (cc < 4 + n || off + n > scanline)  | 
110  | 0  |                     goto bad;  | 
111  | 0  |                 _TIFFmemcpy(row + off, bp + 4, n);  | 
112  | 0  |                 bp += 4 + n;  | 
113  | 0  |                 cc -= 4 + n;  | 
114  | 0  |                 break;  | 
115  | 0  |             }  | 
116  | 0  |             default:  | 
117  | 0  |             { | 
118  | 0  |                 uint32_t npixels = 0, grey;  | 
119  | 0  |                 tmsize_t op_offset = 0;  | 
120  | 0  |                 uint32_t imagewidth = tif->tif_dir.td_imagewidth;  | 
121  | 0  |                 if (isTiled(tif))  | 
122  | 0  |                     imagewidth = tif->tif_dir.td_tilewidth;  | 
123  |  |  | 
124  |  |                 /*  | 
125  |  |                  * The scanline is composed of a sequence of constant  | 
126  |  |                  * color ``runs''.  We shift into ``run mode'' and  | 
127  |  |                  * interpret bytes as codes of the form  | 
128  |  |                  * <color><npixels> until we've filled the scanline.  | 
129  |  |                  */  | 
130  | 0  |                 op = row;  | 
131  | 0  |                 for (;;)  | 
132  | 0  |                 { | 
133  | 0  |                     grey = (uint32_t)((n >> 6) & 0x3);  | 
134  | 0  |                     n &= 0x3f;  | 
135  |  |                     /*  | 
136  |  |                      * Ensure the run does not exceed the scanline  | 
137  |  |                      * bounds, potentially resulting in a security  | 
138  |  |                      * issue.  | 
139  |  |                      */  | 
140  | 0  |                     while (n-- > 0 && npixels < imagewidth &&  | 
141  | 0  |                            op_offset < scanline)  | 
142  | 0  |                         SETPIXEL(op, grey);  | 
143  | 0  |                     if (npixels >= imagewidth)  | 
144  | 0  |                         break;  | 
145  | 0  |                     if (op_offset >= scanline)  | 
146  | 0  |                     { | 
147  | 0  |                         TIFFErrorExtR(tif, module,  | 
148  | 0  |                                       "Invalid data for scanline %" PRIu32,  | 
149  | 0  |                                       tif->tif_row);  | 
150  | 0  |                         return (0);  | 
151  | 0  |                     }  | 
152  | 0  |                     if (cc == 0)  | 
153  | 0  |                         goto bad;  | 
154  | 0  |                     n = *bp++;  | 
155  | 0  |                     cc--;  | 
156  | 0  |                 }  | 
157  | 0  |                 break;  | 
158  | 0  |             }  | 
159  | 0  |         }  | 
160  | 0  |     }  | 
161  | 0  |     tif->tif_rawcp = (uint8_t *)bp;  | 
162  | 0  |     tif->tif_rawcc = cc;  | 
163  | 0  |     return (1);  | 
164  | 0  | bad:  | 
165  | 0  |     TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,  | 
166  | 0  |                   tif->tif_row);  | 
167  | 0  |     return (0);  | 
168  | 0  | }  | 
169  |  |  | 
170  |  | static int NeXTPreDecode(TIFF *tif, uint16_t s)  | 
171  | 0  | { | 
172  | 0  |     static const char module[] = "NeXTPreDecode";  | 
173  | 0  |     TIFFDirectory *td = &tif->tif_dir;  | 
174  | 0  |     (void)s;  | 
175  |  | 
  | 
176  | 0  |     if (td->td_bitspersample != 2)  | 
177  | 0  |     { | 
178  | 0  |         TIFFErrorExtR(tif, module, "Unsupported BitsPerSample = %" PRIu16,  | 
179  | 0  |                       td->td_bitspersample);  | 
180  | 0  |         return (0);  | 
181  | 0  |     }  | 
182  | 0  |     return (1);  | 
183  | 0  | }  | 
184  |  |  | 
185  |  | int TIFFInitNeXT(TIFF *tif, int scheme)  | 
186  | 0  | { | 
187  | 0  |     (void)scheme;  | 
188  | 0  |     tif->tif_predecode = NeXTPreDecode;  | 
189  | 0  |     tif->tif_decoderow = NeXTDecode;  | 
190  | 0  |     tif->tif_decodestrip = NeXTDecode;  | 
191  | 0  |     tif->tif_decodetile = NeXTDecode;  | 
192  | 0  |     return (1);  | 
193  | 0  | }  | 
194  |  | #endif /* NEXT_SUPPORT */  |