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 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:
|
||||||
|
|
||||||
|
@@ -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,17 +1109,19 @@ 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
|
||||||
|
|
||||||
#if wxUSE_CLIPBOARD
|
#if wxUSE_CLIPBOARD
|
||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) )
|
void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
|
||||||
{
|
{
|
||||||
#if wxUSE_FILEDLG
|
|
||||||
wxString filename = wxFileSelector(_T("Select image file"));
|
|
||||||
if ( !filename )
|
|
||||||
return;
|
|
||||||
|
|
||||||
wxImage image;
|
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
|
#ifdef wxHAVE_RAW_BITMAP
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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 )
|
||||||
|
Reference in New Issue
Block a user