tif_dirread.c
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C语言 代码 · 共 1,519 行 · 第 1/3 页
C
1,519 行
case TIFFTAG_REFERENCEBLACKWHITE:
(void) TIFFFetchRefBlackWhite(tif, dp);
break;
#endif
/* BEGIN REV 4.0 COMPATIBILITY */
case TIFFTAG_OSUBFILETYPE:
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(module,
"%.1000s: 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).
*/
#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(module,
"%.1000s: 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.
*/
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);
if (!tif->tif_tilesize) {
TIFFError(module, "%s: cannot handle zero tile size",
tif->tif_name);
return (0);
}
if (!tif->tif_scanlinesize) {
TIFFError(module, "%s: cannot handle zero scanline size",
tif->tif_name);
return (0);
}
return (1);
bad:
if (dir)
_TIFFfree(dir);
return (0);
}
static int
EstimateStripByteCounts(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,
"%.1000s: 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 void
MissingRequired(TIFF* tif, const char* tagname)
{
static const char module[] = "MissingRequired";
TIFFError(module,
"%.1000s: 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 int
CheckDirCount(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_t
TIFFFetchData(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) {
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_t
TIFFFetchString(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 int
cvtRational(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 float
TIFFFetchRational(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 float
TIFFFetchFloat(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 int
TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
{
if (dir->tdir_count <= 4) {
/*
* Extract data from offset field.
*/
if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
if (dir->tdir_type == TIFF_SBYTE)
switch (dir->tdir_count) {
case 4: v[3] = (signed char)(dir->tdir_offset & 0xff);
case 3: v[2] = (signed char)((dir->tdir_offset >> 8) & 0xff);
case 2: v[1] = (signed char)((dir->tdir_offset >> 16) & 0xff);
case 1: v[0] = (signed char)(dir->tdir_offset >> 24);
}
else
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 {
if (dir->tdir_type == TIFF_SBYTE)
switch (dir->tdir_count) {
case 4: v[3] = (signed char)(dir->tdir_offset >> 24);
case 3: v[2] = (signed char)((dir->tdir_offset >> 16) & 0xff);
case 2: v[1] = (signed char)((dir->tdir_offset >> 8) & 0xff);
case 1: v[0] = (signed char)(dir->tdir_offset & 0xff);
}
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 int
TIFFFetchShortArray(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 int
TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir)
{
uint16 v[4];
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 int
TIFFFetchLongArray(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 int
TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
{
int ok = 0;
uint32* l;
l = (uint32*)CheckMalloc(tif,
dir->tdir_count, TIFFDataWidth((TIFFDataType) 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 int
TIFFFetchFloatArray(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 int
TIFFFetchDoubleArray(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
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?