add more spacing
[personal-kdebase.git] / runtime / kioslave / thumbnail / jpegcreator.cpp
blob6deb25da5b573cb880f05bb61dfb722c87cb6077
1 /* This file is part of the KDE libraries
2 Copyright (C) 2008 Andre Gemünd <scroogie@gmail.com>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "jpegcreator.h"
22 #include <cstdio>
23 #include <csetjmp>
24 #include <QFile>
25 #include <QImage>
26 #include <kdemacros.h>
28 extern "C"
30 #include <jpeglib.h>
32 KDE_EXPORT ThumbCreator *new_creator()
34 return new JpegCreator;
38 struct jpeg_custom_error_mgr
40 struct jpeg_error_mgr builtin;
41 jmp_buf setjmp_buffer;
44 void jpeg_custom_error_callback(j_common_ptr jpegDecompress)
46 jpeg_custom_error_mgr *custom_err = (jpeg_custom_error_mgr *)jpegDecompress->err;
48 // jump to error recovery (fallback to old method)
49 longjmp(custom_err->setjmp_buffer, 1);
52 JpegCreator::JpegCreator()
56 /**
57 * This is a faster thumbnail creation specifically for JPEG images, as it uses the libjpeg feature of
58 * calculating the inverse dct for a part of coefficients for lower resolutions.
59 * Interesting parameters are the quality settings of libjpeg
60 * jpegDecompress.do_fancy_upsampling (TRUE, FALSE)
61 * jpegDecompress.do_block_smoothing (TRUE, FALSE)
62 * jpegDecompress.dct_method (JDCT_IFAST, JDCT_ISLOW, JDCT_IFLOAT)
63 * and the resampling parameter of QImage.
65 * Important: We do not need to scaled to exact dimesions, as thumbnail.cpp will check dimensions and
66 * rescale anyway.
68 bool JpegCreator::create(const QString &path, int width, int height, QImage &img)
70 const QByteArray name = QFile::encodeName(path);
71 FILE *jpegFile = fopen(name.constData(), "rb");
72 if (jpegFile == 0) {
73 return false;
76 // create jpeglib data structures and calculate scale denominator
77 struct jpeg_decompress_struct jpegDecompress;
78 struct jpeg_custom_error_mgr jpegError;
79 jpegDecompress.err = jpeg_std_error(&jpegError.builtin);
80 jpeg_create_decompress(&jpegDecompress);
81 jpeg_stdio_src(&jpegDecompress, jpegFile);
82 jpeg_read_header(&jpegDecompress, TRUE);
84 const double ratioWidth = jpegDecompress.image_width / (double)width;
85 const double ratioHeight = jpegDecompress.image_height / (double)height;
86 int scale = 1;
87 if (ratioWidth > 7 || ratioHeight > 7) {
88 scale = 8;
89 } else if (ratioWidth > 3.5 || ratioHeight > 3.5) {
90 scale = 4;
91 } else if (ratioWidth > 1.75 || ratioHeight > 1.75) {
92 scale = 2;
95 // set jpeglib decompression parameters
96 jpegDecompress.scale_num = 1;
97 jpegDecompress.scale_denom = scale;
98 jpegDecompress.do_fancy_upsampling = FALSE;
99 jpegDecompress.do_block_smoothing = FALSE;
100 jpegDecompress.dct_method = JDCT_IFAST;
101 jpegDecompress.err->error_exit = jpeg_custom_error_callback;
102 jpegDecompress.out_color_space = JCS_RGB;
104 jpeg_calc_output_dimensions(&jpegDecompress);
106 if (setjmp(jpegError.setjmp_buffer)) {
107 jpeg_abort_decompress(&jpegDecompress);
108 fclose(jpegFile);
109 // libjpeg version failed, fall back to direct loading of QImage
110 if (!img.load(path)) {
111 return false;
113 if (img.depth() != 32) {
114 img = img.convertToFormat(QImage::Format_RGB32);
116 return true;
119 jpeg_start_decompress(&jpegDecompress);
120 img = QImage(jpegDecompress.output_width, jpegDecompress.output_height, QImage::Format_RGB32);
121 uchar *buffer = img.bits();
122 const int bpl = img.bytesPerLine();
123 while (jpegDecompress.output_scanline < jpegDecompress.output_height) {
124 // advance line-pointer to next line
125 uchar *line = buffer + jpegDecompress.output_scanline * bpl;
126 jpeg_read_scanlines(&jpegDecompress, &line, 1);
128 jpeg_finish_decompress(&jpegDecompress);
130 // align correctly for QImage
131 // code copied from Gwenview and digiKam
132 for (int i = 0; i < jpegDecompress.output_height; ++i) {
133 uchar *in = img.scanLine(i) + jpegDecompress.output_width * 3;
134 QRgb *out = (QRgb*)img.scanLine(i);
135 for (int j = jpegDecompress.output_width - 1; j >= 0; --j) {
136 in -= 3;
137 out[j] = qRgb(in[0], in[1], in[2]);
141 fclose(jpegFile);
142 jpeg_destroy_decompress(&jpegDecompress);
143 return true;
146 ThumbCreator::Flags JpegCreator::flags() const
148 return None;