📄 tif_dirread.c
字号:
v = 0; switch (TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)) { case OFILETYPE_REDUCEDIMAGE: v = FILETYPE_REDUCEDIMAGE; break; case OFILETYPE_PAGE: v = FILETYPE_PAGE; break; } if (v) (void) TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (int)v); break;/* END REV 4.0 COMPATIBILITY */ default: (void) TIFFFetchNormalTag(tif, dp); break; } } /* * Verify Palette image has a Colormap. */ if (td->td_photometric == PHOTOMETRIC_PALETTE && !TIFFFieldSet(tif, FIELD_COLORMAP)) { MissingRequired(tif, "Colormap"); goto bad; } /* * Attempt to deal with a missing StripByteCounts tag. */ if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { /* * Some manufacturers violate the spec by not giving * the size of the strips. In this case, assume there * is one uncompressed strip of data. */ if ((td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_nstrips > 1) || (td->td_planarconfig == PLANARCONFIG_SEPARATE && td->td_nstrips != td->td_samplesperpixel)) { MissingRequired(tif, "StripByteCounts"); goto bad; } TIFFWarning(tif->tif_name, "TIFF directory is missing required \"%s\" field, calculating from imagelength", _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
EstimateStripByteCounts(tif, dir, dircount);#define BYTECOUNTLOOKSBAD \ ((td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \ (td->td_compression == COMPRESSION_NONE && \ td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0])) } else if (td->td_nstrips == 1 && BYTECOUNTLOOKSBAD) { /* * Plexus (and others) sometimes give a value * of zero for a tag when they don't know what * the correct value is! Try and handle the * simple case of estimating the size of a one * strip image. */ TIFFWarning(tif->tif_name, "Bogus \"%s\" field, ignoring and calculating from imagelength", _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); EstimateStripByteCounts(tif, dir, dircount); } if (dir) _TIFFfree((char *)dir); if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1); /* * Setup default compression scheme. */ if (!TIFFFieldSet(tif, FIELD_COMPRESSION)) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); /* * Some manufacturers make life difficult by writing * large amounts of uncompressed data as a single strip. * This is contrary to the recommendations of the spec. * The following makes an attempt at breaking such images * into strips closer to the recommended 8k bytes. A * side effect, however, is that the RowsPerStrip tag * value may be changed. */ if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE && (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP) ChopUpSingleUncompressedStrip(tif); /* * Reinitialize i/o since we are starting on a new directory. */ tif->tif_row = (uint32) -1; tif->tif_curstrip = (tstrip_t) -1; tif->tif_col = (uint32) -1; tif->tif_curtile = (ttile_t) -1; tif->tif_tilesize = TIFFTileSize(tif); tif->tif_scanlinesize = TIFFScanlineSize(tif); return (1);bad: if (dir) _TIFFfree(dir); return (0);}static voidEstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount){ register TIFFDirEntry *dp; register TIFFDirectory *td = &tif->tif_dir; uint16 i; if (td->td_stripbytecount) _TIFFfree(td->td_stripbytecount); td->td_stripbytecount = (uint32*) CheckMalloc(tif, td->td_nstrips * sizeof (uint32), "for \"StripByteCounts\" array"); if (td->td_compression != COMPRESSION_NONE) { uint32 space = (uint32)(sizeof (TIFFHeader) + sizeof (uint16) + (dircount * sizeof (TIFFDirEntry)) + sizeof (uint32)); toff_t filesize = TIFFGetFileSize(tif); uint16 n; /* calculate amount of space used by indirect values */ for (dp = dir, n = dircount; n > 0; n--, dp++) { uint32 cc = dp->tdir_count*tiffDataWidth[dp->tdir_type]; if (cc > sizeof (uint32)) space += cc; } space = filesize - space; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) space /= td->td_samplesperpixel; for (i = 0; i < td->td_nstrips; i++) td->td_stripbytecount[i] = space; /* * This gross hack handles the case were the offset to * the last strip is past the place where we think the strip * should begin. Since a strip of data must be contiguous, * it's safe to assume that we've overestimated the amount * of data in the strip and trim this number back accordingly. */ i--; if (((toff_t)(td->td_stripoffset[i]+td->td_stripbytecount[i])) > filesize) td->td_stripbytecount[i] = filesize - td->td_stripoffset[i]; } else { uint32 rowbytes = TIFFScanlineSize(tif); uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage; for (i = 0; i < td->td_nstrips; i++) td->td_stripbytecount[i] = rowbytes*rowsperstrip; } TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) td->td_rowsperstrip = td->td_imagelength;}static voidMissingRequired(TIFF* tif, const char* tagname){ TIFFError(tif->tif_name, "TIFF directory is missing required \"%s\" field", tagname);}/* * Check the count field of a directory * entry against a known value. The caller * is expected to skip/ignore the tag if * there is a mismatch. */static intCheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count){ if (count != dir->tdir_count) { TIFFWarning(tif->tif_name, "incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, dir->tdir_count, count); return (0); } return (1);}/* * Fetch a contiguous directory item. */static tsize_tTIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp){ int w = tiffDataWidth[dir->tdir_type]; tsize_t cc = dir->tdir_count * w; if (!isMapped(tif)) { if (!SeekOK(tif, dir->tdir_offset)) goto bad; if (!ReadOK(tif, cp, cc)) goto bad; } else { if (dir->tdir_offset + cc > tif->tif_size) goto bad; _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc); } if (tif->tif_flags & TIFF_SWAB) { switch (dir->tdir_type) { case TIFF_SHORT: case TIFF_SSHORT: TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); break; case TIFF_LONG: case TIFF_SLONG: case TIFF_FLOAT: TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); break; case TIFF_DOUBLE: TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); break; } } return (cc);bad: TIFFError(tif->tif_name, "Error fetching data for field \"%s\"", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); return ((tsize_t) 0);}/* * Fetch an ASCII item from the file. */static tsize_tTIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp){ if (dir->tdir_count <= 4) { uint32 l = dir->tdir_offset; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&l); _TIFFmemcpy(cp, &l, dir->tdir_count); return (1); } return (TIFFFetchData(tif, dir, cp));}/* * Convert numerator+denominator to float. */static intcvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv){ if (denom == 0) { TIFFError(tif->tif_name, "%s: Rational with zero denominator (num = %lu)", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num); return (0); } else { if (dir->tdir_type == TIFF_RATIONAL) *rv = ((float)num / (float)denom); else *rv = ((float)(int32)num / (float)(int32)denom); return (1); }}/* * Fetch a rational item from the file * at offset off and return the value * as a floating point number. */static floatTIFFFetchRational(TIFF* tif, TIFFDirEntry* dir){ uint32 l[2]; float v; return (!TIFFFetchData(tif, dir, (char *)l) || !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v);}/* * Fetch a single floating point value * from the offset field and return it * as a native float. */static floatTIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir){ long l = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset); float v = *(float*) &l; TIFFCvtIEEEFloatToNative(tif, 1, &v); return (v);}/* * Fetch an array of BYTE or SBYTE values. */static intTIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint16* v){ if (dir->tdir_count <= 4) { /* * Extract data from offset field. */ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { switch (dir->tdir_count) { case 4: v[3] = (uint16)(dir->tdir_offset & 0xff); case 3: v[2] = (uint16)((dir->tdir_offset >> 8) & 0xff); case 2: v[1] = (uint16)((dir->tdir_offset >> 16) & 0xff); case 1: v[0] = (uint16)(dir->tdir_offset >> 24); } } else { switch (dir->tdir_count) { case 4: v[3] = (uint16)(dir->tdir_offset >> 24); case 3: v[2] = (uint16)((dir->tdir_offset >> 16) & 0xff); case 2: v[1] = (uint16)((dir->tdir_offset >> 8) & 0xff); case 1: v[0] = (uint16)(dir->tdir_offset & 0xff); } } return (1); } else return (TIFFFetchData(tif, dir, (char*) v) != 0); /* XXX */}/* * Fetch an array of SHORT or SSHORT values. */static intTIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v){ if (dir->tdir_count <= 2) { if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { switch (dir->tdir_count) { case 2: v[1] = (uint16) (dir->tdir_offset & 0xffff); case 1: v[0] = (uint16) (dir->tdir_offset >> 16); } } else { switch (dir->tdir_count) { case 2: v[1] = (uint16) (dir->tdir_offset >> 16); case 1: v[0] = (uint16) (dir->tdir_offset & 0xffff); } } return (1); } else return (TIFFFetchData(tif, dir, (char *)v) != 0);}/* * Fetch a pair of SHORT or BYTE values. */static intTIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir){ uint16 v[2]; int ok = 0; switch (dir->tdir_type) { case TIFF_SHORT: case TIFF_SSHORT: ok = TIFFFetchShortArray(tif, dir, v); break; case TIFF_BYTE: case TIFF_SBYTE: ok = TIFFFetchByteArray(tif, dir, v); break; } if (ok) TIFFSetField(tif, dir->tdir_tag, v[0], v[1]); return (ok);}/* * Fetch an array of LONG or SLONG values. */static intTIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v){ if (dir->tdir_count == 1) { v[0] = dir->tdir_offset; return (1); } else return (TIFFFetchData(tif, dir, (char*) v) != 0);}/* * Fetch an array of RATIONAL or SRATIONAL values. */static intTIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v){ int ok = 0; uint32* l; l = (uint32*)CheckMalloc(tif, dir->tdir_count*tiffDataWidth[dir->tdir_type], "to fetch array of rationals"); if (l) { if (TIFFFetchData(tif, dir, (char *)l)) { uint32 i; for (i = 0; i < dir->tdir_count; i++) { ok = cvtRational(tif, dir, l[2*i+0], l[2*i+1], &v[i]); if (!ok) break; } } _TIFFfree((char *)l); } return (ok);}/* * Fetch an array of FLOAT values. */static intTIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v){ if (dir->tdir_count == 1) { v[0] = *(float*) &dir->tdir_offset; TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); return (1); } else if (TIFFFetchData(tif, dir, (char*) v)) { TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); return (1); } else return (0);}/* * Fetch an array of DOUBLE values. */static intTIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v){ if (TIFFFetchData(tif, dir, (char*) v)) { TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v); return (1); } else return (0);}/* * Fetch an array of ANY values. The actual values are * returned as doubles which should be able hold all the * types. Yes, there really should be an tany_t to avoid * this potential non-portability ... Note in particular * that we assume that the double return value vector is * large enough to read in any fundamental type. We use * that vector as a buffer to read in the base type vector * and then convert it in place to double (from end * to front of course). */static intTIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v){ int i; switch (dir->tdir_type) { case TIFF_BYTE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -