File indexing completed on 2025-01-05 03:56:02

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-09-25
0007  * Description : a tool to convert RAW file to DNG
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 "dngwriter_p.h"
0016 
0017 // C++ includes
0018 
0019 #include <cstdio>
0020 
0021 // Qt includes
0022 
0023 #include <QFile>
0024 
0025 // KDE includes
0026 
0027 #include "digikam_debug.h"
0028 
0029 // Local includes
0030 
0031 #include "dngwriter.h"
0032 #include "dngwriterhost.h"
0033 
0034 namespace Digikam
0035 {
0036 
0037 DNGWriter::Private::Private(DNGWriter* const dd)
0038     : parent      (dd),
0039       bayerPattern(Unknown),
0040       filter      (0),
0041       metaLoaded  (false),
0042       activeWidth (0),
0043       activeHeight(0),
0044       outputHeight(0),
0045       outputWidth (0),
0046       width       (0),
0047       height      (0),
0048       exif        (nullptr)
0049 {
0050     reset();
0051 }
0052 
0053 DNGWriter::Private::~Private()
0054 {
0055 }
0056 
0057 void DNGWriter::Private::reset()
0058 {
0059     cancel                  = false;
0060     jpegLossLessCompression = true;
0061     updateFileDate          = false;
0062     backupOriginalRawFile   = false;
0063     previewMode             = DNGWriter::FULL_SIZE;
0064 }
0065 
0066 void DNGWriter::Private::cleanup()
0067 {
0068     if (::remove(QFile::encodeName(outputFile).constData()) != 0)
0069     {
0070         qCDebug(DIGIKAM_GENERAL_LOG) << "Cannot remove " << outputFile;
0071     }
0072 }
0073 
0074 dng_date_time DNGWriter::Private::dngDateTime(const QDateTime& qDT) const
0075 {
0076     dng_date_time dngDT;
0077     dngDT.fYear   = qDT.date().year();
0078     dngDT.fMonth  = qDT.date().month();
0079     dngDT.fDay    = qDT.date().day();
0080     dngDT.fHour   = qDT.time().hour();
0081     dngDT.fMinute = qDT.time().minute();
0082     dngDT.fSecond = qDT.time().second();
0083 
0084     return dngDT;
0085 }
0086 
0087 bool DNGWriter::Private::fujiRotate(QByteArray& rawData, DRawInfo& identify) const
0088 {
0089     QByteArray tmpData(rawData);
0090     int height             = identify.outputSize.height();
0091     int width              = identify.outputSize.width();
0092     unsigned short* tmp    = reinterpret_cast<unsigned short*>(tmpData.data());
0093     unsigned short* output = reinterpret_cast<unsigned short*>(rawData.data());
0094 
0095     for (int row = 0 ; row < height ; ++row)
0096     {
0097         for (int col = 0 ; col < width ; ++col)
0098         {
0099             output[col * height + row] = tmp[row * width + col];
0100         }
0101     }
0102 
0103     identify.orientation = DRawInfo::ORIENTATION_Mirror90CCW;
0104     identify.outputSize  = QSize(height, width);
0105 
0106     // TODO: rotate margins
0107 
0108     return true;
0109 }
0110 
0111 QString DNGWriter::Private::dngErrorCodeToString(int errorCode) const
0112 {
0113     switch (errorCode)
0114     {
0115         default:
0116         case 100000: return QLatin1String("Unknown error");
0117 
0118         case 100003: return QLatin1String("Processing stopped by user (or host application) request");
0119 
0120         case 100004: return QLatin1String("Necessary host functionality is not present");
0121 
0122         case 100005: return QLatin1String("Out of memory");
0123 
0124         case 100006: return QLatin1String("File format is not valid");
0125 
0126         case 100007: return QLatin1String("Matrix has wrong shape, is badly conditioned, or similar problem");
0127 
0128         case 100008: return QLatin1String("Could not open file");
0129 
0130         case 100009: return QLatin1String("Error reading file");
0131 
0132         case 100010: return QLatin1String("Error writing file");
0133 
0134         case 100011: return QLatin1String("Unexpected end of file");
0135 
0136         case 100012: return QLatin1String("File is damaged in some way");
0137 
0138         case 100013: return QLatin1String("Image is too big to save as DNG");
0139 
0140         case 100014: return QLatin1String("Image is too big to save as TIFF");
0141 
0142         case 100015: return QLatin1String("DNG version is unsupported");
0143     }
0144 }
0145 
0146 QString DNGWriter::Private::dngBayerPatternToString(int pattern) const
0147 {
0148     switch (pattern)
0149     {
0150         case LinearRaw:
0151         {
0152             return QLatin1String("Bayer Linear Raw Pattern Mosaic");
0153         }
0154 
0155         case Standard:
0156         {
0157             return QLatin1String("Bayer Standard Pattern Mosaic");
0158         }
0159 
0160         case Fuji:
0161         {
0162             return QLatin1String("Bayer Fuji Pattern Mosaic");
0163         }
0164 
0165         case Fuji6x6:
0166         {
0167             return QLatin1String("Bayer Fuji 6x6 Pattern Mosaic");
0168         }
0169 
0170         case FourColor:
0171         {
0172             return QLatin1String("Bayer Four Color Pattern Mosaic");
0173         }
0174 
0175         default:    // Unknown
0176         {
0177             return QLatin1String("Bayer Unknown Pattern Mosaic");
0178         }
0179     }
0180 }
0181 
0182 int DNGWriter::Private::debugExtractedRAWData(const QByteArray& rawData)
0183 {
0184     QString   rawdataFilePath(inputInfo.completeBaseName() + QLatin1String(".dat"));
0185     QFileInfo rawdataInfo(rawdataFilePath);
0186 
0187     QFile rawdataFile(rawdataFilePath);
0188 
0189     if (!rawdataFile.open(QIODevice::WriteOnly))
0190     {
0191         qCDebug(DIGIKAM_GENERAL_LOG) << "DNGWriter: Cannot open file to write RAW data. Aborted..." ;
0192         return PROCESS_FAILED;
0193     }
0194 
0195     QDataStream rawdataStream(&rawdataFile);
0196     rawdataStream.writeRawData(rawData.data(), rawData.size());
0197     rawdataFile.close();
0198 
0199     return PROCESS_CONTINUE;
0200 }
0201 
0202 } // namespace Digikam