Andre Gemünd | 12 Aug 16:11

JPEG Thumbnailer

Hi List,
I'm a fresh subscriber so forgive me if I don't follow the right rules 
for posting. I registered because Peter Penz was so nice as to introduce 
me to the approach of eventual contribution.
I found that the JPEG previews in Dolphin were quite slow so I had a 
look at the corresponding code. The Thumbnail KIO Slave loads the whole 
JPEG and scales it afterwards. So I tried out to load a scaled down 
version with libjpeg and here is the code attached as an additional 
thumbnail implementation for the KIOSlave. It's hard to measure the 
actual difference, but I think it's a significant speedup. I tried it 
out with a test program that uses the QImage way like the 
ImageThumbnailer and the former libjpeg method. If theres interest i can 
post it as well.
Of course it's a tradeoff between quality and speed, so it might need 
some discussion. I tried it out on a local build and attach a patch 
against 4.1.0.
To try it out Caulier Gilles has some nice test images of different 
sizes on http://digikam3rdparty.free.fr/TEST_IMAGES/JPEG/
The method is well known and while browsing the websvn I found out that 
it's also used in Digikam and Gwenview for JPEG thumbnails. I've never 
contributed to KDE before, so I'm not familiar with logging or error 
recovery methods used, so I'd like to get some comments. I hope I can 
hop on the KDE train with that first patch and am looking forward to 
your answers!

Greetings
André
Index: kioslave/thumbnail/jpegcreator.h
(Continue reading)

Carsten Pfeiffer | 14 Aug 21:12

Re: JPEG Thumbnailer

Hiya,

 > The Thumbnail KIO Slave loads the whole JPEG and
 > scales it afterwards. So I tried out to load a scaled down
 > version with libjpeg and here is the code attached as an
 > additional thumbnail implementation for the KIOSlave.

that is certainly a great idea! IIRC there was also some code to use  
the jpeg-embedded thumbnail, if available and if large enough for the  
requested dimensions.

 > +    FILE *fd_in;
 > +    if ((fd_in = fopen(path.toLatin1().data(), "rb")) ==

Can you use the QFile API instead of fopen()? If not, then please use  
QFile::encodeName() instead of latin1() to preserve the filename  
encoding.

Cheers,
Carsten

Andre Gemünd | 14 Aug 23:02

Re: JPEG Thumbnailer

Carsten Pfeiffer schrieb:
> Hiya,
Hello Carsten,
> that is certainly a great idea! IIRC there was also some code to use 
> the jpeg-embedded thumbnail, if available and if large enough for the 
> requested dimensions.
do you mean in the thumbnail slave or Gwenview / digikam? Gwenview afaik 
uses exiv2 to check for the embedded thumbnail. The slave doesn't 
directly do that. It does first check KFileMetaInfo for a stored 
thumbnail, which should in theory come from strigi, but I don't know if 
the strigi analyzer stores the exif thumbnail?

> > +    FILE *fd_in;
> > +    if ((fd_in = fopen(path.toLatin1().data(), "rb")) ==
>
> Can you use the QFile API instead of fopen()? If not, then please use 
> QFile::encodeName() instead of latin1() to preserve the filename 
> encoding.
In theory you can. I'd have to write a custom source manager for that 
then, because we can't use the stdio one of jpeglib in that case. I 
think it would add a lot of code though, is it really needed?
I will change the filename encoding.

Greetings and thanks
André

Michael Pyne | 16 Aug 21:13
X-Face
Favicon

Re: JPEG Thumbnailer

On Thursday 14 August 2008, Andre Gemünd wrote:

> Carsten Pfeiffer schrieb:

> > > + FILE *fd_in;

> > > + if ((fd_in = fopen(path.toLatin1().data(), "rb")) ==

> >

> > Can you use the QFile API instead of fopen()? If not, then please use

> > QFile::encodeName() instead of latin1() to preserve the filename

> > encoding.

>

> In theory you can. I'd have to write a custom source manager for that

> then, because we can't use the stdio one of jpeglib in that case. I

> think it would add a lot of code though, is it really needed?

Actually it's easier than that:

On an opened QFile you can use QFile::handle() to return the file descriptor (i.e. what is passed to write(2)). Using the file descriptior you can use the C stdio fdopen() function to return a FILE* tied to that file descriptor.

This way you can still use stdio functions on a file managed by QFile.

All that this would really buy you is guaranteeing that the file gets closed, which may not be worth the overhead however if you're simply going to be passing the FILE* to libjpeg.

Regards,

- Michael Pyne

Andre Gemünd | 18 Aug 19:07

Re: JPEG Thumbnailer

Michael Pyne schrieb:
>
> Actually it's easier than that:
>
> On an opened QFile you can use QFile::handle() to return the file 
> descriptor (i.e. what is passed to write(2)). Using the file 
> descriptior you can use the C stdio fdopen() function to return a 
> FILE* tied to that file descriptor.
>
> This way you can still use stdio functions on a file managed by QFile.
>
> All that this would really buy you is guaranteeing that the file gets 
> closed, which may not be worth the overhead however if you're simply 
> going to be passing the FILE* to libjpeg.
>
> Regards,
>
Hi Michael,
thanks a lot for you explanation. As I said, I'm not very experienced 
with Qt/KDE programming yet, so your input is very appreciated.
How much overhead are we talking about? We are opening all jpeg files of 
a directory which can be a lot at times, and apply a not-so-costly 
operation, so we should take this into consideration. And you are right, 
I just pass the FILE* to libjpeg and close it after 
jpeg_finish_decompress(), so it doesn't seem very sensible to open it 
twice (QFile and fdopen).

Greetings
André

Ingo Klöcker | 18 Aug 21:12

Re: JPEG Thumbnailer

On Monday 18 August 2008, Andre Gemünd wrote:
> Michael Pyne schrieb:
> > Actually it's easier than that:
> >
> > On an opened QFile you can use QFile::handle() to return the file
> > descriptor (i.e. what is passed to write(2)). Using the file
> > descriptior you can use the C stdio fdopen() function to return a
> > FILE* tied to that file descriptor.
> >
> > This way you can still use stdio functions on a file managed by
> > QFile.
> >
> > All that this would really buy you is guaranteeing that the file
> > gets closed, which may not be worth the overhead however if you're
> > simply going to be passing the FILE* to libjpeg.
> >
> > Regards,
>
> Hi Michael,
> thanks a lot for you explanation. As I said, I'm not very experienced
> with Qt/KDE programming yet, so your input is very appreciated.
> How much overhead are we talking about? We are opening all jpeg files
> of a directory which can be a lot at times, and apply a not-so-costly
> operation, so we should take this into consideration. And you are
> right, I just pass the FILE* to libjpeg and close it after
> jpeg_finish_decompress(), so it doesn't seem very sensible to open it
> twice (QFile and fdopen).

The point of using QFile is that you do not have to take care of the 
file resource yourself. QFile will take care of closing the file. Using 
a class for handling a resource (e.g. QFile for a file, smart pointers 
for objects allocated on the heap, etc.) is always preferable to 
dealing with the resource yourself, because it's so darn easy to leak a 
resource if you do it yourself.

Regards,
Ingo
Thiago Macieira | 19 Aug 08:44

Re: JPEG Thumbnailer

Ingo Klöcker wrote:
>The point of using QFile is that you do not have to take care of the
>file resource yourself. QFile will take care of closing the file. Using
>a class for handling a resource (e.g. QFile for a file, smart pointers
>for objects allocated on the heap, etc.) is always preferable to
>dealing with the resource yourself, because it's so darn easy to leak a
>resource if you do it yourself.

That means you shouldn't use fdopen on the handle returned by QFile.

The handle that QFile returns is closed correctly by QFIle, but if you do 
an fdopen, then you have to remember to fclose.

So, if you need the FILE* anyways, avoid the complexity and open it 
directly.

--

-- 
  Thiago Macieira  -  thiago (AT) macieira.info - thiago (AT) kde.org
    PGP/GPG: 0x6EF45358; fingerprint:
    E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358
Ingo Klöcker | 19 Aug 22:41

Re: JPEG Thumbnailer

On Tuesday 19 August 2008, Thiago Macieira wrote:
> Ingo Klöcker wrote:
> >The point of using QFile is that you do not have to take care of the
> >file resource yourself. QFile will take care of closing the file.
> > Using a class for handling a resource (e.g. QFile for a file, smart
> > pointers for objects allocated on the heap, etc.) is always
> > preferable to dealing with the resource yourself, because it's so
> > darn easy to leak a resource if you do it yourself.
>
> That means you shouldn't use fdopen on the handle returned by QFile.
>
> The handle that QFile returns is closed correctly by QFIle, but if
> you do an fdopen, then you have to remember to fclose.
>
> So, if you need the FILE* anyways, avoid the complexity and open it
> directly.

I know you will kill me for making the following suggestion. :-)

If QFile is too much overhead then I'd use a boost::shared_ptr with 
custom deleter [1], i.e.

    boost::shared_ptr<FILE> fd_in( fopen(path.toLatin1().data(), "rb"), fclose );
    if ( fd_in.get() == NULL )
       return false;

If you want to close the file explicitly then you call fd_in.reset(). 
Otherwise you don't have to do anything.

Reasons for doing the above:
a) We are coding in C++, right? So let's use the power C++ provides. It 
makes no sense to write error prone code, if there's a way to avoid it.
b) Using boost::shared_ptr is just a compile time dependency.
c) Several KDE packages (kdepimlibs, kdepim) do already have a 
dependency on boost.

Regards,

Ingo

[1] http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/sp_techniques.html#handle
Richard Moore | 19 Aug 22:47

Re: JPEG Thumbnailer

On 8/19/08, Ingo Klöcker <kloecker <at> kde.org> wrote:
>
> I know you will kill me for making the following suggestion. :-)

Various phrases around using a hammer to crack a nut spring to mind.
In the context of the question this strikes me as a rather foolish
idea.

Rich.

Ingo Klöcker | 19 Aug 23:41

Re: JPEG Thumbnailer

On Tuesday 19 August 2008, Richard Moore wrote:
> On 8/19/08, Ingo Klöcker <kloecker <at> kde.org> wrote:
> > I know you will kill me for making the following suggestion. :-)
>
> Various phrases around using a hammer to crack a nut spring to mind.
> In the context of the question this strikes me as a rather foolish
> idea.

Indeed. Writing an error prone implementation where you have to make 
sure you do not forget to call fclose() in any of the various code 
paths (the code is question has to call fclose() in two different code 
paths) is comparable to using a hammer to crack a nut. OTOH, using a 
smart pointer with custom deleter is like using a high quality nut 
cracker to crack a nut, because a smart pointer with custom deleter is 
exactly the right tool for dealing with a FILE* resource.

Please allow me to quote from C++ Coding Standards [1] by Herb Sutter 
and Andrei Alexandrescu (a book any serious C++ developer should read 
and take by heart IMHO):

<quote>
Item 13: Ensure resources are owned by objects. Use explicit RAII and 
smart pointers.

Summary
Don't saw by hand when you have power tools: C++'s "resource acquisition 
is initialization" (RAII) idiom is _the_ power tool for correct 
resource handling. [...]

Discussion
C++'s language-enforced constructor/destructor symmetry mirrors the 
symmetry inherent in resource acquire/release function pairs such as 
fopen/fclose, [...].
</quote>

Regards,
Ingo

[1] 
http://www.bookzilla.org/shop/action/productDetails/3266781/herb_sutter_andrei_alexandrescu_c_coding_standards_0321113586.html
Thiago Macieira | 20 Aug 00:05

Re: JPEG Thumbnailer

Ingo Klöcker wrote:
>I know you will kill me for making the following suggestion. :-)

Yes, I will. Using boost is an major overkill for this. Much more than 
QFile, because QFile is in a library already loaded, while boost will 
require additional code being loaded.

