File indexing completed on 2025-01-05 03:57:11
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2008-10-09 0007 * Description : internal private container for DRawDecoder 0008 * 0009 * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "drawdecoder_p.h" 0016 0017 // Qt includes 0018 0019 #include <QString> 0020 #include <QScopedPointer> 0021 0022 // DNG SDK includes 0023 0024 #ifdef USE_DNGSDK 0025 # include "dng_host.h" 0026 #endif 0027 0028 // Local includes 0029 0030 #include "metaengine.h" 0031 0032 namespace Digikam 0033 { 0034 0035 int s_progressCallbackForLibRaw(void* context, enum LibRaw_progress p, int iteration, int expected) 0036 { 0037 if (context) 0038 { 0039 DRawDecoder::Private* const d = static_cast<DRawDecoder::Private*>(context); 0040 0041 return d->progressCallback(p, iteration, expected); 0042 } 0043 0044 return 0; 0045 } 0046 0047 void s_exifParserCallbackForLibRaw(void* context, int tag, int type, int len, unsigned int ord, void* ifp, INT64 base) 0048 { 0049 if (context) 0050 { 0051 DRawDecoder::Private* const d = static_cast<DRawDecoder::Private*>(context); 0052 d->exifParserCallback(tag, type, len, ord, ifp, base); 0053 } 0054 } 0055 0056 // -------------------------------------------------------------------------------------------------- 0057 0058 DRawDecoder::Private::Private(DRawDecoder* const p) 0059 : m_progress(0.0), 0060 m_parent (p) 0061 { 0062 } 0063 0064 DRawDecoder::Private::~Private() 0065 { 0066 } 0067 0068 void DRawDecoder::Private::createPPMHeader(QByteArray& imgData, libraw_processed_image_t* const img) 0069 { 0070 QString header = QString::fromUtf8("P%1\n%2 %3\n%4\n").arg((img->colors == 3) ? QLatin1String("6") : QLatin1String("5")) 0071 .arg(img->width) 0072 .arg(img->height) 0073 .arg((1 << img->bits)-1); 0074 imgData.append(header.toLatin1()); 0075 imgData.append(QByteArray((const char*)img->data, (int)img->data_size)); 0076 } 0077 0078 int DRawDecoder::Private::progressCallback(enum LibRaw_progress p, int iteration, int expected) 0079 { 0080 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw progress:" << libraw_strprogress(p) << "pass" 0081 << iteration << "of" << expected; 0082 0083 // post a little change in progress indicator to show raw processor activity. 0084 0085 setProgress(progressValue() + 0.01); 0086 0087 // Clean processing termination by user... 0088 0089 if (m_parent->checkToCancelWaitingData()) 0090 { 0091 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw process terminaison invoked..."; 0092 m_parent->m_cancel = true; 0093 m_progress = 0.0; 0094 0095 return 1; 0096 } 0097 0098 // Return 0 to continue processing... 0099 0100 return 0; 0101 } 0102 0103 void DRawDecoder::Private::exifParserCallback(int tag, int type, int len, unsigned int ord, void* ifp, INT64 base) 0104 { 0105 // Note: see https://github.com/LibRaw/LibRaw/issues/323 for details 0106 0107 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw Exif Parser:" 0108 << "tag:" << tag 0109 << "type:" << type 0110 << "len:" << len 0111 << "ord:" << ord 0112 << "ifp:" << ifp 0113 << "base:" << base; 0114 } 0115 0116 void DRawDecoder::Private::setProgress(double value) 0117 { 0118 m_progress = value; 0119 m_parent->setWaitingDataProgress(m_progress); 0120 } 0121 0122 double DRawDecoder::Private::progressValue() const 0123 { 0124 return m_progress; 0125 } 0126 0127 void DRawDecoder::Private::fillIndentifyInfo(LibRaw* const raw, DRawInfo& identify) 0128 { 0129 identify.dateTime.setSecsSinceEpoch(raw->imgdata.other.timestamp); 0130 identify.make = QString::fromUtf8(raw->imgdata.idata.make); 0131 identify.model = QString::fromUtf8(raw->imgdata.idata.model); 0132 identify.owner = QString::fromUtf8(raw->imgdata.other.artist); 0133 identify.software = QString::fromUtf8(raw->imgdata.idata.software); 0134 identify.firmware = QString::fromUtf8(raw->imgdata.color.model2); 0135 identify.description = QString::fromUtf8(raw->imgdata.other.desc); 0136 identify.serialNumber = raw->imgdata.other.shot_order; 0137 identify.DNGVersion = QString::number(raw->imgdata.idata.dng_version); 0138 identify.uniqueCameraModel = QString::fromUtf8(raw->imgdata.color.UniqueCameraModel); 0139 identify.localizedCameraModel = QString::fromUtf8(raw->imgdata.color.LocalizedCameraModel); 0140 identify.imageID = QString::fromUtf8(raw->imgdata.color.ImageUniqueID); 0141 identify.rawDataUniqueID = QString::fromUtf8(raw->imgdata.color.RawDataUniqueID); 0142 identify.originalRawFileName = QString::fromUtf8(raw->imgdata.color.RawDataUniqueID); 0143 identify.model = QString::fromUtf8(raw->imgdata.idata.model); 0144 identify.sensitivity = raw->imgdata.other.iso_speed; 0145 identify.exposureTime = raw->imgdata.other.shutter; 0146 identify.aperture = raw->imgdata.other.aperture; 0147 identify.focalLength = raw->imgdata.other.focal_len; 0148 0149 identify.hasGpsInfo = (raw->imgdata.other.parsed_gps.gpsparsed == 1) ? true : false; 0150 identify.latitude = MetaEngine::convertDegreeAngleToDouble(raw->imgdata.other.parsed_gps.latitude[0], 0151 raw->imgdata.other.parsed_gps.latitude[1], 0152 raw->imgdata.other.parsed_gps.latitude[2]); 0153 identify.longitude = MetaEngine::convertDegreeAngleToDouble(raw->imgdata.other.parsed_gps.longitude[0], 0154 raw->imgdata.other.parsed_gps.longitude[1], 0155 raw->imgdata.other.parsed_gps.longitude[2]); 0156 identify.altitude = raw->imgdata.other.parsed_gps.altitude; 0157 identify.imageSize = QSize(raw->imgdata.sizes.width, raw->imgdata.sizes.height); 0158 identify.fullSize = QSize(raw->imgdata.sizes.raw_width, raw->imgdata.sizes.raw_height); 0159 identify.outputSize = QSize(raw->imgdata.sizes.iwidth, raw->imgdata.sizes.iheight); 0160 identify.thumbSize = QSize(raw->imgdata.thumbnail.twidth, raw->imgdata.thumbnail.theight); 0161 identify.topMargin = raw->imgdata.sizes.top_margin; 0162 identify.leftMargin = raw->imgdata.sizes.left_margin; 0163 identify.hasIccProfile = raw->imgdata.color.profile ? true : false; 0164 identify.isDecodable = true; 0165 identify.pixelAspectRatio = raw->imgdata.sizes.pixel_aspect; 0166 identify.baselineExposure = raw->imgdata.color.dng_levels.baseline_exposure; 0167 0168 identify.ambientTemperature = raw->imgdata.makernotes.common.exifAmbientTemperature; 0169 identify.ambientHumidity = raw->imgdata.makernotes.common.exifHumidity; 0170 identify.ambientPressure = raw->imgdata.makernotes.common.exifPressure; 0171 identify.ambientWaterDepth = raw->imgdata.makernotes.common.exifWaterDepth; 0172 identify.ambientAcceleration = raw->imgdata.makernotes.common.exifAcceleration; 0173 identify.ambientElevationAngle = raw->imgdata.makernotes.common.exifCameraElevationAngle; 0174 0175 identify.exposureIndex = raw->imgdata.makernotes.common.exifExposureIndex; 0176 identify.flashUsed = (int)raw->imgdata.color.flash_used; 0177 identify.meteringMode = raw->imgdata.shootinginfo.MeteringMode; 0178 identify.exposureProgram = raw->imgdata.shootinginfo.ExposureProgram; 0179 0180 identify.rawColors = raw->imgdata.idata.colors; 0181 identify.rawImages = raw->imgdata.idata.raw_count; 0182 identify.blackPoint = raw->imgdata.color.black; 0183 0184 for (int ch = 0 ; ch < 4 ; ++ch) 0185 { 0186 identify.blackPointCh[ch] = raw->imgdata.color.cblack[ch]; 0187 } 0188 0189 identify.whitePoint = raw->imgdata.color.maximum; 0190 identify.orientation = (DRawInfo::ImageOrientation)raw->imgdata.sizes.flip; 0191 0192 memcpy(&identify.cameraColorMatrix1, &raw->imgdata.color.cmatrix, sizeof(raw->imgdata.color.cmatrix)); 0193 memcpy(&identify.cameraColorMatrix2, &raw->imgdata.color.rgb_cam, sizeof(raw->imgdata.color.rgb_cam)); 0194 memcpy(&identify.cameraXYZMatrix, &raw->imgdata.color.cam_xyz, sizeof(raw->imgdata.color.cam_xyz)); 0195 0196 if (raw->imgdata.idata.filters) 0197 { 0198 if (!raw->imgdata.idata.cdesc[3]) 0199 { 0200 raw->imgdata.idata.cdesc[3] = 'G'; 0201 } 0202 0203 for (int i = 0 ; i < 16 ; ++i) 0204 { 0205 identify.filterPattern.append(QLatin1Char(raw->imgdata.idata.cdesc[raw->COLOR(i >> 1, i & 1)])); 0206 } 0207 0208 identify.colorKeys = QLatin1String(raw->imgdata.idata.cdesc); 0209 } 0210 0211 for (int c = 0 ; c < raw->imgdata.idata.colors ; ++c) 0212 { 0213 identify.daylightMult[c] = raw->imgdata.color.pre_mul[c]; 0214 } 0215 0216 if (raw->imgdata.color.cam_mul[0] > 0) 0217 { 0218 for (int c = 0 ; c < 4 ; ++c) 0219 { 0220 identify.cameraMult[c] = raw->imgdata.color.cam_mul[c]; 0221 } 0222 } 0223 0224 identify.xmpData = QByteArray(raw->imgdata.idata.xmpdata, raw->imgdata.idata.xmplen); 0225 0226 if (identify.hasIccProfile) 0227 { 0228 identify.iccData = QByteArray((char*)raw->imgdata.color.profile, raw->imgdata.color.profile_length); 0229 } 0230 0231 if (raw->imgdata.thumbnail.tformat != LIBRAW_THUMBNAIL_UNKNOWN) 0232 { 0233 identify.thumbnail = QByteArray((char*)raw->imgdata.thumbnail.thumb, raw->imgdata.thumbnail.tlength); 0234 } 0235 0236 identify.lensModel = QString::fromUtf8(raw->imgdata.lens.Lens); 0237 identify.lensMake = QString::fromUtf8(raw->imgdata.lens.LensMake); 0238 identify.lensSerial = QString::fromUtf8(raw->imgdata.lens.LensSerial); 0239 identify.focalLengthIn35mmFilm = raw->imgdata.lens.FocalLengthIn35mmFormat; 0240 identify.maxAperture = raw->imgdata.lens.EXIF_MaxAp; 0241 } 0242 0243 bool DRawDecoder::Private::loadFromLibraw(const QString& filePath, QByteArray& imageData, 0244 int& width, int& height, int& rgbmax) 0245 { 0246 m_parent->m_cancel = false; 0247 LibRaw* const raw = new LibRaw; 0248 0249 // Set progress call back function. 0250 0251 raw->set_progress_handler(s_progressCallbackForLibRaw, this); 0252 raw->set_exifparser_handler(s_exifParserCallbackForLibRaw, this); 0253 0254 QByteArray deadpixelPath = QFile::encodeName(m_parent->m_decoderSettings.deadPixelMap); 0255 QByteArray cameraProfile = QFile::encodeName(m_parent->m_decoderSettings.inputProfile); 0256 QByteArray outputProfile = QFile::encodeName(m_parent->m_decoderSettings.outputProfile); 0257 0258 if (!m_parent->m_decoderSettings.autoBrightness) 0259 { 0260 // Use a fixed white level, ignoring the image histogram. 0261 0262 raw->imgdata.params.no_auto_bright = 1; 0263 } 0264 0265 if (m_parent->m_decoderSettings.sixteenBitsImage) 0266 { 0267 // (-4) 16bit ppm output 0268 0269 raw->imgdata.params.output_bps = 16; 0270 } 0271 0272 if (m_parent->m_decoderSettings.halfSizeColorImage) 0273 { 0274 // (-h) Half-size color image (3x faster than -q). 0275 0276 raw->imgdata.params.half_size = 1; 0277 } 0278 0279 if (m_parent->m_decoderSettings.RGBInterpolate4Colors) 0280 { 0281 // (-f) Interpolate RGB as four colors. 0282 0283 raw->imgdata.params.four_color_rgb = 1; 0284 } 0285 0286 if (m_parent->m_decoderSettings.DontStretchPixels) 0287 { 0288 // (-j) Do not stretch the image to its correct aspect ratio. 0289 0290 raw->imgdata.params.use_fuji_rotate = 1; 0291 } 0292 0293 // (-H) Unclip highlight color. 0294 0295 raw->imgdata.params.highlight = m_parent->m_decoderSettings.unclipColors; 0296 0297 if (m_parent->m_decoderSettings.brightness != 1.0) 0298 { 0299 // (-b) Set Brightness value. 0300 0301 raw->imgdata.params.bright = m_parent->m_decoderSettings.brightness; 0302 } 0303 0304 if (m_parent->m_decoderSettings.enableBlackPoint) 0305 { 0306 // (-k) Set Black Point value. 0307 0308 raw->imgdata.params.user_black = m_parent->m_decoderSettings.blackPoint; 0309 } 0310 0311 if (m_parent->m_decoderSettings.enableWhitePoint) 0312 { 0313 // (-S) Set White Point value (saturation). 0314 0315 raw->imgdata.params.user_sat = m_parent->m_decoderSettings.whitePoint; 0316 } 0317 0318 if (m_parent->m_decoderSettings.medianFilterPasses > 0) 0319 { 0320 // (-m) After interpolation, clean up color artifacts by repeatedly applying a 3x3 median filter to the R-G and B-G channels. 0321 0322 raw->imgdata.params.med_passes = m_parent->m_decoderSettings.medianFilterPasses; 0323 } 0324 0325 if (!m_parent->m_decoderSettings.deadPixelMap.isEmpty()) 0326 { 0327 // (-P) Read the dead pixel list from this file. 0328 0329 raw->imgdata.params.bad_pixels = deadpixelPath.data(); 0330 } 0331 0332 switch (m_parent->m_decoderSettings.whiteBalance) 0333 { 0334 case DRawDecoderSettings::NONE: 0335 { 0336 break; 0337 } 0338 0339 case DRawDecoderSettings::CAMERA: 0340 { 0341 // (-w) Use camera white balance, if possible. 0342 0343 raw->imgdata.params.use_camera_wb = 1; 0344 break; 0345 } 0346 0347 case DRawDecoderSettings::AUTO: 0348 { 0349 // (-a) Use automatic white balance. 0350 0351 raw->imgdata.params.use_auto_wb = 1; 0352 break; 0353 } 0354 0355 case DRawDecoderSettings::CUSTOM: 0356 { 0357 /* 0358 * Convert between Temperature and RGB. 0359 */ 0360 double RGB[3] = { 0.0 }; 0361 double xD = 0.0; 0362 double yD = 0.0; 0363 double X = 0.0; 0364 double Y = 0.0; 0365 double Z = 0.0; 0366 double T = m_parent->m_decoderSettings.customWhiteBalance; 0367 QScopedPointer<DRawInfo> identify(new DRawInfo); 0368 0369 // ----------------------------------------------------------------------- 0370 // Here starts the code picked and adapted from ufraw (0.12.1) 0371 // to convert Temperature + green multiplier to RGB multipliers 0372 0373 /* 0374 * Convert between Temperature and RGB. 0375 * Base on information from www.brucelindbloom.com/ 0376 * The fit for D-illuminant between 4000K and 12000K are from CIE 0377 * The generalization to 2000K < T < 4000K and the blackbody fits 0378 * are my own and should be taken with a grain of salt. 0379 */ 0380 const double XYZ_to_RGB[3][3] = { 0381 { 3.24071, -0.969258, 0.0556352 }, 0382 {-1.53726, 1.87599, -0.203996 }, 0383 {-0.498571, 0.0415557, 1.05707 } 0384 }; 0385 0386 // Fit for CIE Daylight illuminant 0387 0388 if (T <= 4000) 0389 { 0390 xD = 0.27475e9/(T*T*T) - 0.98598e6/(T*T) + 1.17444e3/T + 0.145986; 0391 } 0392 else if (T <= 7000) 0393 { 0394 xD = -4.6070e9/(T*T*T) + 2.9678e6/(T*T) + 0.09911e3/T + 0.244063; 0395 } 0396 else 0397 { 0398 xD = -2.0064e9/(T*T*T) + 1.9018e6/(T*T) + 0.24748e3/T + 0.237040; 0399 } 0400 0401 yD = -3 * xD * xD + 2.87 * xD - 0.275; 0402 X = xD / yD; 0403 Y = 1; 0404 Z = (1 - xD - yD) / yD; 0405 RGB[0] = X*XYZ_to_RGB[0][0] + Y*XYZ_to_RGB[1][0] + Z*XYZ_to_RGB[2][0]; 0406 RGB[1] = X*XYZ_to_RGB[0][1] + Y*XYZ_to_RGB[1][1] + Z*XYZ_to_RGB[2][1]; 0407 RGB[2] = X*XYZ_to_RGB[0][2] + Y*XYZ_to_RGB[1][2] + Z*XYZ_to_RGB[2][2]; 0408 0409 // End of the code picked to ufraw 0410 // ----------------------------------------------------------------------- 0411 0412 RGB[1] = RGB[1] / m_parent->m_decoderSettings.customWhiteBalanceGreen; 0413 0414 /* 0415 * By default, decraw override his default D65 WB 0416 * We need to keep it as a basis : if not, colors with some 0417 * DSLR will have a high dominant of color that will lead to 0418 * a completely wrong WB 0419 */ 0420 if (rawFileIdentify(*identify, filePath)) 0421 { 0422 RGB[0] = identify->daylightMult[0] / RGB[0]; 0423 RGB[1] = identify->daylightMult[1] / RGB[1]; 0424 RGB[2] = identify->daylightMult[2] / RGB[2]; 0425 } 0426 else 0427 { 0428 RGB[0] = 1.0 / RGB[0]; 0429 RGB[1] = 1.0 / RGB[1]; 0430 RGB[2] = 1.0 / RGB[2]; 0431 qCDebug(DIGIKAM_RAWENGINE_LOG) << "Warning: cannot get daylight multipliers"; 0432 } 0433 0434 // (-r) set Raw Color Balance Multipliers. 0435 0436 raw->imgdata.params.user_mul[0] = RGB[0]; 0437 raw->imgdata.params.user_mul[1] = RGB[1]; 0438 raw->imgdata.params.user_mul[2] = RGB[2]; 0439 raw->imgdata.params.user_mul[3] = RGB[1]; 0440 break; 0441 } 0442 0443 case DRawDecoderSettings::AERA: 0444 { 0445 // (-A) Calculate the white balance by averaging a rectangular area from image. 0446 0447 raw->imgdata.params.greybox[0] = m_parent->m_decoderSettings.whiteBalanceArea.left(); 0448 raw->imgdata.params.greybox[1] = m_parent->m_decoderSettings.whiteBalanceArea.top(); 0449 raw->imgdata.params.greybox[2] = m_parent->m_decoderSettings.whiteBalanceArea.width(); 0450 raw->imgdata.params.greybox[3] = m_parent->m_decoderSettings.whiteBalanceArea.height(); 0451 break; 0452 } 0453 } 0454 0455 // (-q) Use an interpolation method. 0456 0457 raw->imgdata.params.user_qual = m_parent->m_decoderSettings.RAWQuality; 0458 0459 switch (m_parent->m_decoderSettings.NRType) 0460 { 0461 case DRawDecoderSettings::WAVELETSNR: 0462 { 0463 // (-n) Use wavelets to erase noise while preserving real detail. 0464 0465 raw->imgdata.params.threshold = m_parent->m_decoderSettings.NRThreshold; 0466 break; 0467 } 0468 0469 case DRawDecoderSettings::FBDDNR: 0470 { 0471 // (100 - 1000) => (1 - 10) conversion 0472 0473 raw->imgdata.params.fbdd_noiserd = lround(m_parent->m_decoderSettings.NRThreshold / 100.0); 0474 break; 0475 } 0476 0477 default: // No Noise Reduction 0478 { 0479 raw->imgdata.params.threshold = 0; 0480 raw->imgdata.params.fbdd_noiserd = 0; 0481 break; 0482 } 0483 } 0484 0485 // Exposure Correction before interpolation. 0486 0487 raw->imgdata.params.exp_correc = m_parent->m_decoderSettings.expoCorrection; 0488 raw->imgdata.params.exp_shift = m_parent->m_decoderSettings.expoCorrectionShift; 0489 raw->imgdata.params.exp_preser = m_parent->m_decoderSettings.expoCorrectionHighlight; 0490 0491 switch (m_parent->m_decoderSettings.inputColorSpace) 0492 { 0493 case DRawDecoderSettings::EMBEDDED: 0494 { 0495 // (-p embed) Use input profile from RAW file to define the camera's raw colorspace. 0496 0497 raw->imgdata.params.camera_profile = (char*)"embed"; 0498 break; 0499 } 0500 0501 case DRawDecoderSettings::CUSTOMINPUTCS: 0502 { 0503 if (!m_parent->m_decoderSettings.inputProfile.isEmpty()) 0504 { 0505 // (-p) Use input profile file to define the camera's raw colorspace. 0506 0507 raw->imgdata.params.camera_profile = cameraProfile.data(); 0508 } 0509 0510 break; 0511 } 0512 0513 default: 0514 { 0515 // No input profile 0516 0517 break; 0518 } 0519 } 0520 0521 switch (m_parent->m_decoderSettings.outputColorSpace) 0522 { 0523 case DRawDecoderSettings::CUSTOMOUTPUTCS: 0524 { 0525 if (!m_parent->m_decoderSettings.outputProfile.isEmpty()) 0526 { 0527 // (-o) Use ICC profile file to define the output colorspace. 0528 0529 raw->imgdata.params.output_profile = outputProfile.data(); 0530 } 0531 0532 break; 0533 } 0534 0535 default: 0536 { 0537 // (-o) Define the output colorspace. 0538 0539 raw->imgdata.params.output_color = m_parent->m_decoderSettings.outputColorSpace; 0540 break; 0541 } 0542 } 0543 0544 //-- Extended demosaicing settings ---------------------------------------------------------- 0545 0546 raw->imgdata.params.dcb_iterations = m_parent->m_decoderSettings.dcbIterations; 0547 raw->imgdata.params.dcb_enhance_fl = m_parent->m_decoderSettings.dcbEnhanceFl; 0548 0549 #ifdef USE_DNGSDK 0550 0551 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: setup internal DNG SDK"; 0552 0553 raw->imgdata.rawparams.use_dngsdk = LIBRAW_DNG_ALL; 0554 dng_host* const dnghost = new dng_host; 0555 raw->set_dng_host(dnghost); 0556 0557 #endif 0558 0559 //------------------------------------------------------------------------------------------- 0560 0561 setProgress(0.1); 0562 0563 qCDebug(DIGIKAM_RAWENGINE_LOG) << filePath; 0564 qCDebug(DIGIKAM_RAWENGINE_LOG) << m_parent->m_decoderSettings; 0565 0566 #ifdef Q_OS_WIN 0567 0568 int ret = raw->open_file((const wchar_t*)filePath.utf16()); 0569 0570 #else 0571 0572 int ret = raw->open_file(filePath.toUtf8().constData()); 0573 0574 #endif 0575 0576 if (ret != LIBRAW_SUCCESS) 0577 { 0578 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret); 0579 raw->recycle(); 0580 delete raw; 0581 0582 #ifdef USE_DNGSDK 0583 0584 delete dnghost; 0585 0586 #endif 0587 0588 return false; 0589 } 0590 0591 if (m_parent->m_cancel) 0592 { 0593 raw->recycle(); 0594 delete raw; 0595 0596 #ifdef USE_DNGSDK 0597 0598 delete dnghost; 0599 0600 #endif 0601 0602 return false; 0603 } 0604 0605 setProgress(0.2); 0606 0607 ret = raw->unpack(); 0608 0609 if (ret != LIBRAW_SUCCESS) 0610 { 0611 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret); 0612 raw->recycle(); 0613 delete raw; 0614 0615 #ifdef USE_DNGSDK 0616 0617 delete dnghost; 0618 0619 #endif 0620 0621 return false; 0622 } 0623 0624 if (m_parent->m_cancel) 0625 { 0626 raw->recycle(); 0627 delete raw; 0628 0629 #ifdef USE_DNGSDK 0630 0631 delete dnghost; 0632 0633 #endif 0634 0635 return false; 0636 } 0637 0638 setProgress(0.25); 0639 0640 if (m_parent->m_decoderSettings.fixColorsHighlights) 0641 { 0642 qCDebug(DIGIKAM_RAWENGINE_LOG) << "Applying LibRaw highlights adjustments"; 0643 0644 // 1.0 is fallback to default value 0645 0646 raw->imgdata.params.adjust_maximum_thr = 1.0; 0647 } 0648 else 0649 { 0650 qCDebug(DIGIKAM_RAWENGINE_LOG) << "Disabling LibRaw highlights adjustments"; 0651 0652 // 0.0 disables this feature 0653 0654 raw->imgdata.params.adjust_maximum_thr = 0.0; 0655 } 0656 0657 ret = raw->dcraw_process(); 0658 0659 if (ret != LIBRAW_SUCCESS) 0660 { 0661 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); 0662 raw->recycle(); 0663 delete raw; 0664 0665 #ifdef USE_DNGSDK 0666 0667 delete dnghost; 0668 0669 #endif 0670 0671 return false; 0672 } 0673 0674 if (m_parent->m_cancel) 0675 { 0676 raw->recycle(); 0677 delete raw; 0678 0679 #ifdef USE_DNGSDK 0680 0681 delete dnghost; 0682 0683 #endif 0684 0685 return false; 0686 } 0687 0688 setProgress(0.3); 0689 0690 libraw_processed_image_t* img = raw->dcraw_make_mem_image(&ret); 0691 0692 if (!img) 0693 { 0694 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); 0695 raw->recycle(); 0696 delete raw; 0697 0698 #ifdef USE_DNGSDK 0699 0700 delete dnghost; 0701 0702 #endif 0703 0704 return false; 0705 } 0706 0707 if (m_parent->m_cancel) 0708 { 0709 // Clear memory allocation. Introduced with LibRaw 0.11.0 0710 0711 raw->dcraw_clear_mem(img); 0712 raw->recycle(); 0713 delete raw; 0714 0715 #ifdef USE_DNGSDK 0716 0717 delete dnghost; 0718 0719 #endif 0720 0721 return false; 0722 } 0723 0724 setProgress(0.35); 0725 0726 width = img->width; 0727 height = img->height; 0728 rgbmax = (1 << img->bits)-1; 0729 0730 if (img->colors == 3) 0731 { 0732 imageData = QByteArray((const char*)img->data, (int)img->data_size); 0733 } 0734 else 0735 { 0736 // img->colors == 1 (Grayscale) : convert to RGB 0737 0738 imageData = QByteArray(); 0739 0740 for (int i = 0 ; i < (int)img->data_size ; ++i) 0741 { 0742 for (int j = 0 ; j < 3 ; ++j) 0743 { 0744 imageData.append(img->data[i]); 0745 } 0746 } 0747 } 0748 0749 // Clear memory allocation. Introduced with LibRaw 0.11.0 0750 0751 raw->dcraw_clear_mem(img); 0752 raw->recycle(); 0753 delete raw; 0754 0755 #ifdef USE_DNGSDK 0756 0757 delete dnghost; 0758 0759 #endif 0760 0761 if (m_parent->m_cancel) 0762 { 0763 return false; 0764 } 0765 0766 setProgress(0.4); 0767 0768 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: data info: width=" << width 0769 << " height=" << height 0770 << " rgbmax=" << rgbmax; 0771 0772 return true; 0773 } 0774 0775 bool DRawDecoder::Private::loadEmbeddedPreview(QByteArray& imgData, LibRaw* const raw) 0776 { 0777 int ret = raw->unpack_thumb(); 0778 0779 if (ret != LIBRAW_SUCCESS) 0780 { 0781 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run unpack_thumb: " << libraw_strerror(ret); 0782 raw->recycle(); 0783 delete raw; 0784 0785 return false; 0786 } 0787 0788 libraw_processed_image_t* const thumb = raw->dcraw_make_mem_thumb(&ret); 0789 0790 if (!thumb) 0791 { 0792 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_make_mem_thumb: " << libraw_strerror(ret); 0793 raw->recycle(); 0794 delete raw; 0795 0796 return false; 0797 } 0798 0799 if (thumb->type == LIBRAW_IMAGE_BITMAP) 0800 { 0801 createPPMHeader(imgData, thumb); 0802 } 0803 else 0804 { 0805 imgData = QByteArray((const char*)thumb->data, (int)thumb->data_size); 0806 } 0807 0808 // Clear memory allocation. Introduced with LibRaw 0.11.0 0809 0810 raw->dcraw_clear_mem(thumb); 0811 raw->recycle(); 0812 delete raw; 0813 0814 if (imgData.isEmpty()) 0815 { 0816 qCDebug(DIGIKAM_RAWENGINE_LOG) << "Failed to load JPEG thumb from LibRaw!"; 0817 return false; 0818 } 0819 0820 return true; 0821 } 0822 0823 bool DRawDecoder::Private::loadHalfPreview(QImage& image, LibRaw* const raw, bool rotate) 0824 { 0825 raw->imgdata.params.use_auto_wb = 1; // Use automatic white balance. 0826 raw->imgdata.params.use_camera_wb = 1; // Use camera white balance, if possible. 0827 raw->imgdata.params.half_size = 1; // Half-size color image (3x faster than -q). 0828 0829 if (!rotate) 0830 { 0831 raw->imgdata.params.user_flip = 0; 0832 } 0833 0834 #ifdef USE_DNGSDK 0835 0836 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: setup internal DNG SDK"; 0837 0838 raw->imgdata.rawparams.use_dngsdk = LIBRAW_DNG_ALL; 0839 dng_host* const dnghost = new dng_host; 0840 raw->set_dng_host(dnghost); 0841 0842 #endif 0843 0844 QByteArray imgData; 0845 0846 int ret = raw->unpack(); 0847 0848 if (ret != LIBRAW_SUCCESS) 0849 { 0850 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret); 0851 raw->recycle(); 0852 delete raw; 0853 0854 #ifdef USE_DNGSDK 0855 0856 delete dnghost; 0857 0858 #endif 0859 0860 return false; 0861 } 0862 0863 ret = raw->dcraw_process(); 0864 0865 if (ret != LIBRAW_SUCCESS) 0866 { 0867 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); 0868 raw->recycle(); 0869 delete raw; 0870 0871 #ifdef USE_DNGSDK 0872 0873 delete dnghost; 0874 0875 #endif 0876 0877 return false; 0878 } 0879 0880 libraw_processed_image_t* halfImg = raw->dcraw_make_mem_image(&ret); 0881 0882 if (!halfImg) 0883 { 0884 qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); 0885 raw->recycle(); 0886 delete raw; 0887 0888 #ifdef USE_DNGSDK 0889 0890 delete dnghost; 0891 0892 #endif 0893 0894 return false; 0895 } 0896 0897 Private::createPPMHeader(imgData, halfImg); 0898 0899 // Clear memory allocation. Introduced with LibRaw 0.11.0 0900 0901 raw->dcraw_clear_mem(halfImg); 0902 raw->recycle(); 0903 delete raw; 0904 0905 #ifdef USE_DNGSDK 0906 0907 delete dnghost; 0908 0909 #endif 0910 0911 if (imgData.isEmpty()) 0912 { 0913 qCDebug(DIGIKAM_RAWENGINE_LOG) << "Failed to load half preview from LibRaw!"; 0914 return false; 0915 } 0916 0917 if (!image.loadFromData(imgData)) 0918 { 0919 qCDebug(DIGIKAM_RAWENGINE_LOG) << "Failed to load PPM data from LibRaw!"; 0920 return false; 0921 } 0922 0923 return true; 0924 } 0925 0926 } // namespace Digikam