File indexing completed on 2025-01-05 03:56:01
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 - Makernotes storage. 0008 * 0009 * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2010-2011 by Jens Mueller <tschenser at gmx dot de> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "dngwriter_p.h" 0017 0018 // Local includes 0019 0020 #include "dngwriterhost.h" 0021 0022 namespace Digikam 0023 { 0024 0025 int DNGWriter::Private::storeMakernote(DNGWriterHost& host, 0026 AutoPtr<dng_negative>& negative, 0027 DRawInfo* const identify, 0028 DRawInfo* const identifyMake, 0029 DMetadata* const meta) 0030 { 0031 if (metaLoaded) // We only process Makernote storage if Metadata can be loaded at Exif stage. 0032 { 0033 qCDebug(DIGIKAM_GENERAL_LOG) << "DNGWriter: Updating Makernote metadata to DNG Negative"; 0034 0035 backportNikonMakerNote(meta); 0036 backportCanonMakerNote(meta); 0037 backportPentaxMakerNote(meta); 0038 backportOlympusMakerNote(meta); 0039 backportPanasonicMakerNote(meta); 0040 backportSonyMakerNote(meta); 0041 storeLensInformation(); 0042 backupMakernote(host, negative, identify, identifyMake, meta); 0043 } 0044 0045 if (cancel) 0046 { 0047 return PROCESS_CANCELED; 0048 } 0049 0050 return PROCESS_CONTINUE; 0051 } 0052 0053 void DNGWriter::Private::backportNikonMakerNote(DMetadata* const meta) 0054 { 0055 QString str; 0056 long int num, den; 0057 long val; 0058 0059 if (meta->getExifTagRational("Exif.Nikon3.Lens", num, den, 0)) exif->fLensInfo[0] = dng_urational(num, den); 0060 if (meta->getExifTagRational("Exif.Nikon3.Lens", num, den, 1)) exif->fLensInfo[1] = dng_urational(num, den); 0061 if (meta->getExifTagRational("Exif.Nikon3.Lens", num, den, 2)) exif->fLensInfo[2] = dng_urational(num, den); 0062 if (meta->getExifTagRational("Exif.Nikon3.Lens", num, den, 3)) exif->fLensInfo[3] = dng_urational(num, den); 0063 if (meta->getExifTagLong("Exif.Nikon3.ISOSpeed", val, 1)) exif->fISOSpeedRatings[1] = (uint32)val; 0064 0065 str = meta->getExifTagString("Exif.Nikon3.SerialNO"); 0066 if (!str.isEmpty()) str = str.replace(QLatin1String("NO="), QLatin1String("")); 0067 if (!str.isEmpty()) exif->fCameraSerialNumber.Set_ASCII(str.trimmed().toLatin1().constData()); 0068 0069 str = meta->getExifTagString("Exif.Nikon3.SerialNumber"); 0070 if (!str.isEmpty()) exif->fCameraSerialNumber.Set_ASCII(str.toLatin1().constData()); 0071 0072 if (meta->getExifTagLong("Exif.Nikon3.ShutterCount", val)) exif->fImageNumber = (uint32)val; 0073 if (meta->getExifTagLong("Exif.NikonLd1.LensIDNumber", val)) exif->fLensID.Set_ASCII((QString::fromUtf8("%1").arg(val)).toLatin1().constData()); 0074 if (meta->getExifTagLong("Exif.NikonLd2.LensIDNumber", val)) exif->fLensID.Set_ASCII((QString::fromUtf8("%1").arg(val)).toLatin1().constData()); 0075 if (meta->getExifTagLong("Exif.NikonLd3.LensIDNumber", val)) exif->fLensID.Set_ASCII((QString::fromUtf8("%1").arg(val)).toLatin1().constData()); 0076 if (meta->getExifTagLong("Exif.NikonLd2.FocusDistance", val)) exif->fSubjectDistance = dng_urational((uint32)pow(10.0, val/40.0), 100); 0077 if (meta->getExifTagLong("Exif.NikonLd3.FocusDistance", val)) exif->fSubjectDistance = dng_urational((uint32)pow(10.0, val/40.0), 100); 0078 str = meta->getExifTagString("Exif.NikonLd1.LensIDNumber"); 0079 if (!str.isEmpty()) exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0080 str = meta->getExifTagString("Exif.NikonLd2.LensIDNumber"); 0081 if (!str.isEmpty()) exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0082 str = meta->getExifTagString("Exif.NikonLd3.LensIDNumber"); 0083 if (!str.isEmpty()) exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0084 } 0085 0086 void DNGWriter::Private::backportCanonMakerNote(DMetadata* const meta) 0087 { 0088 QString str; 0089 long int num, den; 0090 long val; 0091 0092 if (meta->getExifTagLong("Exif.Canon.SerialNumber", val)) exif->fCameraSerialNumber.Set_ASCII((QString::fromUtf8("%1").arg(val)).toLatin1().constData()); 0093 /* 0094 if (meta->getExifTagLong("Exif.CanonCs.FlashActivity", val)) exif->fFlash = (uint32)val; 0095 if (meta->getExifTagLong("Exif.CanonFi.FileNumber", val)) exif->fImageNumber = (uint32)val; 0096 if (meta->getExifTagLong("Exif.CanonCs.MaxAperture", val)) exif->fMaxApertureValue = dng_urational(val, 100000); 0097 */ 0098 if (meta->getExifTagLong("Exif.CanonCs.ExposureProgram", val)) 0099 { 0100 switch (val) 0101 { 0102 case 1: 0103 { 0104 exif->fExposureProgram = 2; 0105 break; 0106 } 0107 0108 case 2: 0109 { 0110 exif->fExposureProgram = 4; 0111 break; 0112 } 0113 0114 case 3: 0115 { 0116 exif->fExposureProgram = 3; 0117 break; 0118 } 0119 0120 case 4: 0121 { 0122 exif->fExposureProgram = 1; 0123 break; 0124 } 0125 0126 default: 0127 { 0128 break; 0129 } 0130 } 0131 } 0132 0133 if (meta->getExifTagLong("Exif.CanonCs.MeteringMode", val)) 0134 { 0135 switch (val) 0136 { 0137 case 1: 0138 { 0139 exif->fMeteringMode = 3; 0140 break; 0141 } 0142 0143 case 2: 0144 { 0145 exif->fMeteringMode = 1; 0146 break; 0147 } 0148 0149 case 3: 0150 { 0151 exif->fMeteringMode = 5; 0152 break; 0153 } 0154 0155 case 4: 0156 { 0157 exif->fMeteringMode = 6; 0158 break; 0159 } 0160 0161 case 5: 0162 { 0163 exif->fMeteringMode = 2; 0164 break; 0165 } 0166 0167 default: 0168 { 0169 break; 0170 } 0171 } 0172 } 0173 0174 long canonLensUnits = 1; 0175 if (meta->getExifTagRational("Exif.CanonCs.Lens", num, den, 2)) canonLensUnits = num; 0176 if (meta->getExifTagRational("Exif.CanonCs.Lens", num, den, 0)) exif->fLensInfo[1] = dng_urational(num, canonLensUnits); 0177 if (meta->getExifTagRational("Exif.CanonCs.Lens", num, den, 1)) exif->fLensInfo[0] = dng_urational(num, canonLensUnits); 0178 if (meta->getExifTagRational("Exif.Canon.FocalLength", num, den, 1)) exif->fFocalLength = dng_urational(num, canonLensUnits); 0179 long canonLensType = 65535; 0180 0181 if (meta->getExifTagLong("Exif.CanonCs.LensType", canonLensType)) exif->fLensID.Set_ASCII((QString::fromUtf8("%1").arg(canonLensType)).toLatin1().constData()); 0182 str = meta->getExifTagString("Exif.Canon.LensModel"); 0183 0184 if (!str.isEmpty()) 0185 { 0186 exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0187 } 0188 else if (canonLensType != 65535) 0189 { 0190 str = meta->getExifTagString("Exif.CanonCs.LensType"); 0191 if (!str.isEmpty()) exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0192 } 0193 0194 str = meta->getExifTagString("Exif.Canon.OwnerName"); 0195 if (!str.isEmpty()) exif->fOwnerName.Set_ASCII(str.trimmed().toLatin1().constData()); 0196 0197 str = meta->getExifTagString("Exif.Canon.FirmwareVersion"); 0198 if (!str.isEmpty()) str = str.replace(QLatin1String("Firmware"), QLatin1String("")); 0199 if (!str.isEmpty()) str = str.replace(QLatin1String("Version"), QLatin1String("")); 0200 if (!str.isEmpty()) exif->fFirmware.Set_ASCII(str.trimmed().toLatin1().constData()); 0201 0202 str = meta->getExifTagString("Exif.CanonSi.ISOSpeed"); 0203 if (!str.isEmpty()) exif->fISOSpeedRatings[1] = str.toInt(); 0204 } 0205 0206 void DNGWriter::Private::backportPentaxMakerNote(DMetadata* const meta) 0207 { 0208 QString str = meta->getExifTagString("Exif.Pentax.LensType"); 0209 0210 if (!str.isEmpty()) 0211 { 0212 exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0213 exif->fLensName.TrimLeadingBlanks(); 0214 exif->fLensName.TrimTrailingBlanks(); 0215 } 0216 0217 long pentaxLensId1 = 0; 0218 long pentaxLensId2 = 0; 0219 0220 if ((meta->getExifTagLong("Exif.Pentax.LensType", pentaxLensId1, 0)) && 0221 (meta->getExifTagLong("Exif.Pentax.LensType", pentaxLensId2, 1))) 0222 { 0223 exif->fLensID.Set_ASCII(QString::fromUtf8("%1").arg(pentaxLensId1, pentaxLensId2).toLatin1().constData()); 0224 } 0225 } 0226 0227 void DNGWriter::Private::backportOlympusMakerNote(DMetadata* const meta) 0228 { 0229 QString str; 0230 long val; 0231 0232 str = meta->getExifTagString("Exif.OlympusEq.SerialNumber"); 0233 if (!str.isEmpty()) exif->fCameraSerialNumber.Set_ASCII(str.trimmed().toLatin1().constData()); 0234 0235 str = meta->getExifTagString("Exif.OlympusEq.LensSerialNumber"); 0236 if (!str.isEmpty()) exif->fLensSerialNumber.Set_ASCII(str.trimmed().toLatin1().constData()); 0237 0238 str = meta->getExifTagString("Exif.OlympusEq.LensModel"); 0239 if (!str.isEmpty()) exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0240 0241 if (meta->getExifTagLong("Exif.OlympusEq.MinFocalLength", val)) exif->fLensInfo[0] = dng_urational(val, 1); 0242 if (meta->getExifTagLong("Exif.OlympusEq.MaxFocalLength", val)) exif->fLensInfo[1] = dng_urational(val, 1); 0243 } 0244 0245 void DNGWriter::Private::backportPanasonicMakerNote(DMetadata* const meta) 0246 { 0247 QString str; 0248 0249 str = meta->getExifTagString("Exif.Panasonic.LensType"); 0250 if (!str.isEmpty()) exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0251 0252 str = meta->getExifTagString("Exif.Panasonic.LensSerialNumber"); 0253 if (!str.isEmpty()) exif->fLensSerialNumber.Set_ASCII(str.trimmed().toLatin1().constData()); 0254 } 0255 0256 void DNGWriter::Private::backportSonyMakerNote(DMetadata* const meta) 0257 { 0258 QString str; 0259 long val; 0260 0261 if (meta->getExifTagLong("Exif.Sony2.LensID", val)) 0262 { 0263 exif->fLensID.Set_ASCII(QString::fromUtf8("%1").arg(val).toLatin1().constData()); 0264 } 0265 0266 str = meta->getExifTagString("Exif.Photo.LensModel"); 0267 0268 if (str.isEmpty()) 0269 { 0270 str = meta->getExifTagString("Exif.Sony2.LensID"); 0271 } 0272 0273 if (!str.isEmpty()) exif->fLensName.Set_ASCII(str.trimmed().toLatin1().constData()); 0274 } 0275 0276 void DNGWriter::Private::storeLensInformation() 0277 { 0278 if ((exif->fLensName.IsEmpty()) && 0279 (exif->fLensInfo[0].As_real64() > 0) && 0280 (exif->fLensInfo[1].As_real64() > 0)) 0281 { 0282 QString lensName; 0283 QTextStream stream(&lensName); 0284 double dval = (double)exif->fLensInfo[0].n / (double)exif->fLensInfo[0].d; 0285 stream << QString::fromUtf8("%1").arg(dval, 0, 'f', 1); 0286 0287 if (exif->fLensInfo[0].As_real64() != exif->fLensInfo[1].As_real64()) 0288 { 0289 dval = (double)exif->fLensInfo[1].n / (double)exif->fLensInfo[1].d; 0290 stream << QString::fromUtf8("-%1").arg(dval, 0, 'f', 1); 0291 } 0292 0293 stream << " mm"; 0294 0295 if (exif->fLensInfo[2].As_real64() > 0) 0296 { 0297 dval = (double)exif->fLensInfo[2].n / (double)exif->fLensInfo[2].d; 0298 stream << QString::fromUtf8(" 1/%1").arg(dval, 0, 'f', 1); 0299 } 0300 0301 if ((exif->fLensInfo[3].As_real64() > 0) && 0302 (exif->fLensInfo[2].As_real64() != exif->fLensInfo[3].As_real64())) 0303 { 0304 dval = (double)exif->fLensInfo[3].n / (double)exif->fLensInfo[3].d; 0305 stream << QString::fromUtf8("-%1").arg(dval, 0, 'f', 1); 0306 } 0307 0308 exif->fLensName.Set_ASCII(lensName.toLatin1().constData()); 0309 } 0310 } 0311 0312 void DNGWriter::Private::backupMakernote(DNGWriterHost& host, 0313 AutoPtr<dng_negative>& negative, 0314 DRawInfo* const /*identify*/, 0315 DRawInfo* const identifyMake, 0316 DMetadata* const meta) 0317 { 0318 // Original Markernote storage in Standard Exif tag. 0319 0320 long mknOffset = 0; 0321 QString mknMake = identifyMake->make.toUpper(); 0322 QString mknByteOrder = meta->getExifTagString("Exif.MakerNote.ByteOrder"); 0323 QByteArray mknData = meta->getExifTagData("Exif.Photo.MakerNote"); 0324 meta->getExifTagLong("Exif.MakerNote.Offset", mknOffset); 0325 0326 if (!mknData.isEmpty() && 0327 ((mknMake == QLatin1String("NIKON")) || 0328 (mknMake == QLatin1String("OLYMPUS")) || 0329 (mknMake == QLatin1String("FUJIFILM"))) 0330 ) 0331 { 0332 qCDebug(DIGIKAM_GENERAL_LOG) << "DNGWriter: Makernote storage (" 0333 << mknData.size() << " bytes)" ; 0334 0335 dng_memory_allocator memalloc1(gDefaultDNGMemoryAllocator); 0336 dng_memory_stream stream(memalloc1); 0337 stream.Put(mknData.constData(), mknData.size()); 0338 AutoPtr<dng_memory_block> block(host.Allocate(mknData.size())); 0339 stream.SetReadPosition(0); 0340 stream.Get(block->Buffer(), mknData.size()); 0341 0342 negative->SetMakerNoteSafety(true); 0343 negative->SetMakerNote(block); 0344 } 0345 0346 // Backup Makernote in DNG private tag. 0347 // NOTE: Exiv2 report a warning with CR2 conversion: 0348 // Error: Directory Canon with 25665 entries considered invalid; not read. 0349 0350 if (!mknData.isEmpty() && 0351 !mknByteOrder.isEmpty() && 0352 mknOffset) 0353 { 0354 bool padding = ((mknData.size() & 0x01) == 0x01); 0355 dng_memory_stream* const streamPriv = new dng_memory_stream(host.Allocator()); 0356 streamPriv->SetBigEndian(); 0357 0358 // Use Adobe vendor-format for encoding MakerNotes in DNGPrivateTag 0359 0360 streamPriv->Put("Adobe", 5); 0361 streamPriv->Put_uint8(0x00); 0362 streamPriv->Put("MakN", 4); 0363 streamPriv->Put_uint32(mknData.size() + mknByteOrder.size() + 4 + (padding ? 1 : 0)); 0364 streamPriv->Put(mknByteOrder.toLatin1().constData(), mknByteOrder.toLatin1().size()); 0365 streamPriv->Put_uint32(mknOffset); 0366 streamPriv->Put(mknData.constData(), mknData.size()); 0367 0368 if (padding) 0369 { 0370 streamPriv->Put_uint8(0x00); 0371 } 0372 0373 AutoPtr<dng_memory_stream> DNGPrivateTag(streamPriv); 0374 0375 if (DNGPrivateTag.Get()) 0376 { 0377 qCDebug(DIGIKAM_GENERAL_LOG) << "DNGWriter: Backup Makernote as DNG Private data (" 0378 << DNGPrivateTag->Length() << " bytes)"; 0379 0380 AutoPtr<dng_memory_block> blockPriv(DNGPrivateTag->AsMemoryBlock(host.Allocator())); 0381 negative->SetPrivateData(blockPriv); 0382 } 0383 } 0384 } 0385 0386 } // namespace Digikam