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 wxTaskBarIcon::Destroy()
- Added XRC handler for wxSearchCtrl (Sander Berents)
- Read image resolution from TIFF, JPEG and BMP images (Maycon Aparecido Gasoto)
wxGTK:

View File

@@ -118,6 +118,7 @@ public:
void OnAbout( wxCommandEvent &event );
void OnNewFrame( wxCommandEvent &event );
void OnImageInfo( wxCommandEvent &event );
#ifdef wxHAVE_RAW_BITMAP
void OnTestRawBitmap( wxCommandEvent &event );
#endif // wxHAVE_RAW_BITMAP
@@ -131,6 +132,13 @@ public:
MyCanvas *m_canvas;
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_EVENT_TABLE()
};
@@ -1101,7 +1109,8 @@ enum
ID_QUIT = wxID_EXIT,
ID_ABOUT = wxID_ABOUT,
ID_NEW = 100,
ID_SHOWRAW = 101
ID_INFO,
ID_SHOWRAW
};
IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
@@ -1110,6 +1119,7 @@ BEGIN_EVENT_TABLE(MyFrame,wxFrame)
EVT_MENU (ID_ABOUT, MyFrame::OnAbout)
EVT_MENU (ID_QUIT, MyFrame::OnQuit)
EVT_MENU (ID_NEW, MyFrame::OnNewFrame)
EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
#ifdef wxHAVE_RAW_BITMAP
EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
#endif
@@ -1128,8 +1138,9 @@ MyFrame::MyFrame()
wxMenu *menuImage = new wxMenu;
menuImage->Append( ID_NEW, _T("&Show any image...\tCtrl-O"));
menuImage->Append( ID_INFO, _T("Show image &information...\tCtrl-I"));
#ifdef wxHAVE_RAW_BITMAP
menuImage->AppendSeparator();
menuImage->Append( ID_SHOWRAW, _T("Test &raw bitmap...\tCtrl-R"));
#endif
menuImage->AppendSeparator();
@@ -1171,23 +1182,71 @@ void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
_T("About wxImage Demo"), wxICON_INFORMATION | wxOK );
}
void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
wxString MyFrame::LoadUserImage(wxImage& image)
{
#if wxUSE_FILEDLG
wxString filename = wxFileSelector(_T("Select image file"));
if ( !filename )
return;
wxString filename;
wxImage image;
#if wxUSE_FILEDLG
filename = wxFileSelector(_T("Select image file"));
if ( !filename.empty() )
{
if ( !image.LoadFile(filename) )
{
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();
#endif // wxUSE_FILEDLG
}
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;
}
}
wxLogMessage("%s", info);
}
}
#ifdef wxHAVE_RAW_BITMAP

View File

@@ -27,6 +27,7 @@
#include "wx/bitmap.h"
#include "wx/palette.h"
#include "wx/intl.h"
#include "wx/math.h"
#endif
#include "wx/filefn.h"
@@ -154,7 +155,7 @@ bool wxBMPHandler::SaveDib(wxImage *image,
wxUint16 bpp; // bits per pixel
wxUint32 compression; // compression method
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_signif_clrs;// number of significant colors
} hdr;
@@ -181,7 +182,37 @@ bool wxBMPHandler::SaveDib(wxImage *image,
hdr.bpp = wxUINT16_SWAP_ON_BE(bpp);
hdr.compression = 0; // RGB uncompressed
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_signif_clrs = 0; // all colors are significant
@@ -906,6 +937,7 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
}
stream.Read(dbuf, 4 * 2);
int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] );
if (ncolors == 0)
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;
}

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_destroy_decompress( &cinfo );
return true;

View File

@@ -344,6 +344,43 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos
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 );
TIFFClose( tif );
@@ -386,15 +423,37 @@ bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbo
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
if ( image->HasOption(wxIMAGE_OPTION_RESOLUTIONX) &&
image->HasOption(wxIMAGE_OPTION_RESOLUTIONY) )
// save the image resolution if we have it
int xres, yres;
const wxImageResolution res = GetResolutionFromOptions(*image, &xres, &yres);
uint16 tiffRes;
switch ( res )
{
TIFFSetField(tif, TIFFTAG_XRESOLUTION,
(float)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX));
TIFFSetField(tif, TIFFTAG_YRESOLUTION,
(float)image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY));
default:
wxFAIL_MSG( _T("unknown image resolution units") );
// fall through
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);
if ( !spp )
spp = 3;