/* $Header: /roq/tiff/tif_strip.c 1 11/02/99 4:39p Zaphod $ */ /* * Copyright (c) 1991-1996 Sam Leffler * Copyright (c) 1991-1996 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Strip-organized Image Support Routines. */ #include "tiffiop.h" /* * Compute which strip a (row,sample) value is in. */ tstrip_t TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample) { TIFFDirectory *td = &tif->tif_dir; tstrip_t strip; strip = row / td->td_rowsperstrip; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { if (sample >= td->td_samplesperpixel) { TIFFError(tif->tif_name, "%u: Sample out of range, max %u", sample, td->td_samplesperpixel); return ((tstrip_t) 0); } strip += sample*td->td_stripsperimage; } return (strip); } /* * Compute how many strips are in an image. */ tstrip_t TIFFNumberOfStrips(TIFF* tif) { TIFFDirectory *td = &tif->tif_dir; tstrip_t nstrips; nstrips = (td->td_rowsperstrip == (uint32) -1 ? (td->td_imagelength != 0 ? 1 : 0) : TIFFhowmany(td->td_imagelength, td->td_rowsperstrip)); if (td->td_planarconfig == PLANARCONFIG_SEPARATE) nstrips *= td->td_samplesperpixel; return (nstrips); } /* * Compute the # bytes in a variable height, row-aligned strip. */ tsize_t TIFFVStripSize(TIFF* tif, uint32 nrows) { TIFFDirectory *td = &tif->tif_dir; if (nrows == (uint32) -1) nrows = td->td_imagelength; #ifdef YCBCR_SUPPORT 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. */ tsize_t w = TIFFroundup(td->td_imagewidth, td->td_ycbcrsubsampling[0]); tsize_t scanline = TIFFhowmany(w*td->td_bitspersample, 8); tsize_t samplingarea = td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]); /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ return ((tsize_t) (nrows*scanline + 2*(nrows*scanline / samplingarea))); } else #endif return ((tsize_t)(nrows * TIFFScanlineSize(tif))); } /* * Compute the # bytes in a (row-aligned) strip. * * Note that if RowsPerStrip is larger than the * recorded ImageLength, then the strip size is * truncated to reflect the actual space required * to hold the strip. */ tsize_t TIFFStripSize(TIFF* tif) { TIFFDirectory* td = &tif->tif_dir; uint32 rps = td->td_rowsperstrip; if (rps > td->td_imagelength) rps = td->td_imagelength; return (TIFFVStripSize(tif, rps)); } /* * Compute a default strip size based on the image * characteristics and a requested value. If the * request is <1 then we choose a strip size according * to certain heuristics. */ uint32 TIFFDefaultStripSize(TIFF* tif, uint32 request) { return (*tif->tif_defstripsize)(tif, request); } uint32 _TIFFDefaultStripSize(TIFF* tif, uint32 s) { if ((int32) s < 1) { /* * If RowsPerStrip is unspecified, try to break the * image up into strips that are approximately 8Kbytes. */ tsize_t scanline = TIFFScanlineSize(tif); s = (uint32)(8*1024) / (scanline == 0 ? 1 : scanline); if (s == 0) /* very wide images */ s = 1; } return (s); } /* * 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. */ tsize_t TIFFScanlineSize(TIFF* tif) { TIFFDirectory *td = &tif->tif_dir; tsize_t scanline; scanline = td->td_bitspersample * td->td_imagewidth; if (td->td_planarconfig == PLANARCONFIG_CONTIG) scanline *= td->td_samplesperpixel; return ((tsize_t) TIFFhowmany(scanline, 8)); } /* * Return the number of bytes required to store a complete * decoded and packed raster scanline (as opposed to the * I/O size returned by TIFFScanlineSize which may be less * if data is store as separate planes). */ tsize_t TIFFRasterScanlineSize(TIFF* tif) { TIFFDirectory *td = &tif->tif_dir; tsize_t scanline; scanline = td->td_bitspersample * td->td_imagewidth; if (td->td_planarconfig == PLANARCONFIG_CONTIG) { scanline *= td->td_samplesperpixel; return ((tsize_t) TIFFhowmany(scanline, 8)); } else return ((tsize_t) TIFFhowmany(scanline, 8)*td->td_samplesperpixel); }