File indexing completed on 2024-05-05 04:22:00
0001 // SPDX-FileCopyrightText: 2005 Steffen Hansen <hansen@kde.org> 0002 // SPDX-FileCopyrightText: 2005-2012 Jesper K. Pedersen <jesper.pedersen@kdab.com> 0003 // SPDX-FileCopyrightText: 2006-2009 Tuomas Suutari <tuomas@nepnep.net> 0004 // SPDX-FileCopyrightText: 2007 Dirk Mueller <mueller@kde.org> 0005 // SPDX-FileCopyrightText: 2007 Laurent Montel <montel@kde.org> 0006 // SPDX-FileCopyrightText: 2007-2012 Jan Kundrát <jkt@flaska.net> 0007 // SPDX-FileCopyrightText: 2010 Miika Turkia <miika.turkia@gmail.com> 0008 // SPDX-FileCopyrightText: 2012 Rex Dieter <rdieter@math.unl.edu> 0009 // SPDX-FileCopyrightText: 2013-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0010 // SPDX-FileCopyrightText: 2016 Tobias Leupold <tl@stonemx.de> 0011 // SPDX-FileCopyrightText: 2018 Robert Krawitz <rlk@alum.mit.edu> 0012 // 0013 // SPDX-License-Identifier: GPL-2.0-or-later 0014 0015 #include "RawImageDecoder.h" 0016 0017 #include "ImageRequest.h" 0018 0019 #include <Utilities/FastJpeg.h> 0020 #include <kpabase/FileExtensions.h> 0021 #include <kpabase/FileName.h> 0022 #include <kpabase/Logging.h> 0023 #include <kpabase/SettingsData.h> 0024 #include <kpabase/config-kpa-kdcraw.h> 0025 0026 #include <QFile> 0027 #include <QImage> 0028 #ifdef HAVE_KDCRAW 0029 #include <KDCRAW/KDcraw> 0030 #include <libkdcraw_version.h> 0031 #endif 0032 0033 namespace ImageManager 0034 { 0035 0036 bool RAWImageDecoder::_decode(QImage *img, ImageRequest *request, QSize *fullSize, int dim) 0037 { 0038 /* width and height seem to be only hints, ignore */ 0039 Q_UNUSED(dim) 0040 0041 #ifdef HAVE_KDCRAW 0042 QSize size; 0043 QSize *fSize = (fullSize) ? fullSize : &size; 0044 const DB::FileName &imageFile = request->fileSystemFileName(); 0045 QByteArray previewData; 0046 if (!KDcrawIface::KDcraw::loadEmbeddedPreview(previewData, imageFile.absolute())) 0047 return false; 0048 0049 // Faster than allowing loadRawPreview to do the decode itself 0050 if (!Utilities::loadJPEG(img, previewData, fSize, dim)) 0051 return false; 0052 0053 qCDebug(ImageManagerLog) << "Got embedded preview for raw file" << imageFile.relative(); 0054 qCDebug(ImageManagerLog) << " Preview size:" << img->width() << "x" << img->height(); 0055 qCDebug(ImageManagerLog) << " Requested dimension:" << dim; 0056 qCDebug(ImageManagerLog) << " useRawThumbnail:" << Settings::SettingsData::instance()->useRawThumbnail(); 0057 qCDebug(ImageManagerLog) << " useRawThumbnailSize:" << Settings::SettingsData::instance()->useRawThumbnailSize(); 0058 0059 if (Settings::SettingsData::instance()->useRawThumbnail() 0060 && ((dim > 0 && img->width() >= dim && img->height() >= dim) 0061 || (img->width() >= Settings::SettingsData::instance()->useRawThumbnailSize().width() 0062 && img->height() >= Settings::SettingsData::instance()->useRawThumbnailSize().height()))) { 0063 qCDebug(ImageManagerLog) << "Preferring embedded raw thumbnail..."; 0064 return true; 0065 } 0066 0067 KDcrawIface::DcrawInfoContainer metadata; 0068 if (!KDcrawIface::KDcraw::rawFileIdentify(metadata, imageFile.absolute())) 0069 return false; 0070 qCDebug(ImageManagerLog) << " Raw image size:" << metadata.imageSize; 0071 qCDebug(ImageManagerLog) << " Raw image orientation enum:" << metadata.orientation; 0072 if ((img->width() < metadata.imageSize.width() * 0.8) || (img->height() < metadata.imageSize.height() * 0.8)) { 0073 0074 qCDebug(ImageManagerLog) << "Decoding the raw image is required..."; 0075 // let's try to get a better resolution 0076 KDcrawIface::KDcraw decoder; 0077 KDcrawIface::RawDecodingSettings rawDecodingSettings; 0078 0079 if (rawDecodingSettings.sixteenBitsImage) { 0080 qCWarning(ImageManagerLog) << "16 bits per color channel is not supported yet"; 0081 return false; 0082 } else { 0083 QByteArray imageData; /* 3 bytes for each pixel, */ 0084 int width, height, rgbmax; 0085 if (!decoder.decodeRAWImage(imageFile.absolute(), rawDecodingSettings, imageData, width, height, rgbmax)) 0086 return false; 0087 0088 // Now the funny part, how to turn this fugly QByteArray into an QImage. Yay! 0089 *img = QImage(width, height, QImage::Format_RGB32); 0090 if (img->isNull()) 0091 return false; 0092 0093 uchar *data = img->bits(); 0094 0095 for (int i = 0; i < imageData.size(); i += 3, data += 4) { 0096 data[0] = imageData[i + 2]; // blue 0097 data[1] = imageData[i + 1]; // green 0098 data[2] = imageData[i]; // red 0099 data[3] = 0xff; // alpha 0100 } 0101 } 0102 // The preview data for raw images is always returned in its non-rotated form by libkdcraw, 0103 // but the raw image itself is returned in its rotated form. 0104 // For decoded raw images, we therefore need to tell the ImageLoaderThread not to rotate the image a second time. 0105 request->setImageIsPreRotated(true); 0106 0107 } else 0108 qCDebug(ImageManagerLog) << "Embedded raw thumbnail is sufficient..."; 0109 0110 *fSize = img->size(); 0111 0112 return true; 0113 #else /* HAVE_KDCRAW */ 0114 Q_UNUSED(img) 0115 Q_UNUSED(fullSize) 0116 Q_UNUSED(request) 0117 return false; 0118 #endif /* HAVE_KDCRAW */ 0119 } 0120 0121 bool RAWImageDecoder::_mightDecode(const DB::FileName &imageFile) 0122 { 0123 const auto pref = Settings::SettingsData::instance()->skipRawIfOtherMatches() ? KPABase::FileTypePreference::PreferNonRawFile : KPABase::FileTypePreference::NoPreference; 0124 return KPABase::isUsableRawImage(imageFile, pref); 0125 } 0126 0127 } 0128 // vi:expandtab:tabstop=4 shiftwidth=4: