📄 tif_dirread.c
字号:
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)
{
float v;
int32 l = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
_TIFFmemcpy(&v, &l, sizeof(float));
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
* 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 int
TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v)
{
int i;
switch (dir->tdir_type) {
case TIFF_BYTE:
case TIFF_SBYTE:
if (!TIFFFetchByteArray(tif, dir, (uint16*) v))
return (0);
if (dir->tdir_type == TIFF_BYTE) {
uint16* vp = (uint16*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
} else {
int16* vp = (int16*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
}
break;
case TIFF_SHORT:
case TIFF_SSHORT:
if (!TIFFFetchShortArray(tif, dir, (uint16*) v))
return (0);
if (dir->tdir_type == TIFF_SHORT) {
uint16* vp = (uint16*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
} else {
int16* vp = (int16*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
}
break;
case TIFF_LONG:
case TIFF_SLONG:
if (!TIFFFetchLongArray(tif, dir, (uint32*) v))
return (0);
if (dir->tdir_type == TIFF_LONG) {
uint32* vp = (uint32*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
} else {
int32* vp = (int32*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
}
break;
case TIFF_RATIONAL:
case TIFF_SRATIONAL:
if (!TIFFFetchRationalArray(tif, dir, (float*) v))
return (0);
{ float* vp = (float*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
}
break;
case TIFF_FLOAT:
if (!TIFFFetchFloatArray(tif, dir, (float*) v))
return (0);
{ float* vp = (float*) v;
for (i = dir->tdir_count-1; i >= 0; i--)
v[i] = vp[i];
}
break;
case TIFF_DOUBLE:
return (TIFFFetchDoubleArray(tif, dir, (double*) v));
default:
/* TIFF_NOTYPE */
/* TIFF_ASCII */
/* TIFF_UNDEFINED */
TIFFError(tif->tif_name,
"cannot read TIFF_ANY type %d for field \"%s\"",
_TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
return (0);
}
return (1);
}
/*
* Fetch a tag that is not handled by special case code.
*/
static int
TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp)
{
static const char mesg[] = "to fetch tag value";
int ok = 0;
const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag);
if (dp->tdir_count > 1) { /* array of values */
char* cp = NULL;
switch (dp->tdir_type) {
case TIFF_BYTE:
case TIFF_SBYTE:
/* NB: always expand BYTE values to shorts */
cp = CheckMalloc(tif,
dp->tdir_count, sizeof (uint16), mesg);
ok = cp && TIFFFetchByteArray(tif, dp, (uint16*) cp);
break;
case TIFF_SHORT:
case TIFF_SSHORT:
cp = CheckMalloc(tif,
dp->tdir_count, sizeof (uint16), mesg);
ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp);
break;
case TIFF_LONG:
case TIFF_SLONG:
cp = CheckMalloc(tif,
dp->tdir_count, sizeof (uint32), mesg);
ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp);
break;
case TIFF_RATIONAL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -