tif_dirread.c
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C语言 代码 · 共 1,519 行 · 第 1/3 页
C
1,519 行
* 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:
case TIFF_SRATIONAL:
cp = CheckMalloc(tif,
dp->tdir_count, sizeof (float), mesg);
ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp);
break;
case TIFF_FLOAT:
cp = CheckMalloc(tif,
dp->tdir_count, sizeof (float), mesg);
ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp);
break;
case TIFF_DOUBLE:
cp = CheckMalloc(tif,
dp->tdir_count, sizeof (double), mesg);
ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp);
break;
case TIFF_ASCII:
case TIFF_UNDEFINED: /* bit of a cheat... */
/*
* Some vendors write strings w/o the trailing
* NULL byte, so always append one just in case.
*/
cp = CheckMalloc(tif, dp->tdir_count+1, 1, mesg);
if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 )
cp[dp->tdir_count] = '\0'; /* XXX */
break;
}
if (ok) {
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->tdir_tag, dp->tdir_count, cp)
: TIFFSetField(tif, dp->tdir_tag, cp));
}
if (cp != NULL)
_TIFFfree(cp);
} else if (CheckDirCount(tif, dp, 1)) { /* singleton value */
switch (dp->tdir_type) {
case TIFF_BYTE:
case TIFF_SBYTE:
case TIFF_SHORT:
case TIFF_SSHORT:
/*
* If the tag is also acceptable as a LONG or SLONG
* then TIFFSetField will expect an uint32 parameter
* passed to it (through varargs). Thus, for machines
* where sizeof (int) != sizeof (uint32) we must do
* a careful check here. It's hard to say if this
* is worth optimizing.
*
* NB: We use TIFFFieldWithTag here knowing that
* it returns us the first entry in the table
* for the tag and that that entry is for the
* widest potential data type the tag may have.
*/
{ TIFFDataType type = fip->field_type;
if (type != TIFF_LONG && type != TIFF_SLONG) {
uint16 v = (uint16)
TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
ok = (fip->field_passcount ?
TIFFSetField(tif, dp->tdir_tag, 1, &v)
: TIFFSetField(tif, dp->tdir_tag, v));
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 = TIFFSetField(tif, dp->tdir_tag, c);
}
}
break;
}
}
return (ok);
}
#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
/*
* Fetch samples/pixel short values for
* the specified tag and verify that
* all values are the same.
*/
static int
TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, int* pl)
{
int samples = tif->tif_dir.td_samplesperpixel;
int status = 0;
if (CheckDirCount(tif, dir, (uint32) samples)) {
uint16 buf[10];
uint16* v = buf;
if (samples > NITEMS(buf))
v = (uint16*) CheckMalloc(tif, samples, sizeof (uint16),
"to fetch per-sample values");
if (v && TIFFFetchShortArray(tif, dir, v)) {
int i;
for (i = 1; i < samples; i++)
if (v[i] != v[0]) {
TIFFError(tif->tif_name,
"Cannot handle different per-sample values for field \"%s\"",
_TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
goto bad;
}
*pl = v[0];
status = 1;
}
bad:
if (v && v != buf)
_TIFFfree((char*) v);
}
return (status);
}
/*
* Fetch samples/pixel ANY values for
* the specified tag and verify that
* all values are the same.
*/
static int
TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl)
{
int samples = (int) tif->tif_dir.td_samplesperpixel;
int status = 0;
if (CheckDirCount(tif, dir, (uint32) samples)) {
double buf[10];
double* v = buf;
if (samples > NITEMS(buf))
v = (double*) CheckMalloc(tif, samples, sizeof (double),
"to fetch per-sample values");
if (v && TIFFFetchAnyArray(tif, dir, v)) {
int i;
for (i = 1; i < samples; i++)
if (v[i] != v[0]) {
TIFFError(tif->tif_name,
"Cannot handle different per-sample values for field \"%s\"",
_TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
goto bad;
}
*pl = v[0];
status = 1;
}
bad:
if (v && v != buf)
_TIFFfree(v);
}
return (status);
}
#undef NITEMS
/*
* Fetch a set of offsets or lengths.
* While this routine says "strips",
* in fact it's also used for tiles.
*/
static int
TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp)
{
register uint32* lp;
int status;
CheckDirCount(tif, dir, (uint32) nstrips);
/*
* Allocate space for strip information.
*/
if (*lpp == NULL &&
(*lpp = (uint32 *)CheckMalloc(tif,
nstrips, sizeof (uint32), "for strip array")) == NULL)
return (0);
lp = *lpp;
memset( lp, 0, sizeof(uint32) * nstrips );
if (dir->tdir_type == (int)TIFF_SHORT) {
/*
* Handle uint16->uint32 expansion.
*/
uint16* dp = (uint16*) CheckMalloc(tif,
dir->tdir_count, sizeof (uint16), "to fetch strip tag");
if (dp == NULL)
return (0);
if( (status = TIFFFetchShortArray(tif, dir, dp)) != 0 ) {
int i;
for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ )
{
lp[i] = dp[i];
}
}
_TIFFfree((char*) dp);
} else if( nstrips != (int) dir->tdir_count ) {
/* Special case to correct length */
uint32* dp = (uint32*) CheckMalloc(tif,
dir->tdir_count, sizeof (uint32), "to fetch strip tag");
if (dp == NULL)
return (0);
status = TIFFFetchLongArray(tif, dir, dp);
if( status != 0 ) {
int i;
for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ )
{
lp[i] = dp[i];
}
}
_TIFFfree( (char *) dp );
} else
status = TIFFFetchLongArray(tif, dir, lp);
return (status);
}
#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
/*
* Fetch and set the ExtraSamples tag.
*/
static int
TIFFFetchExtraSamples(TIFF* tif, TIFFDirEntry* dir)
{
uint16 buf[10];
uint16* v = buf;
int status;
if (dir->tdir_count > NITEMS(buf)) {
v = (uint16*) CheckMalloc(tif, dir->tdir_count, sizeof (uint16),
"to fetch extra samples");
if (!v)
return (0);
}
if (dir->tdir_type == TIFF_BYTE)
status = TIFFFetchByteArray(tif, dir, v);
else
status = TIFFFetchShortArray(tif, dir, v);
if (status)
status = TIFFSetField(tif, dir->tdir_tag, dir->tdir_count, v);
if (v != buf)
_TIFFfree((char*) v);
return (status);
}
#undef NITEMS
#ifdef COLORIMETRY_SUPPORT
/*
* Fetch and set the RefBlackWhite tag.
*/
static int
TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir)
{
static const char mesg[] = "for \"ReferenceBlackWhite\" array";
char* cp;
int ok;
if (dir->tdir_type == TIFF_RATIONAL)
return (TIFFFetchNormalTag(tif, dir));
/*
* Handle LONG's for backward compatibility.
*/
cp = CheckMalloc(tif, dir->tdir_count, sizeof (uint32), mesg);
if( (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) != 0) {
float* fp = (float*)
CheckMalloc(tif, dir->tdir_count, sizeof (float), mesg);
if( (ok = (fp != NULL)) != 0 ) {
uint32 i;
for (i = 0; i < dir->tdir_count; i++)
fp[i] = (float)((uint32*) cp)[i];
ok = TIFFSetField(tif, dir->tdir_tag, fp);
_TIFFfree((char*) fp);
}
}
if (cp)
_TIFFfree(cp);
return (ok);
}
#endif
/*
* Replace a single strip (tile) of uncompressed data by
* multiple strips (tiles), each approximately 8Kbytes.
* This is useful for dealing with large images or
* for dealing with machines with a limited amount
* memory.
*/
static void
ChopUpSingleUncompressedStrip(TIFF* tif)
{
register TIFFDirectory *td = &tif->tif_dir;
uint32 bytecount = td->td_stripbytecount[0];
uint32 offset = td->td_stripoffset[0];
tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes;
tstrip_t strip, nstrips, rowsperstrip;
uint32* newcounts;
uint32* newoffsets;
/*
* Make the rows hold at least one
* scanline, but fill 8k if possible.
*/
if (rowbytes > 8192) {
stripbytes = rowbytes;
rowsperstrip = 1;
} else if (rowbytes > 0 ) {
rowsperstrip = 8192 / rowbytes;
stripbytes = rowbytes * rowsperstrip;
}
else
return;
/* never increase the number of strips in an image */
if (rowsperstrip >= td->td_rowsperstrip)
return;
nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes);
newcounts = (uint32*) CheckMalloc(tif, nstrips, sizeof (uint32),
"for chopped \"StripByteCounts\" array");
newoffsets = (uint32*) CheckMalloc(tif, nstrips, sizeof (uint32),
"for chopped \"StripOffsets\" array");
if (newcounts == NULL || newoffsets == NULL) {
/*
* Unable to allocate new strip information, give
* up and use the original one strip information.
*/
if (newcounts != NULL)
_TIFFfree(newcounts);
if (newoffsets != NULL)
_TIFFfree(newoffsets);
return;
}
/*
* Fill the strip information arrays with
* new bytecounts and offsets that reflect
* the broken-up format.
*/
for (strip = 0; strip < nstrips; strip++) {
if (stripbytes > (tsize_t) bytecount)
stripbytes = bytecount;
newcounts[strip] = stripbytes;
newoffsets[strip] = offset;
offset += stripbytes;
bytecount -= stripbytes;
}
/*
* Replace old single strip info with multi-strip info.
*/
td->td_stripsperimage = td->td_nstrips = nstrips;
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
_TIFFfree(td->td_stripbytecount);
_TIFFfree(td->td_stripoffset);
td->td_stripbytecount = newcounts;
td->td_stripoffset = newoffsets;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?