Coverage Report

Created: 2026-02-26 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libkdcraw/src/kdcraw.cpp
Line
Count
Source
1
/*
2
    SPDX-FileCopyrightText: 2006-2015 Gilles Caulier <caulier dot gilles at gmail dot com>
3
    SPDX-FileCopyrightText: 2006-2013 Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
4
    SPDX-FileCopyrightText: 2007-2008 Guillaume Castagnino <casta at xwing dot info>
5
6
    SPDX-License-Identifier: GPL-2.0-or-later
7
*/
8
9
#include "kdcraw.h"
10
#include "kdcraw_p.h"
11
12
// Qt includes
13
14
#include <QFile>
15
#include <QFileInfo>
16
#include <QStringList>
17
18
// LibRaw includes
19
20
#include <libraw_version.h>
21
22
#ifdef LIBRAW_HAS_CONFIG
23
#include <libraw_config.h>
24
#endif
25
26
// Local includes
27
28
#include "libkdcraw_debug.h"
29
#include "libkdcraw_version.h"
30
#include "rawfiles.h"
31
32
namespace KDcrawIface
33
{
34
35
KDcraw::KDcraw()
36
0
    : d(new KDcrawPrivate(this))
37
0
{
38
0
    m_cancel = false;
39
0
}
40
41
KDcraw::~KDcraw()
42
0
{
43
0
    cancel();
44
0
}
45
46
QString KDcraw::version()
47
0
{
48
0
    return QString::fromLatin1(KDCRAW_VERSION_STRING);
49
0
}
50
51
void KDcraw::cancel()
52
0
{
53
0
    m_cancel = true;
54
0
}
55
56
bool KDcraw::loadRawPreview(QImage& image, const QString& path)
57
0
{
58
    // In first, try to extract the embedded JPEG preview. Very fast.
59
0
    bool ret = loadEmbeddedPreview(image, path);
60
61
0
    if (ret)
62
0
        return true;
63
64
    // In second, decode and half size of RAW picture. More slow.
65
0
    return (loadHalfPreview(image, path));
66
0
}
67
68
bool KDcraw::loadEmbeddedPreview(QImage& image, const QString& path)
69
0
{
70
0
    QByteArray imgData;
71
72
0
    if ( loadEmbeddedPreview(imgData, path) )
73
0
    {
74
0
        qCDebug(LIBKDCRAW_LOG) << "Preview data size:" << imgData.size();
75
76
0
        if (image.loadFromData( imgData ))
77
0
        {
78
0
            qCDebug(LIBKDCRAW_LOG) << "Using embedded RAW preview extraction";
79
0
            return true;
80
0
        }
81
0
    }
82
83
0
    qCDebug(LIBKDCRAW_LOG) << "Failed to load embedded RAW preview";
84
0
    return false;
85
0
}
86
87
bool KDcraw::loadEmbeddedPreview(QByteArray& imgData, const QString& path)
88
689
{
89
689
    QFileInfo fileInfo(path);
90
689
    QString   rawFilesExt = QString::fromUtf8(rawFiles());
91
689
    QString   ext         = fileInfo.suffix().toUpper();
92
93
689
    if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext))
94
689
        return false;
95
96
0
    LibRaw raw;
97
98
0
    int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData());
99
100
0
    if (ret != LIBRAW_SUCCESS)
101
0
    {
102
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret);
103
0
        raw.recycle();
104
0
        return false;
105
0
    }
106
107
0
    return (KDcrawPrivate::loadEmbeddedPreview(imgData, raw));
108
0
}
109
110
bool KDcraw::loadEmbeddedPreview(QByteArray& imgData, const QBuffer& buffer)
111
0
{
112
0
    QString rawFilesExt = QString::fromUtf8(rawFiles());
113
0
    LibRaw  raw;
114
115
0
    QByteArray inData = buffer.data();
116
0
    int ret           = raw.open_buffer((void*) inData.data(), (size_t) inData.size());
117
118
0
    if (ret != LIBRAW_SUCCESS)
119
0
    {
120
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_buffer: " << libraw_strerror(ret);
121
0
        raw.recycle();
122
0
        return false;
123
0
    }
124
125
0
    return (KDcrawPrivate::loadEmbeddedPreview(imgData, raw));
126
0
}
127
128
bool KDcraw::loadHalfPreview(QImage& image, const QString& path)
129
0
{
130
0
    QFileInfo fileInfo(path);
131
0
    QString   rawFilesExt = QString::fromUtf8(rawFiles());
132
0
    QString   ext = fileInfo.suffix().toUpper();
133
134
0
    if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext))
135
0
        return false;
136
137
0
    qCDebug(LIBKDCRAW_LOG) << "Try to use reduced RAW picture extraction";
138
139
0
    LibRaw raw;
140
0
    raw.imgdata.params.use_auto_wb   = 1;         // Use automatic white balance.
141
0
    raw.imgdata.params.use_camera_wb = 1;         // Use camera white balance, if possible.
142
0
    raw.imgdata.params.half_size     = 1;         // Half-size color image (3x faster than -q).
143
144
0
    int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData());
145
146
0
    if (ret != LIBRAW_SUCCESS)
147
0
    {
148
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret);
149
0
        raw.recycle();
150
0
        return false;
151
0
    }
152
153
154
0
    if(!KDcrawPrivate::loadHalfPreview(image, raw))
155
0
    {
156
0
        qCDebug(LIBKDCRAW_LOG) << "Failed to get half preview from LibRaw!";
157
0
        return false;
158
0
    }
159
160
0
    qCDebug(LIBKDCRAW_LOG) << "Using reduced RAW picture extraction";
161
162
0
    return true;
163
0
}
164
165
bool KDcraw::loadHalfPreview(QByteArray& imgData, const QString& path)
166
0
{
167
0
    QFileInfo fileInfo(path);
168
0
    QString   rawFilesExt = QString::fromUtf8(rawFiles());
169
0
    QString   ext = fileInfo.suffix().toUpper();
170
171
0
    if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext))
172
0
        return false;
173
174
0
    qCDebug(LIBKDCRAW_LOG) << "Try to use reduced RAW picture extraction";
175
176
0
    LibRaw raw;
177
0
    int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData());
178
179
0
    if (ret != LIBRAW_SUCCESS)
180
0
    {
181
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret);
182
0
        raw.recycle();
183
0
        return false;
184
0
    }
185
186
0
    QImage image;
187
188
0
    if (!KDcrawPrivate::loadHalfPreview(image, raw))
189
0
    {
190
0
        qCDebug(LIBKDCRAW_LOG) << "KDcraw: failed to get half preview: " << libraw_strerror(ret);
191
0
        return false;
192
0
    }
193
194
0
    QBuffer buffer(&imgData);
195
0
    buffer.open(QIODevice::WriteOnly);
196
0
    image.save(&buffer, "JPEG"); 
197
198
0
    return true;
199
0
}
200
201
bool KDcraw::loadHalfPreview(QByteArray& imgData, const QBuffer& inBuffer)
202
0
{
203
0
    QString rawFilesExt = QString::fromUtf8(rawFiles());
204
0
    LibRaw  raw;
205
206
0
    QByteArray inData = inBuffer.data();
207
0
    int ret           = raw.open_buffer((void*) inData.data(), (size_t) inData.size());
208
209
0
    if (ret != LIBRAW_SUCCESS)
210
0
    {
211
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret);
212
0
        raw.recycle();
213
0
        return false;
214
0
    }
215
216
0
    QImage image;
217
218
0
    if (!KDcrawPrivate::loadHalfPreview(image, raw))
219
0
    {
220
0
        qCDebug(LIBKDCRAW_LOG) << "KDcraw: failed to get half preview: " << libraw_strerror(ret);
221
0
        return false;
222
0
    }
223
224
0
    QBuffer buffer(&imgData);
225
0
    buffer.open(QIODevice::WriteOnly);
226
0
    image.save(&buffer, "JPG"); 
227
228
0
    return true;
229
0
}
230
231
bool KDcraw::loadFullImage(QImage& image, const QString& path, const RawDecodingSettings& settings)
232
0
{
233
0
    QFileInfo fileInfo(path);
234
0
    QString   rawFilesExt = QString::fromUtf8(rawFiles());
235
0
    QString   ext         = fileInfo.suffix().toUpper();
236
237
0
    if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext))
238
0
        return false;
239
240
0
    qCDebug(LIBKDCRAW_LOG) << "Try to load full RAW picture...";
241
242
0
    RawDecodingSettings prm = settings;
243
0
    prm.sixteenBitsImage    = false;
244
0
    QByteArray imgData;
245
0
    int width, height, rgbmax;
246
247
0
    KDcraw decoder;
248
0
    bool ret = decoder.decodeRAWImage(path, prm, imgData, width, height, rgbmax);
249
250
0
    if (!ret)
251
0
    {
252
0
        qCDebug(LIBKDCRAW_LOG) << "Failed to load full RAW picture";
253
0
        return false;
254
0
    }
255
256
0
    uchar* sptr  = (uchar*)imgData.data();
257
0
    uchar tmp8[2];
258
259
    // Set RGB color components.
260
0
    for (int i = 0 ; i < width * height ; ++i)
261
0
    {
262
        // Swap Red and Blue
263
0
        tmp8[0] = sptr[2];
264
0
        tmp8[1] = sptr[0];
265
0
        sptr[0] = tmp8[0];
266
0
        sptr[2] = tmp8[1];
267
268
0
        sptr += 3;
269
0
    }
270
271
0
    image      = QImage(width, height, QImage::Format_ARGB32);
272
0
    uint* dptr = reinterpret_cast<uint*>(image.bits());
273
0
    sptr       = (uchar*)imgData.data();
274
275
0
    for (int i = 0 ; i < width * height ; ++i)
276
0
    {
277
0
        *dptr++ = qRgba(sptr[2], sptr[1], sptr[0], 0xFF);
278
0
        sptr += 3;
279
0
    }
280
281
0
    qCDebug(LIBKDCRAW_LOG) << "Load full RAW picture done";
282
283
0
    return true;
284
0
}
285
286
bool KDcraw::rawFileIdentify(DcrawInfoContainer& identify, const QString& path)
287
0
{
288
0
    QFileInfo fileInfo(path);
289
0
    QString rawFilesExt  = QString::fromUtf8(rawFiles());
290
0
    QString ext          = fileInfo.suffix().toUpper();
291
0
    identify.isDecodable = false;
292
293
0
    if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext))
294
0
        return false;
295
296
0
    LibRaw raw;
297
298
0
    int ret = raw.open_file((const char*)(QFile::encodeName(path)).constData());
299
300
0
    if (ret != LIBRAW_SUCCESS)
301
0
    {
302
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret);
303
0
        raw.recycle();
304
0
        return false;
305
0
    }
306
307
0
    ret = raw.adjust_sizes_info_only();
308
309
0
    if (ret != LIBRAW_SUCCESS)
310
0
    {
311
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run adjust_sizes_info_only: " << libraw_strerror(ret);
312
0
        raw.recycle();
313
0
        return false;
314
0
    }
315
316
0
    KDcrawPrivate::fillIndentifyInfo(&raw, identify);
317
0
    raw.recycle();
318
0
    return true;
319
0
}
320
321
// ----------------------------------------------------------------------------------
322
323
bool KDcraw::extractRAWData(const QString& filePath, QByteArray& rawData, DcrawInfoContainer& identify, unsigned int shotSelect)
324
0
{
325
0
    QFileInfo fileInfo(filePath);
326
0
    QString rawFilesExt  = QString::fromUtf8(rawFiles());
327
0
    QString ext          = fileInfo.suffix().toUpper();
328
0
    identify.isDecodable = false;
329
330
0
    if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext))
331
0
        return false;
332
333
0
    if (m_cancel)
334
0
        return false;
335
336
0
    d->setProgress(0.1);
337
338
0
    LibRaw raw;
339
    // Set progress call back function.
340
0
    raw.set_progress_handler(callbackForLibRaw, d.get());
341
342
0
    int ret = raw.open_file((const char*)(QFile::encodeName(filePath)).constData());
343
344
0
    if (ret != LIBRAW_SUCCESS)
345
0
    {
346
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret);
347
0
        raw.recycle();
348
0
        return false;
349
0
    }
350
351
0
    if (m_cancel)
352
0
    {
353
0
        raw.recycle();
354
0
        return false;
355
0
    }
356
357
0
    d->setProgress(0.3);
358
359
0
    raw.imgdata.params.output_bps  = 16;
360
0
#if LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 21)
361
0
    raw.imgdata.rawparams.shot_select = shotSelect;
362
#else
363
    raw.imgdata.params.shot_select = shotSelect;
364
#endif
365
0
    ret                            = raw.unpack();
366
367
0
    if (ret != LIBRAW_SUCCESS)
368
0
    {
369
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret);
370
0
        raw.recycle();
371
0
        return false;
372
0
    }
373
374
0
    if (m_cancel)
375
0
    {
376
0
        raw.recycle();
377
0
        return false;
378
0
    }
379
380
0
    d->setProgress(0.4);
381
382
0
    ret = raw.raw2image();
383
384
0
    if (ret != LIBRAW_SUCCESS)
385
0
    {
386
0
        qCDebug(LIBKDCRAW_LOG) << "LibRaw: failed to run raw2image: " << libraw_strerror(ret);
387
0
        raw.recycle();
388
0
        return false;
389
0
    }
390
391
0
    if (m_cancel)
392
0
    {
393
0
        raw.recycle();
394
0
        return false;
395
0
    }
396
397
0
    d->setProgress(0.6);
398
399
0
    KDcrawPrivate::fillIndentifyInfo(&raw, identify);
400
401
0
    if (m_cancel)
402
0
    {
403
0
        raw.recycle();
404
0
        return false;
405
0
    }
406
407
0
    d->setProgress(0.8);
408
409
0
    rawData = QByteArray();
410
411
0
    if (raw.imgdata.idata.filters == 0)
412
0
    {
413
0
        rawData.resize((int)(raw.imgdata.sizes.iwidth * raw.imgdata.sizes.iheight  * raw.imgdata.idata.colors * sizeof(unsigned short)));
414
415
0
        unsigned short* output = reinterpret_cast<unsigned short*>(rawData.data());
416
417
0
        for (unsigned int row = 0; row < raw.imgdata.sizes.iheight; row++)
418
0
        {
419
0
            for (unsigned int col = 0; col < raw.imgdata.sizes.iwidth; col++)
420
0
            {
421
0
                for (int color = 0; color < raw.imgdata.idata.colors; color++)
422
0
                {
423
0
                    *output = raw.imgdata.image[raw.imgdata.sizes.iwidth*row + col][color];
424
0
                    output++;
425
0
                }
426
0
            }
427
0
        }
428
0
    }
429
0
    else
430
0
    {
431
0
        rawData.resize((int)(raw.imgdata.sizes.iwidth * raw.imgdata.sizes.iheight * sizeof(unsigned short)));
432
433
0
        unsigned short* output = reinterpret_cast<unsigned short*>(rawData.data());
434
435
0
        for (uint row = 0; row < raw.imgdata.sizes.iheight; row++)
436
0
        {
437
0
            for (uint col = 0; col < raw.imgdata.sizes.iwidth; col++)
438
0
            {
439
0
                *output = raw.imgdata.image[raw.imgdata.sizes.iwidth*row + col][raw.COLOR(row, col)];
440
0
                output++;
441
0
            }
442
0
        }
443
0
    }
