/src/libtiff/libtiff/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 | 13.0M | { \ |
35 | 13.0M | switch (npixels++ & 3) \ |
36 | 13.0M | { \ |
37 | 3.28M | case 0: \ |
38 | 3.28M | op[0] = (unsigned char)((v) << 6); \ |
39 | 3.28M | break; \ |
40 | 3.27M | case 1: \ |
41 | 3.27M | op[0] |= (unsigned char)((v) << 4); \ |
42 | 3.27M | break; \ |
43 | 3.26M | case 2: \ |
44 | 3.26M | op[0] |= (unsigned char)((v) << 2); \ |
45 | 3.26M | break; \ |
46 | 3.26M | case 3: \ |
47 | 3.26M | *op++ |= (unsigned char)(v); \ |
48 | 3.26M | op_offset++; \ |
49 | 3.26M | break; \ |
50 | 0 | default: \ |
51 | 0 | break; \ |
52 | 13.0M | } \ |
53 | 13.0M | } |
54 | | |
55 | 6.40k | #define LITERALROW 0x00 |
56 | 1.43k | #define LITERALSPAN 0x40 |
57 | | |
58 | | static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) |
59 | 84.4k | { |
60 | 84.4k | static const char module[] = "NeXTDecode"; |
61 | 84.4k | unsigned char *bp, *op; |
62 | 84.4k | tmsize_t cc; |
63 | 84.4k | uint8_t *row; |
64 | 84.4k | tmsize_t scanline, n; |
65 | | |
66 | 84.4k | (void)s; |
67 | | /* |
68 | | * Each scanline is assumed to start off as all |
69 | | * white (we assume a PhotometricInterpretation |
70 | | * of ``min-is-black''). |
71 | | */ |
72 | 34.9M | for (op = (unsigned char *)buf, cc = occ; cc-- > 0;) |
73 | 34.8M | *op++ = 0xff; |
74 | | |
75 | 84.4k | bp = (unsigned char *)tif->tif_rawcp; |
76 | 84.4k | cc = tif->tif_rawcc; |
77 | 84.4k | scanline = tif->tif_dir.td_scanlinesize; |
78 | 84.4k | if (occ % scanline) |
79 | 0 | { |
80 | 0 | TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); |
81 | 0 | return (0); |
82 | 0 | } |
83 | 114k | for (row = buf; cc > 0 && occ > 0; occ -= scanline, row += scanline) |
84 | 30.1k | { |
85 | 30.1k | n = *bp++; |
86 | 30.1k | cc--; |
87 | 30.1k | switch (n) |
88 | 30.1k | { |
89 | 6.40k | case LITERALROW: |
90 | | /* |
91 | | * The entire scanline is given as literal values. |
92 | | */ |
93 | 6.40k | if (cc < scanline) |
94 | 24 | goto bad; |
95 | 6.38k | _TIFFmemcpy(row, bp, scanline); |
96 | 6.38k | bp += scanline; |
97 | 6.38k | cc -= scanline; |
98 | 6.38k | break; |
99 | 1.43k | case LITERALSPAN: |
100 | 1.43k | { |
101 | 1.43k | tmsize_t off; |
102 | | /* |
103 | | * The scanline has a literal span that begins at some |
104 | | * offset. |
105 | | */ |
106 | 1.43k | if (cc < 4) |
107 | 4 | goto bad; |
108 | 1.43k | off = (bp[0] * 256) + bp[1]; |
109 | 1.43k | n = (bp[2] * 256) + bp[3]; |
110 | 1.43k | if (cc < 4 + n || off + n > scanline) |
111 | 26 | goto bad; |
112 | 1.40k | _TIFFmemcpy(row + off, bp + 4, n); |
113 | 1.40k | bp += 4 + n; |
114 | 1.40k | cc -= 4 + n; |
115 | 1.40k | break; |
116 | 1.43k | } |
117 | 22.3k | default: |
118 | 22.3k | { |
119 | 22.3k | uint32_t npixels = 0, grey; |
120 | 22.3k | tmsize_t op_offset = 0; |
121 | 22.3k | uint32_t imagewidth = tif->tif_dir.td_imagewidth; |
122 | 22.3k | if (isTiled(tif)) |
123 | 0 | imagewidth = tif->tif_dir.td_tilewidth; |
124 | | |
125 | | /* |
126 | | * The scanline is composed of a sequence of constant |
127 | | * color ``runs''. We shift into ``run mode'' and |
128 | | * interpret bytes as codes of the form |
129 | | * <color><npixels> until we've filled the scanline. |
130 | | */ |
131 | 22.3k | op = row; |
132 | 22.3k | for (;;) |
133 | 452k | { |
134 | 452k | grey = (uint32_t)((n >> 6) & 0x3); |
135 | 452k | n &= 0x3f; |
136 | | /* |
137 | | * Ensure the run does not exceed the scanline |
138 | | * bounds, potentially resulting in a security |
139 | | * issue. |
140 | | */ |
141 | 13.5M | while (n-- > 0 && npixels < imagewidth && |
142 | 13.0M | op_offset < scanline) |
143 | 13.0M | SETPIXEL(op, grey); |
144 | 452k | if (npixels >= imagewidth) |
145 | 22.2k | break; |
146 | 430k | if (op_offset >= scanline) |
147 | 0 | { |
148 | 0 | TIFFErrorExtR(tif, module, |
149 | 0 | "Invalid data for scanline %" PRIu32, |
150 | 0 | tif->tif_dir.td_row); |
151 | 0 | return (0); |
152 | 0 | } |
153 | 430k | if (cc == 0) |
154 | 80 | goto bad; |
155 | 430k | n = *bp++; |
156 | 430k | cc--; |
157 | 430k | } |
158 | 22.2k | break; |
159 | 22.3k | } |
160 | 30.1k | } |
161 | 30.1k | } |
162 | 84.3k | tif->tif_rawcp = (uint8_t *)bp; |
163 | 84.3k | tif->tif_rawcc = cc; |
164 | 84.3k | return (1); |
165 | 134 | bad: |
166 | 134 | TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32, |
167 | 134 | tif->tif_dir.td_row); |
168 | 134 | return (0); |
169 | 84.4k | } |
170 | | |
171 | | static int NeXTPreDecode(TIFF *tif, uint16_t s) |
172 | 457 | { |
173 | 457 | static const char module[] = "NeXTPreDecode"; |
174 | 457 | TIFFDirectory *td = &tif->tif_dir; |
175 | 457 | (void)s; |
176 | | |
177 | 457 | if (td->td_bitspersample != 2) |
178 | 6 | { |
179 | 6 | TIFFErrorExtR(tif, module, "Unsupported BitsPerSample = %" PRIu16, |
180 | 6 | td->td_bitspersample); |
181 | 6 | return (0); |
182 | 6 | } |
183 | 451 | return (1); |
184 | 457 | } |
185 | | |
186 | | int TIFFInitNeXT(TIFF *tif, int scheme) |
187 | 490 | { |
188 | 490 | (void)scheme; |
189 | 490 | tif->tif_predecode = NeXTPreDecode; |
190 | 490 | tif->tif_decoderow = NeXTDecode; |
191 | 490 | tif->tif_decodestrip = NeXTDecode; |
192 | 490 | tif->tif_decodetile = NeXTDecode; |
193 | 490 | return (1); |
194 | 490 | } |
195 | | #endif /* NEXT_SUPPORT */ |