Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tidying #306

Merged
merged 6 commits into from
Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions MetadataExtractor.Tests/DirectoryExtensionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ void AssertMissingBoolean(Directory dictionary, int i)

// NOTE string is not convertible to boolean other than for "true" and "false"

Test(BuildDirectory(_singleValues.Where(v => !(v is string))), AssertPresentTrueBoolean, AssertMissingBoolean);
Test(BuildDirectory(_singleZeroValues.Where(v => !(v is string))), AssertPresentFalseBoolean, AssertMissingBoolean);
Test(BuildDirectory(_arraysOfSingleValues.Where(v => !(v is string[]))), AssertPresentTrueBoolean, AssertMissingBoolean);
Test(BuildDirectory(_arraysOfSingleZeroValues.Where(v => !(v is string[]))), AssertPresentFalseBoolean, AssertMissingBoolean);
Test(BuildDirectory(_singleValues.Where(v => v is not string)), AssertPresentTrueBoolean, AssertMissingBoolean);
Test(BuildDirectory(_singleZeroValues.Where(v => v is not string)), AssertPresentFalseBoolean, AssertMissingBoolean);
Test(BuildDirectory(_arraysOfSingleValues.Where(v => v is not string[])), AssertPresentTrueBoolean, AssertMissingBoolean);
Test(BuildDirectory(_arraysOfSingleZeroValues.Where(v => v is not string[])), AssertPresentFalseBoolean, AssertMissingBoolean);

var directory = new MockDirectory();

Expand Down
2 changes: 1 addition & 1 deletion MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ protected ExifDescriptorBase(T directory)
if (values == null)
return null;

if (!(Directory.GetObject(TagCfaRepeatPatternDim) is ushort[] repeatPattern))
if (Directory.GetObject(TagCfaRepeatPatternDim) is not ushort[] repeatPattern)
return $"Repeat Pattern not found for CFAPattern ({base.GetDescription(TagCfaPattern2)})";

if (repeatPattern.Length == 2 && values.Length == (repeatPattern[0] * repeatPattern[1]))
Expand Down
130 changes: 66 additions & 64 deletions MetadataExtractor/Formats/Exif/ExifTiffHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using MetadataExtractor.Formats.Exif.Makernotes;
using MetadataExtractor.Formats.Icc;
using MetadataExtractor.Formats.Iptc;
using MetadataExtractor.Formats.Jpeg;
using MetadataExtractor.Formats.Photoshop;
using MetadataExtractor.Formats.Tiff;
using MetadataExtractor.Formats.Xmp;
Expand Down Expand Up @@ -194,7 +195,7 @@ public override bool CustomProcessTag(int tagOffset, HashSet<IfdIdentity> proces
{
var photoshopBytes = reader.GetBytes(tagOffset, byteCount);
var photoshopDirectories = new PhotoshopReader().Extract(new SequentialByteArrayReader(photoshopBytes), byteCount);
if (photoshopDirectories != null)
if (photoshopDirectories.Count != 0)
{
// Could be any number of directories. Only assign the Parent to the PhotoshopDirectory
photoshopDirectories.OfType<PhotoshopDirectory>().First().Parent = CurrentDirectory;
Expand Down Expand Up @@ -270,34 +271,77 @@ public override bool CustomProcessTag(int tagOffset, HashSet<IfdIdentity> proces
case PanasonicRawIfd0Directory.TagWbInfo:
var dirWbInfo = new PanasonicRawWbInfoDirectory { Parent = CurrentDirectory };
Directories.Add(dirWbInfo);
ProcessBinary(dirWbInfo, tagOffset, reader, byteCount, false, 2);
ProcessBinary(dirWbInfo, tagOffset, reader, byteCount, isSigned: false, arrayLength: 2);
return true;
case PanasonicRawIfd0Directory.TagWbInfo2:
var dirWbInfo2 = new PanasonicRawWbInfo2Directory { Parent = CurrentDirectory };
Directories.Add(dirWbInfo2);
ProcessBinary(dirWbInfo2, tagOffset, reader, byteCount, false, 3);
ProcessBinary(dirWbInfo2, tagOffset, reader, byteCount, isSigned: false, arrayLength: 3);
return true;
case PanasonicRawIfd0Directory.TagDistortionInfo:
var dirDistort = new PanasonicRawDistortionDirectory { Parent = CurrentDirectory };
Directories.Add(dirDistort);
ProcessBinary(dirDistort, tagOffset, reader, byteCount);
ProcessBinary(dirDistort, tagOffset, reader, byteCount, isSigned: true, arrayLength: 1);
return true;
}

static void ProcessBinary(Directory directory, int tagValueOffset, IndexedReader reader, int byteCount, bool isSigned, int arrayLength)
{
// expects signed/unsigned int16 (for now)
var byteSize = isSigned ? sizeof(short) : sizeof(ushort);

// 'directory' is assumed to contain tags that correspond to the byte position unless it's a set of bytes
for (var i = 0; i < byteCount; i++)
{
if (directory.HasTagName(i))
{
// only process this tag if the 'next' integral tag exists. Otherwise, it's a set of bytes
if (i < byteCount - 1 && directory.HasTagName(i + 1))
{
if (isSigned)
directory.Set(i, reader.GetInt16(tagValueOffset + i * byteSize));
else
directory.Set(i, reader.GetUInt16(tagValueOffset + i * byteSize));
}
else
{
// the next arrayLength bytes are a multi-byte value
if (isSigned)
{
var val = new short[arrayLength];
for (var j = 0; j < val.Length; j++)
val[j] = reader.GetInt16(tagValueOffset + (i + j) * byteSize);
directory.Set(i, val);
}
else
{
var val = new ushort[arrayLength];
for (var j = 0; j < val.Length; j++)
val[j] = reader.GetUInt16(tagValueOffset + (i + j) * byteSize);
directory.Set(i, val);
}

i += arrayLength - 1;
}
}

}
}
}

// Panasonic RAW sometimes contains an embedded version of the data as a JPG file.
if (tagId == PanasonicRawIfd0Directory.TagJpgFromRaw && CurrentDirectory is PanasonicRawIfd0Directory)
{
var jpegrawbytes = reader.GetBytes(tagOffset, byteCount);

// Extract information from embedded image since it is metadata-rich
var jpegmem = new MemoryStream(jpegrawbytes);
var jpegDirectory = Jpeg.JpegMetadataReader.ReadMetadata(jpegmem);
foreach (var dir in jpegDirectory)
var bytes = reader.GetBytes(tagOffset, byteCount);
var stream = new MemoryStream(bytes);

foreach (var directory in JpegMetadataReader.ReadMetadata(stream))
{
dir.Parent = CurrentDirectory;
Directories.Add(dir);
directory.Parent = CurrentDirectory;
Directories.Add(directory);
}

return true;
}

Expand Down Expand Up @@ -628,16 +672,17 @@ private static bool HandlePrintIM(Directory directory, int tagId)

if (tagId == 0x0E00)
{
// Tempting to say every tagid of 0x0E00 is a PIM tag, but can't be 100% sure
if (directory is CasioType2MakernoteDirectory ||
directory is KyoceraMakernoteDirectory ||
directory is NikonType2MakernoteDirectory ||
directory is OlympusMakernoteDirectory ||
directory is PanasonicMakernoteDirectory ||
directory is PentaxMakernoteDirectory ||
directory is RicohMakernoteDirectory ||
directory is SanyoMakernoteDirectory ||
directory is SonyType1MakernoteDirectory)
// It's tempting to say that every tag with ID 0x0E00 is a PIM tag, but we can't be 100% sure.
// Limit this to a specific set of directories.
if (directory is CasioType2MakernoteDirectory or
KyoceraMakernoteDirectory or
NikonType2MakernoteDirectory or
OlympusMakernoteDirectory or
PanasonicMakernoteDirectory or
PentaxMakernoteDirectory or
RicohMakernoteDirectory or
SanyoMakernoteDirectory or
SonyType1MakernoteDirectory)
return true;
}

Expand Down Expand Up @@ -701,49 +746,6 @@ private static void ProcessPrintIM(PrintIMDirectory directory, int tagValueOffse
}
}

private static void ProcessBinary(Directory directory, int tagValueOffset, IndexedReader reader, int byteCount, bool issigned = true, int arrayLength = 1)
{
// expects signed/unsigned int16 (for now)
var byteSize = issigned ? sizeof(short) : sizeof(ushort);

// 'directory' is assumed to contain tags that correspond to the byte position unless it's a set of bytes
for (var i = 0; i < byteCount; i++)
{
if (directory.HasTagName(i))
{
// only process this tag if the 'next' integral tag exists. Otherwise, it's a set of bytes
if (i < byteCount - 1 && directory.HasTagName(i + 1))
{
if (issigned)
directory.Set(i, reader.GetInt16(tagValueOffset + i * byteSize));
else
directory.Set(i, reader.GetUInt16(tagValueOffset + i * byteSize));
}
else
{
// the next arrayLength bytes are a multi-byte value
if (issigned)
{
var val = new short[arrayLength];
for (var j = 0; j < val.Length; j++)
val[j] = reader.GetInt16(tagValueOffset + (i + j) * byteSize);
directory.Set(i, val);
}
else
{
var val = new ushort[arrayLength];
for (var j = 0; j < val.Length; j++)
val[j] = reader.GetUInt16(tagValueOffset + (i + j) * byteSize);
directory.Set(i, val);
}

i += arrayLength - 1;
}
}

}
}

private static void ProcessKodakMakernote(KodakMakernoteDirectory directory, int tagValueOffset, IndexedReader reader)
{
// Kodak's makernote is not in IFD format. It has values at fixed offsets.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ public CanonMakernoteDirectory() : base(_tagNameMap)

public override void Set(int tagType, object value)
{
if (!(value is ushort[] array))
if (value is not ushort[] array)
{
base.Set(tagType, value);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public LeicaType5MakernoteDescriptor(LeicaType5MakernoteDirectory directory)
/// <returns></returns>
public string? GetExposureModeDescription()
{
if (!(Directory.GetObject(LeicaType5MakernoteDirectory.TagExposureMode) is byte[] values) || values.Length < 4)
if (Directory.GetObject(LeicaType5MakernoteDirectory.TagExposureMode) is not byte[] values || values.Length < 4)
return null;

var join = $"{values[0]} {values[1]} {values[2]} {values[3]}";
Expand Down
Loading