BigTIFF upgrade in progress

This commit is contained in:
Joris Van Damme 2007-03-17 05:21:29 +00:00
parent d5bb03d2e2
commit 513dc25a14

View File

@ -1,4 +1,4 @@
/* $Id: tif_dirread.c,v 1.93 2007-03-17 04:41:29 joris Exp $ */ /* $Id: tif_dirread.c,v 1.94 2007-03-17 05:21:29 joris Exp $ */
/* /*
* Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1988-1997 Sam Leffler
@ -54,10 +54,10 @@ static uint16 TIFFFetchDirectoryBig(TIFF* tif, uint64 diroff, TIFFDirEntryBig**
static uint32 TIFFFetchData(TIFF*, TIFFDirEntryUnion*, char*); static uint32 TIFFFetchData(TIFF*, TIFFDirEntryUnion*, char*);
static uint32 TIFFFetchString(TIFF*, TIFFDirEntryUnion*, char*); static uint32 TIFFFetchString(TIFF*, TIFFDirEntryUnion*, char*);
static float TIFFFetchRational(TIFF*, TIFFDirEntryUnion*); static float TIFFFetchRational(TIFF*, TIFFDirEntryUnion*);
static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*); static int TIFFFetchNormalTag(TIFF*, TIFFDirEntryUnion*);
static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, uint16*); static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntryUnion*, uint16*);
static int TIFFFetchPerSampleLongs(TIFF*, TIFFDirEntry*, uint32*); static int TIFFFetchPerSampleLongs(TIFF*, TIFFDirEntryUnion*, uint32*);
static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*); static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntryUnion*, double*);
static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*); static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*);
static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**); static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**);
static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*); static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*);
@ -1807,225 +1807,243 @@ TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v)
* Fetch a tag that is not handled by special case code. * Fetch a tag that is not handled by special case code.
*/ */
static int static int
TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp) TIFFFetchNormalTag(TIFF* tif, TIFFDirEntryUnion* dp)
{ {
static const char mesg[] = "to fetch tag value"; static const char mesg[] = "to fetch tag value";
int ok = 0; int ok = 0;
const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag); const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->common.tdir_tag);
uint64 count;
if (dp->tdir_count > 1) { /* array of values */ if (!(tif->tif_flags&TIFF_BIGTIFF))
count = dp->classic.tdir_count;
else
count = dp->big.tdir_count;
if (count > 1) {
/* array of values */
char* cp = NULL; char* cp = NULL;
switch (dp->tdir_type) { switch (dp->tdir_type) {
case TIFF_BYTE: case TIFF_BYTE:
case TIFF_SBYTE: case TIFF_SBYTE:
cp = (char *)_TIFFCheckMalloc(tif, cp = (char *)_TIFFCheckMalloc(tif,
dp->tdir_count, sizeof (uint8), mesg); count, sizeof (uint8), mesg);
ok = cp && TIFFFetchByteArray(tif, dp, (uint8*) cp); ok = cp && TIFFFetchByteArray(tif, dp, (uint8*) cp);
break; break;
case TIFF_SHORT: case TIFF_SHORT:
case TIFF_SSHORT: case TIFF_SSHORT:
cp = (char *)_TIFFCheckMalloc(tif, cp = (char *)_TIFFCheckMalloc(tif,
dp->tdir_count, sizeof (uint16), mesg); count, sizeof (uint16), mesg);
ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp); ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp);
break; break;
case TIFF_LONG: case TIFF_LONG:
case TIFF_SLONG: case TIFF_SLONG:
cp = (char *)_TIFFCheckMalloc(tif, cp = (char *)_TIFFCheckMalloc(tif,
dp->tdir_count, sizeof (uint32), mesg); count, sizeof (uint32), mesg);
ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp); ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp);
break; break;
case TIFF_RATIONAL: case TIFF_RATIONAL:
case TIFF_SRATIONAL: case TIFF_SRATIONAL:
cp = (char *)_TIFFCheckMalloc(tif, cp = (char *)_TIFFCheckMalloc(tif,
dp->tdir_count, sizeof (float), mesg); count, sizeof (float), mesg);
ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp); ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp);
break; break;
case TIFF_FLOAT: case TIFF_FLOAT:
cp = (char *)_TIFFCheckMalloc(tif, cp = (char *)_TIFFCheckMalloc(tif,
dp->tdir_count, sizeof (float), mesg); count, sizeof (float), mesg);
ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp); ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp);
break; break;
case TIFF_DOUBLE: case TIFF_DOUBLE:
cp = (char *)_TIFFCheckMalloc(tif, cp = (char *)_TIFFCheckMalloc(tif,
dp->tdir_count, sizeof (double), mesg); count, sizeof (double), mesg);
ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp); ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp);
break; break;
case TIFF_ASCII: case TIFF_ASCII:
case TIFF_UNDEFINED: /* bit of a cheat... */ case TIFF_UNDEFINED: /* bit of a cheat... */
/* /*
* Some vendors write strings w/o the trailing * Some vendors write strings w/o the trailing
* NULL byte, so always append one just in case. * NULL byte, so always append one just in case.
*/ */
cp = (char *)_TIFFCheckMalloc(tif, dp->tdir_count + 1, cp = (char *)_TIFFCheckMalloc(tif, count + 1,
1, mesg); 1, mesg);
if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 ) if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 )
cp[dp->tdir_count] = '\0'; /* XXX */ cp[count] = '\0'; /* XXX */
break; break;
} }
if (ok) { if (ok) {
ok = (fip->field_passcount ? ok = (fip->field_passcount ?
TIFFSetField(tif, dp->tdir_tag, dp->tdir_count, cp) TIFFSetField(tif, dp->common.tdir_tag, count, cp)
: TIFFSetField(tif, dp->tdir_tag, cp)); : TIFFSetField(tif, dp->common.tdir_tag, cp));
} }
if (cp != NULL) if (cp != NULL)
_TIFFfree(cp); _TIFFfree(cp);
} else if (CheckDirCount(tif, dp, 1)) { /* singleton value */ } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */
switch (dp->tdir_type) { switch (dp->common.tdir_type) {
case TIFF_BYTE: case TIFF_BYTE:
case TIFF_SBYTE: case TIFF_SBYTE:
case TIFF_SHORT: case TIFF_SHORT:
case TIFF_SSHORT: case TIFF_SSHORT:
/* /*
* If the tag is also acceptable as a LONG or SLONG * If the tag is also acceptable as a LONG or SLONG
* then TIFFSetField will expect an uint32 parameter * then TIFFSetField will expect an uint32 parameter
* passed to it (through varargs). Thus, for machines * passed to it (through varargs). Thus, for machines
* where sizeof (int) != sizeof (uint32) we must do * where sizeof (int) != sizeof (uint32) we must do
* a careful check here. It's hard to say if this * a careful check here. It's hard to say if this
* is worth optimizing. * is worth optimizing.
* *
* NB: We use TIFFFieldWithTag here knowing that * NB: We use TIFFFieldWithTag here knowing that
* it returns us the first entry in the table * it returns us the first entry in the table
* for the tag and that that entry is for the * for the tag and that that entry is for the
* widest potential data type the tag may have. * widest potential data type the tag may have.
*/ */
{ TIFFDataType type = fip->field_type; {
if (type != TIFF_LONG && type != TIFF_SLONG) { TIFFDataType type = fip->field_type;
uint16 v = (uint16) if (type != TIFF_LONG && type != TIFF_SLONG) {
TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); uint16 v = (uint16)
ok = (fip->field_passcount ? TIFFExtractData(tif, dp->common.tdir_type, dp->tdir_offset dddd);
TIFFSetField(tif, dp->tdir_tag, 1, &v) ok = (fip->field_passcount ?
: TIFFSetField(tif, dp->tdir_tag, v)); TIFFSetField(tif, dp->common.tdir_tag, 1, &v)
: TIFFSetField(tif, dp->common.tdir_tag, v));
break;
}
}
/* fall thru... */
case TIFF_LONG:
case TIFF_SLONG:
{
uint32 v32 = TIFFExtractData(tif, dp->common.tdir_type, dp->tdir_offset ddd);
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->common.tdir_tag, 1, &v32)
: TIFFSetField(tif, dp->common.tdir_tag, v32));
}
break;
case TIFF_RATIONAL:
case TIFF_SRATIONAL:
case TIFF_FLOAT:
{
float v = (dp->common.tdir_type == TIFF_FLOAT ?
TIFFFetchFloat(tif, dp)
: TIFFFetchRational(tif, dp));
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->common.tdir_tag, 1, &v)
: TIFFSetField(tif, dp->common.tdir_tag, v));
}
break;
case TIFF_DOUBLE:
{
double v;
ok = (TIFFFetchDoubleArray(tif, dp, &v) &&
(fip->field_passcount ?
TIFFSetField(tif, dp->common.tdir_tag, 1, &v)
: TIFFSetField(tif, dp->common.tdir_tag, v))
);
}
break;
case TIFF_ASCII:
case TIFF_UNDEFINED: /* bit of a cheat... */
{
char c[2];
if ( (ok = (TIFFFetchString(tif, dp, c) != 0)) != 0 ) {
c[1] = '\0'; /* XXX paranoid */
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->common.tdir_tag, 1, c)
: TIFFSetField(tif, dp->common.tdir_tag, c));
}
}
break; break;
}
}
/* fall thru... */
case TIFF_LONG:
case TIFF_SLONG:
{ uint32 v32 =
TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->tdir_tag, 1, &v32)
: TIFFSetField(tif, dp->tdir_tag, v32));
}
break;
case TIFF_RATIONAL:
case TIFF_SRATIONAL:
case TIFF_FLOAT:
{ float v = (dp->tdir_type == TIFF_FLOAT ?
TIFFFetchFloat(tif, dp)
: TIFFFetchRational(tif, dp));
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->tdir_tag, 1, &v)
: TIFFSetField(tif, dp->tdir_tag, v));
}
break;
case TIFF_DOUBLE:
{ double v;
ok = (TIFFFetchDoubleArray(tif, dp, &v) &&
(fip->field_passcount ?
TIFFSetField(tif, dp->tdir_tag, 1, &v)
: TIFFSetField(tif, dp->tdir_tag, v))
);
}
break;
case TIFF_ASCII:
case TIFF_UNDEFINED: /* bit of a cheat... */
{ char c[2];
if( (ok = (TIFFFetchString(tif, dp, c) != 0)) != 0 ) {
c[1] = '\0'; /* XXX paranoid */
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->tdir_tag, 1, c)
: TIFFSetField(tif, dp->tdir_tag, c));
}
}
break;
} }
} }
return (ok); return (ok);
} }
#define NITEMS(x) (sizeof (x) / sizeof (x[0])) #define NITEMS(x) (sizeof (x) / sizeof (x[0]))
/* /*
* Fetch samples/pixel short values for * Fetch samples/pixel short values for
* the specified tag and verify that * the specified tag and verify that
* all values are the same. * all values are the same.
*/ */
static int static int
TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, uint16* pl) TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntryUnion* dir, uint16* pl)
{ {
uint16 samples = tif->tif_dir.td_samplesperpixel; uint16 samples = tif->tif_dir.td_samplesperpixel;
int status = 0; int status = 0;
if (CheckDirCount(tif, dir, (uint32) samples)) {
if (CheckDirCount(tif, dir, (uint32) samples)) { uint16 buf[10];
uint16 buf[10]; uint16* v = buf;
uint16* v = buf; uint64 count;
if (!(tif->tif_flags&TIFF_BIGTIFF))
if (dir->tdir_count > NITEMS(buf)) count = dir->classic.tdir_count;
v = (uint16*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof(uint16), else
"to fetch per-sample values"); count = dir->big.tdir_count;
if (v && TIFFFetchShortArray(tif, dir, v)) { if (count > NITEMS(buf))
uint16 i; v = (uint16*) _TIFFCheckMalloc(tif, count, sizeof(uint16),
int check_count = dir->tdir_count; "to fetch per-sample values");
if( samples < check_count ) if (v && TIFFFetchShortArray(tif, dir, v)) {
check_count = samples; uint16 i;
uint16 check_count;
for (i = 1; i < check_count; i++) if ((uint64)samples<=count)
if (v[i] != v[0]) { check_count=samples;
else
check_count=(uint16)count;
for (i=1; i<check_count; i++)
if (v[i] != v[0]) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
"Cannot handle different per-sample values for field \"%s\"", "Cannot handle different per-sample values for field \"%s\"",
_TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); _TIFFFieldWithTag(tif, dir->common.tdir_tag)->field_name);
goto bad; goto bad;
} }
*pl = v[0]; *pl = v[0];
status = 1; status = 1;
} }
bad: bad:
if (v && v != buf) if (v && v != buf)
_TIFFfree(v); _TIFFfree(v);
} }
return (status); return (status);
} }
/* /*
* Fetch samples/pixel long values for * Fetch samples/pixel long values for
* the specified tag and verify that * the specified tag and verify that
* all values are the same. * all values are the same.
*/ */
static int static int
TIFFFetchPerSampleLongs(TIFF* tif, TIFFDirEntry* dir, uint32* pl) TIFFFetchPerSampleLongs(TIFF* tif, TIFFDirEntryUnion* dir, uint32* pl)
{ {
uint16 samples = tif->tif_dir.td_samplesperpixel; uint16 samples = tif->tif_dir.td_samplesperpixel;
int status = 0; int status = 0;
if (CheckDirCount(tif, dir, (uint32) samples)) {
if (CheckDirCount(tif, dir, (uint32) samples)) { uint32 buf[10];
uint32 buf[10]; uint32* v = buf;
uint32* v = buf; uint64 count;
if (!(tif->tif_flags&TIFF_BIGTIFF))
if (dir->tdir_count > NITEMS(buf)) count = dir->classic.tdir_count;
v = (uint32*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof(uint32), else
"to fetch per-sample values"); count = dir->big.tdir_count;
if (v && TIFFFetchLongArray(tif, dir, v)) { if (count > NITEMS(buf))
uint16 i; v = (uint32*) _TIFFCheckMalloc(tif, count, sizeof(uint32),
int check_count = dir->tdir_count; "to fetch per-sample values");
if (v && TIFFFetchLongArray(tif, dir, v)) {
if( samples < check_count ) uint16 i;
check_count = samples; uint16 check_count;
for (i = 1; i < check_count; i++) if ((uint64)samples<=count)
if (v[i] != v[0]) { check_count=samples;
else
check_count=(uint16)count;
for (i=1; i<check_count; i++)
if (v[i] != v[0]) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
"Cannot handle different per-sample values for field \"%s\"", "Cannot handle different per-sample values for field \"%s\"",
_TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
goto bad; goto bad;
} }
*pl = v[0]; *pl = v[0];
status = 1; status = 1;
} }
bad: bad:
if (v && v != buf) if (v && v != buf)
_TIFFfree(v); _TIFFfree(v);
} }
return (status); return (status);
} }
/* /*
@ -2035,37 +2053,41 @@ TIFFFetchPerSampleLongs(TIFF* tif, TIFFDirEntry* dir, uint32* pl)
static int static int
TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl) TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl)
{ {
uint16 samples = tif->tif_dir.td_samplesperpixel; uint16 samples = tif->tif_dir.td_samplesperpixel;
int status = 0; int status = 0;
if (CheckDirCount(tif, dir, (uint32) samples)) {
if (CheckDirCount(tif, dir, (uint32) samples)) { double buf[10];
double buf[10]; double* v = buf;
double* v = buf; uint64 count;
if (!(tif->tif_flags&TIFF_BIGTIFF))
if (dir->tdir_count > NITEMS(buf)) count = dir->classic.tdir_count;
v = (double*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof (double), else
"to fetch per-sample values"); count = dir->big.tdir_count;
if (v && TIFFFetchAnyArray(tif, dir, v)) { if (count > NITEMS(buf))
uint16 i; v = (double*) _TIFFCheckMalloc(tif, count, sizeof(double),
int check_count = dir->tdir_count; "to fetch per-sample values");
if( samples < check_count ) if (v && TIFFFetchAnyArray(tif, dir, v)) {
check_count = samples; uint16 i;
uint16 check_count;
for (i = 1; i < check_count; i++) if ((uint64)samples<=count)
if (v[i] != v[0]) { check_count=samples;
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, else
"Cannot handle different per-sample values for field \"%s\"", check_count=(uint16)count;
_TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); for (i=1; i<check_count; i++)
goto bad; if (v[i] != v[0]) {
} TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
*pl = v[0]; "Cannot handle different per-sample values for field \"%s\"",
status = 1; _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
} goto bad;
bad: }
if (v && v != buf) *pl = v[0];
_TIFFfree(v); status = 1;
} }
return (status); bad:
if (v && v != buf)
_TIFFfree(v);
}
return (status);
} }
#undef NITEMS #undef NITEMS