📄 tif_dirread.c
字号:
tif->tif_flags &= ~TIFF_ISTILED; } else { td->td_nstrips = TIFFNumberOfTiles(tif); tif->tif_flags |= TIFF_ISTILED; } if (!td->td_nstrips) { TIFFError(module, "%s: cannot handle zero number of %s", tif->tif_name, isTiled(tif) ? "tiles" : "strips"); goto bad; } td->td_stripsperimage = td->td_nstrips; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { MissingRequired(tif, isTiled(tif) ? "TileOffsets" : "StripOffsets"); goto bad; } /* * Second pass: extract other information. */ for (dp = dir, n = dircount; n > 0; n--, dp++) { if (dp->tdir_tag == IGNORE) continue; switch (dp->tdir_tag) { case TIFFTAG_MINSAMPLEVALUE: case TIFFTAG_MAXSAMPLEVALUE: case TIFFTAG_BITSPERSAMPLE: case TIFFTAG_DATATYPE: case TIFFTAG_SAMPLEFORMAT: /* * The 5.0 spec says the Compression tag has * one value, while earlier specs say it has * one value per sample. Because of this, we * accept the tag if one value is supplied. * * The MinSampleValue, MaxSampleValue, BitsPerSample * DataType and SampleFormat tags are supposed to be * written as one value/sample, but some vendors * incorrectly write one value only -- so we accept * that as well (yech). Other vendors write correct * value for NumberOfSamples, but incorrect one for * BitsPerSample and friends, and we will read this * too. */ if (dp->tdir_count == 1) { v = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v)) goto bad; /* XXX: workaround for broken TIFFs */ } else if (dp->tdir_tag == TIFFTAG_BITSPERSAMPLE && dp->tdir_type == TIFF_LONG) { if (!TIFFFetchPerSampleLongs(tif, dp, &v) || !TIFFSetField(tif, dp->tdir_tag, (uint16)v)) goto bad; } else { if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || !TIFFSetField(tif, dp->tdir_tag, iv)) goto bad; } break; case TIFFTAG_SMINSAMPLEVALUE: case TIFFTAG_SMAXSAMPLEVALUE: if (!TIFFFetchPerSampleAnys(tif, dp, &dv) || !TIFFSetField(tif, dp->tdir_tag, dv)) goto bad; break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_TILEOFFSETS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripoffset)) goto bad; break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripbytecount)) goto bad; break; case TIFFTAG_COLORMAP: case TIFFTAG_TRANSFERFUNCTION: /* * TransferFunction can have either 1x or 3x data * values; Colormap can have only 3x items. */ v = 1L<<td->td_bitspersample; if (dp->tdir_tag == TIFFTAG_COLORMAP || dp->tdir_count != v) { if (!CheckDirCount(tif, dp, 3 * v)) break; } v *= sizeof(uint16); cp = CheckMalloc(tif, dp->tdir_count, sizeof (uint16), "to read \"TransferFunction\" tag"); if (cp != NULL) { if (TIFFFetchData(tif, dp, cp)) { /* * This deals with there being only * one array to apply to all samples. */ uint32 c = 1L << td->td_bitspersample; if (dp->tdir_count == c) v = 0L; TIFFSetField(tif, dp->tdir_tag, cp, cp+v, cp+2*v); } _TIFFfree(cp); } break; case TIFFTAG_PAGENUMBER: case TIFFTAG_HALFTONEHINTS: case TIFFTAG_YCBCRSUBSAMPLING: case TIFFTAG_DOTRANGE: (void) TIFFFetchShortPair(tif, dp); break; case TIFFTAG_REFERENCEBLACKWHITE: (void) TIFFFetchRefBlackWhite(tif, dp); break;/* BEGIN REV 4.0 COMPATIBILITY */ case TIFFTAG_OSUBFILETYPE: v = 0L; 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) TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 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(module, "%s: TIFF directory is missing required " "\"%s\" field, calculating from imagelength", tif->tif_name, _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); if (EstimateStripByteCounts(tif, dir, dircount) < 0) goto bad;/* * Assume we have wrong StripByteCount value (in case of single strip) in * following cases: * - it is equal to zero along with StripOffset; * - it is larger than file itself (in case of uncompressed image); * - it is smaller than the size of the bytes per row multiplied on the * number of rows. The last case should not be checked in the case of * writing new image, because we may do not know the exact strip size * until the whole image will be written and directory dumped out. */#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]) || \ (tif->tif_mode == O_RDONLY && \ td->td_compression == COMPRESSION_NONE && \ td->td_stripbytecount[0] < TIFFScanlineSize(tif) * td->td_imagelength) ) } 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(module, "%s: Bogus \"%s\" field, ignoring and calculating from imagelength", tif->tif_name, _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); if(EstimateStripByteCounts(tif, dir, dircount) < 0) goto bad; } if (dir) { _TIFFfree((char *)dir); dir = NULL; } if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1); /* * Setup default compression scheme. */ /* * XXX: We can optimize checking for the strip bounds using the sorted * bytecounts array. See also comments for TIFFAppendToStrip() * function in tif_write.c. */ if (td->td_nstrips > 1) { tstrip_t strip; td->td_stripbytecountsorted = 1; for (strip = 1; strip < td->td_nstrips; strip++) { if (td->td_stripoffset[strip - 1] > td->td_stripoffset[strip]) { td->td_stripbytecountsorted = 0; break; } } } 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 = (tsize_t) -1; tif->tif_scanlinesize = TIFFScanlineSize(tif); if (!tif->tif_scanlinesize) { TIFFError(module, "%s: cannot handle zero scanline size", tif->tif_name); return (0); } if (isTiled(tif)) { tif->tif_tilesize = TIFFTileSize(tif); if (!tif->tif_tilesize) { TIFFError(module, "%s: cannot handle zero tile size", tif->tif_name); return (0); } } else { if (!TIFFStripSize(tif)) { TIFFError(module, "%s: cannot handle zero strip size", tif->tif_name); return (0); } } return (1);bad: if (dir) _TIFFfree(dir); return (0);}static intEstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount){ static const char module[] = "EstimateStripByteCounts"; 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 = TIFFDataWidth((TIFFDataType) dp->tdir_type); if (cc == 0) { TIFFError(module, "%s: Cannot determine size of unknown tag type %d", tif->tif_name, dp->tdir_type); return -1; } cc = cc * dp->tdir_count; 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; return 1;}static voidMissingRequired(TIFF* tif, const char* tagname){ static const char module[] = "MissingRequired"; TIFFError(module, "%s: TIFF directory is missing required \"%s\" field", tif->tif_name, 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); } else if (count < dir->tdir_count) { TIFFWarning(tif->tif_name, "incorrect count for field \"%s\" (%lu, expecting %lu); tag trimmed", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, dir->tdir_count, count); return (1); } return (1);}/* * Fetch a contiguous directory item. */static tsize_tTIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp){ int w = TIFFDataWidth((TIFFDataType) 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -