/* * Compute the # bytes in a variable height, row-aligned strip. */ uint64 TIFFVStripSize64(TIFF* tif, uint32 nrows) { static const char module[] = "TIFFVStripSize64"; TIFFDirectory *td = &tif->tif_dir; if (nrows==(uint32)(-1)) nrows=td->td_imagelength; if ((td->td_planarconfig==PLANARCONFIG_CONTIG)&& (td->td_photometric == PHOTOMETRIC_YCBCR)&& (!isUpSampled(tif))) { /* * Packed YCbCr data contain one Cb+Cr for every * HorizontalSampling*VerticalSampling Y values. * Must also roundup width and height when calculating * since images that are not a multiple of the * horizontal/vertical subsampling area include * YCbCr data for the extended image. */ uint16 ycbcrsubsampling[2]; uint16 samplingblock_samples; uint32 samplingblocks_hor; uint32 samplingblocks_ver; uint64 samplingrow_samples; uint64 samplingrow_size; if(td->td_samplesperpixel!=3) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid td_samplesperpixel value"); return 0; } TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampling+0, ycbcrsubsampling+1); if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4) ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && ycbcrsubsampling[1] != 4)) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid YCbCr subsampling (%dx%d)", ycbcrsubsampling[0], ycbcrsubsampling[1] ); return 0; } samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; samplingblocks_hor=TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]); samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module)); return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,module)); } else return(_TIFFMultiply64(tif,nrows,TIFFScanlineSize64(tif),module)); }
/* * Return the number of bytes to read/write in a call to * one of the scanline-oriented i/o routines. Note that * this number may be 1/samples-per-pixel if data is * stored as separate planes. * The ScanlineSize in case of YCbCrSubsampling is defined as the * strip size divided by the strip height, i.e. the size of a pack of vertical * subsampling lines divided by vertical subsampling. It should thus make * sense when multiplied by a multiple of vertical subsampling. */ uint64 TIFFScanlineSize64(TIFF* tif) { static const char module[] = "TIFFScanlineSize64"; TIFFDirectory *td = &tif->tif_dir; uint64 scanline_size; if (td->td_planarconfig==PLANARCONFIG_CONTIG) { if ((td->td_photometric==PHOTOMETRIC_YCBCR)&& (td->td_samplesperpixel==3)&& (!isUpSampled(tif))) { uint16 ycbcrsubsampling[2]; uint16 samplingblock_samples; uint32 samplingblocks_hor; uint64 samplingrow_samples; uint64 samplingrow_size; if(td->td_samplesperpixel!=3) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid td_samplesperpixel value"); return 0; } TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING, ycbcrsubsampling+0, ycbcrsubsampling+1); if (((ycbcrsubsampling[0]!=1)&&(ycbcrsubsampling[0]!=2)&&(ycbcrsubsampling[0]!=4)) || ((ycbcrsubsampling[1]!=1)&&(ycbcrsubsampling[1]!=2)&&(ycbcrsubsampling[1]!=4))) { TIFFErrorExt(tif->tif_clientdata,module, "Invalid YCbCr subsampling"); return 0; } samplingblock_samples = ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; samplingblocks_hor = TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); samplingrow_samples = _TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); samplingrow_size = TIFFhowmany_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module),8); /* IMLIB scanline_size = (samplingrow_size/ycbcrsubsampling[1]); See tif_jpeg.c */ scanline_size = samplingrow_size; } else { uint64 scanline_samples; scanline_samples=_TIFFMultiply64(tif,td->td_imagewidth,td->td_samplesperpixel,module); scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,scanline_samples,td->td_bitspersample,module),8); } } else { scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,td->td_imagewidth,td->td_bitspersample,module),8); } if (scanline_size == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Computed scanline size is zero"); return 0; } return(scanline_size); }
/* * Set state to appear as if a * tile has just been read in. */ static int TIFFStartTile(TIFF* tif, uint32 tile) { static const char module[] = "TIFFStartTile"; TIFFDirectory *td = &tif->tif_dir; uint32 howmany32; if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupdecode)(tif)) return (0); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_curtile = tile; howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth); if (howmany32 == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); return 0; } tif->tif_row = (tile % howmany32) * td->td_tilelength; howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength); if (howmany32 == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); return 0; } tif->tif_col = (tile % howmany32) * td->td_tilewidth; tif->tif_flags &= ~TIFF_BUF4WRITE; if (tif->tif_flags&TIFF_NOREADRAW) { tif->tif_rawcp = NULL; tif->tif_rawcc = 0; } else { tif->tif_rawcp = tif->tif_rawdata; if( tif->tif_rawdataloaded > 0 ) tif->tif_rawcc = tif->tif_rawdataloaded; else tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[tile]; } return ((*tif->tif_predecode)(tif, (uint16)(tile/td->td_stripsperimage))); }
/* * Compute how many strips are in an image. */ uint32 TIFFNumberOfStrips(TIFF* tif) { TIFFDirectory *td = &tif->tif_dir; uint32 nstrips; nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 : TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip)); if (td->td_planarconfig == PLANARCONFIG_SEPARATE) nstrips = _TIFFMultiply32(tif, nstrips, (uint32)td->td_samplesperpixel, "TIFFNumberOfStrips"); return (nstrips); }
/* * Write the supplied data to the specified strip. * * NB: Image length must be setup before writing. */ tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) { static const char module[] = "TIFFWriteRawStrip"; TIFFDirectory *td = &tif->tif_dir; if (!WRITECHECKSTRIPS(tif, module)) return ((tmsize_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, module, "Can not grow image by strips when using separate planes"); return ((tmsize_t) -1); } /* * 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) td->td_stripsperimage = TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip); if (!TIFFGrowStrips(tif, 1, module)) return ((tmsize_t) -1); } tif->tif_curstrip = strip; if (td->td_stripsperimage == 0) { TIFFErrorExt(tif->tif_clientdata, module,"Zero strips per image"); return ((tmsize_t) -1); } tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ? cc : (tmsize_t) -1); }
/* * Compute how many strips are in an image. */ uint32 TIFFNumberOfStrips(TIFF* tif) { TIFFDirectory *td = &tif->tif_dir; uint32 nstrips; /* If the value was already computed and store in td_nstrips, then return it, since ChopUpSingleUncompressedStrip might have altered and resized the since the td_stripbytecount and td_stripoffset arrays to the new value after the initial affectation of td_nstrips = TIFFNumberOfStrips() in tif_dirread.c ~line 3612. See http://bugzilla.maptools.org/show_bug.cgi?id=2587 */ if( td->td_nstrips ) return td->td_nstrips; nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 : TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip)); if (td->td_planarconfig == PLANARCONFIG_SEPARATE) nstrips = _TIFFMultiply32(tif, nstrips, (uint32)td->td_samplesperpixel, "TIFFNumberOfStrips"); return (nstrips); }
int TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) { static const char module[] = "TIFFWriteScanline"; register TIFFDirectory *td; int status, imagegrew = 0; uint32 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); tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/ 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, module, "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, module, "%lu: Sample out of range, max %lu", (unsigned long) sample, (unsigned long) 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_32(td->td_imagelength,td->td_rowsperstrip); if (td->td_stripsperimage == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); return (-1); } 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, (uint8*) buf, tif->tif_scanlinesize ); status = (*tif->tif_encoderow)(tif, (uint8*) buf, tif->tif_scanlinesize, sample); /* we are now poised at the beginning of the next row */ tif->tif_row = row + 1; return (status); }
/* * 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). */ tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) { static const char module[] = "TIFFWriteEncodedTile"; TIFFDirectory *td; uint16 sample; uint32 howmany32; if (!WRITECHECKTILES(tif, module)) return ((tmsize_t)(-1)); td = &tif->tif_dir; if (tile >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tmsize_t)(-1)); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if (!BUFFERCHECK(tif)) return ((tmsize_t)(-1)); tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_curtile = tile; if( td->td_stripbytecount[tile] > 0 ) { /* Make sure that at the first attempt of rewriting the tile, we will have */ /* more bytes available in the output buffer than the previous byte count, */ /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] ) { if( !(TIFFWriteBufferSetup(tif, NULL, (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) ) return ((tmsize_t)(-1)); } /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; /* * Compute tiles per row & per column to compute * current row and column */ howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength); if (howmany32 == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); return ((tmsize_t)(-1)); } tif->tif_row = (tile % howmany32) * td->td_tilelength; howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth); if (howmany32 == 0) { TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); return ((tmsize_t)(-1)); } tif->tif_col = (tile % howmany32) * td->td_tilewidth; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tmsize_t)(-1)); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_flags &= ~TIFF_POSTENCODE; /* * 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; /* shortcut to avoid an extra memcpy() */ if( td->td_compression == COMPRESSION_NONE ) { /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*) data, cc); if (cc > 0 && !TIFFAppendToStrip(tif, tile, (uint8*) data, cc)) return ((tmsize_t) -1); return (cc); } sample = (uint16)(tile/td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_t)(-1)); /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample)) return ((tmsize_t) -1); if (!(*tif->tif_postencode)(tif)) return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc)) return ((tmsize_t)(-1)); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * Encode the supplied data and write it to the * specified strip. * * NB: Image length must be setup before writing. */ tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) { static const char module[] = "TIFFWriteEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; uint16 sample; if (!WRITECHECKSTRIPS(tif, module)) return ((tmsize_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, module, "Can not grow image by strips when using separate planes"); return ((tmsize_t) -1); } if (!TIFFGrowStrips(tif, 1, module)) return ((tmsize_t) -1); td->td_stripsperimage = TIFFhowmany_32(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 ((tmsize_t) -1); tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_curstrip = strip; if (td->td_stripsperimage == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); return ((tmsize_t) -1); } tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tmsize_t) -1); tif->tif_flags |= TIFF_CODERSETUP; } if( td->td_stripbytecount[strip] > 0 ) { /* Make sure that at the first attempt of rewriting the tile, we will have */ /* more bytes available in the output buffer than the previous byte count, */ /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] ) { if( !(TIFFWriteBufferSetup(tif, NULL, (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) ) return ((tmsize_t)(-1)); } /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; tif->tif_flags &= ~TIFF_POSTENCODE; /* shortcut to avoid an extra memcpy() */ if( td->td_compression == COMPRESSION_NONE ) { /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*) data, cc); if (cc > 0 && !TIFFAppendToStrip(tif, strip, (uint8*) data, cc)) return ((tmsize_t) -1); return (cc); } sample = (uint16)(strip / td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_t) -1); /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample)) return ((tmsize_t) -1); if (!(*tif->tif_postencode)(tif)) return ((tmsize_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 ((tmsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * 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). */ tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) { static const char module[] = "TIFFWriteEncodedTile"; TIFFDirectory *td; uint16 sample; if (!WRITECHECKTILES(tif, module)) return ((tmsize_t)(-1)); td = &tif->tif_dir; if (tile >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tmsize_t)(-1)); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if (!BUFFERCHECK(tif)) return ((tmsize_t)(-1)); tif->tif_flags |= TIFF_BUF4WRITE; 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_32(td->td_imagelength, td->td_tilelength)) * td->td_tilelength; tif->tif_col = (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth)) * td->td_tilewidth; if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupencode)(tif)) return ((tmsize_t)(-1)); tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_flags &= ~TIFF_POSTENCODE; sample = (uint16)(tile/td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_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, (uint8*) data, cc ); if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample)) return (0); if (!(*tif->tif_postencode)(tif)) return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc)) return ((tmsize_t)(-1)); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }
/* * Encode the supplied data and write it to the * specified strip. * * NB: Image length must be setup before writing. */ tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) { static const char module[] = "TIFFWriteEncodedStrip"; TIFFDirectory *td = &tif->tif_dir; uint16 sample; if (!WRITECHECKSTRIPS(tif, module)) return ((tmsize_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, module, "Can not grow image by strips when using separate planes"); return ((tmsize_t) -1); } if (!TIFFGrowStrips(tif, 1, module)) return ((tmsize_t) -1); td->td_stripsperimage = TIFFhowmany_32(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 ((tmsize_t) -1); tif->tif_flags |= TIFF_BUF4WRITE; 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 ((tmsize_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 = (uint16)(strip / td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_t) -1); /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample)) return (0); if (!(*tif->tif_postencode)(tif)) return ((tmsize_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 ((tmsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); }