File indexing completed on 2024-04-28 15:50:41
0001 /* 0002 SPDX-FileCopyrightText: 2008-2015 Gilles Caulier <caulier dot gilles at gmail dot com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kdcraw.h" 0008 #include "kdcraw_p.h" 0009 0010 // Qt includes 0011 0012 #include <QString> 0013 #include <QFile> 0014 0015 // Local includes 0016 0017 #include "libkdcraw_debug.h" 0018 0019 namespace KDcrawIface 0020 { 0021 0022 int callbackForLibRaw(void* data, enum LibRaw_progress p, int iteration, int expected) 0023 { 0024 if (data) 0025 { 0026 KDcrawPrivate* const d = static_cast<KDcrawPrivate*>(data); 0027 0028 if (d) 0029 { 0030 return d->progressCallback(p, iteration, expected); 0031 } 0032 } 0033 0034 return 0; 0035 } 0036 0037 // -------------------------------------------------------------------------------------------------- 0038 0039 KDcrawPrivate::KDcrawPrivate(KDcraw* const p) 0040 : m_parent(p) 0041 { 0042 m_progress = 0.0; 0043 } 0044 0045 KDcrawPrivate::~KDcrawPrivate() = default; 0046 0047 void KDcrawPrivate::createPPMHeader(QByteArray& imgData, libraw_processed_image_t* const img) 0048 { 0049 QString header = QString::fromUtf8("P%1\n%2 %3\n%4\n").arg(img->colors == 3 ? QLatin1String("6") : QLatin1String("5")) 0050 .arg(img->width) 0051 .arg(img->height) 0052 .arg((1 << img->bits)-1); 0053 imgData.append(header.toLatin1()); 0054 imgData.append(QByteArray((const char*)img->data, (int)img->data_size)); 0055 } 0056 0057 int KDcrawPrivate::progressCallback(enum LibRaw_progress p, int iteration, int expected) 0058 { 0059 qCDebug(LIBKDCRAW_LOG) << "LibRaw progress: " << libraw_strprogress(p) << " pass " 0060 << iteration << " of " << expected; 0061 0062 // post a little change in progress indicator to show raw processor activity. 0063 setProgress(progressValue()+0.01); 0064 0065 // Clean processing termination by user... 0066 if (m_parent->checkToCancelWaitingData()) 0067 { 0068 qCDebug(LIBKDCRAW_LOG) << "LibRaw process termination invoked..."; 0069 m_parent->m_cancel = true; 0070 m_progress = 0.0; 0071 return 1; 0072 } 0073 0074 // Return 0 to continue processing... 0075 return 0; 0076 } 0077 0078 void KDcrawPrivate::setProgress(double value) 0079 { 0080 m_progress = value; 0081 m_parent->setWaitingDataProgress(m_progress); 0082 } 0083 0084 double KDcrawPrivate::progressValue() const 0085 { 0086 return m_progress; 0087 } 0088 0089 void KDcrawPrivate::fillIndentifyInfo(LibRaw* const raw, DcrawInfoContainer& identify) 0090 { 0091 identify.dateTime.setMSecsSinceEpoch(raw->imgdata.other.timestamp * 1000); 0092 identify.make = QString::fromUtf8(raw->imgdata.idata.make); 0093 identify.model = QString::fromUtf8(raw->imgdata.idata.model); 0094 identify.owner = QString::fromUtf8(raw->imgdata.other.artist); 0095 identify.DNGVersion = QString::number(raw->imgdata.idata.dng_version); 0096 identify.sensitivity = raw->imgdata.other.iso_speed; 0097 identify.exposureTime = raw->imgdata.other.shutter; 0098 identify.aperture = raw->imgdata.other.aperture; 0099 identify.focalLength = raw->imgdata.other.focal_len; 0100 identify.imageSize = QSize(raw->imgdata.sizes.width, raw->imgdata.sizes.height); 0101 identify.fullSize = QSize(raw->imgdata.sizes.raw_width, raw->imgdata.sizes.raw_height); 0102 identify.outputSize = QSize(raw->imgdata.sizes.iwidth, raw->imgdata.sizes.iheight); 0103 identify.thumbSize = QSize(raw->imgdata.thumbnail.twidth, raw->imgdata.thumbnail.theight); 0104 identify.topMargin = raw->imgdata.sizes.top_margin; 0105 identify.leftMargin = raw->imgdata.sizes.left_margin; 0106 identify.hasIccProfile = raw->imgdata.color.profile ? true : false; 0107 identify.isDecodable = true; 0108 identify.pixelAspectRatio = raw->imgdata.sizes.pixel_aspect; 0109 identify.rawColors = raw->imgdata.idata.colors; 0110 identify.rawImages = raw->imgdata.idata.raw_count; 0111 identify.blackPoint = raw->imgdata.color.black; 0112 0113 for (int ch = 0; ch < 4; ch++) 0114 { 0115 identify.blackPointCh[ch] = raw->imgdata.color.cblack[ch]; 0116 } 0117 0118 identify.whitePoint = raw->imgdata.color.maximum; 0119 identify.orientation = (DcrawInfoContainer::ImageOrientation)raw->imgdata.sizes.flip; 0120 0121 memcpy(&identify.cameraColorMatrix1, &raw->imgdata.color.cmatrix, sizeof(raw->imgdata.color.cmatrix)); 0122 memcpy(&identify.cameraColorMatrix2, &raw->imgdata.color.rgb_cam, sizeof(raw->imgdata.color.rgb_cam)); 0123 memcpy(&identify.cameraXYZMatrix, &raw->imgdata.color.cam_xyz, sizeof(raw->imgdata.color.cam_xyz)); 0124 0125 if (raw->imgdata.idata.filters) 0126 { 0127 if (!raw->imgdata.idata.cdesc[3]) 0128 { 0129 raw->imgdata.idata.cdesc[3] = 'G'; 0130 } 0131 0132 for (int i=0; i < 16; i++) 0133 { 0134 identify.filterPattern.append(QChar::fromLatin1(raw->imgdata.idata.cdesc[raw->COLOR(i >> 1, i & 1)])); 0135 } 0136 0137 identify.colorKeys = QString::fromLatin1(raw->imgdata.idata.cdesc); 0138 } 0139 0140 for(int c = 0 ; c < raw->imgdata.idata.colors ; c++) 0141 { 0142 identify.daylightMult[c] = raw->imgdata.color.pre_mul[c]; 0143 } 0144 0145 if (raw->imgdata.color.cam_mul[0] > 0) 0146 { 0147 for(int c = 0 ; c < 4 ; c++) 0148 { 0149 identify.cameraMult[c] = raw->imgdata.color.cam_mul[c]; 0150 } 0151 } 0152 } 0153 0154 bool KDcrawPrivate::loadFromLibraw(const QString& filePath, QByteArray& imageData, 0155 int& width, int& height, int& rgbmax) 0156 { 0157 m_parent->m_cancel = false; 0158 0159 LibRaw raw; 0160 // Set progress call back function. 0161 raw.set_progress_handler(callbackForLibRaw, this); 0162 0163 QByteArray deadpixelPath = QFile::encodeName(m_parent->m_rawDecodingSettings.deadPixelMap); 0164 QByteArray cameraProfile = QFile::encodeName(m_parent->m_rawDecodingSettings.inputProfile); 0165 QByteArray outputProfile = QFile::encodeName(m_parent->m_rawDecodingSettings.outputProfile); 0166 0167 if (!m_parent->m_rawDecodingSettings.autoBrightness) 0168 { 0169 // Use a fixed white level, ignoring the image histogram. 0170 raw.imgdata.params.no_auto_bright = 1; 0171 } 0172 0173 if (m_parent->m_rawDecodingSettings.sixteenBitsImage) 0174 { 0175 // (-4) 16bit ppm output 0176 raw.imgdata.params.output_bps = 16; 0177 } 0178 0179 if (m_parent->m_rawDecodingSettings.halfSizeColorImage) 0180 { 0181 // (-h) Half-size color image (3x faster than -q). 0182 raw.imgdata.params.half_size = 1; 0183 } 0184 0185 if (m_parent->m_rawDecodingSettings.RGBInterpolate4Colors) 0186 { 0187 // (-f) Interpolate RGB as four colors. 0188 raw.imgdata.params.four_color_rgb = 1; 0189 } 0190 0191 if (m_parent->m_rawDecodingSettings.DontStretchPixels) 0192 { 0193 // (-j) Do not stretch the image to its correct aspect ratio. 0194 raw.imgdata.params.use_fuji_rotate = 1; 0195 } 0196 0197 // (-H) Unclip highlight color. 0198 raw.imgdata.params.highlight = m_parent->m_rawDecodingSettings.unclipColors; 0199 0200 if (m_parent->m_rawDecodingSettings.brightness != 1.0) 0201 { 0202 // (-b) Set Brightness value. 0203 raw.imgdata.params.bright = m_parent->m_rawDecodingSettings.brightness; 0204 } 0205 0206 if (m_parent->m_rawDecodingSettings.enableBlackPoint) 0207 { 0208 // (-k) Set Black Point value. 0209 raw.imgdata.params.user_black = m_parent->m_rawDecodingSettings.blackPoint; 0210 } 0211 0212 if (m_parent->m_rawDecodingSettings.enableWhitePoint) 0213 { 0214 // (-S) Set White Point value (saturation). 0215 raw.imgdata.params.user_sat = m_parent->m_rawDecodingSettings.whitePoint; 0216 } 0217 0218 if (m_parent->m_rawDecodingSettings.medianFilterPasses > 0) 0219 { 0220 // (-m) After interpolation, clean up color artifacts by repeatedly applying a 3x3 median filter to the R-G and B-G channels. 0221 raw.imgdata.params.med_passes = m_parent->m_rawDecodingSettings.medianFilterPasses; 0222 } 0223 0224 if (!m_parent->m_rawDecodingSettings.deadPixelMap.isEmpty()) 0225 { 0226 // (-P) Read the dead pixel list from this file. 0227 raw.imgdata.params.bad_pixels = deadpixelPath.data(); 0228 } 0229 0230 switch (m_parent->m_rawDecodingSettings.whiteBalance) 0231 { 0232 case RawDecodingSettings::NONE: 0233 { 0234 break; 0235 } 0236 case RawDecodingSettings::CAMERA: 0237 { 0238 // (-w) Use camera white balance, if possible. 0239 raw.imgdata.params.use_camera_wb = 1; 0240 break; 0241 } 0242 case RawDecodingSettings::AUTO: 0243 { 0244 // (-a) Use automatic white balance. 0245 raw.imgdata.params.use_auto_wb = 1; 0246 break; 0247 } 0248 case RawDecodingSettings::CUSTOM: 0249 { 0250 /* Convert between Temperature and RGB. 0251 */ 0252 double T; 0253 double RGB[3]; 0254 double xD, yD, X, Y, Z; 0255 DcrawInfoContainer identify; 0256 T = m_parent->m_rawDecodingSettings.customWhiteBalance; 0257 0258 /* Here starts the code picked and adapted from ufraw (0.12.1) 0259 to convert Temperature + green multiplier to RGB multipliers 0260 */ 0261 /* Convert between Temperature and RGB. 0262 * Base on information from http://www.brucelindbloom.com/ 0263 * The fit for D-illuminant between 4000K and 12000K are from CIE 0264 * The generalization to 2000K < T < 4000K and the blackbody fits 0265 * are my own and should be taken with a grain of salt. 0266 */ 0267 const double XYZ_to_RGB[3][3] = { 0268 { 3.24071, -0.969258, 0.0556352 }, 0269 {-1.53726, 1.87599, -0.203996 }, 0270 {-0.498571, 0.0415557, 1.05707 } 0271 }; 0272 0273 // Fit for CIE Daylight illuminant 0274 if (T <= 4000) 0275 { 0276 xD = 0.27475e9/(T*T*T) - 0.98598e6/(T*T) + 1.17444e3/T + 0.145986; 0277 } 0278 else if (T <= 7000) 0279 { 0280 xD = -4.6070e9/(T*T*T) + 2.9678e6/(T*T) + 0.09911e3/T + 0.244063; 0281 } 0282 else 0283 { 0284 xD = -2.0064e9/(T*T*T) + 1.9018e6/(T*T) + 0.24748e3/T + 0.237040; 0285 } 0286 0287 yD = -3*xD*xD + 2.87*xD - 0.275; 0288 X = xD/yD; 0289 Y = 1; 0290 Z = (1-xD-yD)/yD; 0291 RGB[0] = X*XYZ_to_RGB[0][0] + Y*XYZ_to_RGB[1][0] + Z*XYZ_to_RGB[2][0]; 0292 RGB[1] = X*XYZ_to_RGB[0][1] + Y*XYZ_to_RGB[1][1] + Z*XYZ_to_RGB[2][1]; 0293 RGB[2] = X*XYZ_to_RGB[0][2] + Y*XYZ_to_RGB[1][2] + Z*XYZ_to_RGB[2][2]; 0294 /* End of the code picked to ufraw 0295 */ 0296 0297 RGB[1] = RGB[1] / m_parent->m_rawDecodingSettings.customWhiteBalanceGreen; 0298 0299 /* By default, decraw override his default D65 WB 0300 We need to keep it as a basis : if not, colors with some 0301 DSLR will have a high dominant of color that will lead to 0302 a completely wrong WB 0303 */ 0304 if (KDcraw::rawFileIdentify(identify, filePath)) 0305 { 0306 RGB[0] = identify.daylightMult[0] / RGB[0]; 0307 RGB[1] = identify.daylightMult[1] / RGB[1]; 0308 RGB[2] = identify.daylightMult[2] / RGB[2]; 0309 } 0310 else 0311 { 0312 RGB[0] = 1.0 / RGB[0]; 0313 RGB[1] = 1.0 / RGB[1]; 0314 RGB[2] = 1.0 / RGB[2]; 0315 qCDebug(LIBKDCRAW_LOG) << "Warning: cannot get daylight multipliers"; 0316 } 0317 0318 // (-r) set Raw Color Balance Multipliers. 0319 raw.imgdata.params.user_mul[0] = RGB[0]; 0320 raw.imgdata.params.user_mul[1] = RGB[1]; 0321 raw.imgdata.params.user_mul[2] = RGB[2]; 0322 raw.imgdata.params.user_mul[3] = RGB[1]; 0323 break; 0324 } 0325 case RawDecodingSettings::AERA: 0326 { 0327 // (-A) Calculate the white balance by averaging a rectangular area from image. 0328 raw.imgdata.params.greybox[0] = m_parent->m_rawDecodingSettings.whiteBalanceArea.left(); 0329 raw.imgdata.params.greybox[1] = m_parent->m_rawDecodingSettings.whiteBalanceArea.top(); 0330 raw.imgdata.params.greybox[2] = m_parent->m_rawDecodingSettings.whiteBalanceArea.width(); 0331 raw.imgdata.params.greybox[3] = m_parent->m_rawDecodingSettings.whiteBalanceArea.height(); 0332 break; 0333 } 0334 } 0335 0336 // (-q) Use an interpolation method. 0337 raw.imgdata.params.user_qual = m_parent->m_rawDecodingSettings.RAWQuality; 0338 0339 switch (m_parent->m_rawDecodingSettings.NRType) 0340 { 0341 case RawDecodingSettings::WAVELETSNR: 0342 { 0343 // (-n) Use wavelets to erase noise while preserving real detail. 0344 raw.imgdata.params.threshold = m_parent->m_rawDecodingSettings.NRThreshold; 0345 break; 0346 } 0347 case RawDecodingSettings::FBDDNR: 0348 { 0349 // (100 - 1000) => (1 - 10) conversion 0350 raw.imgdata.params.fbdd_noiserd = lround(m_parent->m_rawDecodingSettings.NRThreshold / 100.0); 0351 break; 0352 } 0353 #if !LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 19) 0354 case RawDecodingSettings::LINENR: 0355 { 0356 // (100 - 1000) => (0.001 - 0.02) conversion. 0357 raw.imgdata.params.linenoise = m_parent->m_rawDecodingSettings.NRThreshold * 2.11E-5 + 0.00111111; 0358 raw.imgdata.params.cfaline = true; 0359 break; 0360 } 0361 0362 case RawDecodingSettings::IMPULSENR: 0363 { 0364 // (100 - 1000) => (0.005 - 0.05) conversion. 0365 raw.imgdata.params.lclean = m_parent->m_rawDecodingSettings.NRThreshold * 5E-5; 0366 raw.imgdata.params.cclean = m_parent->m_rawDecodingSettings.NRChroThreshold * 5E-5; 0367 raw.imgdata.params.cfa_clean = true; 0368 break; 0369 } 0370 #endif 0371 default: // No Noise Reduction 0372 { 0373 raw.imgdata.params.threshold = 0; 0374 raw.imgdata.params.fbdd_noiserd = 0; 0375 #if !LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 19) 0376 raw.imgdata.params.linenoise = 0; 0377 raw.imgdata.params.cfaline = false; 0378 raw.imgdata.params.lclean = 0; 0379 raw.imgdata.params.cclean = 0; 0380 raw.imgdata.params.cfa_clean = false; 0381 #endif 0382 break; 0383 } 0384 } 0385 0386 #if !LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 19) 0387 // Chromatic aberration correction. 0388 raw.imgdata.params.ca_correc = m_parent->m_rawDecodingSettings.enableCACorrection; 0389 raw.imgdata.params.cared = m_parent->m_rawDecodingSettings.caMultiplier[0]; 0390 raw.imgdata.params.cablue = m_parent->m_rawDecodingSettings.caMultiplier[1]; 0391 #endif 0392 0393 // Exposure Correction before interpolation. 0394 raw.imgdata.params.exp_correc = m_parent->m_rawDecodingSettings.expoCorrection; 0395 raw.imgdata.params.exp_shift = m_parent->m_rawDecodingSettings.expoCorrectionShift; 0396 raw.imgdata.params.exp_preser = m_parent->m_rawDecodingSettings.expoCorrectionHighlight; 0397 0398 switch (m_parent->m_rawDecodingSettings.inputColorSpace) 0399 { 0400 case RawDecodingSettings::EMBEDDED: 0401 { 0402 // (-p embed) Use input profile from RAW file to define the camera's raw colorspace. 0403 raw.imgdata.params.camera_profile = (char*)"embed"; 0404 break; 0405 } 0406 case RawDecodingSettings::CUSTOMINPUTCS: 0407 { 0408 if (!m_parent->m_rawDecodingSettings.inputProfile.isEmpty()) 0409 { 0410 // (-p) Use input profile file to define the camera's raw colorspace. 0411 raw.imgdata.params.camera_profile = cameraProfile.data(); 0412 } 0413 break; 0414 } 0415 default: 0416 { 0417 // No input profile 0418 break; 0419 } 0420 } 0421 0422 switch (m_parent->m_rawDecodingSettings.outputColorSpace) 0423 { 0424 case RawDecodingSettings::CUSTOMOUTPUTCS: 0425 { 0426 if (!m_parent->m_rawDecodingSettings.outputProfile.isEmpty()) 0427 { 0428 // (-o) Use ICC profile file to define the output colorspace. 0429 raw.imgdata.params.output_profile = outputProfile.data(); 0430 } 0431 break; 0432 } 0433 default: 0434 { 0435 // (-o) Define the output colorspace. 0436 raw.imgdata.params.output_color = m_parent->m_rawDecodingSettings.outputColorSpace; 0437 break; 0438 } 0439 } 0440 0441 //-- Extended demosaicing settings ---------------------------------------------------------- 0442 0443 raw.imgdata.params.dcb_iterations = m_parent->m_rawDecodingSettings.dcbIterations; 0444 raw.imgdata.params.dcb_enhance_fl = m_parent->m_rawDecodingSettings.dcbEnhanceFl; 0445 #if !LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 19) 0446 raw.imgdata.params.eeci_refine = m_parent->m_rawDecodingSettings.eeciRefine; 0447 raw.imgdata.params.es_med_passes = m_parent->m_rawDecodingSettings.esMedPasses; 0448 #endif 0449 0450 //------------------------------------------------------------------------------------------- 0451 0452 setProgress(0.1); 0453 0454 qCDebug(LIBKDCRAW_LOG) << filePath; 0455 qCDebug(LIBKDCRAW_LOG) << m_parent->m_rawDecodingSettings; 0456 0457 int ret = raw.open_file((const char*)(QFile::encodeName(filePath)).constData()); 0458 0459 if (ret != LIBRAW_SUCCESS) 0460 { 0461 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret); 0462 raw.recycle(); 0463 return false; 0464 } 0465 0466 if (m_parent->m_cancel) 0467 { 0468 raw.recycle(); 0469 return false; 0470 } 0471 0472 setProgress(0.2); 0473 0474 ret = raw.unpack(); 0475 0476 if (ret != LIBRAW_SUCCESS) 0477 { 0478 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret); 0479 raw.recycle(); 0480 return false; 0481 } 0482 0483 if (m_parent->m_cancel) 0484 { 0485 raw.recycle(); 0486 return false; 0487 } 0488 0489 setProgress(0.25); 0490 0491 if (m_parent->m_rawDecodingSettings.fixColorsHighlights) 0492 { 0493 qCDebug(LIBKDCRAW_LOG) << "Applying LibRaw highlights adjustments"; 0494 // 1.0 is fallback to default value 0495 raw.imgdata.params.adjust_maximum_thr = 1.0; 0496 } 0497 else 0498 { 0499 qCDebug(LIBKDCRAW_LOG) << "Disabling LibRaw highlights adjustments"; 0500 // 0.0 disables this feature 0501 raw.imgdata.params.adjust_maximum_thr = 0.0; 0502 } 0503 0504 ret = raw.dcraw_process(); 0505 0506 if (ret != LIBRAW_SUCCESS) 0507 { 0508 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); 0509 raw.recycle(); 0510 return false; 0511 } 0512 0513 if (m_parent->m_cancel) 0514 { 0515 raw.recycle(); 0516 return false; 0517 } 0518 0519 setProgress(0.3); 0520 0521 libraw_processed_image_t* img = raw.dcraw_make_mem_image(&ret); 0522 0523 if(!img) 0524 { 0525 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); 0526 raw.recycle(); 0527 return false; 0528 } 0529 0530 if (m_parent->m_cancel) 0531 { 0532 // Clear memory allocation. Introduced with LibRaw 0.11.0 0533 raw.dcraw_clear_mem(img); 0534 raw.recycle(); 0535 return false; 0536 } 0537 0538 setProgress(0.35); 0539 0540 width = img->width; 0541 height = img->height; 0542 rgbmax = (1 << img->bits)-1; 0543 0544 if (img->colors == 3) 0545 { 0546 imageData = QByteArray((const char*)img->data, (int)img->data_size); 0547 } 0548 else 0549 { 0550 // img->colors == 1 (Grayscale) : convert to RGB 0551 imageData = QByteArray(); 0552 0553 for (int i = 0 ; i < (int)img->data_size ; ++i) 0554 { 0555 for (int j = 0 ; j < 3 ; ++j) 0556 { 0557 imageData.append(img->data[i]); 0558 } 0559 } 0560 } 0561 0562 // Clear memory allocation. Introduced with LibRaw 0.11.0 0563 raw.dcraw_clear_mem(img); 0564 raw.recycle(); 0565 0566 if (m_parent->m_cancel) 0567 { 0568 return false; 0569 } 0570 0571 setProgress(0.4); 0572 0573 qCDebug(LIBKDCRAW_LOG) << "LibRaw: data info: width=" << width 0574 << " height=" << height 0575 << " rgbmax=" << rgbmax; 0576 0577 return true; 0578 } 0579 0580 bool KDcrawPrivate::loadEmbeddedPreview(QByteArray& imgData, LibRaw& raw) 0581 { 0582 int ret = raw.unpack_thumb(); 0583 0584 if (ret != LIBRAW_SUCCESS) 0585 { 0586 raw.recycle(); 0587 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run unpack_thumb: " << libraw_strerror(ret); 0588 raw.recycle(); 0589 return false; 0590 } 0591 0592 libraw_processed_image_t* const thumb = raw.dcraw_make_mem_thumb(&ret); 0593 0594 if(!thumb) 0595 { 0596 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_make_mem_thumb: " << libraw_strerror(ret); 0597 raw.recycle(); 0598 return false; 0599 } 0600 0601 if(thumb->type == LIBRAW_IMAGE_BITMAP) 0602 { 0603 createPPMHeader(imgData, thumb); 0604 } 0605 else 0606 { 0607 imgData = QByteArray((const char*)thumb->data, (int)thumb->data_size); 0608 } 0609 0610 // Clear memory allocation. Introduced with LibRaw 0.11.0 0611 raw.dcraw_clear_mem(thumb); 0612 raw.recycle(); 0613 0614 if ( imgData.isEmpty() ) 0615 { 0616 qCDebug(LIBKDCRAW_LOG) << "Failed to load JPEG thumb from LibRaw!"; 0617 return false; 0618 } 0619 0620 return true; 0621 } 0622 0623 bool KDcrawPrivate::loadHalfPreview(QImage& image, LibRaw& raw) 0624 { 0625 raw.imgdata.params.use_auto_wb = 1; // Use automatic white balance. 0626 raw.imgdata.params.use_camera_wb = 1; // Use camera white balance, if possible. 0627 raw.imgdata.params.half_size = 1; // Half-size color image (3x faster than -q). 0628 QByteArray imgData; 0629 0630 int ret = raw.unpack(); 0631 0632 if (ret != LIBRAW_SUCCESS) 0633 { 0634 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret); 0635 raw.recycle(); 0636 return false; 0637 } 0638 0639 ret = raw.dcraw_process(); 0640 0641 if (ret != LIBRAW_SUCCESS) 0642 { 0643 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); 0644 raw.recycle(); 0645 return false; 0646 } 0647 0648 libraw_processed_image_t* halfImg = raw.dcraw_make_mem_image(&ret); 0649 0650 if(!halfImg) 0651 { 0652 qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); 0653 raw.recycle(); 0654 return false; 0655 } 0656 0657 KDcrawPrivate::createPPMHeader(imgData, halfImg); 0658 // Clear memory allocation. Introduced with LibRaw 0.11.0 0659 raw.dcraw_clear_mem(halfImg); 0660 raw.recycle(); 0661 0662 if ( imgData.isEmpty() ) 0663 { 0664 qCDebug(LIBKDCRAW_LOG) << "Failed to load half preview from LibRaw!"; 0665 return false; 0666 } 0667 0668 if (!image.loadFromData(imgData)) 0669 { 0670 qCDebug(LIBKDCRAW_LOG) << "Failed to load PPM data from LibRaw!"; 0671 return false; 0672 } 0673 0674 return true; 0675 } 0676 0677 } // namespace KDcrawIface