From 361f4288eb65063e2c6e1cfebbbf91667fce3c38 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 21 Apr 2007 19:29:01 +0000 Subject: [PATCH] added support for image resolution options to PNG handler (heavily modified patch 1704128) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45567 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/image.h | 17 ++++++++++++++++- src/common/image.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/common/imagjpeg.cpp | 33 ++++++--------------------------- src/common/imagpng.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 28 deletions(-) diff --git a/include/wx/image.h b/include/wx/image.h index b1d7eea62a..afcbaf95c2 100644 --- a/include/wx/image.h +++ b/include/wx/image.h @@ -37,9 +37,17 @@ #define wxIMAGE_OPTION_RESOLUTIONUNIT wxString(_T("ResolutionUnit")) // constants used with wxIMAGE_OPTION_RESOLUTIONUNIT -enum +// +// NB: don't change these values, they correspond to libjpeg constants +enum wxImageResolution { + // Resolution not specified + wxIMAGE_RESOLUTION_NONE = 0, + + // Resolution specified in inches wxIMAGE_RESOLUTION_INCHES = 1, + + // Resolution specified in centimeters wxIMAGE_RESOLUTION_CM = 2 }; @@ -112,6 +120,13 @@ protected: bool CallDoCanRead(wxInputStream& stream); #endif // wxUSE_STREAMS + // helper for the derived classes SaveFile() implementations: returns the + // values of x- and y-resolution options specified as the image options if + // any + static wxImageResolution + GetResolutionFromOptions(const wxImage& image, int *x, int *y); + + wxString m_name; wxString m_extension; wxString m_mime; diff --git a/src/common/image.cpp b/src/common/image.cpp index 9436fdd28e..d91c445e04 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -2645,6 +2645,42 @@ bool wxImageHandler::CallDoCanRead(wxInputStream& stream) #endif // wxUSE_STREAMS +/* static */ +wxImageResolution +wxImageHandler::GetResolutionFromOptions(const wxImage& image, int *x, int *y) +{ + wxCHECK_MSG( x && y, wxIMAGE_RESOLUTION_NONE, _T("NULL pointer") ); + + if ( image.HasOption(wxIMAGE_OPTION_RESOLUTIONX) && + image.HasOption(wxIMAGE_OPTION_RESOLUTIONY) ) + { + *x = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX); + *y = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY); + } + else if ( image.HasOption(wxIMAGE_OPTION_RESOLUTION) ) + { + *x = + *y = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTION); + } + else // no resolution options specified + { + *x = + *y = 0; + + return wxIMAGE_RESOLUTION_NONE; + } + + // get the resolution unit too + int resUnit = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT); + if ( !resUnit ) + { + // this is the default + resUnit = wxIMAGE_RESOLUTION_INCHES; + } + + return (wxImageResolution)resUnit; +} + // ---------------------------------------------------------------------------- // image histogram stuff // ---------------------------------------------------------------------------- diff --git a/src/common/imagjpeg.cpp b/src/common/imagjpeg.cpp index c6326116c5..64cc2b859d 100644 --- a/src/common/imagjpeg.cpp +++ b/src/common/imagjpeg.cpp @@ -414,37 +414,16 @@ bool wxJPEGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo jpeg_set_quality(&cinfo, image->GetOptionInt(wxIMAGE_OPTION_QUALITY), TRUE); // set the resolution fields in the output file - UINT16 resX, - resY; - if ( image->HasOption(wxIMAGE_OPTION_RESOLUTIONX) && - image->HasOption(wxIMAGE_OPTION_RESOLUTIONY) ) - { - resX = (UINT16)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX); - resY = (UINT16)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY); - } - else if ( image->HasOption(wxIMAGE_OPTION_RESOLUTION) ) - { - resX = - resY = (UINT16)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTION); - } - else - { - resX = - resY = 0; - } - - if ( resX && resY ) + int resX, resY; + wxImageResolution res = GetResolutionFromOptions(*image, &resX, &resY); + if ( res != wxIMAGE_RESOLUTION_NONE ) { cinfo.X_density = resX; cinfo.Y_density = resY; - } - // sets the resolution unit field in the output file - // wxIMAGE_RESOLUTION_INCHES for inches - // wxIMAGE_RESOLUTION_CM for centimeters - if ( image->HasOption(wxIMAGE_OPTION_RESOLUTIONUNIT) ) - { - cinfo.density_unit = (UINT8)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT); + // it so happens that wxIMAGE_RESOLUTION_INCHES/CM values are the same + // ones as used by libjpeg, so we can assign them directly + cinfo.density_unit = res; } jpeg_start_compress(&cinfo, TRUE); diff --git a/src/common/imagpng.cpp b/src/common/imagpng.cpp index 009f133de9..8acc531db2 100644 --- a/src/common/imagpng.cpp +++ b/src/common/imagpng.cpp @@ -63,6 +63,8 @@ enum Transparency Transparency_Alpha }; +static const double INCHES_IN_METER = 39.3700787; + // ---------------------------------------------------------------------------- // local functions // ---------------------------------------------------------------------------- @@ -748,6 +750,30 @@ bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbos if ( iBitDepth == 16 ) iElements *= 2; + // save the image resolution if we have it + int resX, resY; + switch ( GetResolutionFromOptions(*image, &resX, &resY) ) + { + case wxIMAGE_RESOLUTION_INCHES: + resX *= INCHES_IN_METER; + resY *= INCHES_IN_METER; + break; + + case wxIMAGE_RESOLUTION_CM: + resX *= 100; + resY *= 100; + break; + + case wxIMAGE_RESOLUTION_NONE: + break; + + default: + wxFAIL_MSG( _T("unsupported image resolution units") ); + } + + if ( resX && resY ) + png_set_pHYs( png_ptr, info_ptr, resX, resY, PNG_RESOLUTION_METER ); + png_set_sBIT( png_ptr, info_ptr, &sig_bit ); png_write_info( png_ptr, info_ptr ); png_set_shift( png_ptr, &sig_bit ); -- 2.45.2