]> git.saurik.com Git - wxWidgets.git/commitdiff
added the possibility to rescale the image during loading, especially useful with...
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 17 Nov 2008 13:54:42 +0000 (13:54 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 17 Nov 2008 13:54:42 +0000 (13:54 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56821 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/image.h
interface/wx/image.h
src/common/image.cpp
src/common/imagjpeg.cpp

index b09aaf2ed1b518b9b071c3f62380aef21f68c10b..ffb1e3777b9025115efecc1a81c1bab59144a9e3 100644 (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
index 89a17138936fc5b08755de9a3622a78151d722d1..06bf3ac297396213bb517558fc128162c27cacca 100644 (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).
index 6857a0d3da03e20edfee19523857523c5fe8d570..07ae7ac0ac936710d6dbfa8ed9f40a8dafdfba04 100644 (file)
@@ -1978,12 +1978,10 @@ 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);
-    if (idx == wxNOT_FOUND)
+    if ( idx == wxNOT_FOUND )
     {
         M_IMGDATA->m_optionNames.Add(name);
         M_IMGDATA->m_optionValues.Add(value);
@@ -2004,10 +2002,11 @@ 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)
+    if ( idx == wxNOT_FOUND )
         return wxEmptyString;
     else
         return M_IMGDATA->m_optionValues[idx];
@@ -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;
 
index 8260ad683fa16bd38ea65b6a3885973ca96be9bc..f14027cb78d4bd0ed122b7e051eef07a2e646759 100644 (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 );