444
445
0
    raw.recycle();
446
0
    d->setProgress(1.0);
447
448
0
    return true;
449
0
}
450
451
bool KDcraw::decodeHalfRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings,
452
                                QByteArray& imageData, int& width, int& height, int& rgbmax)
453
0
{
454
0
    m_rawDecodingSettings                    = rawDecodingSettings;
455
0
    m_rawDecodingSettings.halfSizeColorImage = true;
456
0
    return (d->loadFromLibraw(filePath, imageData, width, height, rgbmax));
457
0
}
458
459
bool KDcraw::decodeRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings,
460
                            QByteArray& imageData, int& width, int& height, int& rgbmax)
461
0
{
462
0
    m_rawDecodingSettings = rawDecodingSettings;
463
0
    return (d->loadFromLibraw(filePath, imageData, width, height, rgbmax));
464
0
}
465
466
bool KDcraw::checkToCancelWaitingData()
467
0
{
468
0
    return m_cancel;
469
0
}
470
471
void KDcraw::setWaitingDataProgress(double)
472
0
{
473
0
}
474
475
const char* KDcraw::rawFiles()
476
689
{
477
689
    return raw_file_extentions;
478
689
}
479
480
QStringList KDcraw::rawFilesList()
481
0
{
482
0
    QString string = QString::fromLatin1(rawFiles());
483
0
    return string.remove(QLatin1String("*.")).split(QLatin1Char(' '));
484
0
}
485
486
int KDcraw::rawFilesVersion()
487
0
{
488
0
    return raw_file_extensions_version;
489
0
}
490
491
QStringList KDcraw::supportedCamera()
492
0
{
493
0
    QStringList camera;
494
0
    const char** const list = LibRaw::cameraList();
495
496
0
    for (int i = 0; i < LibRaw::cameraCount(); i++)
497
0
        camera.append(QString::fromUtf8(list[i]));
498
499
0
    return camera;
500
0
}
501
502
QString KDcraw::librawVersion()
503
0
{
504
0
    return QString::fromLatin1(LIBRAW_VERSION_STR).remove(QLatin1String("-Release"));
505
0
}
506
507
int KDcraw::librawUseGomp()
508
0
{
509
#ifdef LIBRAW_HAS_CONFIG
510
#   ifdef LIBRAW_USE_OPENMP
511
    return true;
512
#   else
513
    return false;
514
#   endif
515
#else
516
0
    return -1;
517
0
#endif
518
0
}
519
520
int KDcraw::librawUseRawSpeed()
521
0
{
522
#ifdef LIBRAW_HAS_CONFIG
523
#   ifdef LIBRAW_USE_RAWSPEED
524
    return true;
525
#   else
526
    return false;
527
#   endif
528
#else
529
0
    return -1;
530
0
#endif
531
0
}
532
533
int KDcraw::librawUseGPL2DemosaicPack()
534
0
{
535
#ifdef LIBRAW_HAS_CONFIG
536
#   ifdef LIBRAW_USE_DEMOSAIC_PACK_GPL2
537
    return true;
538
#   else
539
    return false;
540
#   endif
541
#else
542
0
    return -1;
543
0
#endif
544
0
}
545
546
int KDcraw::librawUseGPL3DemosaicPack()
547
0
{
548
#ifdef LIBRAW_HAS_CONFIG
549
#   ifdef LIBRAW_USE_DEMOSAIC_PACK_GPL3
550
    return true;
551
#   else
552
    return false;
553
#   endif
554
#else
555
0
    return -1;
556
0
#endif
557
0
}
558
559
}  // namespace KDcrawIface
560
561
#include "moc_kdcraw.cpp"