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