Re: JPEG Thumbnailer
On 8/20/08, Thiago Macieira <thiago <at> kde.org> wrote:
> Just do whatever you were doing, but use QFile::encodeName(filename) to
> convert from QString to the char* that fopen uses.
Ok here it is. Sorry it took me so long, i was a bit busy with studies
(going to start my thesis soon, hurray!).
I changed the encoding and replaced convertDepth with convertToFormat
because the former is deprecated.
As a reminder, here is test pictures:
http://digikam3rdparty.free.fr/TEST_IMAGES/JPEG
Its easier to compare if you change CacheThumbnail to false in
jpegthumbnail.desktop
Greetings
Andre
Index: kioslave/thumbnail/jpegcreator.h
===================================================================
--- kioslave/thumbnail/jpegcreator.h (revision 0)
+++ kioslave/thumbnail/jpegcreator.h (revision 0)
@@ -0,0 +1,32 @@
+/* This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _JPEGCREATOR_H_
+#define _JPEGCREATOR_H_
+
+#include <kio/thumbcreator.h>
+
+class JpegCreator : public ThumbCreator
+{
+public:
+ JpegCreator() {}
+ virtual bool create(const QString &path, int, int, QImage &img);
+ virtual Flags flags() const;
+};
+
+#endif
Index: kioslave/thumbnail/jpegthumbnail.desktop
===================================================================
--- kioslave/thumbnail/jpegthumbnail.desktop (revision 0)
+++ kioslave/thumbnail/jpegthumbnail.desktop (revision 0)
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Type=Service
+Name=Jpeg
+X-KDE-ServiceTypes=ThumbCreator
+MimeType=image/jpeg;
+X-KDE-Library=jpegthumbnail
+CacheThumbnail=true
Index: kioslave/thumbnail/CMakeLists.txt
===================================================================
--- kioslave/thumbnail/CMakeLists.txt (revision 841377)
+++ kioslave/thumbnail/CMakeLists.txt (working copy)
@@ -25,6 +25,16 @@
########### next target ###############
+set(jpegthumbnail_PART_SRCS jpegcreator.cpp)
+
+kde4_add_plugin(jpegthumbnail ${jpegthumbnail_PART_SRCS})
+
+target_link_libraries(jpegthumbnail ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} jpeg)
+
+install(TARGETS jpegthumbnail DESTINATION ${PLUGIN_INSTALL_DIR})
+
+########### next target ###############
+
set(svgthumbnail_PART_SRCS svgcreator.cpp)
kde4_add_plugin(svgthumbnail ${svgthumbnail_PART_SRCS})
@@ -103,6 +113,7 @@
thumbnail.protocol
svgthumbnail.desktop
imagethumbnail.desktop
+ jpegthumbnail.desktop
textthumbnail.desktop
htmlthumbnail.desktop
djvuthumbnail.desktop
Index: kioslave/thumbnail/jpegcreator.cpp
===================================================================
--- kioslave/thumbnail/jpegcreator.cpp (revision 0)
+++ kioslave/thumbnail/jpegcreator.cpp (revision 0)
@@ -0,0 +1,140 @@
+/* This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "jpegcreator.h"
+
+#include <assert.h>
+#include <cstdio>
+#include <csetjmp>
+#include <jpeglib.h>
+#include <QFile>
+#include <QImage>
+#include <kdemacros.h>
+
+extern "C"
+{
+ KDE_EXPORT ThumbCreator *new_creator()
+ {
+ return new JpegCreator;
+ }
+}
+
+struct jpeg_custom_error_mgr {
+ struct jpeg_error_mgr builtin;
+
+ jmp_buf setjmp_buffer;
+};
+
+void jpeg_custom_error_callback(j_common_ptr jpeg_decompress)
+{
+ jpeg_custom_error_mgr *custom_err = (jpeg_custom_error_mgr *)jpeg_decompress->err;
+
+ // jump to error recovery (fallback to old method)
+ longjmp(custom_err->setjmp_buffer, 1);
+}
+
+/**
+ * This is a faster thumbnail creation specifically for JPEG images, as it uses the libjpeg feature of
+ * calculating the inverse dct for a part of coefficients for lower resolutions.
+ * Interesting parameters are the quality settings of libjpeg
+ * jpeg_decompress.do_fancy_upsampling (TRUE, FALSE)
+ * jpeg_decompress.do_block_smoothing (TRUE, FALSE)
+ * jpeg_decompress.dct_method (JDCT_IFAST, JDCT_ISLOW, JDCT_IFLOAT).
+ *
+ * Important: We do not need to scaled to exact dimesions, as thumbnail.cpp will check dimensions and
+ * rescale anyway.
+ */
+bool JpegCreator::create(const QString &path, int width, int height, QImage &img)
+{
+ FILE *fd_in;
+ if ((fd_in = fopen(QFile::encodeName(path), "rb")) == NULL)
+ return false;
+ // create jpeglib data structures and calculate scale denominator
+ struct jpeg_decompress_struct jpeg_decompress;
+ struct jpeg_custom_error_mgr jpeg_error;
+ jpeg_decompress.err = jpeg_std_error(&jpeg_error.builtin);
+ jpeg_create_decompress(&jpeg_decompress);
+ jpeg_stdio_src(&jpeg_decompress, fd_in);
+ jpeg_read_header(&jpeg_decompress, TRUE);
+
+ double ratio_width = jpeg_decompress.image_width / (double)width;
+ double ratio_height = jpeg_decompress.image_height / (double)height;
+ int scale = 1;
+ if (ratio_width > 7 || ratio_height > 7)
+ scale = 8;
+ else if (ratio_width > 3.5 || ratio_height > 3.5)
+ scale = 4;
+ else if (ratio_width > 1.75 || ratio_height > 1.75)
+ scale = 2;
+
+ // set jpeglib decompression parameters
+ jpeg_decompress.scale_num = 1;
+ jpeg_decompress.scale_denom = scale;
+ jpeg_decompress.do_fancy_upsampling = FALSE;
+ jpeg_decompress.do_block_smoothing = FALSE;
+ jpeg_decompress.dct_method = JDCT_IFAST;
+ jpeg_decompress.err->error_exit = jpeg_custom_error_callback;
+ jpeg_decompress.out_color_space = JCS_RGB;
+
+ jpeg_calc_output_dimensions(&jpeg_decompress);
+
+ if (setjmp(jpeg_error.setjmp_buffer))
+ {
+ jpeg_abort_decompress(&jpeg_decompress);
+ fclose(fd_in);
+ // libjpeg version failed, fall back to direct loading of QImage
+ if (!img.load( path ))
+ return false;
+ if (img.depth() != 32)
+ img = img.convertToFormat(QImage::Format_RGB32);
+ return true;
+ }
+ jpeg_start_decompress(&jpeg_decompress);
+ img = QImage(jpeg_decompress.output_width, jpeg_decompress.output_height, QImage::Format_RGB32);
+ uchar *buffer = img.bits();
+ int bpl = img.bytesPerLine();
+ while (jpeg_decompress.output_scanline < jpeg_decompress.output_height)
+ {
+ // advance line-pointer to next line
+ uchar *line = buffer + jpeg_decompress.output_scanline * bpl;
+ jpeg_read_scanlines(&jpeg_decompress, &line, 1);
+ }
+ jpeg_finish_decompress(&jpeg_decompress);
+
+ // align correctly for QImage
+ // code copied from Gwenview and digiKam
+ for (uint i = 0; i < jpeg_decompress.output_height; ++i)
+ {
+ uchar *in = img.scanLine(i) + jpeg_decompress.output_width * 3;
+ QRgb *out = (QRgb*)img.scanLine(i);
+ for (uint j = jpeg_decompress.output_width; j--; )
+ {
+ in -= 3;
+ out[j] = qRgb(in[0], in[1], in[2]);
+ }
+ }
+
+ fclose(fd_in);
+ jpeg_destroy_decompress(&jpeg_decompress);
+ return true;
+}
+
+ThumbCreator::Flags JpegCreator::flags() const
+{
+ return None;
+}
Index: kioslave/thumbnail/imagethumbnail.desktop
===================================================================
--- kioslave/thumbnail/imagethumbnail.desktop (revision 841377)
+++ kioslave/thumbnail/imagethumbnail.desktop (working copy)
@@ -77,6 +77,6 @@
Name[zh_CN]=å¾å
Name[zh_TW]=å½±å
X-KDE-ServiceTypes=ThumbCreator
-MimeType=image/cgm;image/fax-g3;image/gif;image/jpeg2000;image/jpeg;image/png;image/tiff;image/bmp;image/x-dds;image/x-ico;image/x-jng;image/x-pcx;image/x-photo-cd;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-rgb;image/x-tga;image/x-wmf;image/x-xbitmap;image/x-xcf;image/x-xfig;image/x-xpixmap;
+MimeType=image/cgm;image/fax-g3;image/gif;image/jpeg2000;image/png;image/tiff;image/bmp;image/x-dds;image/x-ico;image/x-jng;image/x-pcx;image/x-photo-cd;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-rgb;image/x-tga;image/x-wmf;image/x-xbitmap;image/x-xcf;image/x-xfig;image/x-xpixmap;
X-KDE-Library=imagethumbnail
CacheThumbnail=true