2009.11.29 17:02 "[Tiff] [PATCH 1/3] Make TIFFGetFieldDefaulted of WhitePoint reentrant", by Adam Goode
When custom fields were introduced in 2005, many internal fields
were converted to use custom fields, and TIFFGetFieldDefaulted got
a bit more complicated each time (with TIFFDefaultDirectory getting
simpler). Unfortunately for TIFFTAG_WHITEPOINT, the default result
is returned in a static buffer. If a multi-threaded program would
try to get the default value of WhitePoint, even with different TIFF*
objects, it would go wrong.
This fix returns WhitePoint to a non-custom field, which may not be
perfect, but it does remove the static buffer.
---
libtiff/tif_aux.c | 13 ++-----------
libtiff/tif_dir.c | 17 +++++++++++++++++
libtiff/tif_dir.h | 2 ++
libtiff/tif_dirinfo.c | 2 +-
libtiff/tif_print.c | 7 +++----
5 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/libtiff/tif_aux.c b/libtiff/tif_aux.c
index 560b5a4..149a95f 100644
--- a/libtiff/tif_aux.c
+++ b/libtiff/tif_aux.c
@@ -201,17 +201,8 @@ TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap)
*va_arg(ap, uint16 *) = td->td_ycbcrpositioning;
return (1);
case TIFFTAG_WHITEPOINT:
- {
- static float whitepoint[2];
-
- /* TIFF 6.0 specification tells that it is no default
- value for the WhitePoint, but AdobePhotoshop TIFF
- Technical Note tells that it should be CIE D50. */
- whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0);
- whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0);
- *va_arg(ap, float **) = whitepoint;
- return 1;
- }
- + *va_arg(ap, float**) = td->td_whitepoint;
+ return (1);
case TIFFTAG_TRANSFERFUNCTION:
if (!td->td_transferfunction[0] &&
!TIFFDefaultTransferFunction(td)) {
diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index 7e24622..6556cac 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -372,6 +372,9 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, uint16_vap);
td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, uint16_vap);
break;
+ case TIFFTAG_WHITEPOINT:
+ _TIFFsetFloatArray(&td->td_whitepoint, va_arg(ap, float*), 2);
+ break;
case TIFFTAG_TRANSFERFUNCTION:
v = (td->td_samplesperpixel - td->td_extrasamples) > 1? 3: 1;
for (i = 0; i < v; i++)
@@ -880,6 +883,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
*va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0];
*va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1];
break;
+ case TIFFTAG_WHITEPOINT:
+ *va_arg(ap, float**) = td->td_whitepoint;
+ break;
case TIFFTAG_TRANSFERFUNCTION:
*va_arg(ap, uint16**) = td->td_transferfunction[0];
if (td->td_samplesperpixel - td->td_extrasamples > 1) {
@@ -1075,6 +1081,7 @@ TIFFFreeDirectory(TIFF* tif)
CleanupField(td_sampleinfo);
CleanupField(td_subifd);
CleanupField(td_inknames);
+ CleanupField(td_whitepoint);
CleanupField(td_transferfunction[0]);
CleanupField(td_transferfunction[1]);
CleanupField(td_transferfunction[2]);
@@ -1156,6 +1163,16 @@ TIFFDefaultDirectory(TIFF* tif)
td->td_ycbcrsubsampling[0] = 2;
td->td_ycbcrsubsampling[1] = 2;
td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
+
+ /* TIFF 6.0 specification tells that it is no default
+ value for the WhitePoint, but AdobePhotoshop TIFF
+ Technical Note tells that it should be CIE D50. */
+ td->td_whitepoint = (float *) _TIFFmalloc(2 * sizeof (float));
+ if (!td->td_whitepoint)
+ return 0;
+ td->td_whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0);
+ td->td_whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0);
+
tif->tif_postdecode = _TIFFNoPostDecode;
tif->tif_foundfield = NULL;
tif->tif_tagmethods.vsetfield = _TIFFVSetField;
diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h
index a0d333f..49e463e 100644
--- a/libtiff/tif_dir.h
+++ b/libtiff/tif_dir.h
@@ -81,6 +81,7 @@ typedef struct {
uint16 td_ycbcrsubsampling[2];
uint16 td_ycbcrpositioning;
/* Colorimetry parameters */
+ float* td_whitepoint;
uint16* td_transferfunction[3];
/* CMYK parameters */
int td_inknameslen;
@@ -136,6 +137,7 @@ typedef struct {
#define FIELD_HALFTONEHINTS 37
#define FIELD_YCBCRSUBSAMPLING 39
#define FIELD_YCBCRPOSITIONING 40
+#define FIELD_WHITEPOINT 42
#define FIELD_TRANSFERFUNCTION 44
#define FIELD_INKNAMES 46
#define FIELD_SUBIFD 49
diff --git a/libtiff/tif_dirinfo.c b/libtiff/tif_dirinfo.c
index fa4935a..b88fca7 100644
--- a/libtiff/tif_dirinfo.c
+++ b/libtiff/tif_dirinfo.c
@@ -87,7 +87,7 @@ tiffFields[] = {
{ TIFFTAG_DATETIME, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTime", NULL },
{ TIFFTAG_ARTIST, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Artist", NULL },
{ TIFFTAG_HOSTCOMPUTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HostComputer", NULL }, - { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhitePoint", NULL }, + { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_WHITEPOINT, 1, 0, "WhitePoint", NULL },
{ TIFFTAG_PRIMARYCHROMATICITIES, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PrimaryChromaticities", NULL },
{ TIFFTAG_COLORMAP, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_COLORMAP, 1, 0, "ColorMap", NULL },
{ TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_HALFTONEHINTS, 1, 0, "HalftoneHints", NULL }, diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c
index 4b19964..10c1ece 100644
--- a/libtiff/tif_print.c
+++ b/libtiff/tif_print.c
@@ -159,10 +159,6 @@ _TIFFPrettyPrintField(TIFF* tif, FILE* fd, uint32 tag,
fprintf(fd, " Dot Range: %u-%u\n",
((uint16*)raw_data)[0],
((uint16*)raw_data)[1]);
return 1;
- case TIFFTAG_WHITEPOINT:
- fprintf(fd, " White Point: %g-%g\n",
- ((float *)raw_data)[0], ((float *)raw_data)[1]);
- return 1;
case TIFFTAG_REFERENCEBLACKWHITE:
{
uint16 i;
@@ -497,6 +493,9 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
} else
fprintf(fd, "(present)\n");
}
+ if (TIFFFieldSet(tif,FIELD_WHITEPOINT))
+ fprintf(fd, " White Point: %g-%g\n",
+ td->td_whitepoint[0], td->td_whitepoint[1]);
if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) {
fprintf(fd, " Transfer Function: ");
if (flags & TIFFPRINT_CURVES) {
--
1.6.5.2