?? tif_read.c
字號:
/* $Id: tif_read.c,v 1.15 2006/10/12 15:01:30 dron Exp $ *//* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 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. * Scanline-oriented Read Support */#include "tiffiop.h"#include <stdio.h> int TIFFFillStrip(TIFF*, tstrip_t); int TIFFFillTile(TIFF*, ttile_t);static int TIFFStartStrip(TIFF*, tstrip_t);static int TIFFStartTile(TIFF*, ttile_t);static int TIFFCheckRead(TIFF*, int);#define NOSTRIP ((tstrip_t) -1) /* undefined state */#define NOTILE ((ttile_t) -1) /* undefined state *//* * Seek to a random row+sample in a file. */static intTIFFSeek(TIFF* tif, uint32 row, tsample_t sample){ register TIFFDirectory *td = &tif->tif_dir; tstrip_t strip; 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 = sample*td->td_stripsperimage + row/td->td_rowsperstrip; } else strip = row / td->td_rowsperstrip; if (strip != tif->tif_curstrip) { /* different strip, refill */ if (!TIFFFillStrip(tif, strip)) return (0); } else 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 (!TIFFStartStrip(tif, strip)) return (0); } if (row != tif->tif_row) { /* * Seek forward to the desired row. */ if (!(*tif->tif_seek)(tif, row - tif->tif_row)) return (0); tif->tif_row = row; } return (1);}intTIFFReadScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample){ int e; if (!TIFFCheckRead(tif, 0)) return (-1); if( (e = TIFFSeek(tif, row, sample)) != 0) { /* * Decompress desired row into user buffer. */ e = (*tif->tif_decoderow) (tif, (tidata_t) buf, tif->tif_scanlinesize, sample); /* we are now poised at the beginning of the next row */ tif->tif_row = row + 1; if (e) (*tif->tif_postdecode)(tif, (tidata_t) buf, tif->tif_scanlinesize); } return (e > 0 ? 1 : -1);}/* * Read a strip of data and decompress the specified * amount into the user-supplied buffer. */tsize_tTIFFReadEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size){ TIFFDirectory *td = &tif->tif_dir; uint32 nrows; tsize_t stripsize; tstrip_t sep_strip, strips_per_sep; if (!TIFFCheckRead(tif, 0)) return (-1); if (strip >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%ld: Strip out of range, max %ld", (long) strip, (long) td->td_nstrips); return (-1); } /* * Calculate the strip size according to the number of * rows in the strip (check for truncated last strip on any * of the separations). */ if( td->td_rowsperstrip >= td->td_imagelength ) strips_per_sep = 1; else strips_per_sep = (td->td_imagelength+td->td_rowsperstrip-1) / td->td_rowsperstrip; sep_strip = strip % strips_per_sep; if (sep_strip != strips_per_sep-1 || (nrows = td->td_imagelength % td->td_rowsperstrip) == 0) nrows = td->td_rowsperstrip; stripsize = TIFFVStripSize(tif, nrows); if (size == (tsize_t) -1) size = stripsize; else if (size > stripsize) size = stripsize; if (TIFFFillStrip(tif, strip) && (*tif->tif_decodestrip)(tif, (tidata_t) buf, size, (tsample_t)(strip / td->td_stripsperimage)) > 0 ) { (*tif->tif_postdecode)(tif, (tidata_t) buf, size); return (size); } else return ((tsize_t) -1);}static tsize_tTIFFReadRawStrip1(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size, const char* module){ TIFFDirectory *td = &tif->tif_dir; assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tsize_t cc; if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Seek error at scanline %lu, strip %lu", tif->tif_name, (unsigned long) tif->tif_row, (unsigned long) strip); return (-1); } cc = TIFFReadFile(tif, buf, size); if (cc != size) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Read error at scanline %lu; got %lu bytes, expected %lu", tif->tif_name, (unsigned long) tif->tif_row, (unsigned long) cc, (unsigned long) size); return (-1); } } else { if (td->td_stripoffset[strip] + size > tif->tif_size) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu", tif->tif_name, (unsigned long) tif->tif_row, (unsigned long) strip, (unsigned long) tif->tif_size - td->td_stripoffset[strip], (unsigned long) size); return (-1); } _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip], size); } return (size);}/* * Read a strip of data from the file. */tsize_tTIFFReadRawStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size){ static const char module[] = "TIFFReadRawStrip"; TIFFDirectory *td = &tif->tif_dir; tsize_t bytecount; if (!TIFFCheckRead(tif, 0)) return ((tsize_t) -1); if (strip >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Strip out of range, max %lu", (unsigned long) strip, (unsigned long) td->td_nstrips); return ((tsize_t) -1); } if (tif->tif_flags&TIFF_NOREADRAW) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Compression scheme does not support access to raw uncompressed data"); return ((tsize_t) -1); } bytecount = td->td_stripbytecount[strip]; if (bytecount <= 0) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%lu: Invalid strip byte count, strip %lu", (unsigned long) bytecount, (unsigned long) strip); return ((tsize_t) -1); } if (size != (tsize_t)-1 && size < bytecount) bytecount = size; return (TIFFReadRawStrip1(tif, strip, buf, bytecount, module));}/* * Read the specified strip and setup for decoding. The data buffer is * expanded, as necessary, to hold the strip's data. */intTIFFFillStrip(TIFF* tif, tstrip_t strip){ static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; if ((tif->tif_flags&TIFF_NOREADRAW)==0) { tsize_t bytecount = td->td_stripbytecount[strip]; if (bytecount <= 0) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Invalid strip byte count %lu, strip %lu", tif->tif_name, (unsigned long) bytecount, (unsigned long) strip); 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_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 > tif->tif_size || td->td_stripoffset[strip] > tif->tif_size - bytecount) { /* * This error message might seem strange, but * it's what would happen if a read were done * instead. */ TIFFErrorExt(tif->tif_clientdata, module, "%s: Read error on strip %lu; " "got %lu bytes, expected %lu", tif->tif_name, (unsigned long) strip, (unsigned long) tif->tif_size - td->td_stripoffset[strip], (unsigned long) bytecount); tif->tif_curstrip = NOSTRIP; return (0); } tif->tif_rawdatasize = bytecount; tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip]; } 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?). */ if (bytecount > tif->tif_rawdatasize) { tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Data buffer too small to hold strip %lu", tif->tif_name, (unsigned long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, TIFFroundup(bytecount, 1024))) return (0); } if (TIFFReadRawStrip1(tif, strip, (unsigned char *)tif->tif_rawdata, bytecount, module) != bytecount) return (0); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, bytecount); } } return (TIFFStartStrip(tif, strip));}/* * Tile-oriented Read Support * Contributed by Nancy Cam (Silicon Graphics). *//* * Read and decompress a tile of data. The * tile is selected by the (x,y,z,s) coordinates. */tsize_tTIFFReadTile(TIFF* tif, tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s){
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -