
Thread
2009.11.29 17:02 "[Tiff] [PATCH 3/3] Eliminate static buffer for default YCbCrCoefficients", 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 TIFFDefaultDirectorygetting
simpler). Unfortunately for TIFFTAG_YCBCRCOEFFICIENTS, the default result
is returned in a static buffer. If a program altered the data stored
in this buffer, it would change the defaults for all other users of
the entire library (in the current address space). The buffer cannot
be const because of the ABI.
This fix returns YCbCrCoefficients to a non-custom field, which may not be
perfect, but it does remove the static buffer.
---
libtiff/tif_aux.c | 8 ++------
libtiff/tif_dir.c | 16 ++++++++++++++++
libtiff/tif_dir.h | 2 ++
libtiff/tif_dirinfo.c | 2 +-
4 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/libtiff/tif_aux.c b/libtiff/tif_aux.c
index e8d89f4..61cab87 100644
--- a/libtiff/tif_aux.c
+++ b/libtiff/tif_aux.c
@@ -216,12 +216,8 @@ TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap)
*va_arg(ap, uint32 *) = td->td_imagedepth;
return (1);
case TIFFTAG_YCBCRCOEFFICIENTS:
- {
- /* defaults are from CCIR Recommendation 601-1 */
- static float ycbcrcoeffs[] = { 0.299f, 0.587f, 0.114f };
- *va_arg(ap, float **) = ycbcrcoeffs;
- return 1;
- }
+ *va_arg(ap, float **) = td->td_ycbcrcoeffs;
+ return (1);
case TIFFTAG_YCBCRSUBSAMPLING:
*va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0];
*va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1];
diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index 56863df..0a50f8d 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -365,6 +365,9 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
status = 0;
}
break;
+ case TIFFTAG_YCBCRCOEFFICIENTS:
+ _TIFFsetFloatArray(&td->td_ycbcrcoeffs, va_arg(ap, float*), 3);
+ break;
case TIFFTAG_YCBCRPOSITIONING:
td->td_ycbcrpositioning = (uint16) va_arg(ap, uint16_vap);
break;
@@ -880,6 +883,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
*va_arg(ap, uint16*) = td->td_nsubifd;
*va_arg(ap, uint64**) = td->td_subifd;
break;
+ case TIFFTAG_YCBCRCOEFFICIENTS:
+ *va_arg(ap, float**) = td->td_ycbcrcoeffs;
+ break;
case TIFFTAG_YCBCRPOSITIONING:
*va_arg(ap, uint16*) = td->td_ycbcrpositioning;
break;
@@ -1087,6 +1093,7 @@ TIFFFreeDirectory(TIFF* tif)
CleanupField(td_colormap[2]);
CleanupField(td_sampleinfo);
CleanupField(td_subifd);
+ CleanupField(td_ycbcrcoeffs);
CleanupField(td_inknames);
CleanupField(td_whitepoint);
CleanupField(td_refblackwhite);
@@ -1168,6 +1175,15 @@ TIFFDefaultDirectory(TIFF* tif)
td->td_resolutionunit = RESUNIT_INCH;
td->td_sampleformat = SAMPLEFORMAT_UINT;
td->td_imagedepth = 1;
+
+ /* YCbCrCoefficients defaults are from CCIR Recommendation 601-1 */
+ td->td_ycbcrcoeffs = (float *) _TIFFmalloc(3 * sizeof (float));
+ if (!td->td_ycbcrcoeffs)
+ return (0);
+ td->td_ycbcrcoeffs[0] = 0.299f;
+ td->td_ycbcrcoeffs[1] = 0.587f;
+ td->td_ycbcrcoeffs[2] = 0.114f;
+
td->td_ycbcrsubsampling[0] = 2;
td->td_ycbcrsubsampling[1] = 2;
td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h
index 70b68f2..1b7d035 100644
--- a/libtiff/tif_dir.h
+++ b/libtiff/tif_dir.h
@@ -78,6 +78,7 @@ typedef struct {
uint16 td_nsubifd;
uint64* td_subifd;
/* YCbCr parameters */
+ float* td_ycbcrcoeffs;
uint16 td_ycbcrsubsampling[2];
uint16 td_ycbcrpositioning;
/* Colorimetry parameters */
@@ -136,6 +137,7 @@ typedef struct {
#define FIELD_IMAGEDEPTH 35
#define FIELD_TILEDEPTH 36
#define FIELD_HALFTONEHINTS 37
+#define FIELD_YCBCRCOEFFICIENTS 38
#define FIELD_YCBCRSUBSAMPLING 39
#define FIELD_YCBCRPOSITIONING 40
index 4a927aa..ac4f47c 100644
--- a/libtiff/tif_dirinfo.c
+++ b/libtiff/tif_dirinfo.c
@@ -109,7 +109,7 @@ tiffFields[] = {
{ TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SLONG, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL },
{ TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SBYTE, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL },
{ TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SLONG, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YClipPathUnits", NULL },
+ { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_YCBCRCOEFFICIENTS, 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_REFBLACKWHITE, 1, 0, "ReferenceBlackWhite", NULL },
--
1.6.5.2