Added option to TIFF handler for specifying the photometric interpretation.

Added option wxIMAGE_OPTION_TIFF_PHOTOMETRIC for reading and writing TIFF images. This is mostly for being able to distinguish between PHOTOMETRIC_MINISBLACK (chocolate flavour) and PHOTOMETRIC_MINISWHITE (vanilla) as currently the flavour used was fixed. It applies to greyscale as well as black and white images. Added unit tests to verify the written photometric value.

Also see #13194.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@68785 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Dimitri Schoolwerth
2011-08-19 03:47:40 +00:00
parent 8e28cc4701
commit fc695138b4
3 changed files with 38 additions and 6 deletions

View File

@@ -25,6 +25,7 @@
#define wxIMAGE_OPTION_TIFF_BITSPERSAMPLE wxString(wxT("BitsPerSample")) #define wxIMAGE_OPTION_TIFF_BITSPERSAMPLE wxString(wxT("BitsPerSample"))
#define wxIMAGE_OPTION_TIFF_SAMPLESPERPIXEL wxString(wxT("SamplesPerPixel")) #define wxIMAGE_OPTION_TIFF_SAMPLESPERPIXEL wxString(wxT("SamplesPerPixel"))
#define wxIMAGE_OPTION_TIFF_COMPRESSION wxString(wxT("Compression")) #define wxIMAGE_OPTION_TIFF_COMPRESSION wxString(wxT("Compression"))
#define wxIMAGE_OPTION_TIFF_PHOTOMETRIC wxString(wxT("Photometric"))
#define wxIMAGE_OPTION_TIFF_IMAGEDESCRIPTOR wxString(wxT("ImageDescriptor")) #define wxIMAGE_OPTION_TIFF_IMAGEDESCRIPTOR wxString(wxT("ImageDescriptor"))
// for backwards compatibility // for backwards compatibility

View File

@@ -437,6 +437,8 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos
} }
image->SetOption(wxIMAGE_OPTION_TIFF_PHOTOMETRIC, photometric);
uint16 spp, bps, compression; uint16 spp, bps, compression;
/* /*
Read some baseline TIFF tags which helps when re-saving a TIFF Read some baseline TIFF tags which helps when re-saving a TIFF
@@ -603,6 +605,27 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
spp = 1; spp = 1;
} }
int photometric = PHOTOMETRIC_RGB;
if ( image->HasOption(wxIMAGE_OPTION_TIFF_PHOTOMETRIC) )
{
photometric = image->GetOptionInt(wxIMAGE_OPTION_TIFF_PHOTOMETRIC);
if (photometric == PHOTOMETRIC_MINISWHITE
|| photometric == PHOTOMETRIC_MINISBLACK)
{
// either b/w or greyscale
spp = 1;
}
}
else if (spp == 1)
{
photometric = PHOTOMETRIC_MINISBLACK;
}
const bool isColouredImage = (spp > 1)
&& (photometric != PHOTOMETRIC_MINISWHITE)
&& (photometric != PHOTOMETRIC_MINISBLACK);
int compression = image->GetOptionInt(wxIMAGE_OPTION_TIFF_COMPRESSION); int compression = image->GetOptionInt(wxIMAGE_OPTION_TIFF_COMPRESSION);
if ( !compression ) if ( !compression )
{ {
@@ -615,8 +638,7 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, spp); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, spp);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, spp*bps == 1 ? PHOTOMETRIC_MINISBLACK TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
: PHOTOMETRIC_RGB);
TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
// scanlinesize if determined by spp and bps // scanlinesize if determined by spp and bps
@@ -627,7 +649,7 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
unsigned char *buf; unsigned char *buf;
if (TIFFScanlineSize(tif) > linebytes || (spp * bps < 24)) if (TIFFScanlineSize(tif) > linebytes || !isColouredImage)
{ {
buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif)); buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif));
if (!buf) if (!buf)
@@ -649,12 +671,13 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,TIFFDefaultStripSize(tif, (uint32) -1)); TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,TIFFDefaultStripSize(tif, (uint32) -1));
const bool minIsWhite = (photometric == PHOTOMETRIC_MINISWHITE);
unsigned char *ptr = image->GetData(); unsigned char *ptr = image->GetData();
for ( int row = 0; row < image->GetHeight(); row++ ) for ( int row = 0; row < image->GetHeight(); row++ )
{ {
if ( buf ) if ( buf )
{ {
if ( spp * bps > 1 ) if (isColouredImage)
{ {
// color image // color image
memcpy(buf, ptr, image->GetWidth()); memcpy(buf, ptr, image->GetWidth());
@@ -663,7 +686,13 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
{ {
for ( int column = 0; column < linebytes; column++ ) for ( int column = 0; column < linebytes; column++ )
{ {
buf[column] = ptr[column*3 + 1]; uint8 value = ptr[column*3 + 1];
if (minIsWhite)
{
value = 255 - value;
}
buf[column] = value;
} }
} }
else // black and white image else // black and white image
@@ -673,7 +702,7 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
uint8 reverse = 0; uint8 reverse = 0;
for ( int bp = 0; bp < 8; bp++ ) for ( int bp = 0; bp < 8; bp++ )
{ {
if ( ptr[column*24 + bp*3 + 1] > 127 ) if ( (ptr[column*24 + bp*3 + 1] <=127) == minIsWhite )
{ {
// check only green as this is sufficient // check only green as this is sufficient
reverse = (uint8)(reverse | 128 >> bp); reverse = (uint8)(reverse | 128 >> bp);

View File

@@ -1116,6 +1116,8 @@ void ImageTestCase::SaveTIFF()
{ {
TestTIFFImage(wxIMAGE_OPTION_TIFF_BITSPERSAMPLE, 1); TestTIFFImage(wxIMAGE_OPTION_TIFF_BITSPERSAMPLE, 1);
TestTIFFImage(wxIMAGE_OPTION_TIFF_SAMPLESPERPIXEL, 1); TestTIFFImage(wxIMAGE_OPTION_TIFF_SAMPLESPERPIXEL, 1);
TestTIFFImage(wxIMAGE_OPTION_TIFF_PHOTOMETRIC, 0/*PHOTOMETRIC_MINISWHITE*/);
TestTIFFImage(wxIMAGE_OPTION_TIFF_PHOTOMETRIC, 1/*PHOTOMETRIC_MINISBLACK*/);
} }
void ImageTestCase::SaveAnimatedGIF() void ImageTestCase::SaveAnimatedGIF()