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