void dng_xmp_sdk::Parse (dng_host &host, const char *buffer, uint32 count) { MakeMeta (); try { try { fPrivate->fMeta->ParseFromBuffer (buffer, count); } CATCH_XMP ("ParseFromBuffer", true) } catch (dng_exception &except) { ClearMeta (); if (host.IsTransientError (except.ErrorCode ())) { throw; } ThrowBadFormat (); } }
dng_linearize_plane::dng_linearize_plane (dng_host &host, dng_linearization_info &info, const dng_image &srcImage, dng_image &dstImage, uint32 plane) : fSrcImage (srcImage) , fDstImage (dstImage) , fPlane (plane) , fActiveArea (info.fActiveArea) , fSrcPixelType (srcImage.PixelType ()) , fDstPixelType (dstImage.PixelType ()) , fReal32 (false) , fScale (0.0f) , fScale_buffer () , fBlack_2D_rows (0) , fBlack_2D_cols (0) , fBlack_2D_buffer () , fBlack_1D_rows (0) , fBlack_1D_buffer () { uint32 j; uint32 k; // Make sure the source pixel type is supported. if (fSrcPixelType != ttByte && fSrcPixelType != ttShort && fSrcPixelType != ttLong) { DNG_REPORT ("Unsupported source pixel type"); ThrowProgramError (); } if (fDstPixelType != ttShort && fDstPixelType != ttFloat) { DNG_REPORT ("Unsupported destination pixel type"); ThrowProgramError (); } // Are we using floating point math? fReal32 = (fSrcPixelType == ttLong || fDstPixelType == ttFloat); // Find the scale for this plane. real64 maxBlack = info.MaxBlackLevel (plane); real64 minRange = info.fWhiteLevel [plane] - maxBlack; if (minRange <= 0.0) { ThrowBadFormat (); } real64 scale = 1.0 / minRange; fScale = (real32) scale; // Calculate two-dimensional black pattern, if any. if (info.fBlackDeltaH.Get ()) { fBlack_2D_rows = info.fBlackLevelRepeatRows; fBlack_2D_cols = info.fActiveArea.W (); } else if (info.fBlackLevelRepeatCols > 1) { fBlack_2D_rows = info.fBlackLevelRepeatRows; fBlack_2D_cols = info.fBlackLevelRepeatCols; } if (fBlack_2D_rows) { fBlack_2D_buffer.Reset (host.Allocate (fBlack_2D_rows * fBlack_2D_cols * 4)); for (j = 0; j < fBlack_2D_rows; j++) { for (k = 0; k < fBlack_2D_cols; k++) { real64 x = info.fBlackLevel [j] [k % info.fBlackLevelRepeatCols] [plane]; if (info.fBlackDeltaH.Get ()) { x += info.fBlackDeltaH->Buffer_real64 () [k]; } x *= scale; uint32 index = j * fBlack_2D_cols + k; if (fReal32) { fBlack_2D_buffer->Buffer_real32 () [index] = (real32) x; } else { x *= 0x0FFFF * 256.0; int32 y = Round_int32 (x); fBlack_2D_buffer->Buffer_int32 () [index] = y; } } } } // Calculate one-dimensional (per row) black pattern, if any. if (info.fBlackDeltaV.Get ()) { fBlack_1D_rows = info.fActiveArea.H (); } else if (fBlack_2D_rows == 0 && (info.fBlackLevelRepeatRows > 1 || fSrcPixelType != ttShort)) { fBlack_1D_rows = info.fBlackLevelRepeatRows; } if (fBlack_1D_rows) { fBlack_1D_buffer.Reset (host.Allocate (fBlack_1D_rows * 4)); for (j = 0; j < fBlack_1D_rows; j++) { real64 x = 0.0; if (fBlack_2D_rows == 0) { x = info.fBlackLevel [j % info.fBlackLevelRepeatRows] [0] [plane]; } if (info.fBlackDeltaV.Get ()) { x += info.fBlackDeltaV->Buffer_real64 () [j]; } x *= scale; if (fReal32) { fBlack_1D_buffer->Buffer_real32 () [j] = (real32) x; } else { x *= 0x0FFFF * 256.0; int32 y = Round_int32 (x); fBlack_1D_buffer->Buffer_int32 () [j] = y; } } } // Calculate scale table, if any. if (fSrcPixelType != ttLong) { // Find linearization table, if any. uint16 *lut = NULL; uint32 lutEntries = 0; if (info.fLinearizationTable.Get ()) { lut = info.fLinearizationTable->Buffer_uint16 (); lutEntries = info.fLinearizationTable->LogicalSize () >> 1; }
void dng_info::Parse (dng_host &host, dng_stream &stream) { fTIFFBlockOffset = stream.Position (); fTIFFBlockOriginalOffset = stream.PositionInOriginalFile (); // Check byte order indicator. uint16 byteOrder = stream.Get_uint16 (); if (byteOrder == byteOrderII) { fBigEndian = false; #if qDNGValidate if (gVerbose) { printf ("\nUses little-endian byte order\n"); } #endif stream.SetLittleEndian (); } else if (byteOrder == byteOrderMM) { fBigEndian = true; #if qDNGValidate if (gVerbose) { printf ("\nUses big-endian byte order\n"); } #endif stream.SetBigEndian (); } else { #if qDNGValidate ReportError ("Unknown byte order"); #endif ThrowBadFormat (); } // Check "magic number" indicator. fMagic = stream.Get_uint16 (); #if qDNGValidate if (gVerbose) { printf ("Magic number = %u\n\n", (unsigned) fMagic); } #endif ValidateMagic (); // Parse IFD 0. uint64 next_offset = stream.Get_uint32 (); fExif.Reset (host.Make_dng_exif ()); fShared.Reset (host.Make_dng_shared ()); fIFD [0].Reset (host.Make_dng_ifd ()); ParseIFD (host, stream, fExif.Get (), fShared.Get (), fIFD [0].Get (), fTIFFBlockOffset + next_offset, fTIFFBlockOffset, 0); next_offset = fIFD [0]->fNextIFD; fIFDCount = 1; // Parse chained IFDs. while (next_offset) { if (next_offset >= stream.Length ()) { #if qDNGValidate { ReportWarning ("Chained IFD offset past end of stream"); } #endif break; } // Some TIFF file writers forget about the next IFD offset, so // validate the IFD at that offset before parsing it. if (!ValidateIFD (stream, fTIFFBlockOffset + next_offset, fTIFFBlockOffset)) { #if qDNGValidate { ReportWarning ("Chained IFD is not valid"); } #endif break; } if (fChainedIFDCount == kMaxChainedIFDs) { #if qDNGValidate { ReportWarning ("Chained IFD count exceeds DNG SDK parsing limit"); } #endif break; } fChainedIFD [fChainedIFDCount].Reset (host.Make_dng_ifd ()); ParseIFD (host, stream, NULL, NULL, fChainedIFD [fChainedIFDCount].Get (), fTIFFBlockOffset + next_offset, fTIFFBlockOffset, tcFirstChainedIFD + fChainedIFDCount); next_offset = fChainedIFD [fChainedIFDCount]->fNextIFD; fChainedIFDCount++; } // Parse SubIFDs. uint32 searchedIFDs = 0; bool tooManySubIFDs = false; while (searchedIFDs < fIFDCount && !tooManySubIFDs) { uint32 searchLimit = fIFDCount; for (uint32 searchIndex = searchedIFDs; searchIndex < searchLimit && !tooManySubIFDs; searchIndex++) { for (uint32 subIndex = 0; subIndex < fIFD [searchIndex]->fSubIFDsCount; subIndex++) { if (fIFDCount == kMaxSubIFDs + 1) { tooManySubIFDs = true; break; } stream.SetReadPosition (fIFD [searchIndex]->fSubIFDsOffset + subIndex * 4); uint32 sub_ifd_offset = stream.Get_uint32 (); fIFD [fIFDCount].Reset (host.Make_dng_ifd ()); ParseIFD (host, stream, fExif.Get (), fShared.Get (), fIFD [fIFDCount].Get (), fTIFFBlockOffset + sub_ifd_offset, fTIFFBlockOffset, tcFirstSubIFD + fIFDCount - 1); fIFDCount++; } searchedIFDs = searchLimit; } } #if qDNGValidate { if (tooManySubIFDs) { ReportWarning ("SubIFD count exceeds DNG SDK parsing limit"); } } #endif // Parse EXIF IFD. if (fShared->fExifIFD) { ParseIFD (host, stream, fExif.Get (), fShared.Get (), NULL, fTIFFBlockOffset + fShared->fExifIFD, fTIFFBlockOffset, tcExifIFD); } // Parse GPS IFD. if (fShared->fGPSInfo) { ParseIFD (host, stream, fExif.Get (), fShared.Get (), NULL, fTIFFBlockOffset + fShared->fGPSInfo, fTIFFBlockOffset, tcGPSInfo); } // Parse Interoperability IFD. if (fShared->fInteroperabilityIFD) { // Some Kodak KDC files have bogus Interoperability IFDs, so // validate the IFD before trying to parse it. if (ValidateIFD (stream, fTIFFBlockOffset + fShared->fInteroperabilityIFD, fTIFFBlockOffset)) { ParseIFD (host, stream, fExif.Get (), fShared.Get (), NULL, fTIFFBlockOffset + fShared->fInteroperabilityIFD, fTIFFBlockOffset, tcInteroperabilityIFD); } #if qDNGValidate else { ReportWarning ("The Interoperability IFD is not a valid IFD"); } #endif } // Parse Kodak DCR Private IFD. if (fShared->fKodakDCRPrivateIFD) { ParseIFD (host, stream, fExif.Get (), fShared.Get (), NULL, fTIFFBlockOffset + fShared->fKodakDCRPrivateIFD, fTIFFBlockOffset, tcKodakDCRPrivateIFD); } // Parse Kodak KDC Private IFD. if (fShared->fKodakKDCPrivateIFD) { ParseIFD (host, stream, fExif.Get (), fShared.Get (), NULL, fTIFFBlockOffset + fShared->fKodakKDCPrivateIFD, fTIFFBlockOffset, tcKodakKDCPrivateIFD); } // Parse MakerNote tag. if (fShared->fMakerNoteCount) { ParseMakerNote (host, stream, (uint32) (fTIFFBlockOffset + fShared->fMakerNoteCount), fShared->fMakerNoteOffset, fTIFFBlockOffset, 0, stream.Length ()); } // Parse DNGPrivateData tag. if (fShared->fDNGPrivateDataCount && fShared->fDNGVersion) { ParseDNGPrivateData (host, stream); } #if qDNGValidate // If we are running dng_validate on stand-alone camera profile file, // complete the validation of the profile. if (fMagic == magicExtendedProfile) { dng_camera_profile_info &profileInfo = fShared->fCameraProfile; dng_camera_profile profile; profile.Parse (stream, profileInfo); if (profileInfo.fColorPlanes < 3 || !profile.IsValid (profileInfo.fColorPlanes)) { ReportError ("Invalid camera profile file"); } } #endif }
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++; } } }
dng_opcode_DeltaPerRow::dng_opcode_DeltaPerRow (dng_host &host, dng_stream &stream) : dng_inplace_opcode (dngOpcode_DeltaPerRow, stream, "DeltaPerRow") , fAreaSpec () , fTable () , fScale (1.0f) { uint32 dataSize = stream.Get_uint32 (); fAreaSpec.GetData (stream); uint32 deltas = (fAreaSpec.Area ().H () + fAreaSpec.RowPitch () - 1) / fAreaSpec.RowPitch (); if (deltas != stream.Get_uint32 ()) { ThrowBadFormat (); } if (dataSize != dng_area_spec::kDataSize + 4 + deltas * 4) { ThrowBadFormat (); } fTable.Reset (host.Allocate (deltas * sizeof (real32))); real32 *table = fTable->Buffer_real32 (); for (uint32 j = 0; j < deltas; j++) { table [j] = stream.Get_real32 (); } #if qDNGValidate if (gVerbose) { printf ("Count: %u\n", (unsigned) deltas); for (uint32 k = 0; k < deltas && k < gDumpLineLimit; k++) { printf (" Delta [%u] = %f\n", k, table [k]); } if (deltas > gDumpLineLimit) { printf (" ... %u deltas skipped\n", deltas - gDumpLineLimit); } } #endif }
dng_opcode_MapTable::dng_opcode_MapTable (dng_host &host, dng_stream &stream) : dng_inplace_opcode (dngOpcode_MapTable, stream, "MapTable") , fAreaSpec () , fTable () , fCount (0) { uint32 dataSize = stream.Get_uint32 (); fAreaSpec.GetData (stream); fCount = stream.Get_uint32 (); if (dataSize != dng_area_spec::kDataSize + 4 + fCount * 2) { ThrowBadFormat (); } if (fCount == 0 || fCount > 0x10000) { ThrowBadFormat (); } fTable.Reset (host.Allocate (0x10000 * sizeof (uint16))); uint16 *table = fTable->Buffer_uint16 (); for (uint32 index = 0; index < fCount; index++) { table [index] = stream.Get_uint16 (); } ReplicateLastEntry (); #if qDNGValidate if (gVerbose) { printf ("Count: %u\n", (unsigned) fCount); for (uint32 j = 0; j < fCount && j < gDumpLineLimit; j++) { printf (" Table [%5u] = %5u\n", j, table [j]); } if (fCount > gDumpLineLimit) { printf (" ... %u table entries skipped\n", fCount - gDumpLineLimit); } } #endif }
dng_opcode_ScalePerColumn::dng_opcode_ScalePerColumn (dng_host &host, dng_stream &stream) : dng_inplace_opcode (dngOpcode_ScalePerColumn, stream, "ScalePerColumn") , fAreaSpec () , fTable () { uint32 dataSize = stream.Get_uint32 (); fAreaSpec.GetData (stream); uint32 scales = (fAreaSpec.Area ().W () + fAreaSpec.ColPitch () - 1) / fAreaSpec.ColPitch (); if (scales != stream.Get_uint32 ()) { ThrowBadFormat (); } if (dataSize != dng_area_spec::kDataSize + 4 + scales * 4) { ThrowBadFormat (); } fTable.Reset (host.Allocate (scales * sizeof (real32))); real32 *table = fTable->Buffer_real32 (); for (uint32 j = 0; j < scales; j++) { table [j] = stream.Get_real32 (); } #if qDNGValidate if (gVerbose) { printf ("Count: %u\n", (unsigned) scales); for (uint32 k = 0; k < scales && k < gDumpLineLimit; k++) { printf (" Scale [%u] = %f\n", k, table [k]); } if (scales > gDumpLineLimit) { printf (" ... %u deltas skipped\n", scales - gDumpLineLimit); } } #endif }