void dng_jpeg_preview::SpoolAdobeThumbnail (dng_stream &stream) const { DNG_ASSERT (fCompressedData.Get (), "SpoolAdobeThumbnail: no data"); DNG_ASSERT (fPhotometricInterpretation == piYCbCr, "SpoolAdobeThumbnail: Non-YCbCr"); uint32 compressedSize = fCompressedData->LogicalSize (); stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M')); stream.Put_uint16 (1036); stream.Put_uint16 (0); stream.Put_uint32 (compressedSize + 28); uint32 widthBytes = (fPreviewSize.h * 24 + 31) / 32 * 4; stream.Put_uint32 (1); stream.Put_uint32 (fPreviewSize.h); stream.Put_uint32 (fPreviewSize.v); stream.Put_uint32 (widthBytes); stream.Put_uint32 (widthBytes * fPreviewSize.v); stream.Put_uint32 (compressedSize); stream.Put_uint16 (24); stream.Put_uint16 (1); stream.Put (fCompressedData->Buffer (), compressedSize); if (compressedSize & 1) { stream.Put_uint8 (0); } }
void dng_info::ParseDNGPrivateData (dng_host &host, dng_stream &stream) { if (fShared->fDNGPrivateDataCount < 2) { return; } // DNG private data should always start with a null-terminated // company name, to define the format of the private data. dng_string privateName; { char buffer [64]; stream.SetReadPosition (fShared->fDNGPrivateDataOffset); uint32 readLength = Min_uint32 (fShared->fDNGPrivateDataCount, sizeof (buffer) - 1); stream.Get (buffer, readLength); buffer [readLength] = 0; privateName.Set (buffer); } // Pentax is storing their MakerNote in the DNGPrivateData data. if (privateName.StartsWith ("PENTAX" ) || privateName.StartsWith ("SAMSUNG")) { #if qDNGValidate if (gVerbose) { printf ("Parsing Pentax/Samsung DNGPrivateData\n\n"); } #endif stream.SetReadPosition (fShared->fDNGPrivateDataOffset + 8); bool bigEndian = stream.BigEndian (); uint16 endianMark = stream.Get_uint16 (); if (endianMark == byteOrderMM) { bigEndian = true; } else if (endianMark == byteOrderII) { bigEndian = false; } TempBigEndian temp_endian (stream, bigEndian); ParseMakerNoteIFD (host, stream, fShared->fDNGPrivateDataCount - 10, fShared->fDNGPrivateDataOffset + 10, fShared->fDNGPrivateDataOffset, fShared->fDNGPrivateDataOffset, fShared->fDNGPrivateDataOffset + fShared->fDNGPrivateDataCount, tcPentaxMakerNote); return; } // Stop parsing if this is not an Adobe format block. if (!privateName.Matches ("Adobe")) { return; } TempBigEndian temp_order (stream); uint32 section_offset = 6; while (section_offset + 8 < fShared->fDNGPrivateDataCount) { stream.SetReadPosition (fShared->fDNGPrivateDataOffset + section_offset); uint32 section_key = stream.Get_uint32 (); uint32 section_count = stream.Get_uint32 (); if (section_key == DNG_CHAR4 ('M','a','k','N') && section_count > 6) { #if qDNGValidate if (gVerbose) { printf ("Found MakerNote inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint64 old_offset = stream.Get_uint32 (); uint32 tempSize = section_count - 6; AutoPtr<dng_memory_block> tempBlock (host.Allocate (tempSize)); uint64 positionInOriginalFile = stream.PositionInOriginalFile(); stream.Get (tempBlock->Buffer (), tempSize); dng_stream tempStream (tempBlock->Buffer (), tempSize, positionInOriginalFile); tempStream.SetBigEndian (order_mark == byteOrderMM); ParseMakerNote (host, tempStream, tempSize, 0, 0 - old_offset, 0, tempSize); } else if (section_key == DNG_CHAR4 ('S','R','2',' ') && section_count > 6) { #if qDNGValidate if (gVerbose) { printf ("Found Sony private data inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint64 old_offset = stream.Get_uint32 (); uint64 new_offset = fShared->fDNGPrivateDataOffset + section_offset + 14; TempBigEndian sr2_order (stream, order_mark == byteOrderMM); ParseSonyPrivateData (host, stream, section_count - 6, old_offset, new_offset); } else if (section_key == DNG_CHAR4 ('R','A','F',' ') && section_count > 4) { #if qDNGValidate if (gVerbose) { printf ("Found Fuji RAF tags inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); if (tagCount) { TempBigEndian raf_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcFujiRAF, tcFujiHeader, ttUndefined, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagCount); } tagCount = stream.Get_uint32 (); tagOffset = stream.Position (); if (tagCount) { TempBigEndian raf_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcFujiRAF, tcFujiRawInfo1, ttUndefined, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagCount); } tagCount = stream.Get_uint32 (); tagOffset = stream.Position (); if (tagCount) { TempBigEndian raf_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcFujiRAF, tcFujiRawInfo2, ttUndefined, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagCount); } } else if (section_key == DNG_CHAR4 ('C','n','t','x') && section_count > 4) { #if qDNGValidate if (gVerbose) { printf ("Found Contax Raw header inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); if (tagCount) { TempBigEndian contax_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcContaxRAW, tcContaxHeader, ttUndefined, tagCount, tagOffset, 0); } } else if (section_key == DNG_CHAR4 ('C','R','W',' ') && section_count > 4) { #if qDNGValidate if (gVerbose) { printf ("Found Canon CRW tags inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 entries = stream.Get_uint16 (); uint64 crwTagStart = stream.Position (); for (uint32 parsePass = 1; parsePass <= 2; parsePass++) { stream.SetReadPosition (crwTagStart); for (uint32 index = 0; index < entries; index++) { uint32 tagCode = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); // We need to grab the model id tag first, and then all the // other tags. if ((parsePass == 1) == (tagCode == 0x5834)) { TempBigEndian tag_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcCanonCRW, tagCode, ttUndefined, tagCount, tagOffset, 0); } stream.SetReadPosition (tagOffset + tagCount); } } } else if (section_count > 4) { uint32 parentCode = 0; bool code32 = false; bool hasType = true; switch (section_key) { case DNG_CHAR4 ('M','R','W',' '): { parentCode = tcMinoltaMRW; code32 = true; hasType = false; break; } case DNG_CHAR4 ('P','a','n','o'): { parentCode = tcPanasonicRAW; break; } case DNG_CHAR4 ('L','e','a','f'): { parentCode = tcLeafMOS; break; } case DNG_CHAR4 ('K','o','d','a'): { parentCode = tcKodakDCRPrivateIFD; break; } case DNG_CHAR4 ('K','D','C',' '): { parentCode = tcKodakKDCPrivateIFD; break; } default: break; } if (parentCode) { #if qDNGValidate if (gVerbose) { printf ("Found %s tags inside DNGPrivateData\n\n", LookupParentCode (parentCode)); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 entries = stream.Get_uint16 (); for (uint32 index = 0; index < entries; index++) { uint32 tagCode = code32 ? stream.Get_uint32 () : stream.Get_uint16 (); uint32 tagType = hasType ? stream.Get_uint16 () : ttUndefined; uint32 tagCount = stream.Get_uint32 (); uint32 tagSize = tagCount * TagTypeSize (tagType); uint64 tagOffset = stream.Position (); TempBigEndian tag_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, parentCode, tagCode, tagType, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagSize); } } } section_offset += 8 + section_count; if (section_offset & 1) { section_offset++; } } }
void NegativeProcessor::setExifFromRaw(const dng_date_time_info &dateTimeNow, const dng_string &appNameVersion) { dng_exif *negExif = m_negative->GetExif(); // ----------------------------------------------------------------------------------------- // TIFF 6.0 "D. Other Tags" getRawExifTag("Exif.Image.DateTime", &negExif->fDateTime); getRawExifTag("Exif.Image.ImageDescription", &negExif->fImageDescription); getRawExifTag("Exif.Image.Make", &negExif->fMake); getRawExifTag("Exif.Image.Model", &negExif->fModel); getRawExifTag("Exif.Image.Software", &negExif->fSoftware); getRawExifTag("Exif.Image.Artist", &negExif->fArtist); getRawExifTag("Exif.Image.Copyright", &negExif->fCopyright); // ----------------------------------------------------------------------------------------- // Exif 2.3 "A. Tags Relating to Version" (order as in spec) getRawExifTag("Exif.Photo.ExifVersion", 0, &negExif->fExifVersion); // Exif.Photo.FlashpixVersion - fFlashPixVersion : ignoring this here // ----------------------------------------------------------------------------------------- // Exif 2.3 "B. Tags Relating to Image data Characteristics" (order as in spec) getRawExifTag("Exif.Photo.ColorSpace", 0, &negExif->fColorSpace); // Gamma : Supported by DNG SDK (fGamma) but not Exiv2 (v0.24) // ----------------------------------------------------------------------------------------- // Exif 2.3 "C. Tags Relating To Image Configuration" (order as in spec) getRawExifTag("Exif.Photo.ComponentsConfiguration", 0, &negExif->fComponentsConfiguration); getRawExifTag("Exif.Photo.CompressedBitsPerPixel", 0, &negExif->fCompresssedBitsPerPixel); // nice typo in DNG SDK... getRawExifTag("Exif.Photo.PixelXDimension", 0, &negExif->fPixelXDimension); getRawExifTag("Exif.Photo.PixelYDimension", 0, &negExif->fPixelYDimension); // ----------------------------------------------------------------------------------------- // Exif 2.3 "D. Tags Relating to User Information" (order as in spec) // MakerNote: We'll deal with that below getRawExifTag("Exif.Photo.UserComment", &negExif->fUserComment); // ----------------------------------------------------------------------------------------- // Exif 2.3 "E. Tags Relating to Related File Information" (order as in spec) // RelatedSoundFile : DNG SDK doesn't support this // ----------------------------------------------------------------------------------------- // Exif 2.3 "F. Tags Relating to Date and Time" (order as in spec) getRawExifTag("Exif.Photo.DateTimeOriginal", &negExif->fDateTimeOriginal); getRawExifTag("Exif.Photo.DateTimeDigitized", &negExif->fDateTimeDigitized); // SubSecTime : DNG SDK doesn't support this // SubSecTimeOriginal : DNG SDK doesn't support this // SubSecTimeDigitized : DNG SDK doesn't support this // ----------------------------------------------------------------------------------------- // Exif 2.3 "G. Tags Relating to Picture-Taking Conditions" (order as in spec) getRawExifTag("Exif.Photo.ExposureTime", 0, &negExif->fExposureTime); getRawExifTag("Exif.Photo.FNumber", 0, &negExif->fFNumber); getRawExifTag("Exif.Photo.ExposureProgram", 0, &negExif->fExposureProgram); // SpectralSensitivity : DNG SDK doesn't support this getRawExifTag("Exif.Photo.ISOSpeedRatings", negExif->fISOSpeedRatings, 3); // PhotographicSensitivity in Exif 2.3 // OECF : DNG SDK doesn't support this getRawExifTag("Exif.Photo.SensitivityType", 0, &negExif->fSensitivityType); getRawExifTag("Exif.Photo.StandardOutputSensitivity", 0, &negExif->fStandardOutputSensitivity); getRawExifTag("Exif.Photo.RecommendedExposureIndex", 0, &negExif->fRecommendedExposureIndex); getRawExifTag("Exif.Photo.ISOSpeed", 0, &negExif->fISOSpeed); getRawExifTag("Exif.Photo.ISOSpeedLatitudeyyy", 0, &negExif->fISOSpeedLatitudeyyy); getRawExifTag("Exif.Photo.ISOSpeedLatitudezzz", 0, &negExif->fISOSpeedLatitudezzz); getRawExifTag("Exif.Photo.ShutterSpeedValue", 0, &negExif->fShutterSpeedValue); getRawExifTag("Exif.Photo.ApertureValue", 0, &negExif->fApertureValue); getRawExifTag("Exif.Photo.BrightnessValue", 0, &negExif->fBrightnessValue); getRawExifTag("Exif.Photo.ExposureBiasValue", 0, &negExif->fExposureBiasValue); getRawExifTag("Exif.Photo.MaxApertureValue", 0, &negExif->fMaxApertureValue); getRawExifTag("Exif.Photo.SubjectDistance", 0, &negExif->fSubjectDistance); getRawExifTag("Exif.Photo.MeteringMode", 0, &negExif->fMeteringMode); getRawExifTag("Exif.Photo.LightSource", 0, &negExif->fLightSource); getRawExifTag("Exif.Photo.Flash", 0, &negExif->fFlash); getRawExifTag("Exif.Photo.FocalLength", 0, &negExif->fFocalLength); negExif->fSubjectAreaCount = getRawExifTag("Exif.Photo.SubjectArea", negExif->fSubjectArea, 4); // FlashEnergy : DNG SDK doesn't support this // SpatialFrequencyResponse : DNG SDK doesn't support this getRawExifTag("Exif.Photo.FocalPlaneXResolution", 0, &negExif->fFocalPlaneXResolution); getRawExifTag("Exif.Photo.FocalPlaneYResolution", 0, &negExif->fFocalPlaneYResolution); getRawExifTag("Exif.Photo.FocalPlaneResolutionUnit", 0, &negExif->fFocalPlaneResolutionUnit); // SubjectLocation : DNG SDK doesn't support this getRawExifTag("Exif.Photo.ExposureIndex", 0, &negExif->fExposureIndex); getRawExifTag("Exif.Photo.SensingMethod", 0, &negExif->fSensingMethod); getRawExifTag("Exif.Photo.FileSource", 0, &negExif->fFileSource); getRawExifTag("Exif.Photo.SceneType", 0, &negExif->fSceneType); // CFAPattern: we write it manually from raw data further below getRawExifTag("Exif.Photo.CustomRendered", 0, &negExif->fCustomRendered); getRawExifTag("Exif.Photo.ExposureMode", 0, &negExif->fExposureMode); getRawExifTag("Exif.Photo.WhiteBalance", 0, &negExif->fWhiteBalance); getRawExifTag("Exif.Photo.DigitalZoomRatio", 0, &negExif->fDigitalZoomRatio); getRawExifTag("Exif.Photo.FocalLengthIn35mmFilm", 0, &negExif->fFocalLengthIn35mmFilm); getRawExifTag("Exif.Photo.SceneCaptureType", 0, &negExif->fSceneCaptureType); getRawExifTag("Exif.Photo.GainControl", 0, &negExif->fGainControl); getRawExifTag("Exif.Photo.Contrast", 0, &negExif->fContrast); getRawExifTag("Exif.Photo.Saturation", 0, &negExif->fSaturation); getRawExifTag("Exif.Photo.Sharpness", 0, &negExif->fSharpness); // DeviceSettingsDescription : DNG SDK doesn't support this getRawExifTag("Exif.Photo.SubjectDistanceRange", 0, &negExif->fSubjectDistanceRange); // ----------------------------------------------------------------------------------------- // Exif 2.3 "H. Other Tags" (order as in spec) // ImageUniqueID : DNG SDK doesn't support this getRawExifTag("Exif.Photo.CameraOwnerName", &negExif->fOwnerName); getRawExifTag("Exif.Photo.BodySerialNumber", &negExif->fCameraSerialNumber); getRawExifTag("Exif.Photo.LensSpecification", negExif->fLensInfo, 4); getRawExifTag("Exif.Photo.LensMake", &negExif->fLensMake); getRawExifTag("Exif.Photo.LensModel", &negExif->fLensName); getRawExifTag("Exif.Photo.LensSerialNumber", &negExif->fLensSerialNumber); // ----------------------------------------------------------------------------------------- // Exif 2.3 GPS "A. Tags Relating to GPS" (order as in spec) uint32 gpsVer[4]; gpsVer[0] = gpsVer[1] = gpsVer[2] = gpsVer[3] = 0; getRawExifTag("Exif.GPSInfo.GPSVersionID", gpsVer, 4); negExif->fGPSVersionID = (gpsVer[0] << 24) + (gpsVer[1] << 16) + (gpsVer[2] << 8) + gpsVer[3]; getRawExifTag("Exif.GPSInfo.GPSLatitudeRef", &negExif->fGPSLatitudeRef); getRawExifTag("Exif.GPSInfo.GPSLatitude", negExif->fGPSLatitude, 3); getRawExifTag("Exif.GPSInfo.GPSLongitudeRef", &negExif->fGPSLongitudeRef); getRawExifTag("Exif.GPSInfo.GPSLongitude", negExif->fGPSLongitude, 3); getRawExifTag("Exif.GPSInfo.GPSAltitudeRef", 0, &negExif->fGPSAltitudeRef); getRawExifTag("Exif.GPSInfo.GPSAltitude", 0, &negExif->fGPSAltitude); getRawExifTag("Exif.GPSInfo.GPSTimeStamp", negExif->fGPSTimeStamp, 3); getRawExifTag("Exif.GPSInfo.GPSSatellites", &negExif->fGPSSatellites); getRawExifTag("Exif.GPSInfo.GPSStatus", &negExif->fGPSStatus); getRawExifTag("Exif.GPSInfo.GPSMeasureMode", &negExif->fGPSMeasureMode); getRawExifTag("Exif.GPSInfo.GPSDOP", 0, &negExif->fGPSDOP); getRawExifTag("Exif.GPSInfo.GPSSpeedRef", &negExif->fGPSSpeedRef); getRawExifTag("Exif.GPSInfo.GPSSpeed", 0, &negExif->fGPSSpeed); getRawExifTag("Exif.GPSInfo.GPSTrackRef", &negExif->fGPSTrackRef); getRawExifTag("Exif.GPSInfo.GPSTrack", 0, &negExif->fGPSTrack); getRawExifTag("Exif.GPSInfo.GPSImgDirectionRef", &negExif->fGPSImgDirectionRef); getRawExifTag("Exif.GPSInfo.GPSImgDirection", 0, &negExif->fGPSImgDirection); getRawExifTag("Exif.GPSInfo.GPSMapDatum", &negExif->fGPSMapDatum); getRawExifTag("Exif.GPSInfo.GPSDestLatitudeRef", &negExif->fGPSDestLatitudeRef); getRawExifTag("Exif.GPSInfo.GPSDestLatitude", negExif->fGPSDestLatitude, 3); getRawExifTag("Exif.GPSInfo.GPSDestLongitudeRef", &negExif->fGPSDestLongitudeRef); getRawExifTag("Exif.GPSInfo.GPSDestLongitude", negExif->fGPSDestLongitude, 3); getRawExifTag("Exif.GPSInfo.GPSDestBearingRef", &negExif->fGPSDestBearingRef); getRawExifTag("Exif.GPSInfo.GPSDestBearing", 0, &negExif->fGPSDestBearing); getRawExifTag("Exif.GPSInfo.GPSDestDistanceRef", &negExif->fGPSDestDistanceRef); getRawExifTag("Exif.GPSInfo.GPSDestDistance", 0, &negExif->fGPSDestDistance); getRawExifTag("Exif.GPSInfo.GPSProcessingMethod", &negExif->fGPSProcessingMethod); getRawExifTag("Exif.GPSInfo.GPSAreaInformation", &negExif->fGPSAreaInformation); getRawExifTag("Exif.GPSInfo.GPSDateStamp", &negExif->fGPSDateStamp); getRawExifTag("Exif.GPSInfo.GPSDifferential", 0, &negExif->fGPSDifferential); // GPSHPositioningError : Supported by DNG SDK (fGPSHPositioningError) but not Exiv2 (v0.24) // ----------------------------------------------------------------------------------------- // Exif 2.3, Interoperability IFD "A. Attached Information Related to Interoperability" getRawExifTag("Exif.Iop.InteroperabilityIndex", &negExif->fInteroperabilityIndex); getRawExifTag("Exif.Iop.InteroperabilityVersion", 0, &negExif->fInteroperabilityVersion); // this is not in the Exif standard but in DNG SDK and Exiv2 /* Fields in the DNG SDK Exif structure that we are ignoring here. Some could potentially be read through Exiv2 but are not part of the Exif standard so we leave them out: - fBatteryLevelA, fBatteryLevelR - fSelfTimerMode - fTIFF_EP_StandardID, fImageNumber - fApproxFocusDistance - fFlashCompensation, fFlashMask - fFirmware - fLensID - fLensNameWasReadFromExif (--> available but not used by SDK) - fRelatedImageFileFormat, fRelatedImageWidth, fRelatedImageLength */ // ----------------------------------------------------------------------------------------- // Write CFAPattern (section G) manually from mosaicinfo const dng_mosaic_info* mosaicinfo = m_negative->GetMosaicInfo(); if (mosaicinfo != NULL) { negExif->fCFARepeatPatternCols = mosaicinfo->fCFAPatternSize.v; negExif->fCFARepeatPatternRows = mosaicinfo->fCFAPatternSize.h; for (uint16 c = 0; c < negExif->fCFARepeatPatternCols; c++) for (uint16 r = 0; r < negExif->fCFARepeatPatternRows; r++) negExif->fCFAPattern[r][c] = mosaicinfo->fCFAPattern[c][r]; } // ----------------------------------------------------------------------------------------- // Reconstruct LensName from LensInfo if not present if (negExif->fLensName.IsEmpty()) { dng_urational *li = negExif->fLensInfo; std::stringstream lensName; lensName.precision(1); lensName.setf(std::ios::fixed, std::ios::floatfield); if (li[0].IsValid()) lensName << li[0].As_real64(); if (li[1] != li[2]) lensName << "-" << li[1].As_real64(); if (lensName.tellp() > 0) lensName << " mm"; if (li[2].IsValid()) lensName << " f/" << li[2].As_real64(); if (li[3] != li[2]) lensName << "-" << li[3].As_real64(); negExif->fLensName.Set_ASCII(lensName.str().c_str()); } // ----------------------------------------------------------------------------------------- // Overwrite date, software, version - these are now referencing the DNG-creation negExif->fDateTime = dateTimeNow; negExif->fSoftware = appNameVersion; negExif->fExifVersion = DNG_CHAR4 ('0','2','3','0'); }