>If QFile is too much overhead then I'd use a boost::shared_ptr with
>custom deleter [1], i.e.
>
>    boost::shared_ptr<FILE> fd_in( fopen(path.toLatin1().data(), "rb"),
> fclose ); if ( fd_in.get() == NULL )
>       return false;
>
>If you want to close the file explicitly then you call fd_in.reset().
>Otherwise you don't have to do anything.
>
>Reasons for doing the above:
>a) We are coding in C++, right? So let's use the power C++ provides. It
>makes no sense to write error prone code, if there's a way to avoid it.

Uh... std::fstream?

>b) Using boost::shared_ptr is just a compile time dependency.

Right, but it'll bring in all of boost's atomic reference counting code 
along. Also remember that some compilers are brain-dead and will 
instantiate the entire class, as opposed to just the parts of it that you 
actually use.

Not to mention that a custom deleter would have to be written.

What you really want here is std::auto_ptr with a custom deleter. There is 
no shared pointer in this circumstance, so no need to add the overhead 
associated with that,

>c) Several KDE packages (kdepimlibs, kdepim) do already have a
>dependency on boost.

Sometimes unwarranted. There's a lot of boost that has equivalents in Qt, 
including shared_ptr/intrusive_ptr (Qt 4.5's QSharedPointer for both). 
But there are nice things in it too.

Also, there's a very, very simple way of making sure there are 
no "returns" where you forgot to close the file: create a different 
function.

    FILE *f = fopen(...);
    bool result = doTheWork(f);
    fclose(f);
    return result;

Remember: the only reason QFile was mentioned in this thread wasn't 
because of "forgetting to close". It was to encode the name properly from 
QString to the 8-bit format.

--

-- 
  Thiago Macieira  -  thiago (AT) macieira.info - thiago (AT) kde.org
    PGP/GPG: 0x6EF45358; fingerprint:
    E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

Re: JPEG Thumbnailer



On Wed, Aug 20, 2008 at 12:05 AM, Thiago Macieira <thiago <at> kde.org> wrote:
Remember: the only reason QFile was mentioned in this thread wasn't
because of "forgetting to close". It was to encode the name properly from
QString to the 8-bit format.

Hello everyone,
it's a delight to read this discussion, but about the original issue, what is the conclusion I should draw now. Is the file buffer
also closed when the QFile leaves scope, although I fdopened it's handle? Or should I use auto_ptr with a custom delete, or should I even use a class that closes the file in its destructor? :)

Greetings
André
Thiago Macieira | 20 Aug 19:07

Re: JPEG Thumbnailer

On Wednesday 20 August 2008 18:49:11 Andre Gemünd wrote:
> Hello everyone,
> it's a delight to read this discussion, but about the original issue, what
> is the conclusion I should draw now. Is the file buffer
> also closed when the QFile leaves scope, although I fdopened it's handle?
> Or should I use auto_ptr with a custom delete, or should I even use a class
> that closes the file in its destructor? :)

Just do whatever you were doing, but use QFile::encodeName(filename) to 
convert from QString to the char* that fopen uses.

--

-- 
  Thiago Macieira  -  thiago (AT) macieira.info - thiago (AT) kde.org
    PGP/GPG: 0x6EF45358; fingerprint:
    E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

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
Riccardo Iaconelli | 10 Sep 14:01
Gravatar

Re: JPEG Thumbnailer

On Tuesday 02 September 2008 21:13:37 Andre Gemünd wrote:
> Ok here it is.

What's the status of this patch? Has it been committed?

-Riccardo
--

-- 
GPG key:
3D0F6376
When encrypting, please encrypt also for this subkey:
9EBD7FE1
-----
Pace Peace Paix Paz Frieden Pax Pokój Friður Fred Béke 和平
Hasiti Lapé Hetep Malu Mир Wolakota Santiphap Irini Peoch שלום
Shanti Vrede Baris Rój Mír Taika Rongo Sulh Mir Py'guapy 평화

Ingo Klöcker | 21 Aug 23:51

Re: JPEG Thumbnailer

On Wednesday 20 August 2008, Thiago Macieira wrote:
> Ingo Klöcker wrote:
> >I know you will kill me for making the following suggestion. :-)
>
> Yes, I will. Using boost is an major overkill for this. Much more
> than QFile, because QFile is in a library already loaded, while boost
> will require additional code being loaded.
>
> >If QFile is too much overhead then I'd use a boost::shared_ptr with
> >custom deleter [1], i.e.
> >
> >    boost::shared_ptr<FILE> fd_in( fopen(path.toLatin1().data(),
> > "rb"), fclose ); if ( fd_in.get() == NULL )
> >       return false;
> >
> >If you want to close the file explicitly then you call
> > fd_in.reset(). Otherwise you don't have to do anything.
> >
> >Reasons for doing the above:
> >a) We are coding in C++, right? So let's use the power C++ provides.
> > It makes no sense to write error prone code, if there's a way to
> > avoid it.
>
> Uh... std::fstream?

std::fstream does not seem to give access to the FILE handle, so it 
cannot be used in this particular situation.

> >b) Using boost::shared_ptr is just a compile time dependency.
>
> Right, but it'll bring in all of boost's atomic reference counting
> code along. Also remember that some compilers are brain-dead and will
> instantiate the entire class, as opposed to just the parts of it that
> you actually use.

Which compilers? Do we care for those compilers?

> Not to mention that a custom deleter would have to be written.

In this particular case that's not true since
  boost::shared_ptr<FILE> fd_in( fopen( "foo.jpg", "rb" ), fclose );
works perfectly alright.

> What you really want here is std::auto_ptr with a custom deleter.
> There is no shared pointer in this circumstance, so no need to add
> the overhead associated with that,

True.

> >c) Several KDE packages (kdepimlibs, kdepim) do already have a
> >dependency on boost.
>
> Sometimes unwarranted. There's a lot of boost that has equivalents in
> Qt, including shared_ptr/intrusive_ptr (Qt 4.5's QSharedPointer for
> both). But there are nice things in it too.

The same can be said about Qt (in place of boost) and STL (in place of 
Qt). Yes, I know there were reasons for writing your own container 
classes when Qt 1 was written. But even though there might still be 
some broken STL implementations on certain platforms, I'd rather see 
you adopting the STL containers. There's a plethora of useful C++ 
libraries out there that all use STL containers and it really sucks 
that when using Qt one has to use a second set of container classes.

Regards,
Ingo
Ingo Klöcker | 22 Aug 00:03

Re: JPEG Thumbnailer

On Thursday 21 August 2008, Ingo Klöcker wrote:
> On Wednesday 20 August 2008, Thiago Macieira wrote:
> > Ingo Klöcker wrote:
> > >I know you will kill me for making the following suggestion. :-)
> >
> > Yes, I will. Using boost is an major overkill for this. Much more
> > than QFile, because QFile is in a library already loaded, while
> > boost will require additional code being loaded.
> >
> > >If QFile is too much overhead then I'd use a boost::shared_ptr
> > > with custom deleter [1], i.e.
> > >
> > >    boost::shared_ptr<FILE> fd_in( fopen(path.toLatin1().data(),
> > > "rb"), fclose ); if ( fd_in.get() == NULL )
> > >       return false;
> > >
> > >If you want to close the file explicitly then you call
> > > fd_in.reset(). Otherwise you don't have to do anything.
> > >
> > >Reasons for doing the above:
> > >a) We are coding in C++, right? So let's use the power C++
> > > provides. It makes no sense to write error prone code, if there's
> > > a way to avoid it.
> >
> > Uh... std::fstream?
>
> std::fstream does not seem to give access to the FILE handle, so it
> cannot be used in this particular situation.
>
> > >b) Using boost::shared_ptr is just a compile time dependency.
> >
> > Right, but it'll bring in all of boost's atomic reference counting
> > code along. Also remember that some compilers are brain-dead and
> > will instantiate the entire class, as opposed to just the parts of
> > it that you actually use.
>
> Which compilers? Do we care for those compilers?
>
> > Not to mention that a custom deleter would have to be written.
>
> In this particular case that's not true since
>   boost::shared_ptr<FILE> fd_in( fopen( "foo.jpg", "rb" ), fclose );
> works perfectly alright.
>
> > What you really want here is std::auto_ptr with a custom deleter.
> > There is no shared pointer in this circumstance, so no need to add
> > the overhead associated with that,
>
> True.

