[Digikam-devel] [Bug 132047] Faster display of images and/or prefetch wished for
Marcel Wiesweg
marcel.wiesweg at gmx.de
Wed Feb 14 17:10:43 GMT 2007
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
http://bugs.kde.org/show_bug.cgi?id=132047
------- Additional Comments From marcel.wiesweg gmx de 2007-02-14 18:10 -------
SVN commit 633639 by mwiesweg:
Use faster JPEG loading method (scale before decoding) for JPEG previews
- move code from thumbnail ioslave to libs/jpegutils
- use code in PreviewTask
CCBUG: 132047
M +2 -149 kioslave/digikamthumbnail.cpp
M +135 -0 libs/jpegutils/jpegutils.cpp
M +2 -0 libs/jpegutils/jpegutils.h
M +1 -0 libs/threadimageio/Makefile.am
M +9 -2 libs/threadimageio/previewtask.cpp
M +1 -0 showfoto/Makefile.am
--- trunk/extragear/graphics/digikam/kioslave/digikamthumbnail.cpp #633638:633639
@ -68,6 +68,7 @
#include "rawfiles.h"
#include "dcrawiface.h"
#include "dmetadata.h"
+#include "jpegutils.h"
#include "digikamthumbnail.h"
#include "digikam_export.h"
@ -76,7 +77,6 @
extern "C"
{
#include <unistd.h>
-#include <jpeglib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
@ -274,156 +274,9 @
return false;
}
-// -- JPEG Extraction ---------------------------------------------------------------------
-
-struct myjpeg_error_mgr : public jpeg_error_mgr
-{
- jmp_buf setjmp_buffer;
-};
-
-extern "C"
-{
- static void myjpeg_error_exit(j_common_ptr cinfo)
- {
- myjpeg_error_mgr* myerr = (myjpeg_error_mgr*) cinfo->err;
-
- char buffer[JMSG_LENGTH_MAX];
- (*cinfo->err->format_message)(cinfo, buffer);
- kdWarning() << buffer << endl;
- longjmp(myerr->setjmp_buffer, 1);
- }
-}
-
bool kio_digikamthumbnailProtocol::loadJPEG(QImage& image, const QString& path)
{
- QString format = QImageIO::imageFormat(path);
- if (format !="JPEG") return false;
-
- FILE* inputFile=fopen(QFile::encodeName(path), "rb");
- if(!inputFile)
- return false;
-
- struct jpeg_decompress_struct cinfo;
- struct myjpeg_error_mgr jerr;
-
- // JPEG error handling - thanks to Marcus Meissner
- cinfo.err = jpeg_std_error(&jerr);
- cinfo.err->error_exit = myjpeg_error_exit;
-
- if (setjmp(jerr.setjmp_buffer))
- {
- jpeg_destroy_decompress(&cinfo);
- fclose(inputFile);
- return false;
- }
-
- jpeg_create_decompress(&cinfo);
- jpeg_stdio_src(&cinfo, inputFile);
- jpeg_read_header(&cinfo, true);
-
- int imgSize = QMAX(cinfo.image_width, cinfo.image_height);
-
- int scale=1;
- while(cachedSize_*scale*2<=imgSize)
- {
- scale*=2;
- }
- if(scale>8) scale=8;
-
- cinfo.scale_num=1;
- cinfo.scale_denom=scale;
-
- switch (cinfo.jpeg_color_space)
- {
- case JCS_UNKNOWN:
- break;
- case JCS_GRAYSCALE:
- case JCS_RGB:
- case JCS_YCbCr:
- cinfo.out_color_space = JCS_RGB;
- break;
- case JCS_CMYK:
- case JCS_YCCK:
- cinfo.out_color_space = JCS_CMYK;
- break;
- }
-
- jpeg_start_decompress(&cinfo);
-
- QImage img;
-
- // We only take RGB with 1 or 3 components, or CMYK with 4 components
- if (!(
- (cinfo.out_color_space == JCS_RGB && (cinfo.output_components == 3 || cinfo.output_components == 1))
- || (cinfo.out_color_space == JCS_CMYK && cinfo.output_components == 4)
- ))
- {
- jpeg_destroy_decompress(&cinfo);
- fclose(inputFile);
- return false;
- }
-
- switch(cinfo.output_components)
- {
- case 3:
- case 4:
- img.create( cinfo.output_width, cinfo.output_height, 32 );
- break;
- case 1: // B&W image
- img.create( cinfo.output_width, cinfo.output_height, 8, 256 );
- for (int i = 0 ; i < 256 ; i++)
- img.setColor(i, qRgb(i, i, i));
- break;
- }
-
- uchar** lines = img.jumpTable();
- while (cinfo.output_scanline < cinfo.output_height)
- jpeg_read_scanlines(&cinfo, lines + cinfo.output_scanline, cinfo.output_height);
-
- jpeg_finish_decompress(&cinfo);
-
- // Expand 24->32 bpp
- if ( cinfo.output_components == 3 )
- {
- for (uint j=0; j<cinfo.output_height; j++)
- {
- uchar *in = img.scanLine(j) + cinfo.output_width*3;
- QRgb *out = (QRgb*)( img.scanLine(j) );
-
- for (uint i=cinfo.output_width; i--; )
- {
- in -= 3;
- out[i] = qRgb(in[0], in[1], in[2]);
- }
- }
- }
- else if ( cinfo.output_components == 4 )
- {
- // CMYK conversion
- for (uint j=0; j<cinfo.output_height; j++)
- {
- uchar *in = img.scanLine(j) + cinfo.output_width*4;
- QRgb *out = (QRgb*)( img.scanLine(j) );
-
- for (uint i=cinfo.output_width; i--; )
- {
- in -= 4;
- int k = in[3];
- out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255);
- }
- }
- }
-
- int newMax = QMAX(cinfo.output_width, cinfo.output_height);
- int newx = cachedSize_*cinfo.output_width / newMax;
- int newy = cachedSize_*cinfo.output_height / newMax;
-
- jpeg_destroy_decompress(&cinfo);
- fclose(inputFile);
-
- image = img.smoothScale(newx,newy);
-
- return true;
+ return Digikam::loadJPEGScaled(image, path, cachedSize_);
}
void kio_digikamthumbnailProtocol::exifRotate(const QString& filePath, QImage& thumb)
--- trunk/extragear/graphics/digikam/libs/jpegutils/jpegutils.cpp #633638:633639
@ -108,6 +108,141 @
#endif
}
+bool loadJPEGScaled(QImage& image, const QString& path, int maximumSize)
+{
+ QString format = QImageIO::imageFormat(path);
+ if (format !="JPEG") return false;
+
+ FILE* inputFile=fopen(QFile::encodeName(path), "rb");
+ if(!inputFile)
+ return false;
+
+ struct jpeg_decompress_struct cinfo;
+ struct jpegutils_jpeg_error_mgr jerr;
+
+ // JPEG error handling - thanks to Marcus Meissner
+ cinfo.err = jpeg_std_error(&jerr);
+ cinfo.err->error_exit = jpegutils_jpeg_error_exit;
+ cinfo.err->emit_message = jpegutils_jpeg_emit_message;
+ cinfo.err->output_message = jpegutils_jpeg_output_message;
+
+ if (setjmp(jerr.setjmp_buffer))
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(inputFile);
+ return false;
+ }
+
+ jpeg_create_decompress(&cinfo);
+ jpeg_stdio_src(&cinfo, inputFile);
+ jpeg_read_header(&cinfo, true);
+
+ int imgSize = QMAX(cinfo.image_width, cinfo.image_height);
+
+ // libjpeg supports 1/1, 1/2, 1/4, 1/8
+ int scale=1;
+ while(maximumSize*scale*2<=imgSize)
+ {
+ scale*=2;
+ }
+ if(scale>8) scale=8;
+
+ cinfo.scale_num=1;
+ cinfo.scale_denom=scale;
+
+ switch (cinfo.jpeg_color_space)
+ {
+ case JCS_UNKNOWN:
+ break;
+ case JCS_GRAYSCALE:
+ case JCS_RGB:
+ case JCS_YCbCr:
+ cinfo.out_color_space = JCS_RGB;
+ break;
+ case JCS_CMYK:
+ case JCS_YCCK:
+ cinfo.out_color_space = JCS_CMYK;
+ break;
+ }
+
+ jpeg_start_decompress(&cinfo);
+
+ QImage img;
+
+ // We only take RGB with 1 or 3 components, or CMYK with 4 components
+ if (!(
+ (cinfo.out_color_space == JCS_RGB && (cinfo.output_components == 3 || cinfo.output_components == 1))
+ || (cinfo.out_color_space == JCS_CMYK && cinfo.output_components == 4)
+ ))
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(inputFile);
+ return false;
+ }
+
+ switch(cinfo.output_components)
+ {
+ case 3:
+ case 4:
+ img.create( cinfo.output_width, cinfo.output_height, 32 );
+ break;
+ case 1: // B&W image
+ img.create( cinfo.output_width, cinfo.output_height, 8, 256 );
+ for (int i = 0 ; i < 256 ; i++)
+ img.setColor(i, qRgb(i, i, i));
+ break;
+ }
+
+ uchar** lines = img.jumpTable();
+ while (cinfo.output_scanline < cinfo.output_height)
+ jpeg_read_scanlines(&cinfo, lines + cinfo.output_scanline, cinfo.output_height);
+
+ jpeg_finish_decompress(&cinfo);
+
+ // Expand 24->32 bpp
+ if ( cinfo.output_components == 3 )
+ {
+ for (uint j=0; j<cinfo.output_height; j++)
+ {
+ uchar *in = img.scanLine(j) + cinfo.output_width*3;
+ QRgb *out = (QRgb*)( img.scanLine(j) );
+
+ for (uint i=cinfo.output_width; i--; )
+ {
+ in -= 3;
+ out[i] = qRgb(in[0], in[1], in[2]);
+ }
+ }
+ }
+ else if ( cinfo.output_components == 4 )
+ {
+ // CMYK conversion
+ for (uint j=0; j<cinfo.output_height; j++)
+ {
+ uchar *in = img.scanLine(j) + cinfo.output_width*4;
+ QRgb *out = (QRgb*)( img.scanLine(j) );
+
+ for (uint i=cinfo.output_width; i--; )
+ {
+ in -= 4;
+ int k = in[3];
+ out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255);
+ }
+ }
+ }
+
+ int newMax = QMAX(cinfo.output_width, cinfo.output_height);
+ int newx = maximumSize*cinfo.output_width / newMax;
+ int newy = maximumSize*cinfo.output_height / newMax;
+
+ jpeg_destroy_decompress(&cinfo);
+ fclose(inputFile);
+
+ image = img.smoothScale(newx,newy);
+
+ return true;
+}
+
bool exifRotate(const QString& file, const QString& documentName)
{
QFileInfo fi(file);
--- trunk/extragear/graphics/digikam/libs/jpegutils/jpegutils.h #633638:633639
@ -26,10 +26,12 @
// Qt includes.
#include <qstring.h>
+#include <qimage.h>
namespace Digikam
{
+bool loadJPEGScaled(QImage& image, const QString& path, int maximumSize);
bool exifRotate(const QString& file, const QString& documentName);
bool jpegConvert(const QString& src, const QString& dest, const QString& documentName,
const QString& format=QString("PNG"));
--- trunk/extragear/graphics/digikam/libs/threadimageio/Makefile.am #633638:633639
@ -18,5 +18,6 @
-I$(top_srcdir)/digikam/libs/dimg/loaders \
-I$(top_srcdir)/digikam/libs/dmetadata \
-I$(top_srcdir)/digikam/libs/dcraw \
+ -I$(top_srcdir)/digikam/libs/jpegutils \
-I$(top_srcdir)/digikam/digikam \
$(all_includes)
--- trunk/extragear/graphics/digikam/libs/threadimageio/previewtask.cpp #633638:633639
@ -31,6 +31,7 @
#include "ddebug.h"
#include "dmetadata.h"
#include "dcrawiface.h"
+#include "jpegutils.h"
#include "previewloadthread.h"
#include "previewtask.h"
@ -137,8 +138,14 @
{
// Try to extract Exif/Iptc preview.
if ( !loadImagePreview(qimage, m_loadingDescription.filePath) )
- // Try to load with Qt/KDE.
- qimage.load(m_loadingDescription.filePath);
+ {
+ // Try to load a JPEG with the fast scale-before-decoding method
+ if (!loadJPEGScaled(qimage, m_loadingDescription.filePath, size))
+ {
+ // Try to load with Qt/KDE.
+ qimage.load(m_loadingDescription.filePath);
+ }
+ }
}
if (qimage.isNull())
--- trunk/extragear/graphics/digikam/showfoto/Makefile.am #633638:633639
@ -33,6 +33,7 @
$(top_builddir)/digikam/utilities/splashscreen/libsplashscreen.la \
$(top_builddir)/digikam/utilities/slideshow/libslideshow.la \
$(top_builddir)/digikam/libs/threadimageio/libthreadimageio.la \
+ $(top_builddir)/digikam/libs/jpegutils/libjpegutils.la \
$(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIB_KUTILS) \
$(LIB_KFILE) $(LIB_KPARTS) $(LIBJPEG) $(EXIV2_LIBS)
More information about the Digikam-devel
mailing list