/* * Read the specified strip and setup for decoding. The data buffer is * expanded, as necessary, to hold the strip's data. */ int TIFFFillStrip(TIFF* tif, uint32 strip) { static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[strip]; if ((int64)bytecount <= 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count %I64u, strip %lu", (unsigned __int64) bytecount, (unsigned long) strip); #else TIFFErrorExt(tif->tif_clientdata, module, "Invalid strip byte count %llu, strip %lu", (unsigned long long) bytecount, (unsigned long) strip); #endif return (0); } if (isMapped(tif) && (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { /* * The image is mapped into memory and we either don't * need to flip bits or the compression routine is * going to handle this operation itself. In this * case, avoid copying the raw data and instead just * reference the data from the memory mapped file * image. This assumes that the decompression * routines do not modify the contents of the raw data * buffer (if they try to, the application will get a * fault since the file is mapped read-only). */ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { _TIFFfree(tif->tif_rawdata); tif->tif_rawdata = NULL; tif->tif_rawdatasize = 0; } tif->tif_flags &= ~TIFF_MYBUFFER; /* * We must check for overflow, potentially causing * an OOB read. Instead of simple * * td->td_stripoffset[strip]+bytecount > tif->tif_size * * comparison (which can overflow) we do the following * two comparisons: */ if (bytecount > (uint64)tif->tif_size || td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) { /* * This error message might seem strange, but * it's what would happen if a read were done * instead. */ #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error on strip %lu; " "got %I64u bytes, expected %I64u", (unsigned long) strip, (unsigned __int64) tif->tif_size - td->td_stripoffset[strip], (unsigned __int64) bytecount); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error on strip %lu; " "got %llu bytes, expected %llu", (unsigned long) strip, (unsigned long long) tif->tif_size - td->td_stripoffset[strip], (unsigned long long) bytecount); #endif tif->tif_curstrip = NOSTRIP; return (0); } tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; /* * When we have tif_rawdata reference directly into the memory mapped file * we need to be pretty careful about how we use the rawdata. It is not * a general purpose working buffer as it normally otherwise is. So we * keep track of this fact to avoid using it improperly. */ tif->tif_flags |= TIFF_BUFFERMMAP; } else { /* * Expand raw data buffer, if needed, to hold data * strip coming from file (perhaps should set upper * bound on the size of a buffer we'll use?). */ tmsize_t bytecountm; bytecountm=(tmsize_t)bytecount; if ((uint64)bytecountm!=bytecount) { TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); return(0); } if (bytecountm > tif->tif_rawdatasize) { tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold strip %lu", (unsigned long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (tif->tif_flags&TIFF_BUFFERMMAP) { tif->tif_curstrip = NOSTRIP; if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, bytecountm, module) != bytecountm) return (0); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecountm); } } return (TIFFStartStrip(tif, strip)); }
/* * Read a strip of data and decompress the specified * amount into the user-supplied buffer. */ tmsize_t TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) { static const char module[] = "TIFFReadEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; uint32 rowsperstrip; uint32 stripsperplane; uint32 stripinplane; uint16 plane; uint32 rows; tmsize_t stripsize; if (!TIFFCheckRead(tif,0)) return((tmsize_t)(-1)); if (strip>=td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata,module, "%lu: Strip out of range, max %lu",(unsigned long)strip, (unsigned long)td->td_nstrips); return((tmsize_t)(-1)); } /* * Calculate the strip size according to the number of * rows in the strip (check for truncated last strip on any * of the separations). */ rowsperstrip=td->td_rowsperstrip; if (rowsperstrip>td->td_imagelength) rowsperstrip=td->td_imagelength; stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); stripinplane=(strip%stripsperplane); plane=(uint16)(strip/stripsperplane); rows=td->td_imagelength-stripinplane*rowsperstrip; if (rows>rowsperstrip) rows=rowsperstrip; stripsize=TIFFVStripSize(tif,rows); if (stripsize==0) return((tmsize_t)(-1)); /* shortcut to avoid an extra memcpy() */ if( td->td_compression == COMPRESSION_NONE && size!=(tmsize_t)(-1) && size >= stripsize && !isMapped(tif) && ((tif->tif_flags&TIFF_NOREADRAW)==0) ) { if (TIFFReadRawStrip1(tif, strip, buf, stripsize, module) != stripsize) return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(buf,stripsize); (*tif->tif_postdecode)(tif,buf,stripsize); return (stripsize); } if ((size!=(tmsize_t)(-1))&&(size<stripsize)) stripsize=size; if (!TIFFFillStrip(tif,strip)) return((tmsize_t)(-1)); if ((*tif->tif_decodestrip)(tif,buf,stripsize,plane)<=0) return((tmsize_t)(-1)); (*tif->tif_postdecode)(tif,buf,stripsize); return(stripsize); }
static int TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) { static const char module[] = "TIFFFillStripPartial"; register TIFFDirectory *td = &tif->tif_dir; tmsize_t unused_data; uint64 read_offset; tmsize_t cc, to_read; /* tmsize_t bytecountm; */ if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; /* * Expand raw data buffer, if needed, to hold data * strip coming from file (perhaps should set upper * bound on the size of a buffer we'll use?). */ /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ if (read_ahead*2 > tif->tif_rawdatasize) { assert( restart ); tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold part of strip %lu", (unsigned long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, read_ahead*2)) return (0); } if( restart ) { tif->tif_rawdataloaded = 0; tif->tif_rawdataoff = 0; } /* ** If we are reading more data, move any unused data to the ** start of the buffer. */ if( tif->tif_rawdataloaded > 0 ) unused_data = tif->tif_rawdataloaded - (tif->tif_rawcp - tif->tif_rawdata); else unused_data = 0; if( unused_data > 0 ) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); memmove( tif->tif_rawdata, tif->tif_rawcp, unused_data ); } /* ** Seek to the point in the file where more data should be read. */ read_offset = td->td_stripoffset[strip] + tif->tif_rawdataoff + tif->tif_rawdataloaded; if (!SeekOK(tif, read_offset)) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu, strip %lu", (unsigned long) tif->tif_row, (unsigned long) strip); return 0; } /* ** How much do we want to read? */ to_read = tif->tif_rawdatasize - unused_data; if( (uint64) to_read > td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded ) { to_read = (tmsize_t) td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded; } assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); cc = TIFFReadFile(tif, tif->tif_rawdata + unused_data, to_read); if (cc != to_read) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned __int64) cc, (unsigned __int64) to_read); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long long) cc, (unsigned long long) to_read); #endif return 0; } tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ; tif->tif_rawdataloaded = unused_data + to_read; tif->tif_rawcp = tif->tif_rawdata; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); TIFFReverseBits(tif->tif_rawdata + unused_data, to_read ); } /* ** When starting a strip from the beginning we need to ** restart the decoder. */ if( restart ) return TIFFStartStrip(tif, strip); else return 1; }
int TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample) { static const char module[] = "TIFFWriteScanline"; register TIFFDirectory *td; int status, imagegrew = 0; tstrip_t strip; if (!WRITECHECKSTRIPS(tif, module)) return (-1); /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if (!BUFFERCHECK(tif)) return (-1); td = &tif->tif_dir; /* * Extend image length if needed * (but only for PlanarConfig=1). */ if (row >= td->td_imagelength) { /* extend image */ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not change \"ImageLength\" when using separate planes"); return (-1); } td->td_imagelength = row+1; imagegrew = 1; } /* * Calculate strip and check for crossings. */ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { if (sample >= td->td_samplesperpixel) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%d: Sample out of range, max %d", sample, td->td_samplesperpixel); return (-1); } strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; } else strip = row / td->td_rowsperstrip; /* * Check strip array to make sure there's space. We don't support * dynamically growing files that have data organized in separate * bitplanes because it's too painful. In that case we require that * the imagelength be set properly before the first write (so that the * strips array will be fully allocated above). */ if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) return (-1); if (strip != tif->tif_curstrip) { /* * Changing strips -- flush any data present. */ if (!TIFFFlushData(tif)) return (-1); tif->tif_curstrip = strip; /* * Watch out for a growing image. The value of strips/image * will initially be 1 (since it can't be deduced until the * imagelength is known). */ if (strip >= td->td_stripsperimage && imagegrew) td->td_stripsperimage = TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return (-1); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; if( td->td_stripbytecount[strip] > 0 ) { /* if we are writing over existing tiles, zero length */ td->td_stripbytecount[strip] = 0; /* this forces TIFFAppendToStrip() to do a seek */ tif->tif_curoff = 0; } if (!(*tif->tif_preencode)(tif, sample)) return (-1); tif->tif_flags |= TIFF_POSTENCODE; } /* * Ensure the write is either sequential or at the * beginning of a strip (or that we can randomly * access the data -- i.e. no encoding). */ if (row != tif->tif_row) { if (row < tif->tif_row) { /* * Moving backwards within the same strip: * backup to the start and then decode * forward (below). */ tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; tif->tif_rawcp = tif->tif_rawdata; } /* * Seek forward to the desired row. */ if (!(*tif->tif_seek)(tif, row - tif->tif_row)) return (-1); tif->tif_row = row; } /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize ); status = (*tif->tif_encoderow)(tif, (tidata_t) buf, tif->tif_scanlinesize, sample); /* we are now poised at the beginning of the next row */ tif->tif_row = row + 1; return (status); }
/* * Seek to a random row+sample in a file. * * Only used by TIFFReadScanline, and is only used on * strip organized files. We do some tricky stuff to try * and avoid reading the whole compressed raw data for big * strips. */ static int TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) { register TIFFDirectory *td = &tif->tif_dir; uint32 strip; int whole_strip; tmsize_t read_ahead = 0; /* ** Establish what strip we are working from. */ if (row >= td->td_imagelength) { /* out of range */ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Row out of range, max %lu", (unsigned long) row, (unsigned long) td->td_imagelength); return (0); } if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { if (sample >= td->td_samplesperpixel) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Sample out of range, max %lu", (unsigned long) sample, (unsigned long) td->td_samplesperpixel); return (0); } strip = (uint32)sample*td->td_stripsperimage + row/td->td_rowsperstrip; } else strip = row / td->td_rowsperstrip; /* * Do we want to treat this strip as one whole chunk or * read it a few lines at a time? */ #if defined(CHUNKY_STRIP_READ_SUPPORT) if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10 || isMapped(tif); #else whole_strip = 1; #endif if( !whole_strip ) { read_ahead = tif->tif_scanlinesize * 16 + 5000; } /* * If we haven't loaded this strip, do so now, possibly * only reading the first part. */ if (strip != tif->tif_curstrip) { /* different strip, refill */ if( whole_strip ) { if (!TIFFFillStrip(tif, strip)) return (0); } else { if( !TIFFFillStripPartial(tif,strip,read_ahead,1) ) return 0; } } /* ** If we already have some data loaded, do we need to read some more? */ else if( !whole_strip ) { if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead && (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < td->td_stripbytecount[strip] ) { if( !TIFFFillStripPartial(tif,strip,read_ahead,0) ) return 0; } } if (row < tif->tif_row) { /* * Moving backwards within the same strip: backup * to the start and then decode forward (below). * * NB: If you're planning on lots of random access within a * strip, it's better to just read and decode the entire * strip, and then access the decoded data in a random fashion. */ if( tif->tif_rawdataoff != 0 ) { if( !TIFFFillStripPartial(tif,strip,read_ahead,1) ) return 0; } else { if (!TIFFStartStrip(tif, strip)) return (0); } } if (row != tif->tif_row) { /* * Seek forward to the desired row. */ /* TODO: Will this really work with partial buffers? */ if (!(*tif->tif_seek)(tif, row - tif->tif_row)) return (0); tif->tif_row = row; } return (1); }
int TIFFInitZIP(TIFF* tif, int scheme) { static const char module[] = "TIFFInitZIP"; ZIPState* sp; assert( (scheme == COMPRESSION_DEFLATE) || (scheme == COMPRESSION_ADOBE_DEFLATE)); /* * Merge codec-specific tag information. */ if (!_TIFFMergeFields(tif, zipFields, TIFFArrayCount(zipFields))) { TIFFErrorExt(tif->tif_clientdata, module, "Merging Deflate codec-specific tags failed"); return 0; } /* * Allocate state block so tag methods have storage to record values. */ tif->tif_data = (uint8*) _TIFFmalloc(sizeof (ZIPState)); if (tif->tif_data == NULL) goto bad; sp = ZState(tif); sp->stream.zalloc = NULL; sp->stream.zfree = NULL; sp->stream.opaque = NULL; sp->stream.data_type = Z_BINARY; /* * Override parent get/set field methods. */ sp->vgetparent = tif->tif_tagmethods.vgetfield; tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */ sp->vsetparent = tif->tif_tagmethods.vsetfield; tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */ /* Default values for codec-specific fields */ sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */ sp->state = 0; /* * Install codec methods. */ tif->tif_fixuptags = ZIPFixupTags; tif->tif_setupdecode = ZIPSetupDecode; tif->tif_predecode = ZIPPreDecode; tif->tif_decoderow = ZIPDecode; tif->tif_decodestrip = ZIPDecode; tif->tif_decodetile = ZIPDecode; tif->tif_setupencode = ZIPSetupEncode; tif->tif_preencode = ZIPPreEncode; tif->tif_postencode = ZIPPostEncode; tif->tif_encoderow = ZIPEncode; tif->tif_encodestrip = ZIPEncode; tif->tif_encodetile = ZIPEncode; tif->tif_cleanup = ZIPCleanup; /* * Setup predictor setup. */ (void) TIFFPredictorInit(tif); return (1); bad: TIFFErrorExt(tif->tif_clientdata, module, "No space for ZIP state block"); return (0); }
/* * Encode the supplied data and write it to the * specified tile. There must be space for the * data. The function clamps individual writes * to a tile to the tile size, but does not (and * can not) check that multiple writes to the same * tile do not write more than tile size data. * * NB: Image length must be setup before writing; this * interface does not support automatically growing * the image on each write (as TIFFWriteScanline does). */ tsize_t TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) { static const char module[] = "TIFFWriteEncodedTile"; TIFFDirectory *td; tsample_t sample; if (!WRITECHECKTILES(tif, module)) return ((tsize_t) -1); td = &tif->tif_dir; if (tile >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tsize_t) -1); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if (!BUFFERCHECK(tif)) return ((tsize_t) -1); tif->tif_curtile = tile; tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; if( td->td_stripbytecount[tile] > 0 ) { /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } /* * Compute tiles per row & per column to compute * current row and column */ tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) * td->td_tilelength; tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) * td->td_tilewidth; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tsize_t) -1); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_flags &= ~TIFF_POSTENCODE; sample = (tsample_t)(tile/td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tsize_t) -1); /* * Clamp write amount to the tile size. This is mostly * done so that callers can pass in some large number * (e.g. -1) and have the tile size used instead. */ if ( cc < 1 || cc > tif->tif_tilesize) cc = tif->tif_tilesize; /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (tidata_t) data, cc ); if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample)) return ((tsize_t) 0); if (!(*tif->tif_postencode)(tif)) return ((tsize_t) -1); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc)) return ((tsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * Verify file is writable and that the directory * information is setup properly. In doing the latter * we also "freeze" the state of the directory so * that important information is not changed. */ int TIFFWriteCheck(TIFF *tif, int tiles, const char *module) { if (tif->tif_mode == O_RDONLY) { TIFFErrorExt(tif->tif_clientdata, module, "%s: File not open for writing", tif->tif_name); return (0); } if (tiles ^ isTiled(tif)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? "Can not write tiles to a stripped image" : "Can not write scanlines to a tiled image"); return (0); } /* * On the first write verify all the required information * has been setup and initialize any data structures that * had to wait until directory information was set. * Note that a lot of our work is assumed to remain valid * because we disallow any of the important parameters * from changing after we start writing (i.e. once * TIFF_BEENWRITING is set, TIFFSetField will only allow * the image's length to be changed). */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Must set \"ImageWidth\" before writing data", tif->tif_name); return (0); } if (tif->tif_dir.td_samplesperpixel == 1) { /* * Planarconfiguration is irrelevant in case of single band * images and need not be included. We will set it anyway, * because this field is used in other parts of library even * in the single band case. */ if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG; } else { if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Must set \"PlanarConfiguration\" before writing data", tif->tif_name); return (0); } } if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { tif->tif_dir.td_nstrips = 0; TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for %s arrays", tif->tif_name, isTiled(tif) ? "tile" : "strip"); return (0); } tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; tif->tif_scanlinesize = TIFFScanlineSize(tif); tif->tif_flags |= TIFF_BEENWRITING; return (1); }
/* * Decode a string of 32-bit pixels. */ static int LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { static const char module[] = "LogLuvDecode32"; LogLuvState* sp; int shft; tmsize_t i; tmsize_t npixels; unsigned char* bp; uint32* tp; uint32 b; tmsize_t cc; int rc; assert(s == 0); sp = DecoderState(tif); assert(sp != NULL); npixels = occ / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32*) op; else { assert(sp->tbuflen >= npixels); tp = (uint32*) sp->tbuf; } _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); bp = (unsigned char*) tif->tif_rawcp; cc = tif->tif_rawcc; /* get each byte string */ for (shft = 4*8; (shft -= 8) >= 0; ) { for (i = 0; i < npixels && cc > 0; ) if (*bp >= 128) { /* run */ rc = *bp++ + (2-128); b = (uint32)*bp++ << shft; cc -= 2; /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ while (rc-- && i < npixels) tp[i++] |= b; } else { /* non-run */ rc = *bp++; /* nul is noop */ while (--cc && rc-- && i < npixels) tp[i++] |= (uint32)*bp++ << shft; } if (i != npixels) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at row %lu (short %I64d pixels)", (unsigned long) tif->tif_row, (unsigned __int64) (npixels - i)); #else TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at row %lu (short %llu pixels)", (unsigned long) tif->tif_row, (unsigned long long) (npixels - i)); #endif tif->tif_rawcp = (uint8*) bp; tif->tif_rawcc = cc; return (0); } } (*sp->tfunc)(sp, op, npixels); tif->tif_rawcp = (uint8*) bp; tif->tif_rawcc = cc; return (1); }
/* * Setup state for decoding a strip. */ static int LZWPreDecode(TIFF* tif, uint16 s) { static const char module[] = "LZWPreDecode"; LZWCodecState *sp = DecoderState(tif); (void) s; assert(sp != NULL); if( sp->dec_codetab == NULL ) { tif->tif_setupdecode( tif ); } /* * Check for old bit-reversed codes. */ if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { #ifdef LZW_COMPAT if (!sp->dec_decode) { TIFFWarningExt(tif->tif_clientdata, module, "Old-style LZW codes, convert file"); /* * Override default decoding methods with * ones that deal with the old coding. * Otherwise the predictor versions set * above will call the compatibility routines * through the dec_decode method. */ tif->tif_decoderow = LZWDecodeCompat; tif->tif_decodestrip = LZWDecodeCompat; tif->tif_decodetile = LZWDecodeCompat; /* * If doing horizontal differencing, must * re-setup the predictor logic since we * switched the basic decoder methods... */ (*tif->tif_setupdecode)(tif); sp->dec_decode = LZWDecodeCompat; } sp->lzw_maxcode = MAXCODE(BITS_MIN); #else /* !LZW_COMPAT */ if (!sp->dec_decode) { TIFFErrorExt(tif->tif_clientdata, module, "Old-style LZW codes not supported"); sp->dec_decode = LZWDecode; } return (0); #endif/* !LZW_COMPAT */ } else { sp->lzw_maxcode = MAXCODE(BITS_MIN)-1; sp->dec_decode = LZWDecode; } sp->lzw_nbits = BITS_MIN; sp->lzw_nextbits = 0; sp->lzw_nextdata = 0; sp->dec_restart = 0; sp->dec_nbitsmask = MAXCODE(BITS_MIN); #ifdef LZW_CHECKEOS sp->dec_bitsleft = ((uint64)tif->tif_rawcc) << 3; #endif sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; /* * Zero entries that are not yet filled in. We do * this to guard against bogus input data that causes * us to index into undefined entries. If you can * come up with a way to safely bounds-check input codes * while decoding then you can remove this operation. */ _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); sp->dec_oldcodep = &sp->dec_codetab[-1]; sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1]; return (1); }
static int LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) { static const char module[] = "LZWDecodeCompat"; LZWCodecState *sp = DecoderState(tif); char *op = (char*) op0; long occ = (long) occ0; char *tp; unsigned char *bp; int code, nbits; long nextbits, nextdata, nbitsmask; code_t *codep, *free_entp, *maxcodep, *oldcodep; (void) s; assert(sp != NULL); /* Fail if value does not fit in long. */ if ((tmsize_t) occ != occ0) return (0); /* * Restart interrupted output operation. */ if (sp->dec_restart) { long residue; codep = sp->dec_codep; residue = codep->length - sp->dec_restart; if (residue > occ) { /* * Residue from previous decode is sufficient * to satisfy decode request. Skip to the * start of the decoded string, place decoded * values in the output buffer, and return. */ sp->dec_restart += occ; do { codep = codep->next; } while (--residue > occ); tp = op + occ; do { *--tp = codep->value; codep = codep->next; } while (--occ); return (1); } /* * Residue satisfies only part of the decode request. */ op += residue, occ -= residue; tp = op; do { *--tp = codep->value; codep = codep->next; } while (--residue); sp->dec_restart = 0; } bp = (unsigned char *)tif->tif_rawcp; nbits = sp->lzw_nbits; nextdata = sp->lzw_nextdata; nextbits = sp->lzw_nextbits; nbitsmask = sp->dec_nbitsmask; oldcodep = sp->dec_oldcodep; free_entp = sp->dec_free_entp; maxcodep = sp->dec_maxcodep; while (occ > 0) { NextCode(tif, sp, bp, code, GetNextCodeCompat); if (code == CODE_EOI) break; if (code == CODE_CLEAR) { free_entp = sp->dec_codetab + CODE_FIRST; _TIFFmemset(free_entp, 0, (CSIZE - CODE_FIRST) * sizeof (code_t)); nbits = BITS_MIN; nbitsmask = MAXCODE(BITS_MIN); maxcodep = sp->dec_codetab + nbitsmask; NextCode(tif, sp, bp, code, GetNextCodeCompat); if (code == CODE_EOI) break; if (code >= CODE_CLEAR) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "LZWDecode: Corrupted LZW table at scanline %d", tif->tif_row); return (0); } *op++ = (char)code, occ--; oldcodep = sp->dec_codetab + code; continue; } codep = sp->dec_codetab + code; /* * Add the new entry to the code table. */ if (free_entp < &sp->dec_codetab[0] || free_entp >= &sp->dec_codetab[CSIZE]) { TIFFErrorExt(tif->tif_clientdata, module, "Corrupted LZW table at scanline %d", tif->tif_row); return (0); } free_entp->next = oldcodep; if (free_entp->next < &sp->dec_codetab[0] || free_entp->next >= &sp->dec_codetab[CSIZE]) { TIFFErrorExt(tif->tif_clientdata, module, "Corrupted LZW table at scanline %d", tif->tif_row); return (0); } free_entp->firstchar = free_entp->next->firstchar; free_entp->length = free_entp->next->length+1; free_entp->value = (codep < free_entp) ? codep->firstchar : free_entp->firstchar; if (++free_entp > maxcodep) { if (++nbits > BITS_MAX) /* should not happen */ nbits = BITS_MAX; nbitsmask = MAXCODE(nbits); maxcodep = sp->dec_codetab + nbitsmask; } oldcodep = codep; if (code >= 256) { /* * Code maps to a string, copy string * value to output (written in reverse). */ if(codep->length == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Wrong length of decoded " "string: data probably corrupted at scanline %d", tif->tif_row); return (0); } if (codep->length > occ) { /* * String is too long for decode buffer, * locate portion that will fit, copy to * the decode buffer, and setup restart * logic for the next decoding call. */ sp->dec_codep = codep; do { codep = codep->next; } while (codep->length > occ); sp->dec_restart = occ; tp = op + occ; do { *--tp = codep->value; codep = codep->next; } while (--occ); break; } assert(occ >= codep->length); op += codep->length, occ -= codep->length; tp = op; do { *--tp = codep->value; } while( (codep = codep->next) != NULL ); } else *op++ = (char)code, occ--; } tif->tif_rawcp = (uint8*) bp; sp->lzw_nbits = (unsigned short) nbits; sp->lzw_nextdata = nextdata; sp->lzw_nextbits = nextbits; sp->dec_nbitsmask = nbitsmask; sp->dec_oldcodep = oldcodep; sp->dec_free_entp = free_entp; sp->dec_maxcodep = maxcodep; if (occ > 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__)) TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at scanline %d (short %I64d bytes)", tif->tif_row, (unsigned __int64) occ); #else TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at scanline %d (short %llu bytes)", tif->tif_row, (unsigned long long) occ); #endif return (0); } return (1); }
TIFF* TIFFClientOpen( const char* name, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc ) { static const char module[] = "TIFFClientOpen"; TIFF *tif; int m; const char* cp; /* The following are configuration checks. They should be redundant, but should not * compile to any actual code in an optimised release build anyway. If any of them * fail, (makefile-based or other) configuration is not correct */ assert(sizeof(uint8)==1); assert(sizeof(int8)==1); assert(sizeof(uint16)==2); assert(sizeof(int16)==2); assert(sizeof(uint32)==4); assert(sizeof(int32)==4); assert(sizeof(uint64)==8); assert(sizeof(int64)==8); assert(sizeof(tmsize_t)==sizeof(void*)); { union{ uint8 a8[2]; uint16 a16; } n; n.a8[0]=1; n.a8[1]=0; #ifdef WORDS_BIGENDIAN assert(n.a16==256); #else assert(n.a16==1); #endif } m = _TIFFgetMode(mode, module); if (m == -1) goto bad2; tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1)); if (tif == NULL) { TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name); goto bad2; } _TIFFmemset(tif, 0, sizeof (*tif)); tif->tif_name = (char *)tif + sizeof (TIFF); strcpy(tif->tif_name, name); tif->tif_mode = m &~ (O_CREAT|O_TRUNC); tif->tif_curdir = (uint16) -1; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = (uint32) -1; /* invalid strip */ tif->tif_row = (uint32) -1; /* read/write pre-increment */ tif->tif_clientdata = clientdata; if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { TIFFErrorExt(clientdata, module, "One of the client procedures is NULL pointer."); goto bad2; } tif->tif_readproc = readproc; tif->tif_writeproc = writeproc; tif->tif_seekproc = seekproc; tif->tif_closeproc = closeproc; tif->tif_sizeproc = sizeproc; if (mapproc) tif->tif_mapproc = mapproc; else tif->tif_mapproc = _tiffDummyMapProc; if (unmapproc) tif->tif_unmapproc = unmapproc; else tif->tif_unmapproc = _tiffDummyUnmapProc; _TIFFSetDefaultCompressionState(tif); /* setup default state */ /* * Default is to return data MSB2LSB and enable the * use of memory-mapped files and strip chopping when * a file is opened read-only. */ tif->tif_flags = FILLORDER_MSB2LSB; if (m == O_RDONLY ) tif->tif_flags |= TIFF_MAPPED; #ifdef STRIPCHOP_DEFAULT if (m == O_RDONLY || m == O_RDWR) tif->tif_flags |= STRIPCHOP_DEFAULT; #endif /* * Process library-specific flags in the open mode string. * The following flags may be used to control intrinsic library * behaviour that may or may not be desirable (usually for * compatibility with some application that claims to support * TIFF but only supports some brain dead idea of what the * vendor thinks TIFF is): * * 'l' use little-endian byte order for creating a file * 'b' use big-endian byte order for creating a file * 'L' read/write information using LSB2MSB bit order * 'B' read/write information using MSB2LSB bit order * 'H' read/write information using host bit order * 'M' enable use of memory-mapped files when supported * 'm' disable use of memory-mapped files * 'C' enable strip chopping support when reading * 'c' disable strip chopping support * 'h' read TIFF header only, do not load the first IFD * '4' ClassicTIFF for creating a file (default) * '8' BigTIFF for creating a file * * The use of the 'l' and 'b' flags is strongly discouraged. * These flags are provided solely because numerous vendors, * typically on the PC, do not correctly support TIFF; they * only support the Intel little-endian byte order. This * support is not configured by default because it supports * the violation of the TIFF spec that says that readers *MUST* * support both byte orders. It is strongly recommended that * you not use this feature except to deal with busted apps * that write invalid TIFF. And even in those cases you should * bang on the vendors to fix their software. * * The 'L', 'B', and 'H' flags are intended for applications * that can optimize operations on data by using a particular * bit order. By default the library returns data in MSB2LSB * bit order for compatibility with older versions of this * library. Returning data in the bit order of the native CPU * makes the most sense but also requires applications to check * the value of the FillOrder tag; something they probably do * not do right now. * * The 'M' and 'm' flags are provided because some virtual memory * systems exhibit poor behaviour when large images are mapped. * These options permit clients to control the use of memory-mapped * files on a per-file basis. * * The 'C' and 'c' flags are provided because the library support * for chopping up large strips into multiple smaller strips is not * application-transparent and as such can cause problems. The 'c' * option permits applications that only want to look at the tags, * for example, to get the unadulterated TIFF tag information. */ for (cp = mode; *cp; cp++) switch (*cp) { case 'b': #ifndef WORDS_BIGENDIAN if (m&O_CREAT) tif->tif_flags |= TIFF_SWAB; #endif break; case 'l': #ifdef WORDS_BIGENDIAN if ((m&O_CREAT)) tif->tif_flags |= TIFF_SWAB; #endif break; case 'B': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_MSB2LSB; break; case 'L': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_LSB2MSB; break; case 'H': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | HOST_FILLORDER; break; case 'M': if (m == O_RDONLY) tif->tif_flags |= TIFF_MAPPED; break; case 'm': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_MAPPED; break; case 'C': if (m == O_RDONLY) tif->tif_flags |= TIFF_STRIPCHOP; break; case 'c': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_STRIPCHOP; break; case 'h': tif->tif_flags |= TIFF_HEADERONLY; break; case '8': if (m&O_CREAT) tif->tif_flags |= TIFF_BIGTIFF; break; } /* * Read in TIFF header. */ if ((m & O_TRUNC) || !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) { if (tif->tif_mode == O_RDONLY) { TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header"); goto bad; } /* * Setup header and write. */ #ifdef WORDS_BIGENDIAN tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; #else tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; #endif if (!(tif->tif_flags&TIFF_BIGTIFF)) { tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC; tif->tif_header.classic.tiff_diroff = 0; if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.common.tiff_version); tif->tif_header_size = sizeof(TIFFHeaderClassic); } else { tif->tif_header.common.tiff_version = TIFF_VERSION_BIG; tif->tif_header.big.tiff_offsetsize = 8; tif->tif_header.big.tiff_unused = 0; tif->tif_header.big.tiff_diroff = 0; if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.common.tiff_version); TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); } tif->tif_header_size = sizeof (TIFFHeaderBig); } /* * The doc for "fopen" for some STD_C_LIBs says that if you * open a file for modify ("+"), then you must fseek (or * fflush?) between any freads and fwrites. This is not * necessary on most systems, but has been shown to be needed * on Solaris. */ TIFFSeekFile( tif, 0, SEEK_SET ); if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) { TIFFErrorExt(tif->tif_clientdata, name, "Error writing TIFF header"); goto bad; } /* * Setup the byte order handling. */ if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { #ifndef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } else { #ifdef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } /* * Setup default directory. */ if (!TIFFDefaultDirectory(tif)) goto bad; tif->tif_diroff = 0; tif->tif_dirlist = NULL; tif->tif_dirlistsize = 0; tif->tif_dirnumber = 0; return (tif); } /* * Setup the byte order handling. */ if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN #if MDI_SUPPORT && #if HOST_BIGENDIAN tif->tif_header.common.tiff_magic != MDI_BIGENDIAN #else tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN #endif ) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF or MDI file, bad magic number %d (0x%x)", #else ) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad magic number %d (0x%x)", #endif tif->tif_header.common.tiff_magic, tif->tif_header.common.tiff_magic); goto bad; } if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { #ifndef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } else { #ifdef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.common.tiff_version); if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&& (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad version number %d (0x%x)", tif->tif_header.common.tiff_version, tif->tif_header.common.tiff_version); goto bad; } if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC) { if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&tif->tif_header.classic.tiff_diroff); tif->tif_header_size = sizeof(TIFFHeaderClassic); } else { if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic)))) { TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header"); goto bad; } if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); TIFFSwabLong8(&tif->tif_header.big.tiff_diroff); } if (tif->tif_header.big.tiff_offsetsize != 8) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)", tif->tif_header.big.tiff_offsetsize, tif->tif_header.big.tiff_offsetsize); goto bad; } if (tif->tif_header.big.tiff_unused != 0) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad BigTIFF unused %d (0x%x)", tif->tif_header.big.tiff_unused, tif->tif_header.big.tiff_unused); goto bad; } tif->tif_header_size = sizeof(TIFFHeaderBig); tif->tif_flags |= TIFF_BIGTIFF; } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawcp = tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = 0; switch (mode[0]) { case 'r': if (!(tif->tif_flags&TIFF_BIGTIFF)) tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff; else tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff; /* * Try to use a memory-mapped file if the client * has not explicitly suppressed usage with the * 'm' flag in the open mode (see above). */ if (tif->tif_flags & TIFF_MAPPED) { toff_t n; if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n)) { tif->tif_size=(tmsize_t)n; assert((toff_t)tif->tif_size==n); } else tif->tif_flags &= ~TIFF_MAPPED; } /* * Sometimes we do not want to read the first directory (for example, * it may be broken) and want to proceed to other directories. I this * case we use the TIFF_HEADERONLY flag to open file and return * immediately after reading TIFF header. */ if (tif->tif_flags & TIFF_HEADERONLY) return (tif); /* * Setup initial directory. */ if (TIFFReadDirectory(tif)) { tif->tif_rawcc = (tmsize_t)-1; tif->tif_flags |= TIFF_BUFFERSETUP; return (tif); } break; case 'a': /* * New directories are automatically append * to the end of the directory chain when they * are written out (see TIFFWriteDirectory). */ if (!TIFFDefaultDirectory(tif)) goto bad; return (tif); } bad: tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFCleanup(tif); bad2: return ((TIFF*)0); }
int TIFFInitLZMA(TIFF* tif, int scheme) { static const char module[] = "TIFFInitLZMA"; LZMAState* sp; lzma_stream tmp_stream = LZMA_STREAM_INIT; assert( scheme == COMPRESSION_LZMA ); /* * Merge codec-specific tag information. */ if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) { TIFFErrorExt(tif->tif_clientdata, module, "Merging LZMA2 codec-specific tags failed"); return 0; } /* * Allocate state block so tag methods have storage to record values. */ tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState)); if (tif->tif_data == NULL) goto bad; sp = LState(tif); memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream)); /* * Override parent get/set field methods. */ sp->vgetparent = tif->tif_tagmethods.vgetfield; tif->tif_tagmethods.vgetfield = LZMAVGetField; /* hook for codec tags */ sp->vsetparent = tif->tif_tagmethods.vsetfield; tif->tif_tagmethods.vsetfield = LZMAVSetField; /* hook for codec tags */ /* Default values for codec-specific fields */ sp->preset = LZMA_PRESET_DEFAULT; /* default comp. level */ sp->check = LZMA_CHECK_NONE; sp->state = 0; /* Data filters. So far we are using delta and LZMA2 filters only. */ sp->opt_delta.type = LZMA_DELTA_TYPE_BYTE; /* * The sample size in bytes seems to be reasonable distance for delta * filter. */ sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ? 1 : tif->tif_dir.td_bitspersample / 8; sp->filters[0].id = LZMA_FILTER_DELTA; sp->filters[0].options = &sp->opt_delta; lzma_lzma_preset(&sp->opt_lzma, sp->preset); sp->filters[1].id = LZMA_FILTER_LZMA2; sp->filters[1].options = &sp->opt_lzma; sp->filters[2].id = LZMA_VLI_UNKNOWN; sp->filters[2].options = NULL; /* * Install codec methods. */ tif->tif_fixuptags = LZMAFixupTags; tif->tif_setupdecode = LZMASetupDecode; tif->tif_predecode = LZMAPreDecode; tif->tif_decoderow = LZMADecode; tif->tif_decodestrip = LZMADecode; tif->tif_decodetile = LZMADecode; tif->tif_setupencode = LZMASetupEncode; tif->tif_preencode = LZMAPreEncode; tif->tif_postencode = LZMAPostEncode; tif->tif_encoderow = LZMAEncode; tif->tif_encodestrip = LZMAEncode; tif->tif_encodetile = LZMAEncode; tif->tif_cleanup = LZMACleanup; /* * Setup predictor setup. */ (void) TIFFPredictorInit(tif); return 1; bad: TIFFErrorExt(tif->tif_clientdata, module, "No space for LZMA2 state block"); return 0; }
static int LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { static const char module[] = "LZMADecode"; LZMAState* sp = DecoderState(tif); (void) s; assert(sp != NULL); assert(sp->state == LSTATE_INIT_DECODE); sp->stream.next_in = tif->tif_rawcp; sp->stream.avail_in = (size_t) tif->tif_rawcc; sp->stream.next_out = op; sp->stream.avail_out = (size_t) occ; if ((tmsize_t)sp->stream.avail_out != occ) { TIFFErrorExt(tif->tif_clientdata, module, "Liblzma cannot deal with buffers this size"); return 0; } do { /* * Save the current stream state to properly recover from the * decoding errors later. */ const uint8_t *next_in = sp->stream.next_in; size_t avail_in = sp->stream.avail_in; lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN); if (ret == LZMA_STREAM_END) break; if (ret == LZMA_MEMLIMIT_ERROR) { lzma_ret r = lzma_stream_decoder(&sp->stream, lzma_memusage(&sp->stream), 0); if (r != LZMA_OK) { TIFFErrorExt(tif->tif_clientdata, module, "Error initializing the stream decoder, %s", LZMAStrerror(r)); break; } sp->stream.next_in = next_in; sp->stream.avail_in = avail_in; continue; } if (ret != LZMA_OK) { TIFFErrorExt(tif->tif_clientdata, module, "Decoding error at scanline %lu, %s", (unsigned long) tif->tif_row, LZMAStrerror(ret)); break; } } while (sp->stream.avail_out > 0); if (sp->stream.avail_out != 0) { TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at scanline %lu (short %lu bytes)", (unsigned long) tif->tif_row, (unsigned long) sp->stream.avail_out); return 0; } tif->tif_rawcp = (uint8 *)sp->stream.next_in; /* cast away const */ tif->tif_rawcc = sp->stream.avail_in; return 1; }
static tmsize_t TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif )) return ((tmsize_t)(-1)); assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tmsize_t cc; if (!SeekOK(tif, td->td_stripoffset[tile])) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at row %lu, col %lu, tile %lu", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) tile); return ((tmsize_t)(-1)); } cc = TIFFReadFile(tif, buf, size); if (cc != size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned __int64) cc, (unsigned __int64) size); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long long) cc, (unsigned long long) size); #endif return ((tmsize_t)(-1)); } } else { tmsize_t ma,mb; tmsize_t n; ma=(tmsize_t)td->td_stripoffset[tile]; mb=ma+size; if ((td->td_stripoffset[tile] > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size)) n=0; else if ((mb<ma)||(mb<size)||(mb>tif->tif_size)) n=tif->tif_size-ma; else n=size; if (n!=size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) tile, (unsigned __int64) n, (unsigned __int64) size); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) tile, (unsigned long long) n, (unsigned long long) size); #endif return ((tmsize_t)(-1)); } _TIFFmemcpy(buf, tif->tif_base + ma, size); } return (size); }
/* * Encode the supplied data and write it to the * specified strip. * * NB: Image length must be setup before writing. */ tsize_t TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) { static const char module[] = "TIFFWriteEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; tsample_t sample; if (!WRITECHECKSTRIPS(tif, module)) return ((tsize_t) -1); /* * Check strip array to make sure there's space. * We don't support dynamically growing files that * have data organized in separate bitplanes because * it's too painful. In that case we require that * the imagelength be set properly before the first * write (so that the strips array will be fully * allocated above). */ if (strip >= td->td_nstrips) { if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not grow image by strips when using separate planes"); return ((tsize_t) -1); } if (!TIFFGrowStrips(tif, 1, module)) return ((tsize_t) -1); td->td_stripsperimage = TIFFhowmany(td->td_imagelength, td->td_rowsperstrip); } /* * Handle delayed allocation of data buffer. This * permits it to be sized according to the directory * info. */ if (!BUFFERCHECK(tif)) return ((tsize_t) -1); tif->tif_curstrip = strip; tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tsize_t) -1); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; if( td->td_stripbytecount[strip] > 0 ) { /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } tif->tif_flags &= ~TIFF_POSTENCODE; sample = (tsample_t)(strip / td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tsize_t) -1); /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (tidata_t) data, cc ); if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample)) return ((tsize_t) 0); if (!(*tif->tif_postencode)(tif)) return ((tsize_t) -1); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) return ((tsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * Read the specified tile and setup for decoding. The data buffer is * expanded, as necessary, to hold the tile's data. */ int TIFFFillTile(TIFF* tif, uint32 tile) { static const char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { uint64 bytecount = td->td_stripbytecount[tile]; if ((int64)bytecount <= 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "%I64u: Invalid tile byte count, tile %lu", (unsigned __int64) bytecount, (unsigned long) tile); #else TIFFErrorExt(tif->tif_clientdata, module, "%llu: Invalid tile byte count, tile %lu", (unsigned long long) bytecount, (unsigned long) tile); #endif return (0); } if (isMapped(tif) && (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { /* * The image is mapped into memory and we either don't * need to flip bits or the compression routine is * going to handle this operation itself. In this * case, avoid copying the raw data and instead just * reference the data from the memory mapped file * image. This assumes that the decompression * routines do not modify the contents of the raw data * buffer (if they try to, the application will get a * fault since the file is mapped read-only). */ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { _TIFFfree(tif->tif_rawdata); tif->tif_rawdata = NULL; tif->tif_rawdatasize = 0; } tif->tif_flags &= ~TIFF_MYBUFFER; /* * We must check for overflow, potentially causing * an OOB read. Instead of simple * * td->td_stripoffset[tile]+bytecount > tif->tif_size * * comparison (which can overflow) we do the following * two comparisons: */ if (bytecount > (uint64)tif->tif_size || td->td_stripoffset[tile] > (uint64)tif->tif_size - bytecount) { tif->tif_curtile = NOTILE; return (0); } tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[tile]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; tif->tif_flags |= TIFF_BUFFERMMAP; } else { /* * Expand raw data buffer, if needed, to hold data * tile coming from file (perhaps should set upper * bound on the size of a buffer we'll use?). */ tmsize_t bytecountm; bytecountm=(tmsize_t)bytecount; if ((uint64)bytecountm!=bytecount) { TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); return(0); } if (bytecountm > tif->tif_rawdatasize) { tif->tif_curtile = NOTILE; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold tile %lu", (unsigned long) tile); return (0); } if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (tif->tif_flags&TIFF_BUFFERMMAP) { tif->tif_curtile = NOTILE; if (!TIFFReadBufferSetup(tif, 0, bytecountm)) return (0); } if (TIFFReadRawTile1(tif, tile, tif->tif_rawdata, bytecountm, module) != bytecountm) return (0); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdataloaded); } } return (TIFFStartTile(tif, tile)); }
static int PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { static const char module[] = "PackBitsDecode"; char *bp; tmsize_t cc; long n; int b; (void) s; bp = (char*) tif->tif_rawcp; cc = tif->tif_rawcc; while (cc > 0 && occ > 0) { n = (long) *bp++, cc--; /* * Watch out for compilers that * don't sign extend chars... */ if (n >= 128) n -= 256; if (n < 0) { /* replicate next byte -n+1 times */ if (n == -128) /* nop */ continue; n = -n + 1; if( occ < (tmsize_t)n ) { TIFFWarningExt(tif->tif_clientdata, module, "Discarding %lu bytes to avoid buffer overrun", (unsigned long) ((tmsize_t)n - occ)); n = (long)occ; } occ -= n; b = *bp++, cc--; while (n-- > 0) *op++ = (uint8) b; } else { /* copy next n+1 bytes literally */ if (occ < (tmsize_t)(n + 1)) { TIFFWarningExt(tif->tif_clientdata, module, "Discarding %lu bytes to avoid buffer overrun", (unsigned long) ((tmsize_t)n - occ + 1)); n = (long)occ - 1; } if (cc < (tmsize_t) (n+1)) { TIFFWarningExt(tif->tif_clientdata, module, "Terminating PackBitsDecode due to lack of data."); break; } _TIFFmemcpy(op, bp, ++n); op += n; occ -= n; bp += n; cc -= n; } } tif->tif_rawcp = (uint8*) bp; tif->tif_rawcc = cc; if (occ > 0) { TIFFErrorExt(tif->tif_clientdata, module, "Not enough data for scanline %lu", (unsigned long) tif->tif_row); return (0); } return (1); }