Actually, this is not true because unfortunately std::auto_ptr does not 
come with support for a custom deleter. I would have suggested 
boost::scoped_ptr instead of boost::shared_ptr, but boost::scoped_ptr 
also lacks support for a custom deleter. Or did you suggest to write an 
own version of std::auto_ptr with support for a custom deleter?

Regards,
Ingo
Thiago Macieira | 22 Aug 00:43

Re: JPEG Thumbnailer

Ingo Klöcker wrote:
>> > What you really want here is std::auto_ptr with a custom deleter.
>> > There is no shared pointer in this circumstance, so no need to add
>> > the overhead associated with that,
>>
>> True.
>
>Actually, this is not true because unfortunately std::auto_ptr does not
>come with support for a custom deleter. I would have suggested
>boost::scoped_ptr instead of boost::shared_ptr, but boost::scoped_ptr
>also lacks support for a custom deleter. Or did you suggest to write an
>own version of std::auto_ptr with support for a custom deleter?

Neither. I was pointing out that it's an overkill either way.

--

-- 
  Thiago Macieira  -  thiago (AT) macieira.info - thiago (AT) kde.org
    PGP/GPG: 0x6EF45358; fingerprint:
    E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358
Thiago Macieira | 22 Aug 00:42

Re: JPEG Thumbnailer

Ingo Klöcker wrote:
>> >a) We are coding in C++, right? So let's use the power C++ provides.
>> > It makes no sense to write error prone code, if there's a way to
>> > avoid it.
>>
>> Uh... std::fstream?
>
>std::fstream does not seem to give access to the FILE handle, so it
>cannot be used in this particular situation.

I agree it doesn't apply to this situation, but I was answering 
your "let's use C++'s power". The C++ class for dealing with files is 
std::fstream.

I can't remember the last time I used it. The only thing from iostream I 
ever use is std::cout, probably once a year.

>> >b) Using boost::shared_ptr is just a compile time dependency.
>>
>> Right, but it'll bring in all of boost's atomic reference counting
>> code along. Also remember that some compilers are brain-dead and will
>> instantiate the entire class, as opposed to just the parts of it that
>> you actually use.
>
>Which compilers? Do we care for those compilers?

Yes, we do: Microsoft Visual Studio.

>> Not to mention that a custom deleter would have to be written.
>
>In this particular case that's not true since
>  boost::shared_ptr<FILE> fd_in( fopen( "foo.jpg", "rb" ), fclose );
>works perfectly alright.

I didn't know that.

>> >c) Several KDE packages (kdepimlibs, kdepim) do already have a
>> >dependency on boost.
>>
>> Sometimes unwarranted. There's a lot of boost that has equivalents in
>> Qt, including shared_ptr/intrusive_ptr (Qt 4.5's QSharedPointer for
>> both). But there are nice things in it too.
>
>The same can be said about Qt (in place of boost) and STL (in place of
>Qt). Yes, I know there were reasons for writing your own container
>classes when Qt 1 was written. But even though there might still be
>some broken STL implementations on certain platforms, I'd rather see
>you adopting the STL containers. There's a plethora of useful C++
>libraries out there that all use STL containers and it really sucks
>that when using Qt one has to use a second set of container classes.

While our containers are better[1] than STL's and while we have to 
maintain an API that works in all platforms we support, we won't be able 
to use STL.

I don't really care for STL containers and iostream, but other parts of 
STL are certainly very, very useful. I just wish we could use it (TR1's 
<type_traits>, for instance), same as C++0x's variadic templates and 
other goodies. Maybe in 2015.

[1] better = clearer API, following Qt guidelines, implicitly shared, just 
as efficient as the best STL implementations (save for the atomic 
refcounting), but consistently efficient in all platforms, regardless of 
which compiler you have.

--

-- 
  Thiago Macieira  -  thiago (AT) macieira.info - thiago (AT) kde.org
    PGP/GPG: 0x6EF45358; fingerprint:
    E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

Gmane