📄 tif_write.c
字号:
if (!WRITECHECKTILES(tif, module)) return ((tsize_t) -1); td = &tif->tif_dir; if (tile >= td->td_nstrips) { TIFFError(module, "%s: Tile %lu out of range, max %lu", tif->tif_name, (u_long) tile, (u_long) td->td_nstrips); return ((tsize_t) -1); } /* * Handle delayed allocation of data buffer. This * permits it to be sized more intelligently (using * directory information). */ if (!BUFFERCHECK(tif)) return ((tsize_t) -1); tif->tif_curtile = tile;#ifdef REWRITE_HACK 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; }#endif /* * 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; 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((u_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_tTIFFWriteRawTile(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, (u_long) tile, (u_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)static intTIFFSetupStrips(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. */intTIFFWriteCheck(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 = TIFFTileSize(tif); tif->tif_scanlinesize = TIFFScanlineSize(tif); tif->tif_flags |= TIFF_BEENWRITING; return (1);}/* * Setup the raw data buffer used for encoding. */intTIFFWriteBufferSetup(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 : tif->tif_scanlinesize); /* * 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 intTIFFGrowStrips(TIFF* tif, int delta, const char* module){ TIFFDirectory *td = &tif->tif_dir; assert(td->td_planarconfig == PLANARCONFIG_CONTIG); td->td_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset, (td->td_nstrips + delta) * sizeof (uint32)); td->td_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount, (td->td_nstrips + delta) * sizeof (uint32)); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) { td->td_nstrips = 0; TIFFError(module, "%s: No space to expand strip arrays", tif->tif_name); return (0); } _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. * * NB: We don't check that there's space in the * file (i.e. that strips do not overlap). */static intTIFFAppendToStrip(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_stripoffset[strip] != 0) { if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFError(module, "%s: Seek error at scanline %lu", tif->tif_name, (u_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, (u_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. */intTIFFFlushData1(TIFF* tif){ if (tif->tif_rawcc > 0) { if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((u_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. */voidTIFFSetWriteOffset(TIFF* tif, toff_t off){ tif->tif_curoff = off;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -