added the possibility to rescale the image during loading, especially useful with JPEGs (#8390) (change to the sample accidentally committed as r56820)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56821 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-11-17 13:54:42 +00:00
parent 95706ac162
commit 36abe9d421
4 changed files with 68 additions and 12 deletions

View File

@@ -36,6 +36,9 @@
#define wxIMAGE_OPTION_RESOLUTIONUNIT wxString(_T("ResolutionUnit"))
#define wxIMAGE_OPTION_MAX_WIDTH wxString(_T("MaxWidth"))
#define wxIMAGE_OPTION_MAX_HEIGHT wxString(_T("MaxHeight"))
// constants used with wxIMAGE_OPTION_RESOLUTIONUNIT
//
// NB: don't change these values, they correspond to libjpeg constants

View File

@@ -763,6 +763,20 @@ public:
If the given option is not present, the function returns 0.
Use HasOption() is 0 is a possibly valid value for the option.
Options common to all formats:
@li wxIMAGE_OPTION_MAX_WIDTH and wxIMAGE_OPTION_MAX_HEIGHT: If either
of these options is specified, the loaded image will be scaled down
(preserving its aspect ratio) so that its width is less than the
max width given if it is not 0 @em and its height is less than the
max height given if it is not 0. This is typically used for loading
thumbnails and the advantage of using these options compared to
calling Rescale() after loading is that some handlers (only JPEG
one right now) support rescaling the image during loading which is
vastly more efficient than loading the entire huge image and
rescaling it later (if these options are not supported by the
handler, this is still what happens however). These options must be
set before calling LoadFile() to have any effect.
Options for wxPNGHandler:
@li wxIMAGE_OPTION_PNG_FORMAT: Format for saving a PNG file.
@li wxIMAGE_OPTION_PNG_BITDEPTH: Bit depth for every channel (R/G/B/A).

View File

@@ -1978,8 +1978,6 @@ void wxImage::SetPalette(const wxPalette& palette)
void wxImage::SetOption(const wxString& name, const wxString& value)
{
wxCHECK_RET( Ok(), wxT("invalid image") );
AllocExclusive();
int idx = M_IMGDATA->m_optionNames.Index(name, false);
@@ -2004,7 +2002,8 @@ void wxImage::SetOption(const wxString& name, int value)
wxString wxImage::GetOption(const wxString& name) const
{
wxCHECK_MSG( Ok(), wxEmptyString, wxT("invalid image") );
if ( !M_IMGDATA )
return wxEmptyString;
int idx = M_IMGDATA->m_optionNames.Index(name, false);
if ( idx == wxNOT_FOUND )
@@ -2020,9 +2019,8 @@ int wxImage::GetOptionInt(const wxString& name) const
bool wxImage::HasOption(const wxString& name) const
{
wxCHECK_MSG( Ok(), false, wxT("invalid image") );
return (M_IMGDATA->m_optionNames.Index(name, false) != wxNOT_FOUND);
return M_IMGDATA ? M_IMGDATA->m_optionNames.Index(name, false) != wxNOT_FOUND
: false;
}
// ----------------------------------------------------------------------------
@@ -2214,18 +2212,42 @@ int wxImage::GetImageCount( wxInputStream &stream, wxBitmapType type )
bool wxImage::DoLoad(wxImageHandler& handler, wxInputStream& stream, int index)
{
// save the options values which can be clobbered by the handler (e.g. many
// of them call Destroy() before trying to load the file)
const unsigned maxWidth = GetOptionInt(wxIMAGE_OPTION_MAX_WIDTH),
maxHeight = GetOptionInt(wxIMAGE_OPTION_MAX_HEIGHT);
if ( !handler.LoadFile(this, stream, true/*verbose*/, index) )
return false;
M_IMGDATA->m_type = handler.GetType();
// rescale the image to the specified size if needed
if ( maxWidth || maxHeight )
{
const unsigned widthOrig = GetWidth(),
heightOrig = GetHeight();
// this uses the same (trivial) algorithm as the JPEG handler
unsigned width = widthOrig,
height = heightOrig;
while ( (maxWidth && width > maxWidth) ||
(maxHeight && height > maxHeight) )
{
width /= 2;
height /= 2;
}
if ( width != widthOrig || height != heightOrig )
Rescale(width, height, wxIMAGE_QUALITY_HIGH);
}
return true;
}
bool wxImage::LoadFile( wxInputStream& stream, wxBitmapType type, int index )
{
UnRef();
m_refData = new wxImageRefData;
AllocExclusive();
wxImageHandler *handler;

View File

@@ -228,11 +228,17 @@ static inline void wx_cmyk_to_rgb(unsigned char* rgb, const unsigned char* cmyk)
bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) )
{
wxCHECK_MSG( image, false, "NULL image pointer" );
struct jpeg_decompress_struct cinfo;
wx_error_mgr jerr;
unsigned char *ptr;
// save this before calling Destroy()
const unsigned maxWidth = image->GetOptionInt(wxIMAGE_OPTION_MAX_WIDTH),
maxHeight = image->GetOptionInt(wxIMAGE_OPTION_MAX_HEIGHT);
image->Destroy();
cinfo.err = jpeg_std_error( &jerr );
jerr.error_exit = wx_error_exit;
@@ -268,9 +274,20 @@ bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos
bytesPerPixel = 3;
}
// scale the picture to fit in the specified max size if necessary
if ( maxWidth > 0 || maxHeight > 0 )
{
unsigned& scale = cinfo.scale_denom;
while ( (maxWidth && (cinfo.image_width / scale > maxWidth)) ||
(maxHeight && (cinfo.image_height / scale > maxHeight)) )
{
scale *= 2;
}
}
jpeg_start_decompress( &cinfo );
image->Create( cinfo.image_width, cinfo.image_height );
image->Create( cinfo.output_width, cinfo.output_height );
if (!image->Ok()) {
jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );