📄 tif_write.c
字号:
/* $Header: /cvsroot/osrs/libtiff/libtiff/tif_write.c,v 1.5 2000/02/11 19:28:17 warmerda 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 Write Support */#include "tiffiop.h"#include <assert.h>#include <stdio.h>#define REWRITE_HACK#define STRIPINCR 20 /* expansion factor on strip array */#define WRITECHECKSTRIPS(tif, module) \ (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module))#define WRITECHECKTILES(tif, module) \ (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module))#define BUFFERCHECK(tif) \ ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \ TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1))static int TIFFGrowStrips(TIFF*, int, const char*);static int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);static int TIFFSetupStrips(TIFF*);intTIFFWriteScanline(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) { TIFFError(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) { TIFFError(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; 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; } if (!(*tif->tif_preencode)(tif, sample)) return (-1); tif->tif_flags |= TIFF_POSTENCODE; } /* * 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); /* * 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; } status = (*tif->tif_encoderow)(tif, (tidata_t) buf, tif->tif_scanlinesize, sample); tif->tif_row++; return (status);}/* * Encode the supplied data and write it to the * specified strip. There must be space for the * data; we don't check if strips overlap! * * NB: Image length must be setup before writing. */tsize_tTIFFWriteEncodedStrip(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) { TIFFError(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; } #ifdef REWRITE_HACK 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; }#endif tif->tif_flags &= ~TIFF_POSTENCODE; sample = (tsample_t)(strip / td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tsize_t) -1); 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);}/* * Write the supplied data to the specified strip. * There must be space for the data; we don't check * if strips overlap! * * NB: Image length must be setup before writing. */tsize_tTIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc){ static const char module[] = "TIFFWriteRawStrip"; TIFFDirectory *td = &tif->tif_dir; 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) { TIFFError(tif->tif_name, "Can not grow image by strips when using separate planes"); return ((tsize_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(td->td_imagelength,td->td_rowsperstrip); if (!TIFFGrowStrips(tif, 1, module)) return ((tsize_t) -1); } tif->tif_curstrip = strip; tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ? cc : (tsize_t) -1);}/* * Write and compress a tile of data. The * tile is selected by the (x,y,z,s) coordinates. */tsize_tTIFFWriteTile(TIFF* tif, tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s){ if (!TIFFCheckTile(tif, x, y, z, s)) return (-1); /* * NB: A tile size of -1 is used instead of tif_tilesize knowing * that TIFFWriteEncodedTile will clamp this to the tile size. * This is done because the tile size may not be defined until * after the output buffer is setup in TIFFWriteBufferSetup. */ return (TIFFWriteEncodedTile(tif, TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));}/* * 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_tTIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc){ static const char module[] = "TIFFWriteEncodedTile"; TIFFDirectory *td; tsample_t sample;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -