Exemple #1
0
void dng_gain_map::PutStream (dng_stream &stream) const
	{
	
	stream.Put_uint32 (fPoints.v);
	stream.Put_uint32 (fPoints.h);
	
	stream.Put_real64 (fSpacing.v);
	stream.Put_real64 (fSpacing.h);
	
	stream.Put_real64 (fOrigin.v);
	stream.Put_real64 (fOrigin.h);
	
	stream.Put_uint32 (fPlanes);
	
	for (int32 rowIndex = 0; rowIndex < fPoints.v; rowIndex++)
		{
		
		for (int32 colIndex = 0; colIndex < fPoints.h; colIndex++)
			{
			
			for (uint32 plane = 0; plane < fPlanes; plane++)
				{
				
				stream.Put_real32 (Entry (rowIndex,
										  colIndex,
										  plane));
										  
				}
				
			}
			
		}
	
	}
Exemple #2
0
dng_opcode_GainMap::dng_opcode_GainMap (dng_host &host,
										dng_stream &stream)
												
	:	dng_inplace_opcode (dngOpcode_GainMap,
							stream,
							"GainMap")
							
	,	fAreaSpec ()
							
	,	fGainMap ()
							
	{
	
	uint32 byteCount = stream.Get_uint32 ();
	
	uint64 startPosition = stream.Position ();
	
	fAreaSpec.GetData (stream);
	
	fGainMap.Reset (dng_gain_map::GetStream (host, stream));
	
	if (stream.Position () != startPosition + byteCount)
		{
		ThrowBadFormat ();
		}
		
	}
Exemple #3
0
void dng_stream::DuplicateStream (dng_stream &dstStream)
	{
	
	// Turn off sniffers for this operation.
	
	TempStreamSniffer noSniffer1 (*this    , NULL);
	TempStreamSniffer noSniffer2 (dstStream, NULL);
		
	// First grow the destination stream if required, in an attempt to
	// reserve any needed space before overwriting the existing data.
	
	if (dstStream.Length () < Length ())
		{
		dstStream.SetLength (Length ());
		}
		
	SetReadPosition (0);
	
	dstStream.SetWritePosition (0);
	
	CopyToStream (dstStream, Length ());
	
	dstStream.Flush ();
							
	dstStream.SetLength (Length ());

	}
void dng_camera_profile::ReadHueSatMap (dng_stream &stream,
										dng_hue_sat_map &hueSatMap,
										uint32 hues,
										uint32 sats,
										uint32 vals,
										bool skipSat0)
	{

	hueSatMap.SetDivisions (hues, sats, vals);

	for (uint32 val = 0; val < vals; val++)
		{

		for (uint32 hue = 0; hue < hues; hue++)
			{

			for (uint32 sat = skipSat0 ? 1 : 0; sat < sats; sat++)
				{

				dng_hue_sat_map::HSBModify modify;

				modify.fHueShift = stream.Get_real32 ();
				modify.fSatScale = stream.Get_real32 ();
				modify.fValScale = stream.Get_real32 ();

				hueSatMap.SetDelta (hue, sat, val, modify);
				
				}
				
			}
			
		}
	
	}
Exemple #5
0
dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (dng_stream &stream)

	:	dng_inplace_opcode (dngOpcode_MapPolynomial,
							stream,
							"MapPolynomial")

	,	fAreaSpec ()
	,	fDegree   (0)

	{

	uint32 dataSize = stream.Get_uint32 ();

	fAreaSpec.GetData (stream);

	fDegree = stream.Get_uint32 ();

	if (dataSize != dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8)
		{
		ThrowBadFormat ();
		}

	if (fDegree > kMaxDegree)
		{
		ThrowBadFormat ();
		}

	for (uint32 j = 0; j <= kMaxDegree; j++)
		{

		if (j <= fDegree)
			{
			fCoefficient [j] = stream.Get_real64 ();
			}
		else
			{
			fCoefficient [j] = 0.0;
			}

		}

	#if qDNGValidate

	if (gVerbose)
		{

		for (uint32 k = 0; k <= fDegree; k++)
			{
			printf ("    Coefficient [%u] = %f\n", k, fCoefficient [k]);
			}

		}

	#endif

	}
Exemple #6
0
void dng_opcode_TrimBounds::PutData (dng_stream &stream) const
	{

	stream.Put_uint32 (16);

	stream.Put_int32 (fBounds.t);
	stream.Put_int32 (fBounds.l);
	stream.Put_int32 (fBounds.b);
	stream.Put_int32 (fBounds.r);

	}
Exemple #7
0
void dng_area_spec::GetData (dng_stream &stream)
	{

	fArea.t = stream.Get_int32 ();
	fArea.l = stream.Get_int32 ();
	fArea.b = stream.Get_int32 ();
	fArea.r = stream.Get_int32 ();

	fPlane  = stream.Get_uint32 ();
	fPlanes = stream.Get_uint32 ();

	fRowPitch = stream.Get_uint32 ();
	fColPitch = stream.Get_uint32 ();

	if (fPlanes < 1)
		{
		ThrowBadFormat ();
		}

	if (fRowPitch < 1 || fColPitch < 1)
		{
		ThrowBadFormat ();
		}

	if (fArea.IsEmpty () && (fRowPitch != 1 || fColPitch != 1))
		{
		ThrowBadFormat ();
		}

	#if qDNGValidate

	if (gVerbose)
		{

		printf ("AreaSpec: t=%d, l=%d, b=%d, r=%d, p=%u:%u, rp=%u, cp=%u\n",
				(int) fArea.t,
				(int) fArea.l,
				(int) fArea.b,
				(int) fArea.r,
				(unsigned) fPlane,
				(unsigned) fPlanes,
				(unsigned) fRowPitch,
				(unsigned) fColPitch);

		}

	#endif

	}
Exemple #8
0
void dng_area_spec::PutData (dng_stream &stream) const
	{

	stream.Put_int32 (fArea.t);
	stream.Put_int32 (fArea.l);
	stream.Put_int32 (fArea.b);
	stream.Put_int32 (fArea.r);

	stream.Put_uint32 (fPlane);
	stream.Put_uint32 (fPlanes);

	stream.Put_uint32 (fRowPitch);
	stream.Put_uint32 (fColPitch);

	}
Exemple #9
0
void dng_opcode_MapPolynomial::PutData (dng_stream &stream) const
	{

	stream.Put_uint32 (dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8);

	fAreaSpec.PutData (stream);

	stream.Put_uint32 (fDegree);

	for (uint32 j = 0; j <= fDegree; j++)
		{
		stream.Put_real64 (fCoefficient [j]);
		}

	}
Exemple #10
0
void dng_opcode_MapTable::PutData (dng_stream &stream) const
	{

	stream.Put_uint32 (dng_area_spec::kDataSize + 4 + fCount * 2);

	fAreaSpec.PutData (stream);

	stream.Put_uint32 (fCount);

	uint16 *table = fTable->Buffer_uint16 ();

	for (uint32 index = 0; index < fCount; index++)
		{
		stream.Put_uint16 (table [index]);
		}

	}
Exemple #11
0
void dng_jpeg_preview::WriteData (dng_host & /* host */,
								  dng_image_writer & /* writer */,
								  dng_basic_tag_set &basic,
								  dng_stream &stream) const
	{
	
	basic.SetTileOffset (0, (uint32) stream.Position ());
	
	basic.SetTileByteCount (0, fCompressedData->LogicalSize ());
	
	stream.Put (fCompressedData->Buffer      (),
				fCompressedData->LogicalSize ());

	if (fCompressedData->LogicalSize () & 1)
		{
		stream.Put_uint8 (0);
		}
			
	}
Exemple #12
0
void dng_stream::CopyToStream (dng_stream &dstStream,
							   uint64 count)
	{
	
	uint8 smallBuffer [1024];
		
	if (count <= sizeof (smallBuffer))
		{
		
		Get (smallBuffer, (uint32) count);
		
		dstStream.Put (smallBuffer, (uint32) count);
		
		}
		
	else
		{
	
		const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
													      count);
		
		dng_memory_data bigBuffer (bigBufferSize);
		
		while (count)
			{
			
			uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
													 count);
													 
			Get (bigBuffer.Buffer (),
				 blockCount);
			
			dstStream.Put (bigBuffer.Buffer (),
						   blockCount);
						   
			count -= blockCount;
			
			}
	
		}

	}
Exemple #13
0
void dng_opcode_GainMap::PutData (dng_stream &stream) const
	{
	
	stream.Put_uint32 (dng_area_spec::kDataSize +
					   fGainMap->PutStreamSize ());
					   
	fAreaSpec.PutData (stream);
	
	fGainMap->PutStream (stream);
	
	}
Exemple #14
0
TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
									  dng_abort_sniffer *sniffer)
	
	:	fStream     (stream)
	,	fOldSniffer (stream.Sniffer ())
	
	{
	
	fStream.SetSniffer (sniffer);
	
	}
Exemple #15
0
TempBigEndian::TempBigEndian (dng_stream &stream,
						 	  bool bigEndian)
	
	:	fStream  (stream)
	,	fOldSwap (stream.SwapBytes ())
	
	{
	
	fStream.SetBigEndian (bigEndian);
	
	}
Exemple #16
0
dng_opcode_TrimBounds::dng_opcode_TrimBounds (dng_stream &stream)

	:	dng_opcode (dngOpcode_TrimBounds,
					stream,
					"TrimBounds")

	,	fBounds ()

	{

	if (stream.Get_uint32 () != 16)
		{
		ThrowBadFormat ();
		}

	fBounds.t = stream.Get_int32 ();
	fBounds.l = stream.Get_int32 ();
	fBounds.b = stream.Get_int32 ();
	fBounds.r = stream.Get_int32 ();

	if (fBounds.IsEmpty ())
		{
		ThrowBadFormat ();
		}

	#if qDNGValidate

	if (gVerbose)
		{

		printf ("Bounds: t=%d, l=%d, b=%d, r=%d\n",
				(int) fBounds.t,
				(int) fBounds.l,
				(int) fBounds.b,
				(int) fBounds.r);

		}

	#endif

	}
Exemple #17
0
void dng_opcode_DeltaPerRow::PutData (dng_stream &stream) const
	{

	uint32 deltas = (fAreaSpec.Area ().H () +
					 fAreaSpec.RowPitch () - 1) /
					 fAreaSpec.RowPitch ();

	stream.Put_uint32 (dng_area_spec::kDataSize + 4 + deltas * 4);

	fAreaSpec.PutData (stream);

	stream.Put_uint32 (deltas);

	real32 *table = fTable->Buffer_real32 ();

	for (uint32 j = 0; j < deltas; j++)
		{
		stream.Put_real32 (table [j]);
		}

	}
Exemple #18
0
void dng_opcode_ScalePerColumn::PutData (dng_stream &stream) const
	{

	uint32 scales = (fAreaSpec.Area ().W () +
					 fAreaSpec.ColPitch () - 1) /
					 fAreaSpec.ColPitch ();

	stream.Put_uint32 (dng_area_spec::kDataSize + 4 + scales * 4);

	fAreaSpec.PutData (stream);

	stream.Put_uint32 (scales);

	real32 *table = fTable->Buffer_real32 ();

	for (uint32 j = 0; j < scales; j++)
		{
		stream.Put_real32 (table [j]);
		}

	}
void dng_iptc::ParseString (dng_stream &stream,
						    dng_string &s,
						    CharSet charSet)
	{
	
	uint32 length = stream.Get_uint16 ();
	
	dng_memory_data buffer (length + 1);
	
	char *c = buffer.Buffer_char ();
	
	stream.Get (c, length);
	
	c [length] = 0;
	
	switch (charSet)
		{
		
		case kCharSetUTF8:
			{
			s.Set_UTF8 (c);
			break;
			}
			
		default:
			{
			s.Set_SystemEncoding (c);
			}
			
		}
	
	s.SetLineEndingsToNewLines ();
	
	s.StripLowASCII ();
	
	s.TrimTrailingBlanks ();
	
	}
void dng_memory_stream::CopyToStream (dng_stream &dstStream,
									  uint64 count)
	{
	
	if (count < kBigBufferSize)
		{
	
		dng_stream::CopyToStream (dstStream, count);
		
		}
		
	else
		{
		
		Flush ();
		
		uint64 offset = Position ();
		
		if (offset + count > Length ())
			{
			
			ThrowEndOfFile ();
			
			}
			
		while (count)
			{
			
			uint32 pageIndex  = (uint32) (offset / fPageSize);
			uint32 pageOffset = (uint32) (offset % fPageSize);
			
			uint32 blockCount = (uint32) Min_uint64 (fPageSize - pageOffset, count);
			
			const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () +
								pageOffset;
								
			dstStream.Put (sPtr, blockCount);
			
			offset += blockCount;
			count  -= blockCount;
			
			}
			
		SetReadPosition (offset);
	
		}
	
	}
Exemple #21
0
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
		
	}
Exemple #22
0
void dng_info::ParseTag (dng_host &host,
						 dng_stream &stream,
						 dng_exif *exif,
						 dng_shared *shared,
						 dng_ifd *ifd,
						 uint32 parentCode,
						 uint32 tagCode,
						 uint32 tagType,
						 uint32 tagCount,
						 uint64 tagOffset,
						 int64 offsetDelta)
	{
	
	bool isSubIFD = parentCode >= tcFirstSubIFD &&
					parentCode <= tcLastSubIFD;
					  
	bool isMainIFD = (parentCode == 0 || isSubIFD) &&
					 ifd &&
					 ifd->fUsesNewSubFileType &&
			 		 ifd->fNewSubFileType == sfMainImage;
			 		 
	// Panasonic RAW format stores private tags using tag codes < 254 in
	// IFD 0.  Redirect the parsing of these tags into a logical
	// "PanasonicRAW" IFD.
	
	// Panasonic is starting to use some higher numbers also (280..283).
			 		 
	if (fMagic == 85 && parentCode == 0 && (tagCode < tcNewSubFileType ||
											(tagCode >= 280 && tagCode <= 283)))
		{
		
		parentCode = tcPanasonicRAW;
		
		ifd = NULL;
		
		}
	
	stream.SetReadPosition (tagOffset);
		
	if (ifd && ifd->ParseTag (stream,
						 	  parentCode,
						 	  tagCode,
						 	  tagType,
						 	  tagCount,
						 	  tagOffset))
		{
		
		return;
		
		}
		
	stream.SetReadPosition (tagOffset);
		
	if (exif && shared && exif->ParseTag (stream,
										  *shared,
										  parentCode,
										  isMainIFD,
										  tagCode,
										  tagType,
										  tagCount,
										  tagOffset))
		{
		
		return;
		
		}
		
	stream.SetReadPosition (tagOffset);
		
	if (shared && exif && shared->ParseTag (stream,
											*exif,
								    		parentCode,
								    		isMainIFD,
								    		tagCode,
								    		tagType,
								    		tagCount,
								    		tagOffset,
								    		offsetDelta))
		{
		
		return;
		
		}
		
	if (parentCode == tcOlympusMakerNote &&
		tagType == ttUndefined &&
		tagCount >= 14)
		{
		
		uint32 olympusMakerParent = 0;
		
		switch (tagCode)
			{
			
			case 8208:
				olympusMakerParent = tcOlympusMakerNote8208;
				break;
				
			case 8224:
				olympusMakerParent = tcOlympusMakerNote8224;
				break; 
		
			case 8240:
				olympusMakerParent = tcOlympusMakerNote8240;
				break; 
		
			case 8256:
				olympusMakerParent = tcOlympusMakerNote8256;
				break; 
		
			case 8272:
				olympusMakerParent = tcOlympusMakerNote8272;
				break; 
		
			case 12288:
				olympusMakerParent = tcOlympusMakerNote12288;
				break;
				
			default:
				break;
				
			}
			
		if (olympusMakerParent)
			{
			
			// Olympus made a mistake in some camera models in computing
			// the size of these sub-tags, so we fudge the count.
			
			if (ParseMakerNoteIFD (host,
								   stream,
							       stream.Length () - tagOffset,
				   	  		       tagOffset,
				   	  		       offsetDelta,
				   	  		       tagOffset,
				   	  		       stream.Length (),
				   	  		       olympusMakerParent))
				{
				
				return;
				
				}
			
			}
			
		}
		
	if (parentCode == tcRicohMakerNote &&
		tagCode == 0x2001 &&
		tagType == ttUndefined &&
		tagCount > 22)
		{
		
		char header [20];
		
		stream.SetReadPosition (tagOffset);
		
		stream.Get (header, sizeof (header));
		
		if (memcmp (header, "[Ricoh Camera Info]", 19) == 0)
			{
		
			ParseMakerNoteIFD (host,
							   stream,
							   tagCount - 20,
				   	  		   tagOffset + 20,
				   	  		   offsetDelta,
				   	  		   tagOffset + 20,
				   	  		   tagOffset + tagCount,
				   	  		   tcRicohMakerNoteCameraInfo);

			return;
			
			}
			
		}
		
	#if qDNGValidate
	
		{
		
		stream.SetReadPosition (tagOffset);
		
		if (gVerbose)
			{
					
			printf ("*");
				
			DumpTagValues (stream,
						   LookupTagType (tagType),
						   parentCode,
						   tagCode,
						   tagType,
						   tagCount);
			
			}
			
		// If type is ASCII, then parse anyway so we report any ASCII
		// NULL termination or character set errors.
			
		else if (tagType == ttAscii)
			{
			
			dng_string s;
			
			ParseStringTag (stream,
							parentCode,
							tagCode,
							tagCount,
							s,
							false);

			}
			
		}
	
	#endif
	
	}
Exemple #23
0
void dng_info::ParseMakerNote (dng_host &host,
							   dng_stream &stream,
							   uint32 makerNoteCount,
							   uint64 makerNoteOffset,
							   int64 offsetDelta,
							   uint64 minOffset,
							   uint64 maxOffset)
	{
	
	uint8 firstBytes [16];
	
	memset (firstBytes, 0, sizeof (firstBytes));
	
	stream.SetReadPosition (makerNoteOffset);
	
	stream.Get (firstBytes, (uint32) Min_uint64 (sizeof (firstBytes),
												 makerNoteCount));
	
	// Epson MakerNote with header.
	
	if (memcmp (firstBytes, "EPSON\000\001\000", 8) == 0)
		{
		
		if (makerNoteCount > 8)
			{
		
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - 8,
				   	  		   makerNoteOffset + 8,
				   	  		   offsetDelta,
				   	  		   minOffset,
				   	  		   maxOffset,
				   	  		   tcEpsonMakerNote);
				   	  		   
			}
			
		return;
		
		}
		
	// Fujifilm MakerNote.
	
	if (memcmp (firstBytes, "FUJIFILM", 8) == 0)
		{
		
		stream.SetReadPosition (makerNoteOffset + 8);
		
		TempLittleEndian tempEndian (stream);
		
		uint32 ifd_offset = stream.Get_uint32 ();
		
		if (ifd_offset >= 12 && ifd_offset < makerNoteCount)
			{
			
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - ifd_offset,
							   makerNoteOffset + ifd_offset,
							   makerNoteOffset,
							   minOffset,
							   maxOffset,
							   tcFujiMakerNote);
			
			}
			
		return;
					
		}
		
	// Leica MakerNote.
	
	if (memcmp (firstBytes, "LEICA\000\000\000", 8) == 0)
		{
		
		if (makerNoteCount > 8)
			{
		
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - 8,
							   makerNoteOffset + 8,
							   makerNoteOffset,
							   minOffset,
							   maxOffset,
							   tcLeicaMakerNote);
							   
			}
		
		return;
		
		}
		
	// Nikon version 2 MakerNote with header.
	
	if (memcmp (firstBytes, "Nikon\000\002", 7) == 0)
		{
		
		stream.SetReadPosition (makerNoteOffset + 10);
		
		bool bigEndian = false;
		
		uint16 endianMark = stream.Get_uint16 ();
		
		if (endianMark == byteOrderMM)
			{
			bigEndian = true;
			}
			
		else if (endianMark != byteOrderII)
			{
			return;
			}
			
		TempBigEndian temp_endian (stream, bigEndian);
		
		uint16 magic = stream.Get_uint16 ();
		
		if (magic != 42)
			{
			return;
			}
			
		uint32 ifd_offset = stream.Get_uint32 ();
		
		if (ifd_offset >= 8 && ifd_offset < makerNoteCount - 10)
			{
			
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - 10 - ifd_offset,
							   makerNoteOffset + 10 + ifd_offset,
							   makerNoteOffset + 10,
							   minOffset,
							   maxOffset,
							   tcNikonMakerNote);
			
			}
			
		return;
					
		}
		
	// Newer version of Olympus MakerNote with byte order mark.
	
	if (memcmp (firstBytes, "OLYMPUS\000", 8) == 0)
		{
		
		stream.SetReadPosition (makerNoteOffset + 8);
		
		bool bigEndian = false;
		
		uint16 endianMark = stream.Get_uint16 ();
		
		if (endianMark == byteOrderMM)
			{
			bigEndian = true;
			}
			
		else if (endianMark != byteOrderII)
			{
			return;
			}
			
		TempBigEndian temp_endian (stream, bigEndian);
		
		uint16 version = stream.Get_uint16 ();
		
		if (version != 3)
			{
			return;
			}
		
		if (makerNoteCount > 12)
			{
		
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - 12,
				   	  		   makerNoteOffset + 12,
				   	  		   makerNoteOffset,
				   	  		   minOffset,
				   	  		   maxOffset,
				   	  		   tcOlympusMakerNote);
				   	  		   
			}
			
		return;
		
		}
		
	// Olympus MakerNote with header.
	
	if (memcmp (firstBytes, "OLYMP", 5) == 0)
		{
		
		if (makerNoteCount > 8)
			{
		
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - 8,
				   	  		   makerNoteOffset + 8,
				   	  		   offsetDelta,
				   	  		   minOffset,
				   	  		   maxOffset,
				   	  		   tcOlympusMakerNote);
				   	  		   
			}
			
		return;
		
		}
		
	// Panasonic MakerNote.
	
	if (memcmp (firstBytes, "Panasonic\000\000\000", 12) == 0)
		{
		
		if (makerNoteCount > 12)
			{
		
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - 12,
							   makerNoteOffset + 12,
							   offsetDelta,
							   minOffset,
							   maxOffset,
							   tcPanasonicMakerNote);
							   
			}
		
		return;
		
		}
		
	// Pentax MakerNote.
	
	if (memcmp (firstBytes, "AOC", 4) == 0)
		{
		
		if (makerNoteCount > 6)
			{
					
			stream.SetReadPosition (makerNoteOffset + 4);
			
			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,
							   makerNoteCount - 6,
							   makerNoteOffset + 6,
							   offsetDelta,
							   minOffset,
							   maxOffset,
							   tcPentaxMakerNote);
			
			}
			
		return;
		
		}
					
	// Ricoh MakerNote.
	
	if (memcmp (firstBytes, "RICOH", 5) == 0 ||
		memcmp (firstBytes, "Ricoh", 5) == 0)
		{
		
		if (makerNoteCount > 8)
			{
			
			TempBigEndian tempEndian (stream);
		
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount - 8,
				   	  		   makerNoteOffset + 8,
				   	  		   offsetDelta,
				   	  		   minOffset,
				   	  		   maxOffset,
				   	  		   tcRicohMakerNote);
				   	  		   
			}
			
		return;
		
		}
		
	// Nikon MakerNote without header.
	
	if (fExif->fMake.StartsWith ("NIKON"))
		{
		
		ParseMakerNoteIFD (host,
						   stream,
						   makerNoteCount,
			   	  		   makerNoteOffset,
			   	  		   offsetDelta,
			   	  		   minOffset,
			   	  		   maxOffset,
			   	  		   tcNikonMakerNote);
			   	  		   
		return;
			
		}
	
	// Canon MakerNote.
	
	if (fExif->fMake.StartsWith ("CANON"))
		{
		
		ParseMakerNoteIFD (host,
						   stream,
						   makerNoteCount,
			   	  		   makerNoteOffset,
			   	  		   offsetDelta,
			   	  		   minOffset,
			   	  		   maxOffset,
			   	  		   tcCanonMakerNote);
			
		return;
		
		}
		
	// Minolta MakerNote.
	
	if (fExif->fMake.StartsWith ("MINOLTA"       ) ||
		fExif->fMake.StartsWith ("KONICA MINOLTA"))
		{

		ParseMakerNoteIFD (host,
						   stream,
						   makerNoteCount,
						   makerNoteOffset,
						   offsetDelta,
						   minOffset,
						   maxOffset,
						   tcMinoltaMakerNote);
			
		return;
		
		}
	
	// Sony MakerNote.
	
	if (fExif->fMake.StartsWith ("SONY"))
		{

		ParseMakerNoteIFD (host,
						   stream,
						   makerNoteCount,
						   makerNoteOffset,
						   offsetDelta,
						   minOffset,
						   maxOffset,
						   tcSonyMakerNote);
			
		return;
		
		}
	
	// Kodak MakerNote.
	
	if (fExif->fMake.StartsWith ("EASTMAN KODAK"))
		{
		
		ParseMakerNoteIFD (host,
						   stream,
						   makerNoteCount,
			   	  		   makerNoteOffset,
			   	  		   offsetDelta,
			   	  		   minOffset,
			   	  		   maxOffset,
			   	  		   tcKodakMakerNote);
			   	  		   
		return;
			
		}
	
	// Mamiya MakerNote.
	
	if (fExif->fMake.StartsWith ("Mamiya"))
		{
		
		ParseMakerNoteIFD (host,
						   stream,
						   makerNoteCount,
			   	  		   makerNoteOffset,
			   	  		   offsetDelta,
			   	  		   minOffset,
			   	  		   maxOffset,
			   	  		   tcMamiyaMakerNote);
						   
		// Mamiya uses a MakerNote chain.
						   
		while (fMakerNoteNextIFD)
			{
			   	  		   
			ParseMakerNoteIFD (host,
							   stream,
							   makerNoteCount,
							   offsetDelta + fMakerNoteNextIFD,
							   offsetDelta,
							   minOffset,
							   maxOffset,
							   tcMamiyaMakerNote);
							   
			}
			   	  		   
		return;
			
		}
	
	// Nikon MakerNote without header.
	
	if (fExif->fMake.StartsWith ("Hasselblad"))
		{
		
		ParseMakerNoteIFD (host,
						   stream,
						   makerNoteCount,
			   	  		   makerNoteOffset,
			   	  		   offsetDelta,
			   	  		   minOffset,
			   	  		   maxOffset,
			   	  		   tcHasselbladMakerNote);
			   	  		   
		return;
			
		}
	
	}
Exemple #24
0
bool dng_info::ParseMakerNoteIFD (dng_host &host,
								  dng_stream &stream,
								  uint64 ifdSize,
						 		  uint64 ifdOffset,
								  int64 offsetDelta,
								  uint64 minOffset,
								  uint64 maxOffset,
						 		  uint32 parentCode)
	{
	
	uint32 tagIndex;
	uint32 tagCode;
	uint32 tagType;
	uint32 tagCount;
	
	// Assume there is no next IFD pointer.
	
	fMakerNoteNextIFD = 0;
	
	// If size is too small to hold a single entry IFD, abort.
	
	if (ifdSize < 14)
		{
		return false;
		}
		
	// Get entry count.
	
	stream.SetReadPosition (ifdOffset);
	
	uint32 ifdEntries = stream.Get_uint16 ();
	
	// Make the entry count if reasonable for the MakerNote size.
	
	if (ifdEntries < 1 || 2 + ifdEntries * 12 > ifdSize)
		{
		return false;
		}
		
	// Scan IFD to verify all the tag types are all valid.
		
	for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++)
		{
		
		stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12 + 2);
		
		tagType = stream.Get_uint16 ();
		
		// Kludge: Some Canon MakerNotes contain tagType = 0 tags, so we
		// need to ignore them.  This was a "firmware 1.0.4" Canon 40D raw file.
		
		if (parentCode == tcCanonMakerNote && tagType == 0)
			{
			continue;
			}
		
		if (TagTypeSize (tagType) == 0)
			{
			return false;
			}
		
		}
		
	// OK, the IFD looks reasonable enough to parse.
	
	#if qDNGValidate
	
	if (gVerbose)
		{
		
		printf ("%s: Offset = %u, Entries = %u\n\n",
				LookupParentCode (parentCode),
			    (unsigned) ifdOffset, 
			    (unsigned) ifdEntries);
		
		}
		
	#endif
		
	for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++)
		{
		
		stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12);
		
		tagCode  = stream.Get_uint16 ();
		tagType  = stream.Get_uint16 ();
		tagCount = stream.Get_uint32 ();
		
		if (tagType == 0)
			{
			continue;
			}
		
		uint32 tagSize = tagCount * TagTypeSize (tagType);
		
		uint64 tagOffset = ifdOffset + 2 + tagIndex * 12 + 8;
		
		if (tagSize > 4)
			{
			
			tagOffset = stream.Get_uint32 () + offsetDelta;
			
			if (tagOffset           < minOffset ||
				tagOffset + tagSize > maxOffset)
				{
				
				// Tag data is outside the valid offset range,
				// so ignore this tag.
				
				continue;
				
				}
			
			stream.SetReadPosition (tagOffset);
			
			}
			
		// Olympus switched to using IFDs in version 3 makernotes.
		
		if (parentCode == tcOlympusMakerNote &&
			tagType == ttIFD &&
			tagCount == 1)
			{
			
			uint32 olympusMakerParent = 0;
			
			switch (tagCode)
				{
				
				case 8208:
					olympusMakerParent = tcOlympusMakerNote8208;
					break;
					
				case 8224:
					olympusMakerParent = tcOlympusMakerNote8224;
					break; 
			
				case 8240:
					olympusMakerParent = tcOlympusMakerNote8240;
					break; 
			
				case 8256:
					olympusMakerParent = tcOlympusMakerNote8256;
					break; 
			
				case 8272:
					olympusMakerParent = tcOlympusMakerNote8272;
					break; 
			
				case 12288:
					olympusMakerParent = tcOlympusMakerNote12288;
					break;
					
				default:
					break;
					
				}
				
			if (olympusMakerParent)
				{
				
				stream.SetReadPosition (tagOffset);
			
				uint64 subMakerNoteOffset = stream.Get_uint32 () + offsetDelta;
				
				if (subMakerNoteOffset >= minOffset &&
					subMakerNoteOffset <  maxOffset)
					{
				
					if (ParseMakerNoteIFD (host,
										   stream,
										   maxOffset - subMakerNoteOffset,
										   subMakerNoteOffset,
										   offsetDelta,
										   minOffset,
										   maxOffset,
										   olympusMakerParent))
						{
						
						continue;
						
						}
						
					}
				
				}
				
			stream.SetReadPosition (tagOffset);
			
			}
		
		ParseTag (host,
				  stream,
				  fExif.Get (),
				  fShared.Get (),
				  NULL,
				  parentCode,
				  tagCode,
				  tagType,
				  tagCount,
				  tagOffset,
				  offsetDelta);
			
		}
		
	// Grab next IFD pointer, for possible use.
	
	if (ifdSize >= 2 + ifdEntries * 12 + 4)
		{
		
		stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12);
		
		fMakerNoteNextIFD = stream.Get_uint32 ();
		
		}
		
	#if qDNGValidate
		
	if (gVerbose)
		{
		printf ("\n");
		}
		
	#endif
		
	return true;
		
	}
Exemple #25
0
void dng_info::ParseIFD (dng_host &host,
						 dng_stream &stream,
						 dng_exif *exif,
						 dng_shared *shared,
						 dng_ifd *ifd,
						 uint64 ifdOffset,
						 int64 offsetDelta,
						 uint32 parentCode)
	{
	
	#if qDNGValidate

	bool isMakerNote = (parentCode >= tcFirstMakerNoteIFD &&
						parentCode <= tcLastMakerNoteIFD);
	
	#endif

	stream.SetReadPosition (ifdOffset);
	
	if (ifd)
		{
		ifd->fThisIFD = ifdOffset;
		}
	
	uint32 ifdEntries = stream.Get_uint16 ();
	
	#if qDNGValidate
	
	if (gVerbose)
		{
		
		printf ("%s: Offset = %u, Entries = %u\n\n",
				LookupParentCode (parentCode),
			    (unsigned) ifdOffset, 
			    (unsigned) ifdEntries);
		
		}
		
	if ((ifdOffset & 1) && !isMakerNote)
		{
		
		char message [256];
	
		sprintf (message,
				 "%s has odd offset (%u)",
				 LookupParentCode (parentCode),
				 (unsigned) ifdOffset);
					 
		ReportWarning (message);
		
		}
		
	#endif
		
	uint32 prev_tag_code = 0;
		
	for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++)
		{
		
		stream.SetReadPosition (ifdOffset + 2 + tag_index * 12);
		
		uint32 tagCode  = stream.Get_uint16 ();
		uint32 tagType  = stream.Get_uint16 ();
		
		// Minolta 7D files have a bug in the EXIF block where the count
		// is wrong, and we run off into next IFD link.  So if abort parsing
		// if we get a zero code/type combinations.
		
		if (tagCode == 0 && tagType == 0)
			{
			
			#if qDNGValidate
			
			char message [256];
	
			sprintf (message,
					 "%s had zero/zero tag code/type entry",
					 LookupParentCode (parentCode));
					 
			ReportWarning (message);
			
			#endif
			
			return;
			
			}
		
		uint32 tagCount = stream.Get_uint32 ();
		
		#if qDNGValidate

			{
		
			if (tag_index > 0 && tagCode <= prev_tag_code && !isMakerNote)
				{
				
				char message [256];
		
				sprintf (message,
						 "%s tags are not sorted in ascending numerical order",
						 LookupParentCode (parentCode));
						 
				ReportWarning (message);
				
				}
				
			}
			
		#endif
			
		prev_tag_code = tagCode;
		
		uint32 tag_type_size = TagTypeSize (tagType);
		
		if (tag_type_size == 0)
			{
			
			#if qDNGValidate
			
				{
			
				char message [256];
		
				sprintf (message,
						 "%s %s has unknown type (%u)",
						 LookupParentCode (parentCode),
						 LookupTagCode (parentCode, tagCode),
						 (unsigned) tagType);
						 
				ReportWarning (message);
							 
				}
				
			#endif
					 
			continue;
			
			}
			
		uint64 tagOffset = ifdOffset + 2 + tag_index * 12 + 8;
		
		if (tagCount * tag_type_size > 4)
			{
			
			tagOffset = stream.Get_uint32 ();
			
			#if qDNGValidate
			
				{
			
				if (!(ifdOffset & 1) && 
				     (tagOffset & 1) &&
				    !isMakerNote     &&
				    parentCode != tcKodakDCRPrivateIFD &&
					parentCode != tcKodakKDCPrivateIFD)
					{
					
					char message [256];
		
					sprintf (message,
							 "%s %s has odd data offset (%u)",
						 	 LookupParentCode (parentCode),
						 	 LookupTagCode (parentCode, tagCode),
							 (unsigned) tagOffset);
							 
					ReportWarning (message);
						 
					}
					
				}
				
			#endif
				
			tagOffset += offsetDelta;
				
			stream.SetReadPosition (tagOffset);
			
			}
			
		ParseTag (host,
				  stream,
			      exif,
				  shared,
				  ifd,
				  parentCode,
				  tagCode,
				  tagType,
				  tagCount,
				  tagOffset,
				  offsetDelta);
			
		}
		
	stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12);
	
	uint32 nextIFD = stream.Get_uint32 ();
	
	#if qDNGValidate
		
	if (gVerbose)
		{
		printf ("NextIFD = %u\n", (unsigned) nextIFD);
		}
		
	#endif
		
	if (ifd)
		{
		ifd->fNextIFD = nextIFD;
		}
		
	#if qDNGValidate

	if (nextIFD)
		{
		
		if (parentCode != 0 &&
				(parentCode < tcFirstChainedIFD ||
				 parentCode > tcLastChainedIFD  ))
			{

			char message [256];

			sprintf (message,
					 "%s has an unexpected non-zero NextIFD (%u)",
				 	 LookupParentCode (parentCode),
				 	 (unsigned) nextIFD);
					 
			ReportWarning (message);
					 
			}

		}
		
	if (gVerbose)
		{
		printf ("\n");
		}

	#endif
		
	}
Exemple #26
0
bool dng_info::ValidateIFD (dng_stream &stream,
						    uint64 ifdOffset,
						    int64 offsetDelta)
	{
	
	// Make sure we have a count.
	
	if (ifdOffset + 2 > stream.Length ())
		{
		return false;
		}
		
	// Get entry count.
		
	stream.SetReadPosition (ifdOffset);
	
	uint32 ifdEntries = stream.Get_uint16 ();
	
	if (ifdEntries < 1)
		{
		return false;
		}
		
	// Make sure we have room for all entries and next IFD link.
		
	if (ifdOffset + 2 + ifdEntries * 12 + 4 > stream.Length ())
		{
		return false;
		}
		
	// Check each entry.
	
	for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++)
		{
		
		stream.SetReadPosition (ifdOffset + 2 + tag_index * 12);
		
		stream.Skip (2);		// Ignore tag code.
		
		uint32 tagType  = stream.Get_uint16 ();
		uint32 tagCount = stream.Get_uint32 ();
		
		uint32 tag_type_size = TagTypeSize (tagType);
		
		if (tag_type_size == 0)
			{
			return false;
			}
			
		uint32 tag_data_size = tagCount * tag_type_size;
						
		if (tag_data_size > 4)
			{
			
			uint64 tagOffset = stream.Get_uint32 ();
							
			tagOffset += offsetDelta;
			
			if (tagOffset + tag_data_size > stream.Length ())
				{
				return false;
				}
			
			}
			
		}
		
	return true;
	
	}
Exemple #27
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 dng_iptc::SpoolString (dng_stream &stream,
							const dng_string &s,
							uint8 dataSet,
							uint32 maxChars,
							CharSet charSet)
	{
	
	if (s.IsEmpty ())
		{
		return;
		}
		
	stream.Put_uint16 (0x1C02);
	stream.Put_uint8  (dataSet);
	
	dng_string ss (s);
	
	ss.SetLineEndingsToReturns ();
	
	if (charSet == kCharSetUTF8)
		{
	
		// UTF-8 encoding.
		
		if (ss.Length () > maxChars)
			{
			ss.Truncate (maxChars);
			}
			
		uint32 len = ss.Length ();
			
		stream.Put_uint16 ((uint16) len);
		
		stream.Put (ss.Get (), len);
		
		}
		
	else
		{
	
		// System character set encoding.
		
		dng_memory_data buffer;
		
		uint32 len = ss.Get_SystemEncoding (buffer);
		
		if (len > maxChars)
			{
			
			uint32 lower = 0;
			uint32 upper = ss.Length () - 1;
			
			while (upper > lower)
				{
				
				uint32 middle = (upper + lower + 1) >> 1;
				
				dng_string sss (ss);
				
				sss.Truncate (middle);
				
				len = sss.Get_SystemEncoding (buffer);
				
				if (len <= maxChars)
					{
					
					lower = middle;
					
					}
					
				else
					{
					
					upper = middle - 1;
					
					}
				
				}
				
			ss.Truncate (lower);
			
			len = ss.Get_SystemEncoding (buffer);
			
			}
		
		stream.Put_uint16 ((uint16) len);
		
		stream.Put (buffer.Buffer_char (), len);
		
		}
Exemple #29
0
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_camera_profile::Parse (dng_stream &stream,
								dng_camera_profile_info &profileInfo)
	{
	
	SetUniqueCameraModelRestriction (profileInfo.fUniqueCameraModel.Get ());

	if (profileInfo.fProfileName.NotEmpty ())
		{
		
		SetName (profileInfo.fProfileName.Get ());
		
		}
	
	SetCopyright (profileInfo.fProfileCopyright.Get ());

	SetEmbedPolicy (profileInfo.fEmbedPolicy);

	SetCalibrationIlluminant1 (profileInfo.fCalibrationIlluminant1);
			
	SetColorMatrix1 (profileInfo.fColorMatrix1);
			
	if (profileInfo.fForwardMatrix1.NotEmpty ())
		{
		
		SetForwardMatrix1 (profileInfo.fForwardMatrix1);
		
		}
		
	if (profileInfo.fReductionMatrix1.NotEmpty ())
		{
		
		SetReductionMatrix1 (profileInfo.fReductionMatrix1);
		
		}
		
	if (profileInfo.fColorMatrix2.NotEmpty ())
		{
		
		SetCalibrationIlluminant2 (profileInfo.fCalibrationIlluminant2);
		
		SetColorMatrix2 (profileInfo.fColorMatrix2);
					
		if (profileInfo.fForwardMatrix2.NotEmpty ())
			{
			
			SetForwardMatrix2 (profileInfo.fForwardMatrix2);
			
			}
		
		if (profileInfo.fReductionMatrix2.NotEmpty ())
			{
			
			SetReductionMatrix2 (profileInfo.fReductionMatrix2);
			
			}
		
		}

	SetProfileCalibrationSignature (profileInfo.fProfileCalibrationSignature.Get ());

	if (profileInfo.fHueSatDeltas1Offset != 0 &&
		profileInfo.fHueSatDeltas1Count  != 0)
		{

		TempBigEndian setEndianness (stream, profileInfo.fBigEndian);

		stream.SetReadPosition (profileInfo.fHueSatDeltas1Offset);
		
		bool skipSat0 = (profileInfo.fHueSatDeltas1Count == profileInfo.fProfileHues *
														   (profileInfo.fProfileSats - 1) *
														    profileInfo.fProfileVals * 3);

		ReadHueSatMap (stream,
					   fHueSatDeltas1,
					   profileInfo.fProfileHues,
					   profileInfo.fProfileSats,
					   profileInfo.fProfileVals,
					   skipSat0);

		}

	if (profileInfo.fHueSatDeltas2Offset != 0 &&
		profileInfo.fHueSatDeltas2Count  != 0)
		{

		TempBigEndian setEndianness (stream, profileInfo.fBigEndian);

		stream.SetReadPosition (profileInfo.fHueSatDeltas2Offset);

		bool skipSat0 = (profileInfo.fHueSatDeltas2Count == profileInfo.fProfileHues *
														   (profileInfo.fProfileSats - 1) *
														    profileInfo.fProfileVals * 3);

		ReadHueSatMap (stream,
					   fHueSatDeltas2,
					   profileInfo.fProfileHues,
					   profileInfo.fProfileSats,
					   profileInfo.fProfileVals,
					   skipSat0);

		}

	if (profileInfo.fLookTableOffset != 0 &&
		profileInfo.fLookTableCount  != 0)
		{

		TempBigEndian setEndianness (stream, profileInfo.fBigEndian);

		stream.SetReadPosition (profileInfo.fLookTableOffset);

		bool skipSat0 = (profileInfo.fLookTableCount == profileInfo.fLookTableHues *
													   (profileInfo.fLookTableSats - 1) *
														profileInfo.fLookTableVals * 3);

		ReadHueSatMap (stream,
					   fLookTable,
					   profileInfo.fLookTableHues,
					   profileInfo.fLookTableSats,
					   profileInfo.fLookTableVals,
					   skipSat0);

		}

	if ((profileInfo.fToneCurveCount & 1) == 0)
		{

		TempBigEndian setEndianness (stream, profileInfo.fBigEndian);

		stream.SetReadPosition (profileInfo.fToneCurveOffset);

		uint32 points = profileInfo.fToneCurveCount / 2;

		fToneCurve.fCoord.resize (points);

		for (size_t i = 0; i < points; i++)
			{

			dng_point_real64 point;

			point.h = stream.Get_real32 ();
			point.v = stream.Get_real32 ();

			fToneCurve.fCoord [i] = point;

			}
			
		}
		
	}