Improvements in tag writing code.

This commit is contained in:
Andrey Kiselev 2004-10-30 17:07:01 +00:00
parent c6ffb53725
commit dc65ed605a

View File

@ -1,4 +1,4 @@
/* $Id: tif_dirwrite.c,v 1.25 2004-10-29 10:15:13 dron Exp $ */
/* $Id: tif_dirwrite.c,v 1.26 2004-10-30 17:07:01 dron Exp $ */
/*
* Copyright (c) 1988-1997 Sam Leffler
@ -46,16 +46,11 @@ static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*);
static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*);
static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*);
static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**);
static int TIFFWriteShortArray(TIFF*,
TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint16*);
static int TIFFWriteLongArray(TIFF *,
TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint32*);
static int TIFFWriteRationalArray(TIFF *,
TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);
static int TIFFWriteFloatArray(TIFF *,
TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);
static int TIFFWriteDoubleArray(TIFF *,
TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
static int TIFFWriteShortArray(TIFF*, TIFFDirEntry*, uint16*);
static int TIFFWriteLongArray(TIFF *, TIFFDirEntry*, uint32*);
static int TIFFWriteRationalArray(TIFF *, TIFFDirEntry*, float*);
static int TIFFWriteFloatArray(TIFF *, TIFFDirEntry*, float*);
static int TIFFWriteDoubleArray(TIFF *, TIFFDirEntry*, double*);
static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*);
static int TIFFWriteAnyArray(TIFF*,
TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
@ -65,18 +60,16 @@ static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*);
static int TIFFLinkDirectory(TIFF*);
#define WriteRationalPair(type, tag1, v1, tag2, v2) { \
if (!TIFFWriteRational(tif, type, tag1, dir, v1)) \
goto bad; \
if (!TIFFWriteRational(tif, type, tag2, dir+1, v2)) \
goto bad; \
dir++; \
TIFFWriteRational((tif), (type), (tag1), (dir), (v1)) \
TIFFWriteRational((tif), (type), (tag2), (dir)+1, (v2)) \
(dir)++; \
}
#define TIFFWriteRational(tif, type, tag, dir, v) \
TIFFWriteRationalArray((tif), (type), (tag), (dir), 1, &(v))
#ifndef TIFFWriteRational
static int TIFFWriteRational(TIFF*,
TIFFDataType, ttag_t, TIFFDirEntry*, float);
#endif
#define TIFFWriteRational(tif, type, tag, dir, v) \
(dir)->tdir_tag = (tag); \
(dir)->tdir_type = (type); \
(dir)->tdir_count = 1; \
if (!TIFFWriteRationalArray((tif), (dir), &(v))) \
goto bad;
/*
* Write the contents of the current directory
@ -219,8 +212,11 @@ _TIFFWriteDirectory(TIFF* tif, int done)
TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS;
if (tag != fip->field_tag)
continue;
if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir,
(uint32) td->td_nstrips, td->td_stripoffset))
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (uint16) TIFF_LONG;
dir->tdir_count = (uint32) td->td_nstrips;
if (!TIFFWriteLongArray(tif, dir, td->td_stripoffset))
goto bad;
break;
case FIELD_STRIPBYTECOUNTS:
@ -234,8 +230,12 @@ _TIFFWriteDirectory(TIFF* tif, int done)
TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS;
if (tag != fip->field_tag)
continue;
if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir,
(uint32) td->td_nstrips, td->td_stripbytecount))
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (uint16) TIFF_LONG;
dir->tdir_count = (uint32) td->td_nstrips;
if (!TIFFWriteLongArray(tif, dir,
td->td_stripbytecount))
goto bad;
break;
case FIELD_ROWSPERSTRIP:
@ -429,130 +429,140 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
uint32 wc2;
dir->tdir_tag = (uint16) fip->field_tag;
dir->tdir_type = (unsigned short) fip->field_type;
dir->tdir_type = (uint16) fip->field_type;
dir->tdir_count = wc;
#define WRITEF(x,y) x(tif, fip->field_type, fip->field_tag, dir, wc, y)
switch (fip->field_type) {
case TIFF_SHORT:
case TIFF_SSHORT:
if (wc > 1) {
if (fip->field_passcount) {
uint16* wp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
if (wc == (uint16) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &wp);
dir->tdir_count = wc2;
} else { /* Assume TIFF_VARIABLE */
TIFFGetField(tif, fip->field_tag, &wc, &wp);
else
TIFFGetField(tif, fip->field_tag, &wp);
if (!WRITEF(TIFFWriteShortArray, wp))
return (0);
dir->tdir_count = wc;
}
if (!TIFFWriteShortArray(tif, dir, wp))
return 0;
} else {
if (fip->field_passcount) {
uint16* wp;
TIFFGetField(tif, fip->field_tag, &wc, &wp);
if (!WRITEF(TIFFWriteShortArray, wp))
return 0;
} else {
if (wc == 1) {
uint16 sv;
TIFFGetField(tif, fip->field_tag, &sv);
dir->tdir_offset =
TIFFInsertData(tif, dir->tdir_type, sv);
} else {
uint16* wp;
TIFFGetField(tif, fip->field_tag, &wp);
if (!TIFFWriteShortArray(tif, dir, wp))
return 0;
}
}
break;
case TIFF_LONG:
case TIFF_SLONG:
case TIFF_IFD:
if (wc > 1) {
if (fip->field_passcount) {
uint32* lp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
if (wc == (uint16) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &lp);
dir->tdir_count = wc2;
} else { /* Assume TIFF_VARIABLE */
TIFFGetField(tif, fip->field_tag, &wc, &lp);
else
TIFFGetField(tif, fip->field_tag, &lp);
if (!WRITEF(TIFFWriteLongArray, lp))
return (0);
dir->tdir_count = wc;
}
if (!TIFFWriteLongArray(tif, dir, lp))
return 0;
} else {
if (fip->field_passcount) {
uint32* lp;
TIFFGetField(tif, fip->field_tag, &wc, &lp);
if (!WRITEF(TIFFWriteLongArray, lp))
return 0;
} else {
if (wc == 1) {
/* XXX handle LONG->SHORT conversion */
TIFFGetField(tif, fip->field_tag,
&dir->tdir_offset);
} else {
uint32* lp;
TIFFGetField(tif, fip->field_tag, &lp);
if (!TIFFWriteLongArray(tif, dir, lp))
return 0;
}
}
break;
case TIFF_RATIONAL:
case TIFF_SRATIONAL:
if (wc > 1) {
if (fip->field_passcount) {
float* fp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
if (wc == (uint16) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &fp);
dir->tdir_count = wc2;
} else { /* Assume TIFF_VARIABLE */
TIFFGetField(tif, fip->field_tag, &wc, &fp);
else
TIFFGetField(tif, fip->field_tag, &fp);
if (!WRITEF(TIFFWriteRationalArray, fp))
return (0);
dir->tdir_count = wc;
}
if (!TIFFWriteRationalArray(tif, dir, fp))
return 0;
} else {
if (fip->field_passcount) {
float* fp;
TIFFGetField(tif, fip->field_tag, &wc, &fp);
if (!WRITEF(TIFFWriteRationalArray, fp))
return 0;
} else {
if (wc == 1) {
float fv;
TIFFGetField(tif, fip->field_tag, &fv);
if (!WRITEF(TIFFWriteRationalArray, &fv))
return (0);
if (!TIFFWriteRationalArray(tif, dir, &fv))
return 0;
} else {
float* fp;
TIFFGetField(tif, fip->field_tag, &fp);
if (!TIFFWriteRationalArray(tif, dir, fp))
return 0;
}
}
break;
case TIFF_FLOAT:
if (wc > 1) {
if (fip->field_passcount) {
float* fp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
if (wc == (uint16) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &fp);
dir->tdir_count = wc2;
} else { /* Assume TIFF_VARIABLE */
TIFFGetField(tif, fip->field_tag, &wc, &fp);
else
TIFFGetField(tif, fip->field_tag, &fp);
if (!WRITEF(TIFFWriteFloatArray, fp))
return (0);
dir->tdir_count = wc;
}
if (!TIFFWriteFloatArray(tif, dir, fp))
return 0;
} else {
if (fip->field_passcount) {
float* fp;
TIFFGetField(tif, fip->field_tag, &wc, &fp);
if (!WRITEF(TIFFWriteFloatArray, fp))
return 0;
} else {
if (wc == 1) {
float fv;
TIFFGetField(tif, fip->field_tag, &fv);
if (!WRITEF(TIFFWriteFloatArray, &fv))
return (0);
if (!TIFFWriteFloatArray(tif, dir, &fv))
return 0;
} else {
float* fp;
TIFFGetField(tif, fip->field_tag, &fp);
if (!TIFFWriteFloatArray(tif, dir, fp))
return 0;
}
}
break;
case TIFF_DOUBLE:
if (wc > 1) {
if (fip->field_passcount) {
double* dp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
if (wc == (uint16) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &dp);
dir->tdir_count = wc2;
} else { /* Assume TIFF_VARIABLE */
TIFFGetField(tif, fip->field_tag, &wc, &dp);
else
TIFFGetField(tif, fip->field_tag, &dp);
if (!WRITEF(TIFFWriteDoubleArray, dp))
return (0);
dir->tdir_count = wc;
}
if (!TIFFWriteDoubleArray(tif, dir, dp))
return 0;
} else {
if (fip->field_passcount) {
double* dp;
TIFFGetField(tif, fip->field_tag, &wc, &dp);
if (!WRITEF(TIFFWriteDoubleArray, dp))
return 0;
} else {
if (wc == 1) {
double dv;
TIFFGetField(tif, fip->field_tag, &dv);
if (!WRITEF(TIFFWriteDoubleArray, &dv))
return (0);
if (!TIFFWriteDoubleArray(tif, dir, &dv))
return 0;
} else {
double* dp;
TIFFGetField(tif, fip->field_tag, &dp);
if (!TIFFWriteDoubleArray(tif, dir, dp))
return 0;
}
}
break;
@ -577,7 +587,7 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
if (wc == (uint16) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &cp);
dir->tdir_count = wc2;
} else {
} else { /* Assume TIFF_VARIABLE */
TIFFGetField(tif, fip->field_tag, &wc, &cp);
dir->tdir_count = wc;
}
@ -618,7 +628,6 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
}
return (1);
}
#undef WRITEF
/*
* Setup a directory entry with either a SHORT
@ -651,19 +660,6 @@ TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v)
}
#undef MakeShortDirent
#ifndef TIFFWriteRational
/*
* Setup a RATIONAL directory entry and
* write the associated indirect value.
*/
static int
TIFFWriteRational(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, float v)
{
return (TIFFWriteRationalArray(tif, type, tag, dir, 1, &v));
}
#endif
#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
/*
* Setup a directory entry that references a
@ -689,7 +685,11 @@ TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
TIFFGetField(tif, tag, &v);
for (i = 0; i < samples; i++)
w[i] = v;
status = TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, samples, w);
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (uint16) TIFF_SHORT;
dir->tdir_count = samples;
status = TIFFWriteShortArray(tif, dir, w);
if (w != buf)
_TIFFfree((char*) w);
return (status);
@ -737,7 +737,11 @@ TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
uint16 v[2];
TIFFGetField(tif, tag, &v[0], &v[1]);
return (TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, 2, v));
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (uint16) TIFF_SHORT;
dir->tdir_count = 2;
return (TIFFWriteShortArray(tif, dir, v));
}
/*
@ -783,20 +787,16 @@ TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
* or SSHORT and write the associated indirect values.
*/
static int
TIFFWriteShortArray(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v)
TIFFWriteShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
if (n <= 2) {
if (dir->tdir_count <= 2) {
if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
dir->tdir_offset = (uint32) ((long) v[0] << 16);
if (n == 2)
if (dir->tdir_count == 2)
dir->tdir_offset |= v[1] & 0xffff;
} else {
dir->tdir_offset = v[0] & 0xffff;
if (n == 2)
if (dir->tdir_count == 2)
dir->tdir_offset |= (long) v[1] << 16;
}
return (1);
@ -809,13 +809,9 @@ TIFFWriteShortArray(TIFF* tif,
* or SLONG and write the associated indirect values.
*/
static int
TIFFWriteLongArray(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v)
TIFFWriteLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
if (n == 1) {
if (dir->tdir_count == 1) {
dir->tdir_offset = v[0];
return (1);
} else
@ -827,32 +823,29 @@ TIFFWriteLongArray(TIFF* tif,
* or SRATIONAL and write the associated indirect values.
*/
static int
TIFFWriteRationalArray(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v)
TIFFWriteRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
{
uint32 i;
uint32* t;
int status;
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
t = (uint32*) _TIFFmalloc(2*n * sizeof (uint32));
t = (uint32*) _TIFFmalloc(2 * dir->tdir_count * sizeof (uint32));
if (t == NULL) {
TIFFError(tif->tif_name,
"No space to write RATIONAL array");
return (0);
}
for (i = 0; i < n; i++) {
for (i = 0; i < dir->tdir_count; i++) {
float fv = v[i];
int sign = 1;
uint32 den;
if (fv < 0) {
if (type == TIFF_RATIONAL) {
if (dir->tdir_type == TIFF_RATIONAL) {
TIFFWarning(tif->tif_name,
"\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL",
_TIFFFieldWithTag(tif,tag)->field_name, fv);
_TIFFFieldWithTag(tif,dir->tdir_tag)->field_name,
fv);
fv = 0;
} else
fv = -fv, sign = -1;
@ -871,14 +864,10 @@ TIFFWriteRationalArray(TIFF* tif,
}
static int
TIFFWriteFloatArray(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v)
TIFFWriteFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
TIFFCvtNativeToIEEEFloat(tif, n, v);
if (n == 1) {
TIFFCvtNativeToIEEEFloat(tif, dir->tdir_count, v);
if (dir->tdir_count == 1) {
dir->tdir_offset = *(uint32*) &v[0];
return (1);
} else
@ -886,12 +875,8 @@ TIFFWriteFloatArray(TIFF* tif,
}
static int
TIFFWriteDoubleArray(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
TIFFWriteDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
TIFFCvtNativeToIEEEDouble(tif, n, v);
return (TIFFWriteData(tif, dir, (char*) v));
}
@ -921,71 +906,77 @@ TIFFWriteAnyArray(TIFF* tif,
return (0);
}
}
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (uint16) type;
dir->tdir_count = n;
switch (type) {
case TIFF_BYTE:
{ uint8* bp = (uint8*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (uint8) v[i];
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
if (!TIFFWriteByteArray(tif, dir, (char*) bp))
goto out;
{
uint8* bp = (uint8*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (uint8) v[i];
if (!TIFFWriteByteArray(tif, dir, (char*) bp))
goto out;
}
break;
case TIFF_SBYTE:
{ int8* bp = (int8*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (int8) v[i];
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
if (!TIFFWriteByteArray(tif, dir, (char*) bp))
goto out;
{
int8* bp = (int8*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (int8) v[i];
if (!TIFFWriteByteArray(tif, dir, (char*) bp))
goto out;
}
break;
case TIFF_SHORT:
{ uint16* bp = (uint16*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (uint16) v[i];
if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp))
{
uint16* bp = (uint16*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (uint16) v[i];
if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
goto out;
}
break;
case TIFF_SSHORT:
{ int16* bp = (int16*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (int16) v[i];
if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp))
goto out;
{
int16* bp = (int16*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (int16) v[i];
if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
goto out;
}
break;
case TIFF_LONG:
{ uint32* bp = (uint32*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (uint32) v[i];
if (!TIFFWriteLongArray(tif, type, tag, dir, n, bp))
goto out;
{
uint32* bp = (uint32*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (uint32) v[i];
if (!TIFFWriteLongArray(tif, dir, bp))
goto out;
}
break;
case TIFF_SLONG:
{ int32* bp = (int32*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (int32) v[i];
if (!TIFFWriteLongArray(tif, type, tag, dir, n, (uint32*) bp))
goto out;
{
int32* bp = (int32*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (int32) v[i];
if (!TIFFWriteLongArray(tif, dir, (uint32*) bp))
goto out;
}
break;
case TIFF_FLOAT:
{ float* bp = (float*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (float) v[i];
if (!TIFFWriteFloatArray(tif, type, tag, dir, n, bp))
goto out;
{
float* bp = (float*) w;
for (i = 0; i < (int) n; i++)
bp[i] = (float) v[i];
if (!TIFFWriteFloatArray(tif, dir, bp))
goto out;
}
break;
case TIFF_DOUBLE:
return (TIFFWriteDoubleArray(tif, type, tag, dir, n, v));
return (TIFFWriteDoubleArray(tif, dir, v));
default:
/* TIFF_NOTYPE */
/* TIFF_ASCII */