Summary: | Faster display of images and/or prefetch wished for | ||
---|---|---|---|
Product: | [Applications] digikam | Reporter: | Brad Templeton <kdebug> |
Component: | Preview-Image | Assignee: | Digikam Developers <digikam-bugs-null> |
Status: | RESOLVED FIXED | ||
Severity: | wishlist | CC: | althio.forum, caulier.gilles, cimmino.marco, contact, gaetan, gschintgen, krienke, marcel.wiesweg |
Priority: | NOR | ||
Version: | 0.9.0 | ||
Target Milestone: | --- | ||
Platform: | Debian testing | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | 4.3.0 | |
Sentry Crash Report: |
Description
Brad Templeton
2006-08-08 09:47:16 UTC
Your suggestions for fast rendering are important optimisations. For a viewer. Please note that digikam currently has no viewer, only an image editor. (Showfoto is supposed to be a viewer, but in its heart it is an editor) As the image editor is an editor, it needs the full pixels at any time. Btw, only for JPEGs it is possible to save time loading in a lower resolution. We can preload the next image, that costs RAM (image size), but no problem. Rendering cannot be done in a background thread, it must be done in a foreground thread (it is X server communication in the end). That does not mean we cannot have a dedicated speed-optimized viewer for image _watching_, fully integrated with all sidebar stuff of course, allowing nice slideshows, easily opening the IE if editing is needed. Thanks. My personal taste is I want gimp or other such tools for my true editing, and from my photo organizer I want to edit captions, tags and albums most. Though of course many people do minor edits in photo organizers. (Rotate is not so much an edit, since to be lossless for jpeg it usually involves re-reading the file.) However, I come to digikam mainly for organizing, and it has the potential to be the best at that. Right now the main barriers are the various beta bugs and crashes (since I am using the 9-beta1-2) which will of course go away, and the speed. I have a number of other things I would like ( http://ideas.4brad.com/archives/000189.html ) but I think speed is the key missing element. When I refer to rendering, I mean the decompression of the jpeg, what the editor is doing when it says "loading" with a status bar. That (and also the scaling down to the planned viewing size) can be done in a background thread for the predicted next picture. Then when it's time to display, a foreground thread w ould send the graphics to the X-server. (Though on many displays now it is possible, I believe, to send it in advance to a hidden area, and then reveal the area for a truly instant display. That's more important for slideshows than image management.) If you've tried out kuickshow/pho/xzgv you will have seen how much faster they can move from one picture to the next, without pre-fetch. If you try out gqview, you will see it's not as fast on the loading but does the pre-fetch. RAM, as we know today, costs about $70 per gigabyte. 8 megapixel images require 24mb. Who would not spend $1.68 in memory per picture to get lighting response. If you store it at viewing size, it's probably just 6MB for 1600x1200 screens. I have a 2560x1600 screen but I can handle it. Isn't F3 action opening image viewer? 100% ACK to Brad Templeton. digikam is a really great photo organizer. So it's a pitty that I usually usw kuickshow to actually view my photos because digikam is that slow.... :-( BTW: I haven't heard of the F3 action before. "View Image" should belong into the context menu not only the main menu bar. This viewer is exactly what I want (as you have access to all digikam functions with its hotkeys (rating etc.), but it's still too slow in showing the next image. Ian, I know the problem about F3 preview mode speed. Look my comments #2 in B.K.O #133590 When i said that it's a _FAST_ preview mode, it's true with : * _ALL_ raw files type (500ms-1000ms instead 10s-20s depending of your computer speed). * _ALL PNG or TIFF file saved with digiKam image editor, witch save a preview image in IPTC metadata ((500ms-1000ms instead 3s-5s) Gilles Caulier SVN commit 582220 by cgilles: digikam from trunk : add link to image preview feature into album icon item popup menu. CCBUGS: 132047 M +11 -5 albumiconview.cpp M +2 -1 albumiconview.h M +5 -2 digikamview.cpp --- trunk/extragear/graphics/digikam/digikam/albumiconview.cpp #582219:582220 @@ -107,13 +107,14 @@ #include "cameradragobject.h" #include "dragobjects.h" #include "dmetadata.h" -#include "albumiconitem.h" -#include "albumicongroupitem.h" -#include "albumiconview.h" #include "albumdb.h" #include "imageattributeswatch.h" #include "dcrawbinary.h" #include "deletedialog.h" +#include "albumiconitem.h" +#include "albumicongroupitem.h" +#include "albumiconview.h" +#include "albumiconview.moc" namespace Digikam { @@ -505,6 +506,7 @@ // -------------------------------------------------------- QPopupMenu popmenu(this); + popmenu.insertItem(SmallIcon("viewimage"), i18n("View..."), 18); popmenu.insertItem(SmallIcon("editimage"), i18n("Edit..."), 10); popmenu.insertItem(i18n("Open With"), &openWithMenu, 11); popmenu.insertSeparator(); @@ -657,6 +659,12 @@ slotSetAlbumThumbnail(iconItem); break; } + + case 18: + { + signalPreviewItem(iconItem); + break; + } default: break; @@ -1838,5 +1846,3 @@ } } // namespace Digikam - -#include "albumiconview.moc" --- trunk/extragear/graphics/digikam/digikam/albumiconview.h #582219:582220 @@ -113,8 +113,9 @@ signals: + void signalPreviewItem(AlbumIconItem*); void signalItemsAdded(); - void signalItemDeleted(AlbumIconItem* iconItem); + void signalItemDeleted(AlbumIconItem*); void signalCleared(); public slots: --- trunk/extragear/graphics/digikam/digikam/digikamview.cpp #582219:582220 @@ -69,6 +69,7 @@ #include "dio.h" #include "digikamapp.h" #include "digikamview.h" +#include "digikamview.moc" namespace Digikam { @@ -226,6 +227,10 @@ connect(d->iconView, SIGNAL(signalItemsAdded()), this, SLOT(slotAlbumHighlight())); + connect(d->iconView, SIGNAL(signalPreviewItem(AlbumIconItem*)), + this, SLOT(slot_imagePreview(AlbumIconItem*))); + + //connect(d->iconView, SIGNAL(signalItemDeleted(AlbumIconItem*)), // this, SIGNAL(signal_noCurrentItem())); @@ -977,5 +982,3 @@ } } // namespace Digikam - -#include "digikamview.moc" *** Bug 133590 has been marked as a duplicate of this bug. *** Just pasting a part of my comment from 133590 so that it does not get lost: What gqview does (if the next image has not yet already been loaded in the background, e.g. when trying to go through many images too quickly) is to incrementally display the new image starting from the top. By this it is at least possible to decide earlier to move on or not. Not sure whether this is possible with the widget used for the display. SVN commit 619531 by mwiesweg: Loading of previews is now multithreaded: - integrate preview loading into the load-save framework - the PreviewLoadTask is a cut-down version of the normal SharedLoadingTask - use the same cache CCMAIL: digikam-devel@kde.org M +0 -1 digikam/Makefile.am M +31 -43 digikam/imagepreviewwidget.cpp M +4 -4 digikam/imagepreviewwidget.h M +4 -0 libs/threadimageio/Makefile.am M +11 -3 libs/threadimageio/loadingcache.cpp M +24 -0 libs/threadimageio/loadingdescription.h M +1 -1 libs/threadimageio/loadsavetask.cpp M +1 -1 libs/threadimageio/loadsavetask.h M +13 -3 libs/threadimageio/loadsavethread.cpp M +40 -0 libs/threadimageio/managedloadsavethread.cpp M +1 -0 libs/threadimageio/managedloadsavethread.h A libs/threadimageio/previewloadthread.cpp [License: GPL] A libs/threadimageio/previewloadthread.h [License: GPL] A libs/threadimageio/previewtask.cpp [License: GPL] A libs/threadimageio/previewtask.h [License: GPL] Multithreading is great since I do have dual core. But it still doesn't hold a candle to what pre-decompress gets you or plain old faster jpeg decoding as you would get by just taking the code of the other programs. What might make sense is to have two modes of full-size preview, one of which allows more complex modifications to the image directly, and the other of which requires the image be re-loaded before most pixel modifications (rotate and flip should be possible without re-load since they can be done lossless on the file as in thumb mode.) This would allow the very fastest loads which are, for large images, only needing 1/4 of the pixels or less. Now I have to admit, the speed is getting pretty good for me on my dual core Intel 6600, but that's one of the faster systems out there. Brad, >Multithreading is great since I do have dual core. But it still doesn't hold a candle to what >pre-decompress gets you or plain old faster jpeg decoding as you would get by just taking >the code of the other programs. No need to re-invent the wheel to take the code from other programs. The image loader implementation are very similar and cannot be optimized anymore. The ultimate optimization to do is to preload in background to the cache the next and previous image around the current selected image from current album. Kuickshow and digiKam image editor < 0.9 use this mechanism with imlib2 library. >What might make sense is to have two modes of full-size preview, one of which allows >more complex modifications to the image directly, and the other of which requires the >image be re-loaded before most pixel modifications (rotate and flip should be possible >without re-load since they can be done lossless on the file as in thumb mode.) This is out of context of this file. Please open a new wish. Other optimizations to speed-up the drawing of pictures on the screen can be done using Qt4. No need to re-invent the wheel again... Gilles Caulier > The ultimate optimization to do is to
> preload in background to the cache the next and previous image
> around the current selected image from current album.
One might even think of:
- preloading the next (e.g.) 2-5 images in the background
- keep the last viewed (e.g.) 2-5 images in the cache
The precise numbers + an upper RAM limit for the cache
should be configurable by the user according to his preferences/resources.
Best, Arnd
The last viewed images are kept in the cache, until it is full. (If a full-blown version is in the cache, it is used as well btw) For preloading there is a requirement that we dont meet currently: The ability to stop the loading. We can do this with the DImg loaders, but the preview is based on QImage. I'm currently wondering if it is desirable to use the cheap-loading optimization for JPEGs, that is also used in the thumbnail loader. > The last viewed images are kept in the cache, until it is full. (If > a full-blown version is in the cache, it is used as well btw) I see - very nice. How large is that cache (presently that size is not configurable, right?)? > I'm currently wondering if it is desirable to use the cheap-loading > optimization for JPEGs, that is also used in the thumbnail loader. If that would bring speed-improvements, why not? ;-) Creating of thumbnails: 2-3 seconds per image (raw) Viewing image: 5-7 seconds per image (raw) CPU usage: all free time: 90-95% System: iMac Intel Core Duo 2.00 GHz I would be happy, if it could be faster > Viewing image: 5-7 seconds per image (raw)
If you talking about preview (F3) not Editor (F4), here on my poor computer (PIII-650Mhz-300Mb) it take less than 1 second per RAW image...
Gilles Caulier
Okay... that is realy intresting... I ment eding (left klick/F4)... Preview needs one second... It's faster then the thumbnail action *LOL* I agree that the image viewing in digikam is too slow. Therefore I wrote an OpenGL based image viewer (KIPI plugin). Get it here: http://kde-apps.org/content/show.php?content=52276 Kusi 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) This file is implemented in 0.9.1 release. I close it. Gilles Photos aren't prefetched in 0.9.1 so why closed as fixed? Photos are still loaded when page down is pressed and not before. I went through all comments for this bug, and agree with #21 that prefetching is not yet done. I therefore re-open this bug. Summary of open points: - "The ultimate optimization to do is to preload in background to the cache the next and previous image around the current selected image from current album. " (Gilles, in #11) - "Other optimizations to speed-up the drawing of pictures on the screen can be done using Qt4." (Gilles, in #11) - "For preloading there is a requirement that we dont meet currently: The ability to stop the loading. We can do this with the DImg loaders, but the preview is based on QImage." (Marcel, in #13) Since January a lot has changed: 1) There is preloading in image preview. If you dont believe, start digikam from a console and watch the output in a directory with raw images ;-) 2) This is obviously what we are dealing with in the immediate future (weeks) 3) The preview is now based on DImg, but internally, loading of embbeded previews in raws and in IPTC and half-size preview of raws is non-interruptable (the latter may change I think, why not use the DImg loader). We have solved this problem by using two loading threads. Then the only problem is the use of resources by the non-interruptable operation, when the prediction of the preloading was not met (i.e., the currently preloaded image is not the needed one) Ad 1) Well, I didn't believe, and before posting I did the test with a directory of raw files, however without a look at the console. And it does feel much slower to go from the current to the next image than going back to the previous (or other cached images). I.e., once they are in cache it works brilliantly! Looking at the console ouput: it does indeed say that the next image is preloaded. However, when going to the next image, it again says "Running RAW decoding command kdcraw ...." on that image (?!) *and* the subsequent image (which is fine). Sometimes I even observe a kcdraw call for the previous images? (Just simply going through a bunch of images from the first to the last, in F3 preview mode, "Embedded preview load full image size" in the "Album Settings") Maybe I am interpreting the output incorrectly? BTW, how large is the cache used for all this (is its size configurable)? In general, I know that you have been working very hard on this, and the improvements are brilliant and very much appreciated (All this, including 2) and 3) look technically rather involved!). Thanks a lot, Arnd Arnd, To extract an embedded preview from RAW file the command is "kdcraw -e ..." Look dcraw man page for details. Gilles Right - thanks Gilles! So to me it seems that it does not preload when "Embedded preview load full image size" is set in the "Album Settings". Details: - Folder with 4 raw images: IMG_1939.CR2, ..., IMG_1942.CR2, - album view - then press F3 (to preview IMG_1939.CR2): digikam: IMG_1939.CR2 : RAW file identified Running RAW decoding command: kdcraw -c -v -h -w -a -H 0 -b 1 -q 0 -o1 IMG_1939.CR2 Running RAW decoding command: kdcraw -c -e 'IMG_1940.CR2' Using embedded RAW preview extraction # Is there any preload done here? # I.e. should there be a kcdraw -c -v .... IMG_1940.CR2? - Page Down: digikam: IMG_1940.CR2 : RAW file identified Running RAW decoding command: kdcraw -c -v -h -w -a -H 0 -b 1 -q 0 -o 1 IMG_1940.CR2 Running RAW decoding command: kdcraw -c -e 'IMG_1941.CR2' Using embedded RAW preview extraction Running RAW decoding command: kdcraw -c -e 'IMG_1939.CR2' Using embedded RAW preview extraction If "embedded preview load full image size" is not active, I only see the kdcraw -c -e '...' commands (and just 4 of them), and that's it. Same for jpg. Images load really fast -- unless "Embedded preview load full image size" is set in the "Album Settings" which is unfortunate since I cannot zoom in. While I don't know, where this behaviour comes from, maybe a reasonable workaround is to reload the full image size on zoom? Arnd, Why this file have been re-open ? It's still a problem somewhere ? Gilles Caulier Gilles, the open issue is detailed in c#26. Unless something has changed, this problem is still there ... Marcel, What do you think about comments in #26 from Arnd ? Something is wrong in preloading interface ? Gilles caulier SVN commit 787804 by mwiesweg: Load high quality version also when preloading the preview. Seems to fix the bug. CCBUG: 132047 M +6 -2 imagepreviewview.cpp WebSVN link: http://websvn.kde.org/?view=rev&revision=787804 Arnd, Can you confirm ? Gilles It feels solved - many thanks! Still I have two questions: a) how large is the cache size (it seems that around 3-4 Raws are kept in memory)? Could/should one make this configurable? b) When being in preview mode (with loading of the full image marked as active), there is something which puzzles me: Using PageDown for the sequence IMG_8305.CR2 IMG_8306.CR2 IMG_7061.CR2 I get the following dcraw commands shown on the konsole : - Still in thumbnail view (i.e. initial start): kdcraw -c -v -4 -h -H 0 -b 1 -w -q 0 -o 1 IMG_8305.CR2 - then preview: kdcraw -c -v -h -H 0 -b 1 -w -q 0 -o 1 IMG_8305.CR2 kdcraw -c -v -h -H 0 -b 1 -w -q 0 -o 1 IMG_8306.CR2 (i.e preloading works!) - then PageDown kdcraw -c -v -h -H 0 -b 1 -w -q 0 -o 1 IMG_7061.CR2 kdcraw -c -v -4 -h -H 0 -b 1 -w -q 0 -o 1 IMG_8306.CR2 Question: what is the -4 variant being used for ? Such a command sometimes also gets triggered for images, which apparantly are still in cache (at least the display is instantaneous)? Arnd, "-4" option is dedicated to handle 16 bits color depth. Perhaps are you enabled histogram on righ side bar which render stat using 16 bits color depth... And yes, in this case, both version are loaded in memory... it's not optimum (:=))) Gilles Well, I did not really enable the histogramm ;-) The right side-bar was closed, however, it seems that the histogramm is still computed in the background. So in view of this bug here, everything is fine! However, I will have to open new (separate) bugs for a) don't load histogram if it is not visible b) optimize memory usage/speed for histogram computation (i.e. re-use the data in memory, if availble) c) there is no histogram for raws (only in log scale you see something) d) allow full size preview (i.e. a 100% view should be a 100% and not a 50% one) Best, Arnd For RAW images, the situation is complex, because there is the preview (jpeg from metadata), the full size preview (fast dcraw loading, 8bit), the image for the histogram (fast dcraw loading, 16 bit), and the full 16-bit image for the editor. We usually try to reuse as much cached image as possible, but priority is to load as fast as possible, and when then a higher-quality version is required, the already loaded data must be discarded. There is infrastructure to handle the event of a concurrent "more complete loading event": If the histogram is loading an image, and then the image editor begins to load, the histogram is notified and can decide to cancel its own operation and wait on the other. Worst case is: First thumbnail generation, then preview, then histogram, then editor. This results in four subsequent dcraw calls. But we cannot avoid that: We dont know in advance what the user decides, and if he only wants the preview, we cannot accept to load the full version, which takes much longer, only because the user could choose to need in the next time. We cache what we have, we use higher-quality cached images if lower-quality is requested, and we can handle concurrent operations, cancelling the lower for the higher quality load. Now we could go on and wait in the preview for the 16 bit image from histogram: Gilles, is this now possible after your auto coloradjustment feature for 16bit raws? Previously, the histogram image could not be reused for viewing. You see that it is complex to decide what image can be used for what purpose, Marcel,
>Now we could go on and wait in the preview for the 16 bit image from histogram: >Gilles, is this now possible after your auto coloradjustment feature for 16bit >raws? Previously, the histogram image could not be reused for viewing.
Yes, it's possible, but there is many points where we need to take a care :
- 1st, there is 2 way to get preview : embeded JPEG or half decoded raw image.
- 2nd, histogram is currently always computed in 16 bits color depth with RAW.
- 3rd, preview is always in 8 bits color depth.
- 4th, editor never use half RAW decoded image but full RAW decoded image instead.
Like 8 and 16 bits color depth RAW decoding have the same auto-gamma now, and if preview != embeded JPEG, i propose :
- to always use the same bits depth everywhere to compute preview and histogram
- to use the same image to compute histogram and preview.
- to always use the same settings about RAW color depth handling everywhere.
This way will simplify all RAW cache operations and will optimize memory consumptions.
Gilles
Hello, Here is what's happining in a unnamed commercial program: - fast preview is generated as soon as possible for the current directory. Undoubtly the jpeg thumbnails embedded in jpegs files and DNGs - Fitted previews are then generated after all fast previews are generated. This is used to display "fitted-to-screen" image with the embedded viewer - Fullscale previews are then generated. To work on a file, all previews are discarded and the file is completly decoded. My Humble Opinion: histogram is not important for a folder, so when the user is in a folder view, go fast and load all smalest/quickest previews available. If user wishes to see histogram for image "n", when the panel is opened, decode smallest preview if not available, and then decode for histogram. Don't worry about the worst case. If the histogram is updating and the user click on edit, just discard the histogram and load the complete file. But smallest thumbnails shall be displayed to avoid "white squares of the death" the quickest possible (and not only on the current folder, if I import 5500 photo in 120 differents folder, I don't expect to click on every folder and wait for all the preview to have been generated). Brad, This is an old entry, with some work on it. It still valid using digiKam 2.4 ? Gilles Caulier Speed is much improved. But the opengl viewer, for example, is still much faster, and Digikam's main competition (picasa under wine) is also still faster even though it is several years older! So there is still room for improvement. Unfortunately the opengl viewer crashes (so that the only way out is to get out of the x server and kill it, the escape key does not work) and also is not integrated with the rest of the UI. Truth is everybody who is going to do photo editing has a GPU and opengl, so possibly a new ticket is needed for better integration of opengl and associated code is needed. All improvements done in this file are enough for now and work as expected with current implementation from git/master. For new wish about improvement of Preview mode, please open new file. Gilles Caulier |