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