Skip to content

Commit 1797fee

Browse files
Merge pull request #549 from SixLabors/js/better-identify
Better Jpeg Identify
2 parents eeaf976 + 2f29567 commit 1797fee

File tree

13 files changed

+1238
-450
lines changed

13 files changed

+1238
-450
lines changed

src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ public OrigComponent(byte identifier, int index)
5757
/// </summary>
5858
/// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param>
5959
/// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param>
60-
/// <param name="metadataOnly">Whether to decode metadata only. If this is true, memory allocation for SpectralBlocks will not be necessary</param>
61-
public void InitializeDerivedData(MemoryManager memoryManager, OrigJpegDecoderCore decoder, bool metadataOnly)
60+
public void InitializeDerivedData(MemoryManager memoryManager, OrigJpegDecoderCore decoder)
6261
{
6362
// For 4-component images (either CMYK or YCbCrK), we only support two
6463
// hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22].
@@ -81,10 +80,7 @@ public void InitializeDerivedData(MemoryManager memoryManager, OrigJpegDecoderCo
8180
this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors);
8281
}
8382

84-
if (!metadataOnly)
85-
{
86-
this.SpectralBlocks = memoryManager.Allocate2D<Block8x8>(this.SizeInBlocks.Width, this.SizeInBlocks.Height, true);
87-
}
83+
this.SpectralBlocks = memoryManager.Allocate2D<Block8x8>(this.SizeInBlocks.Width, this.SizeInBlocks.Height, true);
8884
}
8985

9086
/// <summary>

src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ public OrigJpegDecoderCore(Configuration configuration, IJpegDecoderOptions opti
8787
{
8888
this.IgnoreMetadata = options.IgnoreMetadata;
8989
this.configuration = configuration ?? Configuration.Default;
90-
this.HuffmanTrees = OrigHuffmanTree.CreateHuffmanTrees();
91-
this.QuantizationTables = new Block8x8F[MaxTq + 1];
9290
this.Temp = new byte[2 * Block8x8F.Size];
9391
}
9492

@@ -103,10 +101,10 @@ public OrigJpegDecoderCore(Configuration configuration, IJpegDecoderOptions opti
103101
/// <summary>
104102
/// Gets the huffman trees
105103
/// </summary>
106-
public OrigHuffmanTree[] HuffmanTrees { get; }
104+
public OrigHuffmanTree[] HuffmanTrees { get; private set; }
107105

108106
/// <inheritdoc />
109-
public Block8x8F[] QuantizationTables { get; }
107+
public Block8x8F[] QuantizationTables { get; private set; }
110108

111109
/// <summary>
112110
/// Gets the temporary buffer used to store bytes read from the stream.
@@ -193,7 +191,6 @@ public Image<TPixel> Decode<TPixel>(Stream stream)
193191
where TPixel : struct, IPixel<TPixel>
194192
{
195193
this.ParseStream(stream);
196-
197194
return this.PostProcessIntoImage<TPixel>();
198195
}
199196

@@ -204,7 +201,6 @@ public Image<TPixel> Decode<TPixel>(Stream stream)
204201
public IImageInfo Identify(Stream stream)
205202
{
206203
this.ParseStream(stream, true);
207-
208204
return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData);
209205
}
210206

@@ -215,7 +211,7 @@ public void Dispose()
215211
{
216212
foreach (OrigComponent component in this.Components)
217213
{
218-
component.Dispose();
214+
component?.Dispose();
219215
}
220216
}
221217

@@ -233,6 +229,12 @@ public void ParseStream(Stream stream, bool metadataOnly = false)
233229
this.InputStream = stream;
234230
this.InputProcessor = new InputProcessor(stream, this.Temp);
235231

232+
if (!metadataOnly)
233+
{
234+
this.HuffmanTrees = OrigHuffmanTree.CreateHuffmanTrees();
235+
this.QuantizationTables = new Block8x8F[MaxTq + 1];
236+
}
237+
236238
// Check for the Start Of Image marker.
237239
this.InputProcessor.ReadFull(this.Temp, 0, 2);
238240

@@ -332,10 +334,6 @@ public void ParseStream(Stream stream, bool metadataOnly = false)
332334
case OrigJpegConstants.Markers.SOF2:
333335
this.IsProgressive = marker == OrigJpegConstants.Markers.SOF2;
334336
this.ProcessStartOfFrameMarker(remaining, metadataOnly);
335-
if (metadataOnly && this.isJFif)
336-
{
337-
return;
338-
}
339337

340338
break;
341339
case OrigJpegConstants.Markers.DHT:
@@ -361,19 +359,24 @@ public void ParseStream(Stream stream, bool metadataOnly = false)
361359

362360
break;
363361
case OrigJpegConstants.Markers.SOS:
364-
if (metadataOnly)
362+
if (!metadataOnly)
365363
{
366-
return;
364+
this.ProcessStartOfScanMarker(remaining);
365+
if (this.InputProcessor.ReachedEOF)
366+
{
367+
// If unexpected EOF reached. We can stop processing bytes as we now have the image data.
368+
processBytes = false;
369+
}
367370
}
368-
369-
this.ProcessStartOfScanMarker(remaining);
370-
if (this.InputProcessor.ReachedEOF)
371+
else
371372
{
372-
// If unexpected EOF reached. We can stop processing bytes as we now have the image data.
373+
// It's highly unlikely that APPn related data will be found after the SOS marker
374+
// We should have gathered everything we need by now.
373375
processBytes = false;
374376
}
375377

376378
break;
379+
377380
case OrigJpegConstants.Markers.DRI:
378381
if (metadataOnly)
379382
{
@@ -425,7 +428,12 @@ public bool IsAtRestartInterval(int mcuCounter)
425428
/// </summary>
426429
private void InitDerivedMetaDataProperties()
427430
{
428-
if (this.isExif)
431+
if (this.isJFif)
432+
{
433+
this.MetaData.HorizontalResolution = this.jFif.XDensity;
434+
this.MetaData.VerticalResolution = this.jFif.YDensity;
435+
}
436+
else if (this.isExif)
429437
{
430438
double horizontalValue = this.MetaData.ExifProfile.TryGetValue(ExifTag.XResolution, out ExifValue horizonalTag)
431439
? ((Rational)horizonalTag.Value).ToDouble()
@@ -441,11 +449,6 @@ private void InitDerivedMetaDataProperties()
441449
this.MetaData.VerticalResolution = verticalValue;
442450
}
443451
}
444-
else if (this.isJFif)
445-
{
446-
this.MetaData.HorizontalResolution = this.jFif.XDensity;
447-
this.MetaData.VerticalResolution = this.jFif.YDensity;
448-
}
449452
}
450453

451454
/// <summary>
@@ -675,26 +678,29 @@ private void ProcessStartOfFrameMarker(int remaining, bool metadataOnly)
675678
throw new ImageFormatException("SOF has wrong length");
676679
}
677680

678-
this.Components = new OrigComponent[this.ComponentCount];
679-
680-
for (int i = 0; i < this.ComponentCount; i++)
681+
if (!metadataOnly)
681682
{
682-
byte componentIdentifier = this.Temp[6 + (3 * i)];
683-
var component = new OrigComponent(componentIdentifier, i);
684-
component.InitializeCoreData(this);
685-
this.Components[i] = component;
686-
}
683+
this.Components = new OrigComponent[this.ComponentCount];
687684

688-
int h0 = this.Components[0].HorizontalSamplingFactor;
689-
int v0 = this.Components[0].VerticalSamplingFactor;
685+
for (int i = 0; i < this.ComponentCount; i++)
686+
{
687+
byte componentIdentifier = this.Temp[6 + (3 * i)];
688+
var component = new OrigComponent(componentIdentifier, i);
689+
component.InitializeCoreData(this);
690+
this.Components[i] = component;
691+
}
690692

691-
this.ImageSizeInMCU = this.ImageSizeInPixels.DivideRoundUp(8 * h0, 8 * v0);
693+
int h0 = this.Components[0].HorizontalSamplingFactor;
694+
int v0 = this.Components[0].VerticalSamplingFactor;
692695

693-
this.ColorSpace = this.DeduceJpegColorSpace();
696+
this.ImageSizeInMCU = this.ImageSizeInPixels.DivideRoundUp(8 * h0, 8 * v0);
694697

695-
foreach (OrigComponent component in this.Components)
696-
{
697-
component.InitializeDerivedData(this.configuration.MemoryManager, this, metadataOnly);
698+
this.ColorSpace = this.DeduceJpegColorSpace();
699+
700+
foreach (OrigComponent component in this.Components)
701+
{
702+
component.InitializeDerivedData(this.configuration.MemoryManager, this);
703+
}
698704
}
699705
}
700706

0 commit comments

Comments
 (0)