-
Notifications
You must be signed in to change notification settings - Fork 170
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
Introduce BufferReader and eliminate a bunch of allocations #393
Conversation
@drewnoakes Ready for feedback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a promising approach!
MetadataExtractor/IO/BufferReader.cs
Outdated
if (_position + n > _bytes.Length) | ||
throw new IOException("End of data reached."); | ||
|
||
_position += unchecked((int)n); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe checked would be better here. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be safer, yes. Let me spent some time on this file, and go through usual diligence. I was a bit haphazard with copying / pasting here from SequentialByteReader, and overly confident on our test coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generally rely upon the regression test suite to validate changes, as it flexes loads more code paths than unit tests do. That's how I found the regressions fixed in #391. Do you have that repo cloned locally? Let me know if you have any questions about getting that running locally. There are some docs at https://github.com/drewnoakes/metadata-extractor/wiki/Working-with-test-images but they might be out of date. The source to run is actually in the metadata-extractor-images
repo. If you don't have the Java version built locally, you can comment out the JavaRunner
line and rely upon the files already present in the repo. Note that the output files will vary based on Java/.NET version. In general, the main
branch should produce the output in that repo (unless I forget to push).
MetadataExtractor/IO/BufferReader.cs
Outdated
if (n < 0) | ||
throw new ArgumentException("n must be zero or greater."); | ||
|
||
_position += unchecked((int)n); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
MetadataExtractor/IO/BufferReader.cs
Outdated
{ | ||
Span<byte> bytes = stackalloc byte[2]; | ||
|
||
GetBytes(bytes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This copy could be avoided I think. Can't we just slice the inner array? Ditto elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated.
MetadataExtractor/IO/BufferReader.cs
Outdated
private int _position = 0; | ||
private bool _isBigEndian = isBigEndian; | ||
|
||
public long Position => _position; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider returning int here. We don't really support long values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. This was modeled after SequentialByteReader, but this only works on 32 bit spans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arrays don't support long indexing, but Streams do. Some image files can be over 2GB, so it's important that we handle long streams correctly.
MetadataExtractor/IO/BufferReader.cs
Outdated
|
||
public bool TrySkip(long n) | ||
{ | ||
if (n < 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are keeping this type internal, these argument validations could be debug asserts, to avoid overhead in release binaries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. No reason for this to be public, so we can continue to improve.
Did my comments come through? GitHub mobile issues again? Will be at a desktop shortly. |
I just ran your PR branch (merged with main) across the regression test suite and hit this assert:
|
The failing file is Looking at that code, we don't validate that the segment span is long enough for the read operations we want to perform. We need to either add that validation, or reintroduce the precondition and throw an |
Another hit in |
I was able to fix all asserts in the regression suite with the following diff: diff --git a/MetadataExtractor/Formats/Jpeg/JpegReader.cs b/MetadataExtractor/Formats/Jpeg/JpegReader.cs
index 78499c0a..60a02fd2 100644
--- a/MetadataExtractor/Formats/Jpeg/JpegReader.cs
+++ b/MetadataExtractor/Formats/Jpeg/JpegReader.cs
@@ -31,6 +31,14 @@ namespace MetadataExtractor.Formats.Jpeg
var reader = new BufferReader(segment.Span, isBigEndian: true);
+ const int JpegHeaderSize = 1 + 2 + 2 + 1;
+
+ if (segment.Span.Length < JpegHeaderSize)
+ {
+ directory.AddError("Insufficient bytes for JPEG segment header.");
+ return directory;
+ }
+
try
{
directory.Set(JpegDirectory.TagDataPrecision, reader.GetByte());
@@ -41,6 +49,14 @@ namespace MetadataExtractor.Formats.Jpeg
directory.Set(JpegDirectory.TagNumberOfComponents, componentCount);
+ const int JpegComponentSize = 1 + 1 + 1;
+
+ if (segment.Span.Length < JpegHeaderSize + componentCount * JpegComponentSize)
+ {
+ directory.AddError("Insufficient bytes for JPEG the requested number of JPEG components.");
+ return directory;
+ }
+
// For each component, there are three bytes of data:
// 1 - Component ID: 1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q
// 2 - Sampling factors: bit 0-3 vertical, 4-7 horizontal
diff --git a/MetadataExtractor/Formats/Png/PngMetadataReader.cs b/MetadataExtractor/Formats/Png/PngMetadataReader.cs
index 21a0742a..40e7d8bf 100644
--- a/MetadataExtractor/Formats/Png/PngMetadataReader.cs
+++ b/MetadataExtractor/Formats/Png/PngMetadataReader.cs
@@ -295,35 +295,52 @@ namespace MetadataExtractor.Formats.Png
}
else if (chunkType == PngChunkType.tIME)
{
- var reader = new BufferReader(bytes, isBigEndian: true);
- var year = reader.GetUInt16();
- var month = reader.GetByte();
- int day = reader.GetByte();
- int hour = reader.GetByte();
- int minute = reader.GetByte();
- int second = reader.GetByte();
var directory = new PngDirectory(PngChunkType.tIME);
- if (DateUtil.IsValidDate(year, month, day) && DateUtil.IsValidTime(hour, minute, second))
+
+ if (bytes.Length < 2 + 1 + 1 + 1 + 1 + 1)
{
- var time = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified);
- directory.Set(PngDirectory.TagLastModificationTime, time);
+ directory.AddError("Insufficient bytes for PNG tIME chunk.");
}
else
{
- directory.AddError($"PNG tIME data describes an invalid date/time: year={year} month={month} day={day} hour={hour} minute={minute} second={second}");
+ var reader = new BufferReader(bytes, isBigEndian: true);
+ var year = reader.GetUInt16();
+ var month = reader.GetByte();
+ int day = reader.GetByte();
+ int hour = reader.GetByte();
+ int minute = reader.GetByte();
+ int second = reader.GetByte();
+ if (DateUtil.IsValidDate(year, month, day) && DateUtil.IsValidTime(hour, minute, second))
+ {
+ var time = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified);
+ directory.Set(PngDirectory.TagLastModificationTime, time);
+ }
+ else
+ {
+ directory.AddError($"PNG tIME data describes an invalid date/time: year={year} month={month} day={day} hour={hour} minute={minute} second={second}");
+ }
}
yield return directory;
}
else if (chunkType == PngChunkType.pHYs)
{
- var reader = new BufferReader(bytes, isBigEndian: true);
- var pixelsPerUnitX = reader.GetInt32();
- var pixelsPerUnitY = reader.GetInt32();
- var unitSpecifier = reader.GetSByte();
var directory = new PngDirectory(PngChunkType.pHYs);
- directory.Set(PngDirectory.TagPixelsPerUnitX, pixelsPerUnitX);
- directory.Set(PngDirectory.TagPixelsPerUnitY, pixelsPerUnitY);
- directory.Set(PngDirectory.TagUnitSpecifier, unitSpecifier);
+
+ if (bytes.Length < 4 + 4 + 1)
+ {
+ directory.AddError("Insufficient bytes for PNG pHYs chunk.");
+ }
+ else
+ {
+ var reader = new BufferReader(bytes, isBigEndian: true);
+ var pixelsPerUnitX = reader.GetInt32();
+ var pixelsPerUnitY = reader.GetInt32();
+ var unitSpecifier = reader.GetSByte();
+ directory.Set(PngDirectory.TagPixelsPerUnitX, pixelsPerUnitX);
+ directory.Set(PngDirectory.TagPixelsPerUnitY, pixelsPerUnitY);
+ directory.Set(PngDirectory.TagUnitSpecifier, unitSpecifier);
+ }
+
yield return directory;
}
else if (chunkType.Equals(PngChunkType.sBIT)) That said, there are other usages of the reader that aren't validating byte length, so maybe a debug assertion is not enough. Also, there are a few diffs created by this PR that need to be investigated before we can merge this. Full regression diffdiff --git a/jpg/ImageTestSuite/metadata/dotnet/c8bc97335529d069a753c67475b8c82c.jpg.txt b/jpg/ImageTestSuite/metadata/dotnet/c8bc97335529d069a753c67475b8c82c.jpg.txt
index 8a968f55..120d8200 100644
--- a/jpg/ImageTestSuite/metadata/dotnet/c8bc97335529d069a753c67475b8c82c.jpg.txt
+++ b/jpg/ImageTestSuite/metadata/dotnet/c8bc97335529d069a753c67475b8c82c.jpg.txt
@@ -1,14 +1,13 @@
FILE: c8bc97335529d069a753c67475b8c82c.jpg
TYPE: JPEG
-[ERROR: JPEG] End of data reached.
+[ERROR: JPEG] Insufficient bytes for JPEG the requested number of JPEG components.
[JPEG - 0xfffffffd] Compression Type = Baseline
[JPEG - 0x0000] Data Precision = 159 bits
[JPEG - 0x0001] Image Height = 256 pixels
[JPEG - 0x0003] Image Width = 529 pixels
[JPEG - 0x0005] Number of Components = 3
-[JPEG - 0x0006] Component 1 = Unknown (17) component: Quantization table 63, Sampling factors 0 horiz/0 vert
[Ducky - 0x0001] Quality = 60
diff --git a/jpg/metadata/diff/Issue 339.jpg.txt b/jpg/metadata/diff/Issue 339.jpg.txt
index 71f926d8..89cd66af 100644
--- a/jpg/metadata/diff/Issue 339.jpg.txt
+++ b/jpg/metadata/diff/Issue 339.jpg.txt
@@ -110,7 +110,8 @@
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
- [Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0
+JAVA [Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0
+DOTNET [Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a
[Olympus Camera Settings - 0x0500] White Balance 2 = 5300K (Fine Weather)
diff --git a/jpg/metadata/dotnet/Issue 339.jpg.txt b/jpg/metadata/dotnet/Issue 339.jpg.txt
index 11af269d..7a08413b 100644
--- a/jpg/metadata/dotnet/Issue 339.jpg.txt
+++ b/jpg/metadata/dotnet/Issue 339.jpg.txt
@@ -110,7 +110,7 @@ TYPE: JPEG
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a
[Olympus Camera Settings - 0x0500] White Balance 2 = 5300K (Fine Weather)
diff --git a/jpg/metadata/dotnet/Olympus E-M1.jpg.txt b/jpg/metadata/dotnet/Olympus E-M1.jpg.txt
index efb01697..acbde5bc 100644
--- a/jpg/metadata/dotnet/Olympus E-M1.jpg.txt
+++ b/jpg/metadata/dotnet/Olympus E-M1.jpg.txt
@@ -105,7 +105,7 @@ TYPE: JPEG
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto (Keep Warm Color Off)
diff --git a/jpg/metadata/dotnet/Olympus E-M5.jpg.txt b/jpg/metadata/dotnet/Olympus E-M5.jpg.txt
index 9a484704..6a7b3ef8 100644
--- a/jpg/metadata/dotnet/Olympus E-M5.jpg.txt
+++ b/jpg/metadata/dotnet/Olympus E-M5.jpg.txt
@@ -105,7 +105,7 @@ TYPE: JPEG
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/jpg/metadata/dotnet/Olympus PEN E-P3.jpg.txt b/jpg/metadata/dotnet/Olympus PEN E-P3.jpg.txt
index be2c3e57..8d67c7e7 100644
--- a/jpg/metadata/dotnet/Olympus PEN E-P3.jpg.txt
+++ b/jpg/metadata/dotnet/Olympus PEN E-P3.jpg.txt
@@ -106,7 +106,7 @@ TYPE: JPEG
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = 5300K (Fine Weather)
diff --git a/orf/metadata/diff/OM Sytem OM-1.orf.txt b/orf/metadata/diff/OM Sytem OM-1.orf.txt
index cf88dbeb..fe44b12c 100644
--- a/orf/metadata/diff/OM Sytem OM-1.orf.txt
+++ b/orf/metadata/diff/OM Sytem OM-1.orf.txt
@@ -134,7 +134,7 @@ DOTNET [Olympus Camera Settings - 0x0400] Flash Mode = Fill-in
DOTNET [Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
DOTNET [Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
DOTNET [Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-DOTNET [Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+DOTNET [Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
DOTNET [Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
DOTNET [Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
DOTNET [Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/OM Sytem OM-1.orf.txt b/orf/metadata/dotnet/OM Sytem OM-1.orf.txt
index 847d43fb..c329c63d 100644
--- a/orf/metadata/dotnet/OM Sytem OM-1.orf.txt
+++ b/orf/metadata/dotnet/OM Sytem OM-1.orf.txt
@@ -125,7 +125,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/Olympus E-M10.orf.txt b/orf/metadata/dotnet/Olympus E-M10.orf.txt
index ff61af1b..18b6103b 100644
--- a/orf/metadata/dotnet/Olympus E-M10.orf.txt
+++ b/orf/metadata/dotnet/Olympus E-M10.orf.txt
@@ -104,7 +104,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/Olympus E-M5.orf.txt b/orf/metadata/dotnet/Olympus E-M5.orf.txt
index d10f6976..0b6aa19e 100644
--- a/orf/metadata/dotnet/Olympus E-M5.orf.txt
+++ b/orf/metadata/dotnet/Olympus E-M5.orf.txt
@@ -104,7 +104,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/Olympus E-PL7.orf.txt b/orf/metadata/dotnet/Olympus E-PL7.orf.txt
index c10d5e3b..d21aaded 100644
--- a/orf/metadata/dotnet/Olympus E-PL7.orf.txt
+++ b/orf/metadata/dotnet/Olympus E-PL7.orf.txt
@@ -104,7 +104,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = 5300K (Fine Weather)
diff --git a/orf/metadata/dotnet/Olympus E-PM1.orf.txt b/orf/metadata/dotnet/Olympus E-PM1.orf.txt
index 8941edf6..7935e23f 100644
--- a/orf/metadata/dotnet/Olympus E-PM1.orf.txt
+++ b/orf/metadata/dotnet/Olympus E-PM1.orf.txt
@@ -101,7 +101,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/Olympus E30.orf.txt b/orf/metadata/dotnet/Olympus E30.orf.txt
index 7c287341..74e11895 100644
--- a/orf/metadata/dotnet/Olympus E30.orf.txt
+++ b/orf/metadata/dotnet/Olympus E30.orf.txt
@@ -98,7 +98,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/Olympus E600.orf.txt b/orf/metadata/dotnet/Olympus E600.orf.txt
index 6c989653..413f76a7 100644
--- a/orf/metadata/dotnet/Olympus E600.orf.txt
+++ b/orf/metadata/dotnet/Olympus E600.orf.txt
@@ -98,7 +98,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a
[Olympus Camera Settings - 0x0500] White Balance 2 = 5300K (Fine Weather)
diff --git a/orf/metadata/dotnet/Olympus PEN E-P3.orf.txt b/orf/metadata/dotnet/Olympus PEN E-P3.orf.txt
index a5c8d1df..d4651b43 100644
--- a/orf/metadata/dotnet/Olympus PEN E-P3.orf.txt
+++ b/orf/metadata/dotnet/Olympus PEN E-P3.orf.txt
@@ -101,7 +101,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = 5300K (Fine Weather)
diff --git a/orf/metadata/dotnet/Olympus Pen E-PL1.orf.txt b/orf/metadata/dotnet/Olympus Pen E-PL1.orf.txt
index f2a07917..206eabed 100644
--- a/orf/metadata/dotnet/Olympus Pen E-PL1.orf.txt
+++ b/orf/metadata/dotnet/Olympus Pen E-PL1.orf.txt
@@ -100,7 +100,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/Olympus TG-4.orf.txt b/orf/metadata/dotnet/Olympus TG-4.orf.txt
index 5c92ea2d..0466c55a 100644
--- a/orf/metadata/dotnet/Olympus TG-4.orf.txt
+++ b/orf/metadata/dotnet/Olympus TG-4.orf.txt
@@ -86,7 +86,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = 0
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a (x4)
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a (x4)
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/orf/metadata/dotnet/Olympus XZ1.orf.txt b/orf/metadata/dotnet/Olympus XZ1.orf.txt
index 7bb5b45c..885ea28c 100644
--- a/orf/metadata/dotnet/Olympus XZ1.orf.txt
+++ b/orf/metadata/dotnet/Olympus XZ1.orf.txt
@@ -89,7 +89,7 @@ TYPE: ORF
[Olympus Camera Settings - 0x0401] Flash Exposure Comp = -2
[Olympus Camera Settings - 0x0402] Unknown tag (0x0402) = 0
[Olympus Camera Settings - 0x0403] Flash Remote Control = Off
-[Olympus Camera Settings - 0x0404] Flash Control Mode = Off; 0; 0
+[Olympus Camera Settings - 0x0404] Flash Control Mode = OffOff; 0; 0
[Olympus Camera Settings - 0x0405] Flash Intensity = n/a
[Olympus Camera Settings - 0x0406] Manual Flash Strength = n/a
[Olympus Camera Settings - 0x0500] White Balance 2 = Auto
diff --git a/png/ImageTestSuite/metadata/dotnet/e76546768d4a8f2f4c39339345c7614c.png.txt b/png/ImageTestSuite/metadata/dotnet/e76546768d4a8f2f4c39339345c7614c.png.txt
index a37226bf..ac79ab99 100644
--- a/png/ImageTestSuite/metadata/dotnet/e76546768d4a8f2f4c39339345c7614c.png.txt
+++ b/png/ImageTestSuite/metadata/dotnet/e76546768d4a8f2f4c39339345c7614c.png.txt
@@ -1,7 +1,7 @@
FILE: e76546768d4a8f2f4c39339345c7614c.png
TYPE: PNG
-[ERROR: Error] Exception reading PNG chunk: End of data reached.
+[ERROR: PNG-pHYs] Insufficient bytes for PNG pHYs chunk.
[PNG-IHDR - 0x0001] Image Width = 32
[PNG-IHDR - 0x0002] Image Height = 32
@@ -27,7 +27,7 @@ TYPE: PNG
- PNG-IHDR
- PNG-gAMA
- PNG-sBIT
-- Error
+- PNG-pHYs
- File Type
- File The error message diffs would be ok. We could add the same error messages to the Java library too. But the tag value diff is weird and needs fixing. |
Encoding.ASCII converts non-printable characters to '?', yet 4CC may contain non-printable.
Use `Skip` to skip data and completely ignore it.
Thanks again! Great stuff here. I pushed a few changes as I worked with the regression test suite to preserve output parity. |
This PR introduces a ref struct based BufferReader that can operate directly over a span -- and applies it to eliminate a bunch of random allocations.
This same approach can also be used to optimize various Extract functions with a public API change.