📄 tif_dirwrite.c
字号:
rc = _TIFFWriteDirectory(tif, FALSE);
(void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
return rc;
}
/*
* Process tags that are not special cased.
*/
static int
TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
{
unsigned short wc = (unsigned short) fip->field_writecount;
uint32 wc2;
dir->tdir_tag = (uint16) fip->field_tag;
dir->tdir_type = (unsigned short) 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) {
uint16* wp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
TIFFGetField(tif, fip->field_tag, &wc, &wp);
else
TIFFGetField(tif, fip->field_tag, &wp);
if (!WRITEF(TIFFWriteShortArray, wp))
return (0);
} else {
if (fip->field_passcount) {
uint16* wp;
TIFFGetField(tif, fip->field_tag, &wc, &wp);
if (!WRITEF(TIFFWriteShortArray, wp))
return 0;
} else {
uint16 sv;
TIFFGetField(tif, fip->field_tag, &sv);
dir->tdir_offset =
TIFFInsertData(tif, dir->tdir_type, sv);
}
}
break;
case TIFF_LONG:
case TIFF_SLONG:
case TIFF_IFD:
if (wc > 1) {
uint32* lp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
TIFFGetField(tif, fip->field_tag, &wc, &lp);
else
TIFFGetField(tif, fip->field_tag, &lp);
if (!WRITEF(TIFFWriteLongArray, lp))
return (0);
} else {
if (fip->field_passcount) {
uint32* lp;
TIFFGetField(tif, fip->field_tag, &wc, &lp);
if (!WRITEF(TIFFWriteLongArray, lp))
return 0;
} else {
/* XXX handle LONG->SHORT conversion */
TIFFGetField(tif, fip->field_tag,
&dir->tdir_offset);
}
}
break;
case TIFF_RATIONAL:
case TIFF_SRATIONAL:
if (wc > 1) {
float* fp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
TIFFGetField(tif, fip->field_tag, &wc, &fp);
else
TIFFGetField(tif, fip->field_tag, &fp);
if (!WRITEF(TIFFWriteRationalArray, fp))
return (0);
} else {
if (fip->field_passcount) {
float* fp;
TIFFGetField(tif, fip->field_tag, &wc, &fp);
if (!WRITEF(TIFFWriteRationalArray, fp))
return 0;
} else {
float fv;
TIFFGetField(tif, fip->field_tag, &fv);
if (!WRITEF(TIFFWriteRationalArray, &fv))
return (0);
}
}
break;
case TIFF_FLOAT:
if (wc > 1) {
float* fp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
TIFFGetField(tif, fip->field_tag, &wc, &fp);
else
TIFFGetField(tif, fip->field_tag, &fp);
if (!WRITEF(TIFFWriteFloatArray, fp))
return (0);
} else {
if (fip->field_passcount) {
float* fp;
TIFFGetField(tif, fip->field_tag, &wc, &fp);
if (!WRITEF(TIFFWriteFloatArray, fp))
return 0;
} else {
float fv;
TIFFGetField(tif, fip->field_tag, &fv);
if (!WRITEF(TIFFWriteFloatArray, &fv))
return (0);
}
}
break;
case TIFF_DOUBLE:
if (wc > 1) {
double* dp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount)
TIFFGetField(tif, fip->field_tag, &wc, &dp);
else
TIFFGetField(tif, fip->field_tag, &dp);
if (!WRITEF(TIFFWriteDoubleArray, dp))
return (0);
} else {
if (fip->field_passcount) {
double* dp;
TIFFGetField(tif, fip->field_tag, &wc, &dp);
if (!WRITEF(TIFFWriteDoubleArray, dp))
return 0;
} else {
double dv;
TIFFGetField(tif, fip->field_tag, &dv);
if (!WRITEF(TIFFWriteDoubleArray, &dv))
return (0);
}
}
break;
case TIFF_ASCII:
{
char* cp;
if (fip->field_passcount)
TIFFGetField(tif, fip->field_tag, &wc, &cp);
else
TIFFGetField(tif, fip->field_tag, &cp);
dir->tdir_count = (uint32) (strlen(cp) + 1);
if (!TIFFWriteByteArray(tif, dir, cp))
return (0);
}
break;
/* added based on patch request from MARTIN.MCBRIDE.MM@agfa.co.uk,
correctness not verified (FW, 99/08) */
case TIFF_BYTE:
case TIFF_SBYTE:
if (wc > 1) {
char* cp;
if (wc == (unsigned short) TIFF_VARIABLE
|| fip->field_passcount) {
TIFFGetField(tif, fip->field_tag, &wc, &cp);
dir->tdir_count = wc;
} else if (wc == (unsigned short) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &cp);
dir->tdir_count = wc2;
} else
TIFFGetField(tif, fip->field_tag, &cp);
if (!TIFFWriteByteArray(tif, dir, cp))
return (0);
} else {
if (fip->field_passcount) {
char* cp;
TIFFGetField(tif, fip->field_tag, &wc, &cp);
dir->tdir_count = wc;
if (!TIFFWriteByteArray(tif, dir, cp))
return 0;
} else {
char cv;
TIFFGetField(tif, fip->field_tag, &cv);
if (!TIFFWriteByteArray(tif, dir, &cv))
return (0);
}
}
break;
case TIFF_UNDEFINED:
{ char* cp;
if (wc == (unsigned short) TIFF_VARIABLE) {
TIFFGetField(tif, fip->field_tag, &wc, &cp);
dir->tdir_count = wc;
} else if (wc == (unsigned short) TIFF_VARIABLE2) {
TIFFGetField(tif, fip->field_tag, &wc2, &cp);
dir->tdir_count = wc2;
} else
TIFFGetField(tif, fip->field_tag, &cp);
if (!TIFFWriteByteArray(tif, dir, cp))
return (0);
}
break;
case TIFF_NOTYPE:
break;
}
return (1);
}
#undef WRITEF
/*
* Setup a directory entry with either a SHORT
* or LONG type according to the value.
*/
static void
TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_count = 1;
if (v > 0xffffL) {
dir->tdir_type = (short) TIFF_LONG;
dir->tdir_offset = v;
} else {
dir->tdir_type = (short) TIFF_SHORT;
dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
}
}
/*
* Setup a SHORT directory entry
*/
static void
TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_count = 1;
dir->tdir_type = (short) TIFF_SHORT;
dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, 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
* samples/pixel array of SHORT values and
* (potentially) write the associated indirect
* values.
*/
static int
TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
{
uint16 buf[10], v;
uint16* w = buf;
int i, status, samples = tif->tif_dir.td_samplesperpixel;
if (samples > NITEMS(buf)) {
w = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
if (w == NULL) {
TIFFError(tif->tif_name,
"No space to write per-sample shorts");
return (0);
}
}
TIFFGetField(tif, tag, &v);
for (i = 0; i < samples; i++)
w[i] = v;
status = TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, samples, w);
if (w != buf)
_TIFFfree((char*) w);
return (status);
}
/*
* Setup a directory entry that references a samples/pixel array of ``type''
* values and (potentially) write the associated indirect values. The source
* data from TIFFGetField() for the specified tag must be returned as double.
*/
static int
TIFFWritePerSampleAnys(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir)
{
double buf[10], v;
double* w = buf;
int i, status;
int samples = (int) tif->tif_dir.td_samplesperpixel;
if (samples > NITEMS(buf)) {
w = (double*) _TIFFmalloc(samples * sizeof (double));
if (w == NULL) {
TIFFError(tif->tif_name,
"No space to write per-sample values");
return (0);
}
}
TIFFGetField(tif, tag, &v);
for (i = 0; i < samples; i++)
w[i] = v;
status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w);
if (w != buf)
_TIFFfree(w);
return (status);
}
#undef NITEMS
/*
* Setup a pair of shorts that are returned by
* value, rather than as a reference to an array.
*/
static int
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));
}
/*
* Setup a directory entry for an NxM table of shorts,
* where M is known to be 2**bitspersample, and write
* the associated indirect data.
*/
static int
TIFFWriteShortTable(TIFF* tif,
ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table)
{
uint32 i, off;
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) TIFF_SHORT;
/* XXX -- yech, fool TIFFWriteData */
dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample);
off = tif->tif_dataoff;
for (i = 0; i < n; i++)
if (!TIFFWriteData(tif, dir, (char *)table[i]))
return (0);
dir->tdir_count *= n;
dir->tdir_offset = off;
return (1);
}
/*
* Write/copy data associated with an ASCII or opaque tag value.
*/
static int
TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
{
if (dir->tdir_count > 4) {
if (!TIFFWriteData(tif, dir, cp))
return (0);
} else
_TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count);
return (1);
}
/*
* Setup a directory entry of an array of SHORT
* or SSHORT and write the associated indirect values.
*/
static int
TIFFWriteShortArray(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
if (n <= 2) {
if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
dir->tdir_offset = (uint32) ((long) v[0] << 16);
if (n == 2)
dir->tdir_offset |= v[1] & 0xffff;
} else {
dir->tdir_offset = v[0] & 0xffff;
if (n == 2)
dir->tdir_offset |= (long) v[1] << 16;
}
return (1);
} else
return (TIFFWriteData(tif, dir, (char*) v));
}
/*
* Setup a directory entry of an array of LONG
* or SLONG and write the associated indirect values.
*/
static int
TIFFWriteLongArray(TIFF* tif,
TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v)
{
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (short) type;
dir->tdir_count = n;
if (n == 1) {
dir->tdir_offset = v[0];
return (1);
} else
return (TIFFWriteData(tif, dir, (char*) v));
}
/*
* Setup a directory entry of an array of RATIONAL
* or SRATIONAL and write the associated indirect values.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -