
Thread
2009.11.29 17:02 "[Tiff] [PATCH 2/3] Make TIFFGetFieldDefaulted of ReferenceBlackWhite 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_REFERENCEBLACKWHITE, the
default result
is returned in a static buffer. If a multi-threaded program would
try to get the default value of
ReferenceBlackWhite, even with different TIFF* objects, it would
go wrong.
This fix returns ReferenceBlackWhite to a non-custom field, which
may not be perfect, but it does remove the static buffers.
---
libtiff/tif_aux.c | 60 +++++++++++++++++++++++++++----------------------
libtiff/tif_dir.c | 8 ++++++
libtiff/tif_dir.h | 2 +
libtiff/tif_dirinfo.c | 2 +-
4 files changed, 44 insertions(+), 28 deletions(-)
diff --git a/libtiff/tif_aux.c b/libtiff/tif_aux.c
index 149a95f..e8d89f4 100644
--- a/libtiff/tif_aux.c
+++ b/libtiff/tif_aux.c
@@ -100,6 +100,35 @@ bad:
return 0;
}
+static int
+TIFFDefaultRefBlackWhite(TIFFDirectory* td)
+{
+ int i;
+
+ if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float))))
+ return 0;
+ if (td->td_photometric == PHOTOMETRIC_YCBCR) {
+ /*
+ * YCbCr (Class Y) images must have the ReferenceBlackWhite
+ * tag set. Fix the broken images, which lacks that tag.
+ */
+ td->td_refblackwhite[0] = 0.0F;
+ td->td_refblackwhite[1] = td->td_refblackwhite[3] =
+ td->td_refblackwhite[5] = 255.0F;
+ td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F;
+ } else {
+ /*
+ * Assume RGB (Class R)
+ */
+ for (i = 0; i < 3; i++) {
+ td->td_refblackwhite[2*i+0] = 0;
+ td->td_refblackwhite[2*i+1] =
+ (float)((1L<<td->td_bitspersample)-1L);
+ }
+ }
+ return 1;
+}
+
/*
- Like TIFFGetField, but return any default
- value if the tag is not present in the directory.
- @@ -216,33 +245,10 @@ TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap)
- }
return (1);
case TIFFTAG_REFERENCEBLACKWHITE:
- {
- int i;
- static float ycbcr_refblackwhite[] =
- { 0.0F, 255.0F, 128.0F, 255.0F, 128.0F, 255.0F };
- static float rgb_refblackwhite[6];
-
- for (i = 0; i < 3; i++) {
- rgb_refblackwhite[2 * i + 0] = 0.0F;
- rgb_refblackwhite[2 * i + 1] =
- (float)((1L<<td->td_bitspersample)-1L);
- }
- if (td->td_photometric == PHOTOMETRIC_YCBCR) {
- /*
- * YCbCr (Class Y) images must have the
- * ReferenceBlackWhite tag set. Fix the
- * broken images, which lacks that tag.
- */
- *va_arg(ap, float **) = ycbcr_refblackwhite;
- } else {
- /*
- * Assume RGB (Class R)
- */
- *va_arg(ap, float **) = rgb_refblackwhite;
- }
- return 1;
- }
+ if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td))
+ return (0);
+ *va_arg(ap, float **) = td->td_refblackwhite;
+ return (1);
}
return 0;
}
diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index 6556cac..56863df 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -381,6 +381,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
_TIFFsetShortArray(&td->td_transferfunction[i],
va_arg(ap, uint16*),
1L<<td->td_bitspersample);
break;
+ /* XXX should check for null range */
+ _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6);
+ break;
case TIFFTAG_INKNAMES:
v = (uint16) va_arg(ap, uint16_vap);
s = va_arg(ap, char*);
@@ -893,6 +897,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
*va_arg(ap, uint16**) = td->td_transferfunction[2];
}
break;
+ *va_arg(ap, float**) = td->td_refblackwhite;
+ break;
case TIFFTAG_INKNAMES:
*va_arg(ap, char**) = td->td_inknames;
break;
@@ -1082,6 +1089,7 @@ TIFFFreeDirectory(TIFF* tif)
CleanupField(td_subifd);
CleanupField(td_inknames);
+ CleanupField(td_refblackwhite);
CleanupField(td_transferfunction[0]);
CleanupField(td_transferfunction[1]);
CleanupField(td_transferfunction[2]);
diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h
index 49e463e..70b68f2 100644
--- a/libtiff/tif_dir.h
+++ b/libtiff/tif_dir.h
@@ -82,6 +82,7 @@ typedef struct {
uint16 td_ycbcrpositioning;
/* Colorimetry parameters */
+ float* td_refblackwhite;
uint16* td_transferfunction[3];
/* CMYK parameters */
int td_inknameslen;
@@ -137,6 +138,7 @@ typedef struct {
#define FIELD_HALFTONEHINTS 37
#define FIELD_YCBCRSUBSAMPLING 39
#define FIELD_YCBCRPOSITIONING 40
+#define FIELD_REFBLACKWHITE 41
diff --git a/libtiff/tif_dirinfo.c b/libtiff/tif_dirinfo.c
index b88fca7..4a927aa 100644
--- a/libtiff/tif_dirinfo.c
+++ b/libtiff/tif_dirinfo.c
@@ -112,7 +112,7 @@ tiffFields[] = {
{ TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YCbCrCoefficients", NULL },
{ TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_YCBCRSUBSAMPLING, 0, 0, "YCbCrSubsampling", NULL },
{ TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_YCBCRPOSITIONING, 0, 0, "YCbCrPositioning", NULL }, - { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ReferenceBlackWhite", NULL }, + { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_REFBLACKWHITE, 1, 0, "ReferenceBlackWhite", NULL },
{ TIFFTAG_XMLPACKET, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "XMLPacket", NULL },
/* begin SGI tags */
{ TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 0, "Matteing", NULL },
--
1.6.5.2