File indexing completed on 2024-04-28 15:50:40
0001 /* 0002 SPDX-FileCopyrightText: 2006-2015 Gilles Caulier <caulier dot gilles at gmail dot com> 0003 SPDX-FileCopyrightText: 2006-2013 Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0004 SPDX-FileCopyrightText: 2007-2008 Guillaume Castagnino <casta at xwing dot info> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "kdcraw.h" 0010 #include "kdcraw_p.h" 0011 0012 // Qt includes 0013 0014 #include <QFile> 0015 #include <QFileInfo> 0016 #include <QStringList> 0017 0018 // LibRaw includes 0019 0020 #include <libraw_version.h> 0021 0022 #ifdef LIBRAW_HAS_CONFIG 0023 #include <libraw_config.h> 0024 #endif 0025 0026 // Local includes 0027 0028 #include "libkdcraw_debug.h" 0029 #include "libkdcraw_version.h" 0030 #include "rawfiles.h" 0031 0032 namespace KDcrawIface 0033 { 0034 0035 KDcraw::KDcraw() 0036 : d(new KDcrawPrivate(this)) 0037 { 0038 m_cancel = false; 0039 } 0040 0041 KDcraw::~KDcraw() 0042 { 0043 cancel(); 0044 } 0045 0046 QString KDcraw::version() 0047 { 0048 return QString::fromLatin1(KDCRAW_VERSION_STRING); 0049 } 0050 0051 void KDcraw::cancel() 0052 { 0053 m_cancel = true; 0054 } 0055 0056 bool KDcraw::loadRawPreview(QImage& image, const QString& path) 0057 { 0058 // In first, try to extract the embedded JPEG preview. Very fast. 0059 bool ret = loadEmbeddedPreview(image, path); 0060 0061 if (ret) 0062 return true; 0063 0064 // In second, decode and half size of RAW picture. More slow. 0065 return (loadHalfPreview(image, path)); 0066 } 0067 0068 bool KDcraw::loadEmbeddedPreview(QImage& image, const QString& path) 0069 { 0070 QByteArray imgData; 0071 0072 if ( loadEmbeddedPreview(imgData, path) ) 0073 { 0074 qCDebug(LIBKDCRAW_LOG) << "Preview data size:" << imgData.size(); 0075 0076 if (image.loadFromData( imgData )) 0077 { 0078 qCDebug(LIBKDCRAW_LOG) << "Using embedded RAW preview extraction"; 0079 return true; 0080 } 0081 } 0082 0083 qCDebug(LIBKDCRAW_LOG) << "Failed to load embedded RAW preview"; 0084 return false; 0085 } 0086 0087 bool KDcraw::loadEmbeddedPreview(QByteArray& imgData, const QString& path) 0088 { 0089 QFileInfo fileInfo(path); 0090 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0091 QString ext = fileInfo.suffix().toUpper(); 0092 0093 if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) 0094 return false; 0095 0096 LibRaw raw; 0097 0098 int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData()); 0099 0100 if (ret != LIBRAW_SUCCESS) 0101 { 0102 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret); 0103 raw.recycle(); 0104 return false; 0105 } 0106 0107 return (KDcrawPrivate::loadEmbeddedPreview(imgData, raw)); 0108 } 0109 0110 bool KDcraw::loadEmbeddedPreview(QByteArray& imgData, const QBuffer& buffer) 0111 { 0112 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0113 LibRaw raw; 0114 0115 QByteArray inData = buffer.data(); 0116 int ret = raw.open_buffer((void*) inData.data(), (size_t) inData.size()); 0117 0118 if (ret != LIBRAW_SUCCESS) 0119 { 0120 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_buffer: " << libraw_strerror(ret); 0121 raw.recycle(); 0122 return false; 0123 } 0124 0125 return (KDcrawPrivate::loadEmbeddedPreview(imgData, raw)); 0126 } 0127 0128 bool KDcraw::loadHalfPreview(QImage& image, const QString& path) 0129 { 0130 QFileInfo fileInfo(path); 0131 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0132 QString ext = fileInfo.suffix().toUpper(); 0133 0134 if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) 0135 return false; 0136 0137 qCDebug(LIBKDCRAW_LOG) << "Try to use reduced RAW picture extraction"; 0138 0139 LibRaw raw; 0140 raw.imgdata.params.use_auto_wb = 1; // Use automatic white balance. 0141 raw.imgdata.params.use_camera_wb = 1; // Use camera white balance, if possible. 0142 raw.imgdata.params.half_size = 1; // Half-size color image (3x faster than -q). 0143 0144 int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData()); 0145 0146 if (ret != LIBRAW_SUCCESS) 0147 { 0148 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret); 0149 raw.recycle(); 0150 return false; 0151 } 0152 0153 0154 if(!KDcrawPrivate::loadHalfPreview(image, raw)) 0155 { 0156 qCDebug(LIBKDCRAW_LOG) << "Failed to get half preview from LibRaw!"; 0157 return false; 0158 } 0159 0160 qCDebug(LIBKDCRAW_LOG) << "Using reduced RAW picture extraction"; 0161 0162 return true; 0163 } 0164 0165 bool KDcraw::loadHalfPreview(QByteArray& imgData, const QString& path) 0166 { 0167 QFileInfo fileInfo(path); 0168 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0169 QString ext = fileInfo.suffix().toUpper(); 0170 0171 if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) 0172 return false; 0173 0174 qCDebug(LIBKDCRAW_LOG) << "Try to use reduced RAW picture extraction"; 0175 0176 LibRaw raw; 0177 int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData()); 0178 0179 if (ret != LIBRAW_SUCCESS) 0180 { 0181 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); 0182 raw.recycle(); 0183 return false; 0184 } 0185 0186 QImage image; 0187 0188 if (!KDcrawPrivate::loadHalfPreview(image, raw)) 0189 { 0190 qCDebug(LIBKDCRAW_LOG) << "KDcraw: failed to get half preview: " << libraw_strerror(ret); 0191 return false; 0192 } 0193 0194 QBuffer buffer(&imgData); 0195 buffer.open(QIODevice::WriteOnly); 0196 image.save(&buffer, "JPEG"); 0197 0198 return true; 0199 } 0200 0201 bool KDcraw::loadHalfPreview(QByteArray& imgData, const QBuffer& inBuffer) 0202 { 0203 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0204 LibRaw raw; 0205 0206 QByteArray inData = inBuffer.data(); 0207 int ret = raw.open_buffer((void*) inData.data(), (size_t) inData.size()); 0208 0209 if (ret != LIBRAW_SUCCESS) 0210 { 0211 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); 0212 raw.recycle(); 0213 return false; 0214 } 0215 0216 QImage image; 0217 0218 if (!KDcrawPrivate::loadHalfPreview(image, raw)) 0219 { 0220 qCDebug(LIBKDCRAW_LOG) << "KDcraw: failed to get half preview: " << libraw_strerror(ret); 0221 return false; 0222 } 0223 0224 QBuffer buffer(&imgData); 0225 buffer.open(QIODevice::WriteOnly); 0226 image.save(&buffer, "JPG"); 0227 0228 return true; 0229 } 0230 0231 bool KDcraw::loadFullImage(QImage& image, const QString& path, const RawDecodingSettings& settings) 0232 { 0233 QFileInfo fileInfo(path); 0234 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0235 QString ext = fileInfo.suffix().toUpper(); 0236 0237 if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) 0238 return false; 0239 0240 qCDebug(LIBKDCRAW_LOG) << "Try to load full RAW picture..."; 0241 0242 RawDecodingSettings prm = settings; 0243 prm.sixteenBitsImage = false; 0244 QByteArray imgData; 0245 int width, height, rgbmax; 0246 0247 KDcraw decoder; 0248 bool ret = decoder.decodeRAWImage(path, prm, imgData, width, height, rgbmax); 0249 0250 if (!ret) 0251 { 0252 qCDebug(LIBKDCRAW_LOG) << "Failed to load full RAW picture"; 0253 return false; 0254 } 0255 0256 uchar* sptr = (uchar*)imgData.data(); 0257 uchar tmp8[2]; 0258 0259 // Set RGB color components. 0260 for (int i = 0 ; i < width * height ; ++i) 0261 { 0262 // Swap Red and Blue 0263 tmp8[0] = sptr[2]; 0264 tmp8[1] = sptr[0]; 0265 sptr[0] = tmp8[0]; 0266 sptr[2] = tmp8[1]; 0267 0268 sptr += 3; 0269 } 0270 0271 image = QImage(width, height, QImage::Format_ARGB32); 0272 uint* dptr = reinterpret_cast<uint*>(image.bits()); 0273 sptr = (uchar*)imgData.data(); 0274 0275 for (int i = 0 ; i < width * height ; ++i) 0276 { 0277 *dptr++ = qRgba(sptr[2], sptr[1], sptr[0], 0xFF); 0278 sptr += 3; 0279 } 0280 0281 qCDebug(LIBKDCRAW_LOG) << "Load full RAW picture done"; 0282 0283 return true; 0284 } 0285 0286 bool KDcraw::rawFileIdentify(DcrawInfoContainer& identify, const QString& path) 0287 { 0288 QFileInfo fileInfo(path); 0289 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0290 QString ext = fileInfo.suffix().toUpper(); 0291 identify.isDecodable = false; 0292 0293 if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) 0294 return false; 0295 0296 LibRaw raw; 0297 0298 int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData()); 0299 0300 if (ret != LIBRAW_SUCCESS) 0301 { 0302 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret); 0303 raw.recycle(); 0304 return false; 0305 } 0306 0307 ret = raw.adjust_sizes_info_only(); 0308 0309 if (ret != LIBRAW_SUCCESS) 0310 { 0311 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run adjust_sizes_info_only: " << libraw_strerror(ret); 0312 raw.recycle(); 0313 return false; 0314 } 0315 0316 KDcrawPrivate::fillIndentifyInfo(&raw, identify); 0317 raw.recycle(); 0318 return true; 0319 } 0320 0321 // ---------------------------------------------------------------------------------- 0322 0323 bool KDcraw::extractRAWData(const QString& filePath, QByteArray& rawData, DcrawInfoContainer& identify, unsigned int shotSelect) 0324 { 0325 QFileInfo fileInfo(filePath); 0326 QString rawFilesExt = QString::fromUtf8(rawFiles()); 0327 QString ext = fileInfo.suffix().toUpper(); 0328 identify.isDecodable = false; 0329 0330 if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) 0331 return false; 0332 0333 if (m_cancel) 0334 return false; 0335 0336 d->setProgress(0.1); 0337 0338 LibRaw raw; 0339 // Set progress call back function. 0340 raw.set_progress_handler(callbackForLibRaw, d.get()); 0341 0342 int ret = raw.open_file((const char*)(QFile::encodeName(filePath)).constData()); 0343 0344 if (ret != LIBRAW_SUCCESS) 0345 { 0346 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret); 0347 raw.recycle(); 0348 return false; 0349 } 0350 0351 if (m_cancel) 0352 { 0353 raw.recycle(); 0354 return false; 0355 } 0356 0357 d->setProgress(0.3); 0358 0359 raw.imgdata.params.output_bps = 16; 0360 #if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 21) 0361 raw.imgdata.rawparams.shot_select = shotSelect; 0362 #else 0363 raw.imgdata.params.shot_select = shotSelect; 0364 #endif 0365 ret = raw.unpack(); 0366 0367 if (ret != LIBRAW_SUCCESS) 0368 { 0369 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret); 0370 raw.recycle(); 0371 return false; 0372 } 0373 0374 if (m_cancel) 0375 { 0376 raw.recycle(); 0377 return false; 0378 } 0379 0380 d->setProgress(0.4); 0381 0382 ret = raw.raw2image(); 0383 0384 if (ret != LIBRAW_SUCCESS) 0385 { 0386 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run raw2image: " << libraw_strerror(ret); 0387 raw.recycle(); 0388 return false; 0389 } 0390 0391 if (m_cancel) 0392 { 0393 raw.recycle(); 0394 return false; 0395 } 0396 0397 d->setProgress(0.6); 0398 0399 KDcrawPrivate::fillIndentifyInfo(&raw, identify); 0400 0401 if (m_cancel) 0402 { 0403 raw.recycle(); 0404 return false; 0405 } 0406 0407 d->setProgress(0.8); 0408 0409 rawData = QByteArray(); 0410 0411 if (raw.imgdata.idata.filters == 0) 0412 { 0413 rawData.resize((int)(raw.imgdata.sizes.iwidth * raw.imgdata.sizes.iheight * raw.imgdata.idata.colors * sizeof(unsigned short))); 0414 0415 unsigned short* output = reinterpret_cast<unsigned short*>(rawData.data()); 0416 0417 for (unsigned int row = 0; row < raw.imgdata.sizes.iheight; row++) 0418 { 0419 for (unsigned int col = 0; col < raw.imgdata.sizes.iwidth; col++) 0420 { 0421 for (int color = 0; color < raw.imgdata.idata.colors; color++) 0422 { 0423 *output = raw.imgdata.image[raw.imgdata.sizes.iwidth*row + col][color]; 0424 output++; 0425 } 0426 } 0427 } 0428 } 0429 else 0430 { 0431 rawData.resize((int)(raw.imgdata.sizes.iwidth * raw.imgdata.sizes.iheight * sizeof(unsigned short))); 0432 0433 unsigned short* output = reinterpret_cast<unsigned short*>(rawData.data()); 0434 0435 for (uint row = 0; row < raw.imgdata.sizes.iheight; row++) 0436 { 0437 for (uint col = 0; col < raw.imgdata.sizes.iwidth; col++) 0438 { 0439 *output = raw.imgdata.image[raw.imgdata.sizes.iwidth*row + col][raw.COLOR(row, col)]; 0440 output++; 0441 } 0442 } 0443 } 0444 0445 raw.recycle(); 0446 d->setProgress(1.0); 0447 0448 return true; 0449 } 0450 0451 bool KDcraw::decodeHalfRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings, 0452 QByteArray& imageData, int& width, int& height, int& rgbmax) 0453 { 0454 m_rawDecodingSettings = rawDecodingSettings; 0455 m_rawDecodingSettings.halfSizeColorImage = true; 0456 return (d->loadFromLibraw(filePath, imageData, width, height, rgbmax)); 0457 } 0458 0459 bool KDcraw::decodeRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings, 0460 QByteArray& imageData, int& width, int& height, int& rgbmax) 0461 { 0462 m_rawDecodingSettings = rawDecodingSettings; 0463 return (d->loadFromLibraw(filePath, imageData, width, height, rgbmax)); 0464 } 0465 0466 bool KDcraw::checkToCancelWaitingData() 0467 { 0468 return m_cancel; 0469 } 0470 0471 void KDcraw::setWaitingDataProgress(double) 0472 { 0473 } 0474 0475 const char* KDcraw::rawFiles() 0476 { 0477 return raw_file_extentions; 0478 } 0479 0480 QStringList KDcraw::rawFilesList() 0481 { 0482 QString string = QString::fromLatin1(rawFiles()); 0483 return string.remove(QLatin1String("*.")).split(QLatin1Char(' ')); 0484 } 0485 0486 int KDcraw::rawFilesVersion() 0487 { 0488 return raw_file_extensions_version; 0489 } 0490 0491 QStringList KDcraw::supportedCamera() 0492 { 0493 QStringList camera; 0494 const char** const list = LibRaw::cameraList(); 0495 0496 for (int i = 0; i < LibRaw::cameraCount(); i++) 0497 camera.append(QString::fromUtf8(list[i])); 0498 0499 return camera; 0500 } 0501 0502 QString KDcraw::librawVersion() 0503 { 0504 return QString::fromLatin1(LIBRAW_VERSION_STR).remove(QLatin1String("-Release")); 0505 } 0506 0507 int KDcraw::librawUseGomp() 0508 { 0509 #ifdef LIBRAW_HAS_CONFIG 0510 # ifdef LIBRAW_USE_OPENMP 0511 return true; 0512 # else 0513 return false; 0514 # endif 0515 #else 0516 return -1; 0517 #endif 0518 } 0519 0520 int KDcraw::librawUseRawSpeed() 0521 { 0522 #ifdef LIBRAW_HAS_CONFIG 0523 # ifdef LIBRAW_USE_RAWSPEED 0524 return true; 0525 # else 0526 return false; 0527 # endif 0528 #else 0529 return -1; 0530 #endif 0531 } 0532 0533 int KDcraw::librawUseGPL2DemosaicPack() 0534 { 0535 #ifdef LIBRAW_HAS_CONFIG 0536 # ifdef LIBRAW_USE_DEMOSAIC_PACK_GPL2 0537 return true; 0538 # else 0539 return false; 0540 # endif 0541 #else 0542 return -1; 0543 #endif 0544 } 0545 0546 int KDcraw::librawUseGPL3DemosaicPack() 0547 { 0548 #ifdef LIBRAW_HAS_CONFIG 0549 # ifdef LIBRAW_USE_DEMOSAIC_PACK_GPL3 0550 return true; 0551 # else 0552 return false; 0553 # endif 0554 #else 0555 return -1; 0556 #endif 0557 } 0558 0559 } // namespace KDcrawIface 0560 0561 #include "moc_kdcraw.cpp"