added support for reading resolution information from TIFF, JPEG and BMP formats; corrected some bugs with saving resolution; added command allowing to see the image resolution (if available) to the sample (heavily modified patch 1790546)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48612 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-09-08 18:32:36 +00:00
parent 66e2ba91b2
commit 37ba70a520
5 changed files with 192 additions and 25 deletions

View File

@@ -180,6 +180,7 @@ All (GUI):
- Added wxToolTip::SetAutoPop() and SetReshow() (Jan Knepper) - Added wxToolTip::SetAutoPop() and SetReshow() (Jan Knepper)
- Added wxTaskBarIcon::Destroy() - Added wxTaskBarIcon::Destroy()
- Added XRC handler for wxSearchCtrl (Sander Berents) - Added XRC handler for wxSearchCtrl (Sander Berents)
- Read image resolution from TIFF, JPEG and BMP images (Maycon Aparecido Gasoto)
wxGTK: wxGTK:

View File

@@ -118,6 +118,7 @@ public:
void OnAbout( wxCommandEvent &event ); void OnAbout( wxCommandEvent &event );
void OnNewFrame( wxCommandEvent &event ); void OnNewFrame( wxCommandEvent &event );
void OnImageInfo( wxCommandEvent &event );
#ifdef wxHAVE_RAW_BITMAP #ifdef wxHAVE_RAW_BITMAP
void OnTestRawBitmap( wxCommandEvent &event ); void OnTestRawBitmap( wxCommandEvent &event );
#endif // wxHAVE_RAW_BITMAP #endif // wxHAVE_RAW_BITMAP
@@ -131,6 +132,13 @@ public:
MyCanvas *m_canvas; MyCanvas *m_canvas;
private: private:
// ask user for the file name and try to load an image from it
//
// return the file path on success, empty string if we failed to load the
// image or were cancelled by user
static wxString LoadUserImage(wxImage& image);
DECLARE_DYNAMIC_CLASS(MyFrame) DECLARE_DYNAMIC_CLASS(MyFrame)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
@@ -1101,15 +1109,17 @@ enum
ID_QUIT = wxID_EXIT, ID_QUIT = wxID_EXIT,
ID_ABOUT = wxID_ABOUT, ID_ABOUT = wxID_ABOUT,
ID_NEW = 100, ID_NEW = 100,
ID_SHOWRAW = 101 ID_INFO,
ID_SHOWRAW
}; };
IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
BEGIN_EVENT_TABLE(MyFrame,wxFrame) BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU (ID_ABOUT, MyFrame::OnAbout) EVT_MENU (ID_ABOUT, MyFrame::OnAbout)
EVT_MENU (ID_QUIT, MyFrame::OnQuit) EVT_MENU (ID_QUIT, MyFrame::OnQuit)
EVT_MENU (ID_NEW, MyFrame::OnNewFrame) EVT_MENU (ID_NEW, MyFrame::OnNewFrame)
EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
#ifdef wxHAVE_RAW_BITMAP #ifdef wxHAVE_RAW_BITMAP
EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap) EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
#endif #endif
@@ -1128,8 +1138,9 @@ MyFrame::MyFrame()
wxMenu *menuImage = new wxMenu; wxMenu *menuImage = new wxMenu;
menuImage->Append( ID_NEW, _T("&Show any image...\tCtrl-O")); menuImage->Append( ID_NEW, _T("&Show any image...\tCtrl-O"));
menuImage->Append( ID_INFO, _T("Show image &information...\tCtrl-I"));
#ifdef wxHAVE_RAW_BITMAP #ifdef wxHAVE_RAW_BITMAP
menuImage->AppendSeparator();
menuImage->Append( ID_SHOWRAW, _T("Test &raw bitmap...\tCtrl-R")); menuImage->Append( ID_SHOWRAW, _T("Test &raw bitmap...\tCtrl-R"));
#endif #endif
menuImage->AppendSeparator(); menuImage->AppendSeparator();
@@ -1171,23 +1182,71 @@ void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
_T("About wxImage Demo"), wxICON_INFORMATION | wxOK ); _T("About wxImage Demo"), wxICON_INFORMATION | wxOK );
} }
void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) ) wxString MyFrame::LoadUserImage(wxImage& image)
{ {
#if wxUSE_FILEDLG wxString filename;
wxString filename = wxFileSelector(_T("Select image file"));
if ( !filename )
return;
wxImage image; #if wxUSE_FILEDLG
filename = wxFileSelector(_T("Select image file"));
if ( !filename.empty() )
{
if ( !image.LoadFile(filename) ) if ( !image.LoadFile(filename) )
{ {
wxLogError(_T("Couldn't load image from '%s'."), filename.c_str()); wxLogError(_T("Couldn't load image from '%s'."), filename.c_str());
return; return wxEmptyString;
}
}
#endif // wxUSE_FILEDLG
return filename;
}
void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
{
wxImage image;
wxString filename = LoadUserImage(image);
if ( !filename.empty() )
(new MyImageFrame(this, filename, wxBitmap(image)))->Show();
}
void MyFrame::OnImageInfo( wxCommandEvent &WXUNUSED(event) )
{
wxImage image;
if ( !LoadUserImage(image).empty() )
{
// TODO: show more information about the file
wxString info = wxString::Format("Image size: %dx%d",
image.GetWidth(),
image.GetHeight());
int xres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX),
yres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY);
if ( xres || yres )
{
info += wxString::Format("\nResolution: %dx%d", xres, yres);
switch ( image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT) )
{
default:
wxFAIL_MSG( "unknown image resolution units" );
// fall through
case wxIMAGE_RESOLUTION_NONE:
info += " in default units";
break;
case wxIMAGE_RESOLUTION_INCHES:
info += " in";
break;
case wxIMAGE_RESOLUTION_CM:
info += " cm";
break;
}
} }
(new MyImageFrame(this, filename, wxBitmap(image)))->Show(); wxLogMessage("%s", info);
#endif // wxUSE_FILEDLG }
} }
#ifdef wxHAVE_RAW_BITMAP #ifdef wxHAVE_RAW_BITMAP

View File

@@ -27,6 +27,7 @@
#include "wx/bitmap.h" #include "wx/bitmap.h"
#include "wx/palette.h" #include "wx/palette.h"
#include "wx/intl.h" #include "wx/intl.h"
#include "wx/math.h"
#endif #endif
#include "wx/filefn.h" #include "wx/filefn.h"
@@ -154,7 +155,7 @@ bool wxBMPHandler::SaveDib(wxImage *image,
wxUint16 bpp; // bits per pixel wxUint16 bpp; // bits per pixel
wxUint32 compression; // compression method wxUint32 compression; // compression method
wxUint32 size_of_bmp; // size of the bitmap wxUint32 size_of_bmp; // size of the bitmap
wxUint32 h_res, v_res; // image resolution in dpi wxUint32 h_res, v_res; // image resolution in pixels-per-meter
wxUint32 num_clrs; // number of colors used wxUint32 num_clrs; // number of colors used
wxUint32 num_signif_clrs;// number of significant colors wxUint32 num_signif_clrs;// number of significant colors
} hdr; } hdr;
@@ -181,7 +182,37 @@ bool wxBMPHandler::SaveDib(wxImage *image,
hdr.bpp = wxUINT16_SWAP_ON_BE(bpp); hdr.bpp = wxUINT16_SWAP_ON_BE(bpp);
hdr.compression = 0; // RGB uncompressed hdr.compression = 0; // RGB uncompressed
hdr.size_of_bmp = wxUINT32_SWAP_ON_BE(row_width * image->GetHeight()); hdr.size_of_bmp = wxUINT32_SWAP_ON_BE(row_width * image->GetHeight());
hdr.h_res = hdr.v_res = wxUINT32_SWAP_ON_BE(72); // 72dpi is standard
// get the resolution from the image options or fall back to 72dpi standard
// for the BMP format if not specified
wxUint32 hres = image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX),
vres = image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY);
switch ( image->GetOptionInt(wxIMAGE_OPTION_RESOLUTION) )
{
default:
wxFAIL_MSG( _T("unexpected image resolution units") );
// fall through
case wxIMAGE_RESOLUTION_NONE:
hres =
vres = 72;
// fall through to convert it to correct units
case wxIMAGE_RESOLUTION_INCHES:
// convert resolution in inches to resolution in centimeters
hres *= 100*mm2inches;
vres *= 100*mm2inches;
// fall through to convert it to resolution in meters
case wxIMAGE_RESOLUTION_CM:
// convert resolution in centimeters to resolution in meters
hres *= 100;
vres *= 100;
break;
}
hdr.h_res = wxUINT32_SWAP_ON_BE(hres);
hdr.v_res = wxUINT32_SWAP_ON_BE(vres);
hdr.num_clrs = wxUINT32_SWAP_ON_BE(palette_size); // # colors in colormap hdr.num_clrs = wxUINT32_SWAP_ON_BE(palette_size); // # colors in colormap
hdr.num_signif_clrs = 0; // all colors are significant hdr.num_signif_clrs = 0; // all colors are significant
@@ -906,6 +937,7 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
} }
stream.Read(dbuf, 4 * 2); stream.Read(dbuf, 4 * 2);
int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] ); int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] );
if (ncolors == 0) if (ncolors == 0)
ncolors = 1 << bpp; ncolors = 1 << bpp;
@@ -944,6 +976,11 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
} }
// the resolution in the bitmap header is in meters, convert to centimeters
image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, wxIMAGE_RESOLUTION_CM);
image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, dbuf[2]/100);
image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, dbuf[3]/100);
return true; return true;
} }

View File

@@ -310,6 +310,17 @@ bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos
} }
} }
// set up resolution if available: it's part of optional JFIF APP0 chunk
if ( cinfo.saw_JFIF_marker )
{
image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, cinfo.X_density);
image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, cinfo.Y_density);
// we use the same values for this option as libjpeg so we don't need
// any conversion here
image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, cinfo.density_unit);
}
jpeg_finish_decompress( &cinfo ); jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo ); jpeg_destroy_decompress( &cinfo );
return true; return true;

View File

@@ -344,6 +344,43 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos
alpha -= 2*w; alpha -= 2*w;
} }
// set the image resolution if it's available
uint16 tiffRes;
if ( TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &tiffRes) )
{
wxImageResolution res;
switch ( tiffRes )
{
default:
wxLogWarning(_("Unknown TIFF resolution unit %d ignored"),
tiffRes);
// fall through
case RESUNIT_NONE:
res = wxIMAGE_RESOLUTION_NONE;
break;
case RESUNIT_INCH:
res = wxIMAGE_RESOLUTION_INCHES;
break;
case RESUNIT_CENTIMETER:
res = wxIMAGE_RESOLUTION_CM;
break;
}
if ( res != wxIMAGE_RESOLUTION_NONE )
{
float xres, yres;
if ( TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) )
image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, xres);
if ( TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) )
image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, yres);
}
}
_TIFFfree( raster ); _TIFFfree( raster );
TIFFClose( tif ); TIFFClose( tif );
@@ -386,22 +423,44 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
if ( image->HasOption(wxIMAGE_OPTION_RESOLUTIONX) && // save the image resolution if we have it
image->HasOption(wxIMAGE_OPTION_RESOLUTIONY) ) int xres, yres;
const wxImageResolution res = GetResolutionFromOptions(*image, &xres, &yres);
uint16 tiffRes;
switch ( res )
{ {
TIFFSetField(tif, TIFFTAG_XRESOLUTION, default:
(float)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX)); wxFAIL_MSG( _T("unknown image resolution units") );
TIFFSetField(tif, TIFFTAG_YRESOLUTION, // fall through
(float)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY));
case wxIMAGE_RESOLUTION_NONE:
tiffRes = RESUNIT_NONE;
break;
case wxIMAGE_RESOLUTION_INCHES:
tiffRes = RESUNIT_INCH;
break;
case wxIMAGE_RESOLUTION_CM:
tiffRes = RESUNIT_CENTIMETER;
break;
} }
if ( tiffRes != RESUNIT_NONE )
{
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, tiffRes);
TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)xres);
TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)yres);
}
int spp = image->GetOptionInt(wxIMAGE_OPTION_SAMPLESPERPIXEL); int spp = image->GetOptionInt(wxIMAGE_OPTION_SAMPLESPERPIXEL);
if ( !spp ) if ( !spp )
spp = 3; spp = 3;
int bpp = image->GetOptionInt(wxIMAGE_OPTION_BITSPERSAMPLE); int bpp = image->GetOptionInt(wxIMAGE_OPTION_BITSPERSAMPLE);
if ( !bpp ) if ( !bpp )
bpp=8; bpp = 8;
int compression = image->GetOptionInt(wxIMAGE_OPTION_COMPRESSION); int compression = image->GetOptionInt(wxIMAGE_OPTION_COMPRESSION);
if ( !compression ) if ( !compression )