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:
@@ -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:
|
||||
|
||||
|
@@ -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,17 +1109,19 @@ enum
|
||||
ID_QUIT = wxID_EXIT,
|
||||
ID_ABOUT = wxID_ABOUT,
|
||||
ID_NEW = 100,
|
||||
ID_SHOWRAW = 101
|
||||
ID_INFO,
|
||||
ID_SHOWRAW
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
|
||||
|
||||
BEGIN_EVENT_TABLE(MyFrame,wxFrame)
|
||||
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_NEW, MyFrame::OnNewFrame)
|
||||
EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
|
||||
#ifdef wxHAVE_RAW_BITMAP
|
||||
EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
|
||||
EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
|
||||
#endif
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
wxString MyFrame::LoadUserImage(wxImage& image)
|
||||
{
|
||||
wxString filename;
|
||||
|
||||
#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 wxEmptyString;
|
||||
}
|
||||
}
|
||||
#endif // wxUSE_FILEDLG
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
|
||||
{
|
||||
#if wxUSE_FILEDLG
|
||||
wxString filename = wxFileSelector(_T("Select image file"));
|
||||
if ( !filename )
|
||||
return;
|
||||
|
||||
wxImage image;
|
||||
if ( !image.LoadFile(filename) )
|
||||
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() )
|
||||
{
|
||||
wxLogError(_T("Couldn't load image from '%s'."), filename.c_str());
|
||||
// TODO: show more information about the file
|
||||
wxString info = wxString::Format("Image size: %dx%d",
|
||||
image.GetWidth(),
|
||||
image.GetHeight());
|
||||
|
||||
return;
|
||||
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);
|
||||
}
|
||||
|
||||
(new MyImageFrame(this, filename, wxBitmap(image)))->Show();
|
||||
#endif // wxUSE_FILEDLG
|
||||
}
|
||||
|
||||
#ifdef wxHAVE_RAW_BITMAP
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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,22 +423,44 @@ 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;
|
||||
|
||||
int bpp = image->GetOptionInt(wxIMAGE_OPTION_BITSPERSAMPLE);
|
||||
if ( !bpp )
|
||||
bpp=8;
|
||||
bpp = 8;
|
||||
|
||||
int compression = image->GetOptionInt(wxIMAGE_OPTION_COMPRESSION);
|
||||
if ( !compression )
|
||||
|
Reference in New Issue
Block a user