📄 tif_write.c
字号:
return ((tsize_t) -1);
tif->tif_curtile = tile;
tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata;
if( td->td_stripbytecount[tile] > 0 )
{
/* if we are writing over existing tiles, zero length. */
td->td_stripbytecount[tile] = 0;
/* this forces TIFFAppendToStrip() to do a seek */
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);
}
/*
* 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; this
* interface does not support automatically growing
* the image on each write (as TIFFWriteScanline does).
*/
tsize_t
TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
{
static const char module[] = "TIFFWriteRawTile";
if (!WRITECHECKTILES(tif, module))
return ((tsize_t) -1);
if (tile >= tif->tif_dir.td_nstrips) {
TIFFError(module, "%s: Tile %lu out of range, max %lu",
tif->tif_name, (unsigned long) tile,
(unsigned long) tif->tif_dir.td_nstrips);
return ((tsize_t) -1);
}
return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
cc : (tsize_t) -1);
}
#define isUnspecified(tif, f) \
(TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
int
TIFFSetupStrips(TIFF* tif)
{
TIFFDirectory* td = &tif->tif_dir;
if (isTiled(tif))
td->td_stripsperimage =
isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
td->td_samplesperpixel : TIFFNumberOfTiles(tif);
else
td->td_stripsperimage =
isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
td->td_samplesperpixel : TIFFNumberOfStrips(tif);
td->td_nstrips = td->td_stripsperimage;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
td->td_stripsperimage /= td->td_samplesperpixel;
td->td_stripoffset = (uint32 *)
_TIFFmalloc(td->td_nstrips * sizeof (uint32));
td->td_stripbytecount = (uint32 *)
_TIFFmalloc(td->td_nstrips * sizeof (uint32));
if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
return (0);
/*
* Place data at the end-of-file
* (by setting offsets to zero).
*/
_TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
_TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
return (1);
}
#undef isUnspecified
/*
* 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) {
TIFFError(module, "%s: File not open for writing",
tif->tif_name);
return (0);
}
if (tiles ^ isTiled(tif)) {
TIFFError(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)) {
TIFFError(module,
"%s: Must set \"ImageWidth\" before writing data",
tif->tif_name);
return (0);
}
if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
TIFFError(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;
TIFFError(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);
}
/*
* Setup the raw data buffer used for encoding.
*/
int
TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
{
static const char module[] = "TIFFWriteBufferSetup";
if (tif->tif_rawdata) {
if (tif->tif_flags & TIFF_MYBUFFER) {
_TIFFfree(tif->tif_rawdata);
tif->tif_flags &= ~TIFF_MYBUFFER;
}
tif->tif_rawdata = NULL;
}
if (size == (tsize_t) -1) {
size = (isTiled(tif) ?
tif->tif_tilesize : TIFFStripSize(tif));
/*
* Make raw data buffer at least 8K
*/
if (size < 8*1024)
size = 8*1024;
bp = NULL; /* NB: force malloc */
}
if (bp == NULL) {
bp = _TIFFmalloc(size);
if (bp == NULL) {
TIFFError(module, "%s: No space for output buffer",
tif->tif_name);
return (0);
}
tif->tif_flags |= TIFF_MYBUFFER;
} else
tif->tif_flags &= ~TIFF_MYBUFFER;
tif->tif_rawdata = (tidata_t) bp;
tif->tif_rawdatasize = size;
tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata;
tif->tif_flags |= TIFF_BUFFERSETUP;
return (1);
}
/*
* Grow the strip data structures by delta strips.
*/
static int
TIFFGrowStrips(TIFF* tif, int delta, const char* module)
{
TIFFDirectory *td = &tif->tif_dir;
uint32 *new_stripoffset, *new_stripbytecount;
assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
(td->td_nstrips + delta) * sizeof (uint32));
new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
(td->td_nstrips + delta) * sizeof (uint32));
if (new_stripoffset == NULL || new_stripbytecount == NULL) {
if (new_stripoffset)
_TIFFfree(new_stripoffset);
if (new_stripbytecount)
_TIFFfree(new_stripbytecount);
td->td_nstrips = 0;
TIFFError(module, "%s: No space to expand strip arrays",
tif->tif_name);
return (0);
}
td->td_stripoffset = new_stripoffset;
td->td_stripbytecount = new_stripbytecount;
_TIFFmemset(td->td_stripoffset + td->td_nstrips,
0, delta*sizeof (uint32));
_TIFFmemset(td->td_stripbytecount + td->td_nstrips,
0, delta*sizeof (uint32));
td->td_nstrips += delta;
return (1);
}
/*
* Append the data to the specified strip.
*/
static int
TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
{
TIFFDirectory *td = &tif->tif_dir;
static const char module[] = "TIFFAppendToStrip";
if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
/*
* No current offset, set the current strip.
*/
if (td->td_nstrips || td->td_stripoffset[strip] != 0) {
/*
* Prevent overlapping of the data chunks. We need
* this to enable in place updating of the compressed
* images. Larger blocks will be moved at the end of
* the file without any optimization of the spare
* space, so such scheme is not too much effective.
*/
if (td->td_stripbytecountsorted) {
if (strip == td->td_nstrips - 1
|| td->td_stripoffset[strip + 1] <
td->td_stripoffset[strip] + cc) {
td->td_stripoffset[strip] =
TIFFSeekFile(tif, (toff_t)0,
SEEK_END);
}
} else {
tstrip_t i;
for (i = 0; i < td->td_nstrips; i++) {
if (td->td_stripoffset[i] >
td->td_stripoffset[strip]
&& td->td_stripoffset[i] <
td->td_stripoffset[strip] + cc) {
td->td_stripoffset[strip] =
TIFFSeekFile(tif,
(toff_t)0,
SEEK_END);
}
}
}
if (!SeekOK(tif, td->td_stripoffset[strip])) {
TIFFError(module,
"%s: Seek error at scanline %lu",
tif->tif_name,
(unsigned long)tif->tif_row);
return (0);
}
} else
td->td_stripoffset[strip] =
TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
tif->tif_curoff = td->td_stripoffset[strip];
}
if (!WriteOK(tif, data, cc)) {
TIFFError(module, "%s: Write error at scanline %lu",
tif->tif_name, (unsigned long) tif->tif_row);
return (0);
}
tif->tif_curoff += cc;
td->td_stripbytecount[strip] += cc;
return (1);
}
/*
* Internal version of TIFFFlushData that can be
* called by ``encodestrip routines'' w/o concern
* for infinite recursion.
*/
int
TIFFFlushData1(TIFF* tif)
{
if (tif->tif_rawcc > 0) {
if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0)
TIFFReverseBits((unsigned char *)tif->tif_rawdata,
tif->tif_rawcc);
if (!TIFFAppendToStrip(tif,
isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
tif->tif_rawdata, tif->tif_rawcc))
return (0);
tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata;
}
return (1);
}
/*
* Set the current write offset. This should only be
* used to set the offset to a known previous location
* (very carefully), or to 0 so that the next write gets
* appended to the end of the file.
*/
void
TIFFSetWriteOffset(TIFF* tif, toff_t off)
{
tif->tif_curoff = off;
}
/* vim: set ts=8 sts=8 sw=8 noet: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -