static int initImage(void) { uint32 w, h; if (order) TIFFSetField(tif, TIFFTAG_FILLORDER, order); if (photo != (uint16) -1) TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photo); if (!TIFFRGBAImageBegin(&img, tif, stoponerr, title)) { TIFFError(filelist[fileindex], "%s", title); TIFFClose(tif); tif = NULL; return -1; } /* * Setup the image raster as required. */ h = img.height; w = img.width; if (h > ymax) { w = (int)(w * ((float)ymax / h)); h = ymax; } if (w > xmax) { h = (int)(h * ((float)xmax / w)); w = xmax; } if (w != width || h != height) { uint32 rastersize = _TIFFMultiply32(tif, img.width, img.height, "allocating raster buffer"); if (raster != NULL) _TIFFfree(raster), raster = NULL; raster = (uint32*) _TIFFCheckMalloc(tif, rastersize, sizeof (uint32), "allocating raster buffer"); if (raster == NULL) { width = height = 0; TIFFError(filelist[fileindex], "No space for raster buffer"); cleanup_and_exit(); } width = w; height = h; } TIFFRGBAImageGet(&img, raster, img.width, img.height); #if HOST_BIGENDIAN TIFFSwabArrayOfLong(raster,img.width*img.height); #endif return 0; }
int _TIFFMergeFields(TIFF* tif, const TIFFField info[], uint32 n) { static const char module[] = "_TIFFMergeFields"; static const char reason[] = "for fields array"; /* TIFFField** tp; */ uint32 i; tif->tif_foundfield = NULL; if (tif->tif_fields && tif->tif_nfields > 0) { tif->tif_fields = (TIFFField**) _TIFFCheckRealloc(tif, tif->tif_fields, (tif->tif_nfields + n), sizeof(TIFFField *), reason); } else { tif->tif_fields = (TIFFField **) _TIFFCheckMalloc(tif, n, sizeof(TIFFField *), reason); } if (!tif->tif_fields) { TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate fields array"); return 0; } /* tp = tif->tif_fields + tif->tif_nfields; */ for (i = 0; i < n; i++) { const TIFFField *fip = TIFFFindField(tif, info[i].field_tag, TIFF_ANY); /* only add definitions that aren't already present */ if (!fip) { tif->tif_fields[tif->tif_nfields] = (TIFFField *) (info+i); tif->tif_nfields++; } } /* Sort the field info by tag number */ qsort(tif->tif_fields, tif->tif_nfields, sizeof(TIFFField *), tagCompare); return n; }
int _TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n) { static const char module[] = "_TIFFMergeFieldInfo"; static const char reason[] = "for field info array"; TIFFFieldInfo** tp; int i; tif->tif_foundfield = NULL; if (tif->tif_nfields > 0) { tif->tif_fieldinfo = (TIFFFieldInfo**) _TIFFCheckRealloc(tif, tif->tif_fieldinfo, (tif->tif_nfields + n), sizeof (TIFFFieldInfo*), reason); } else { tif->tif_fieldinfo = (TIFFFieldInfo**) _TIFFCheckMalloc(tif, n, sizeof (TIFFFieldInfo*), reason); } if (!tif->tif_fieldinfo) { TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate field info array"); return 0; } tp = tif->tif_fieldinfo + tif->tif_nfields; for (i = 0; i < n; i++) { const TIFFFieldInfo *fip = _TIFFFindFieldInfo(tif, info[i].field_tag, info[i].field_type); /* only add definitions that aren't already present */ if (!fip) { *tp++ = (TIFFFieldInfo*) (info + i); tif->tif_nfields++; } } /* Sort the field info by tag number */ qsort(tif->tif_fieldinfo, tif->tif_nfields, sizeof (TIFFFieldInfo*), tagCompare); return n; }
int TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], uint32 n) { static const char module[] = "TIFFMergeFieldInfo"; static const char reason[] = "for fields array"; TIFFField *tp; size_t nfields; uint32 i; if (tif->tif_nfieldscompat > 0) { tif->tif_fieldscompat = (TIFFFieldArray *) _TIFFCheckRealloc(tif, tif->tif_fieldscompat, tif->tif_nfieldscompat + 1, sizeof(TIFFFieldArray), reason); } else { tif->tif_fieldscompat = (TIFFFieldArray *) _TIFFCheckMalloc(tif, 1, sizeof(TIFFFieldArray), reason); } if (!tif->tif_fieldscompat) { TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate fields array"); return -1; } nfields = tif->tif_nfieldscompat++; tif->tif_fieldscompat[nfields].type = tfiatOther; tif->tif_fieldscompat[nfields].allocated_size = n; tif->tif_fieldscompat[nfields].count = n; tif->tif_fieldscompat[nfields].fields = (TIFFField *)_TIFFCheckMalloc(tif, n, sizeof(TIFFField), reason); if (!tif->tif_fieldscompat[nfields].fields) { TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate fields array"); return -1; } tp = tif->tif_fieldscompat[nfields].fields; for (i = 0; i < n; i++) { tp->field_tag = info[i].field_tag; tp->field_readcount = info[i].field_readcount; tp->field_writecount = info[i].field_writecount; tp->field_type = info[i].field_type; tp->reserved = 0; tp->set_field_type = _TIFFSetGetType(info[i].field_type, info[i].field_readcount, info[i].field_passcount); tp->get_field_type = _TIFFSetGetType(info[i].field_type, info[i].field_readcount, info[i].field_passcount); tp->field_bit = info[i].field_bit; tp->field_oktochange = info[i].field_oktochange; tp->field_passcount = info[i].field_passcount; tp->field_name = info[i].field_name; tp->field_subfields = NULL; tp++; } if (!_TIFFMergeFields(tif, tif->tif_fieldscompat[nfields].fields, n)) { TIFFErrorExt(tif->tif_clientdata, module, "Setting up field info failed"); return -1; } return 0; }
static int tiffcvt(TIFF* in, TIFF* out) { uint32 width, height; /* image width & height */ uint32* raster; /* retrieve RGBA image */ uint16 shortv; float floatv; char *stringv; uint32 longv; size_t pixel_count; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); pixel_count = width * height; /* XXX: Check the integer overflow. */ if (!width || !height || pixel_count / width != height) { TIFFError(TIFFFileName(in), "Malformed input file; " "can't allocate buffer for raster of %lux%lu size", (unsigned long)width, (unsigned long)height); return 0; } raster = (uint32*)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32), "raster buffer"); if (raster == 0) { TIFFError(TIFFFileName(in), "Requested buffer size is %lu elements %lu each", (unsigned long)pixel_count, (unsigned long)sizeof(uint32)); return (0); } if (!TIFFReadRGBAImage(in, width, height, raster, 0)) { _TIFFfree(raster); return (0); } CopyField(TIFFTAG_SUBFILETYPE, longv); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(out, TIFFTAG_IMAGELENGTH, height); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_COMPRESSION, compression); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR); if (compression == COMPRESSION_JPEG) TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW); CopyField(TIFFTAG_FILLORDER, shortv); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3); CopyField(TIFFTAG_XRESOLUTION, floatv); CopyField(TIFFTAG_YRESOLUTION, floatv); CopyField(TIFFTAG_RESOLUTIONUNIT, shortv); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); { char buf[2048]; char *cp = strrchr(TIFFFileName(in), '/'); sprintf(buf, "YCbCr conversion of %s", cp ? cp+1 : TIFFFileName(in)); TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, buf); } TIFFSetField(out, TIFFTAG_SOFTWARE, TIFFGetVersion()); CopyField(TIFFTAG_DOCUMENTNAME, stringv); TIFFSetField(out, TIFFTAG_REFERENCEBLACKWHITE, refBlackWhite); TIFFSetField(out, TIFFTAG_YCBCRSUBSAMPLING, horizSubSampling, vertSubSampling); TIFFSetField(out, TIFFTAG_YCBCRPOSITIONING, YCBCRPOSITION_CENTERED); TIFFSetField(out, TIFFTAG_YCBCRCOEFFICIENTS, ycbcrCoeffs); rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); return (cvtRaster(out, raster, width, height)); }
static int cvt_whole_image( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 row; size_t pixel_count; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); pixel_count = width * height; /* XXX: Check the integer overflow. */ if (!width || !height || pixel_count / width != height) { TIFFError(TIFFFileName(in), "Malformed input file; can't allocate buffer for raster of %lux%lu size", (unsigned long)width, (unsigned long)height); return 0; } rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); raster = (uint32*)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32), "raster buffer"); if (raster == 0) { TIFFError(TIFFFileName(in), "Failed to allocate buffer (%lu elements of %lu each)", (unsigned long)pixel_count, (unsigned long)sizeof(uint32)); return (0); } /* Read the image in one chunk into an RGBA array */ if (!TIFFReadRGBAImageOriented(in, width, height, raster, ORIENTATION_TOPLEFT, 0)) { _TIFFfree(raster); return (0); } /* * XXX: raster array has 4-byte unsigned integer type, that is why * we should rearrange it here. */ #if HOST_BIGENDIAN TIFFSwabArrayOfLong(raster, width * height); #endif /* * Do we want to strip away alpha components? */ if (no_alpha) { size_t count = pixel_count; unsigned char *src, *dst; src = dst = (unsigned char *) raster; while (count > 0) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; count--; } } /* * Write out the result in strips */ for (row = 0; row < height; row += rowsperstrip) { unsigned char * raster_strip; int rows_to_write; int bytes_per_pixel; if (no_alpha) { raster_strip = ((unsigned char *) raster) + 3 * row * width; bytes_per_pixel = 3; } else { raster_strip = (unsigned char *) (raster + row * width); bytes_per_pixel = 4; } if( row + rowsperstrip > height ) rows_to_write = height - row; else rows_to_write = rowsperstrip; if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster_strip, bytes_per_pixel * rows_to_write * width ) == -1 ) { _TIFFfree( raster ); return 0; } } _TIFFfree( raster ); return 1; }
/* * Write the contents of the current directory * to the specified file. This routine doesn't * handle overwriting a directory with auxiliary * storage that's been changed. */ static int _TIFFWriteDirectory(TIFF* tif, int done) { uint64 dircount; /* 16-bit or 64-bit directory entry count */ toff_t diroff; /* 32-bit or 64-bit directory offset */ ttag_t tag; uint32 nfields; tsize_t dirsize; char* data; TIFFDirEntry* dir; TIFFDirectory* td; unsigned long b, fields[FIELD_SETLONGS]; int fi, nfi; if (tif->tif_mode == O_RDONLY) return (1); /* * Clear write state so that subsequent images with * different characteristics get the right buffers * setup for them. */ if (done) { if (tif->tif_flags & TIFF_POSTENCODE) { tif->tif_flags &= ~TIFF_POSTENCODE; if (!(*tif->tif_postencode)(tif)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error post-encoding before directory write"); return (0); } } (*tif->tif_close)(tif); /* shutdown encoder */ /* * Flush any data that might have been written * by the compression close+cleanup routines. */ if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error flushing data before directory write"); return (0); } if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { _TIFFfree(tif->tif_rawdata); tif->tif_rawdata = NULL; tif->tif_rawcc = 0; tif->tif_rawdatasize = 0; } tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); } /* * Loop to allow retry in case transition to BigTIFF required */ while (1) { /* * Directory hasn't been placed yet, put * it at the end of the file and link it * into the existing directory structure. */ if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif)) goto bad2; td = &tif->tif_dir; /* * Size the directory so that we can calculate * offsets for the data items that aren't kept * in-place in each field. */ nfields = 0; for (b = 0; b <= FIELD_LAST; b++) if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM) nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); nfields += td->td_customValueCount; dirsize = nfields * TDIREntryLen(tif); data = (char*) _TIFFmalloc(dirsize); if (data == NULL) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Cannot write directory, out of space"); goto bad2; } _TIFFmemset(data, 0, dirsize); /* * Setup external form of directory * entries and write data items. */ _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); /* * Write out ExtraSamples tag only if * extra samples are present in the data. */ if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) { ResetFieldBit(fields, FIELD_EXTRASAMPLES); nfields--; dirsize -= TDIREntryLen(tif); } /*XXX*/ tif->tif_dataoff = tif->tif_diroff + TIFFDirCntLen(tif) + dirsize + TIFFDirOffLen(tif); (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); dir = (TIFFDirEntry*) data; for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; /* ** For custom fields, we test to see if the custom field ** is set or not. For normal fields, we just use the ** FieldSet test. */ if( fip->field_bit == FIELD_CUSTOM ) { int ci, is_set = FALSE; for( ci = 0; ci < td->td_customValueCount; ci++ ) is_set |= (td->td_customValues[ci].info == fip); if( !is_set ) continue; } else if (!FieldSet(fields, fip->field_bit)) continue; /* ** Handle other fields. */ switch (fip->field_bit) { case FIELD_STRIPOFFSETS: /* * We use one field bit for both strip and tile * offsets, and so must be careful in selecting * the appropriate field descriptor (so that tags * are written in sorted order). */ tag = (isTiled(tif) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS); if (tag != fip->field_tag) continue; dir->s.tdir_tag = (uint16) tag; TDIRSetEntryCount(tif,dir, (uint32) td->td_nstrips); /* * If file is BigTIFF strip/tile offsets are written as 64-bit, * else convert to array of 32-bit offsets. */ if (isBigTIFF(tif)) { dir->s.tdir_type = (uint16) TIFF_LONG8; if (!TIFFWriteLong8Array(tif, dir, td->td_stripoffset)) goto bad; } else { uint32 tdi; int status; uint32 *soff = _TIFFCheckMalloc(tif, td->td_nstrips, sizeof(uint32), "32-bit offset array"); dir->s.tdir_type = (uint16) TIFF_LONG; for (tdi = 0; tdi < td->td_nstrips; tdi++) soff[tdi] = (uint32) td->td_stripoffset[tdi]; status = TIFFWriteLongArray(tif, dir, soff); _TIFFfree(soff); if (!status) goto bad; } break; case FIELD_STRIPBYTECOUNTS: /* * We use one field bit for both strip and tile * byte counts, and so must be careful in selecting * the appropriate field descriptor (so that tags * are written in sorted order). */ tag = (isTiled(tif) ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS); if (tag != fip->field_tag) continue; dir->s.tdir_tag = (uint16) tag; dir->s.tdir_type = (uint16) TIFF_LONG; TDIRSetEntryCount(tif,dir, (uint32) td->td_nstrips); if (!TIFFWriteLongArray(tif, dir, td->td_stripbytecount)) goto bad; break; case FIELD_ROWSPERSTRIP: TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP, dir, td->td_rowsperstrip); break; case FIELD_COLORMAP: if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir, 3, td->td_colormap)) goto bad; break; case FIELD_IMAGEDIMENSIONS: TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH, dir, td->td_imagewidth); TDIREntryNext(tif,dir); TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH, dir, td->td_imagelength); break; case FIELD_TILEDIMENSIONS: TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH, dir, td->td_tilewidth); TDIREntryNext(tif,dir); TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH, dir, td->td_tilelength); break; case FIELD_COMPRESSION: TIFFSetupShort(tif, TIFFTAG_COMPRESSION, dir, td->td_compression); break; case FIELD_PHOTOMETRIC: TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC, dir, td->td_photometric); break; case FIELD_POSITION: WriteRationalPair(TIFF_RATIONAL, TIFFTAG_XPOSITION, td->td_xposition, TIFFTAG_YPOSITION, td->td_yposition); break; case FIELD_RESOLUTION: WriteRationalPair(TIFF_RATIONAL, TIFFTAG_XRESOLUTION, td->td_xresolution, TIFFTAG_YRESOLUTION, td->td_yresolution); break; case FIELD_BITSPERSAMPLE: case FIELD_MINSAMPLEVALUE: case FIELD_MAXSAMPLEVALUE: case FIELD_SAMPLEFORMAT: if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir)) goto bad; break; case FIELD_SMINSAMPLEVALUE: case FIELD_SMAXSAMPLEVALUE: if (!TIFFWritePerSampleAnys(tif, _TIFFSampleToTagType(tif), fip->field_tag, dir)) goto bad; break; case FIELD_PAGENUMBER: case FIELD_HALFTONEHINTS: case FIELD_YCBCRSUBSAMPLING: if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) goto bad; break; case FIELD_INKNAMES: if (!TIFFWriteInkNames(tif, dir)) goto bad; break; case FIELD_TRANSFERFUNCTION: if (!TIFFWriteTransferFunction(tif, dir)) goto bad; break; case FIELD_SUBIFD: /* * Total hack: if this directory includes a SubIFD * tag then force the next <n> directories to be * written as ``sub directories'' of this one. This * is used to write things like thumbnails and * image masks that one wants to keep out of the * normal directory linkage access mechanism. * * If file is BigTIFF subdirectory offsets are written as 64-bit, * else as array of 32-bit offsets. At this point the actual * offset values are unknown (will be set in TIFFLinkDirectory). */ dir->s.tdir_tag = (uint16) fip->field_tag; TDIRSetEntryCount(tif,dir, (uint32) td->td_nsubifd); TDIRSetEntryOff(tif,dir, 0); if (td->td_nsubifd > 0) { tif->tif_flags |= TIFF_INSUBIFD; if (isBigTIFF(tif)) { toff_t *doff = _TIFFCheckMalloc(tif, td->td_nsubifd, sizeof(toff_t), "Allocate SubIFD offset array"); if (!doff) goto bad; _TIFFmemset(doff, 0, td->td_nsubifd * sizeof(toff_t)); dir->b.tdir_type = TIFF_IFD8; if (td->td_nsubifd > TIFFDirOffLen(tif) / sizeof(toff_t)) tif->tif_subifdoff = tif->tif_dataoff; else tif->tif_subifdoff = tif->tif_diroff + TIFFDirCntLen(tif) + (char*) &dir->b.tdir_offset - data; if (!TIFFWriteLong8Array(tif, dir, (toff_t*) doff)) goto bad; _TIFFfree(doff); } else { uint32 *doff = _TIFFCheckMalloc(tif, td->td_nsubifd, sizeof(uint32), "Allocate SubIFD offset array"); if (!doff) goto bad; _TIFFmemset(doff, 0, td->td_nsubifd * sizeof(uint32)); dir->b.tdir_type = TIFF_LONG; if (td->td_nsubifd > TIFFDirOffLen(tif) / sizeof(uint32)) tif->tif_subifdoff = tif->tif_dataoff; else tif->tif_subifdoff = tif->tif_diroff + TIFFDirCntLen(tif) + (char*) &dir->s.tdir_offset - data; if (!TIFFWriteLongArray(tif, dir, doff)) goto bad; _TIFFfree(doff); } } break; default: /* XXX: Should be fixed and removed. */ if (fip->field_tag == TIFFTAG_DOTRANGE) { if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) goto bad; } else if (!TIFFWriteNormalTag(tif, dir, fip)) goto bad; break; } TDIREntryNext(tif,dir); if( fip->field_bit != FIELD_CUSTOM ) ResetFieldBit(fields, fip->field_bit); } /* * Check if BigTIFF now required based on data location. If so reset * data offset to overwrite already-written data for directory, then * convert file to BigTIFF and loop to recreate directory. */ if (isBigTIFF(tif) || !isBigOff(tif->tif_dataoff + sizeof(uint32))) break; _TIFFfree(data); tif->tif_dataoff = tif->tif_diroff; if (!TIFFMakeBigTIFF(tif)) goto bad2; tif->tif_diroff = 0; } /* bottom of BigTIFF retry loop */ /* * Write directory. */ tif->tif_curdir++; TIFFSetDirCnt(tif,dircount, (uint32) nfields); TIFFSetDirOff(tif,diroff,tif->tif_nextdiroff); if (tif->tif_flags & TIFF_SWAB) { /* * The file's byte order is opposite to the * native machine architecture. We overwrite * the directory information with impunity * because it'll be released below after we * write it to the file. Note that all the * other tag construction routines assume that * we do this byte-swapping; i.e. they only * byte-swap indirect data. */ uint32 di; for (dir = (TIFFDirEntry*) data, di = 0; di < nfields; TDIREntryNext(tif,dir), di++) { TIFFSwabShort(&dir->s.tdir_tag); TIFFSwabShort(&dir->s.tdir_type); TDIRSwabEntryCount(tif,dir); TDIRSwabEntryOff(tif,dir); } TIFFSwabDirCnt(tif,&dircount); TIFFSwabDirOff(tif,&diroff); } (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); if (!WriteOK(tif, &dircount, TIFFDirCntLen(tif))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory count (%d)", TIFFGetErrno(tif)); goto bad; } if (!WriteOK(tif, data, dirsize)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory contents (%d)", TIFFGetErrno(tif)); goto bad; } if (!WriteOK(tif, &diroff, TIFFDirOffLen(tif))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory link (%d)", TIFFGetErrno(tif)); goto bad; } if (done) { TIFFFreeDirectory(tif); tif->tif_flags &= ~TIFF_DIRTYDIRECT; (*tif->tif_cleanup)(tif); /* * Reset directory-related state for subsequent * directories. */ TIFFCreateDirectory(tif); } _TIFFfree(data); return (1); bad: _TIFFfree(data); bad2: return (0); }