Browse Source

CalculateJpegChannelSizes()

pull/322/head
Anton Firszov 9 years ago
parent
commit
769d4de78c
  1. 39
      src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs
  2. 8
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegPixelArea.cs
  3. 8
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
  4. 38
      tests/ImageSharp.Tests/Formats/Jpg/ComponentUtilsTests.cs

39
src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs

@ -81,18 +81,45 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
public static bool IsChromaComponent(this IJpegComponent component) => public static bool IsChromaComponent(this IJpegComponent component) =>
component.Index > 0 && component.Index < 3; component.Index > 0 && component.Index < 3;
public static Size CalculateJpegChannelSize(this IJpegComponent component, SubsampleRatio ratio = SubsampleRatio.Undefined) public static Size[] CalculateJpegChannelSizes(IEnumerable<IJpegComponent> components, SubsampleRatio ratio)
{ {
Size size = new Size(component.WidthInBlocks, component.HeightInBlocks) * 8; IJpegComponent[] c = components.ToArray();
Size[] sizes = new Size[c.Length];
if (component.IsChromaComponent()) Size s0 = new Size(c[0].WidthInBlocks, c[0].HeightInBlocks) * 8;
sizes[0] = s0;
if (c.Length > 1)
{ {
return ratio.CalculateChrominanceSize(size.Width, size.Height); Size chromaSize = ratio.CalculateChrominanceSize(s0.Width, s0.Height);
sizes[1] = chromaSize;
if (c.Length > 2)
{
sizes[2] = chromaSize;
}
} }
else
if (c.Length > 3)
{ {
return size; sizes[3] = s0;
} }
return sizes;
} }
//public static Size CalculateJpegChannelSize(this IJpegComponent component, SubsampleRatio ratio = SubsampleRatio.Undefined)
//{
// Size size = new Size(component.WidthInBlocks, component.HeightInBlocks) * 8;
// if (component.IsChromaComponent())
// {
// return ratio.CalculateChrominanceSize(size.Width, size.Height);
// }
// else
// {
// return size;
// }
//}
} }
} }

8
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegPixelArea.cs

@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
: this(Buffer2D<byte>.CreateClean(size)) : this(Buffer2D<byte>.CreateClean(size))
{ {
} }
/// <summary> /// <summary>
/// Gets the pixels buffer. /// Gets the pixels buffer.
/// </summary> /// </summary>
@ -83,12 +83,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
} }
} }
public static OrigJpegPixelArea CreateForComponent(IJpegComponent component, SubsampleRatio ratio = SubsampleRatio.Undefined)
{
Size size = component.CalculateJpegChannelSize(ratio);
return new OrigJpegPixelArea(size);
}
/// <summary> /// <summary>
/// Gets the subarea that belongs to the Block8x8 defined by block indices /// Gets the subarea that belongs to the Block8x8 defined by block indices
/// </summary> /// </summary>

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

@ -782,19 +782,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
/// </summary> /// </summary>
private void InitJpegImageChannels() private void InitJpegImageChannels()
{ {
Size[] sizes = ComponentUtils.CalculateJpegChannelSizes(this.Components, this.SubsampleRatio);
if (this.ComponentCount == 1) if (this.ComponentCount == 1)
{ {
this.grayImage = OrigJpegPixelArea.CreateForComponent(this.Components[0]); this.grayImage = new OrigJpegPixelArea(sizes[0]);
} }
else else
{ {
Size size = this.Components[0].CalculateJpegChannelSize(); Size size = sizes[0];
this.ycbcrImage = new YCbCrImage(size.Width, size.Height, this.SubsampleRatio); this.ycbcrImage = new YCbCrImage(size.Width, size.Height, this.SubsampleRatio);
if (this.ComponentCount == 4) if (this.ComponentCount == 4)
{ {
this.blackImage = OrigJpegPixelArea.CreateForComponent(this.Components[3]); this.blackImage = new OrigJpegPixelArea(sizes[3]);
} }
} }
} }

38
tests/ImageSharp.Tests/Formats/Jpg/ComponentUtilsTests.cs

@ -69,15 +69,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
} }
[Fact] [Fact]
public void CalculateJpegChannelSize_Grayscale() public void CalculateJpegChannelSizes_Grayscale()
{ {
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(TestImages.Jpeg.Baseline.Jpeg400)) using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(TestImages.Jpeg.Baseline.Jpeg400))
{ {
Assert.Equal(1, decoder.ComponentCount); Size[] sizes = ComponentUtils.CalculateJpegChannelSizes(decoder.Components, decoder.SubsampleRatio);
Assert.Equal(1, sizes.Length);
Size expected = decoder.Components[0].SizeInBlocks() * 8; Size expected = decoder.Components[0].SizeInBlocks() * 8;
Size actual = decoder.Components[0].CalculateJpegChannelSize(decoder.SubsampleRatio);
Assert.Equal(expected, actual); Assert.Equal(expected, sizes[0]);
} }
} }
@ -85,38 +87,40 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(TestImages.Jpeg.Baseline.Calliphora, 1)] [InlineData(TestImages.Jpeg.Baseline.Calliphora, 1)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg444, 1)] [InlineData(TestImages.Jpeg.Baseline.Jpeg444, 1)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg420, 2)] [InlineData(TestImages.Jpeg.Baseline.Jpeg420, 2)]
public void CalculateJpegChannelSize_YCbCr( public void CalculateJpegChannelSizes_YCbCr(
string imageFile, string imageFile,
int chromaDiv) int chromaDiv)
{ {
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile)) using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile))
{ {
Size ySize = decoder.Components[0].SizeInBlocks() * 8; Size[] s = ComponentUtils.CalculateJpegChannelSizes(decoder.Components, decoder.SubsampleRatio);
Size cSize = decoder.Components[1].SizeInBlocks() * 8 / chromaDiv;
Size s0 = decoder.Components[0].CalculateJpegChannelSize(decoder.SubsampleRatio); Assert.Equal(3, s.Length);
Size s1 = decoder.Components[1].CalculateJpegChannelSize(decoder.SubsampleRatio);
Size s2 = decoder.Components[2].CalculateJpegChannelSize(decoder.SubsampleRatio);
Assert.Equal(ySize, s0); Size ySize = decoder.Components[0].SizeInBlocks() * 8;
Assert.Equal(cSize, s1); Size cSize = ySize / chromaDiv;
Assert.Equal(cSize, s2);
Assert.Equal(ySize, s[0]);
Assert.Equal(cSize, s[1]);
Assert.Equal(cSize, s[2]);
} }
} }
[Theory] [Theory]
[InlineData(TestImages.Jpeg.Baseline.Ycck)] [InlineData(TestImages.Jpeg.Baseline.Ycck)]
[InlineData(TestImages.Jpeg.Baseline.Cmyk)] [InlineData(TestImages.Jpeg.Baseline.Cmyk)]
public void CalculateJpegChannelSize_4Chan(string imageFile) public void CalculateJpegChannelSizes_4Chan(string imageFile)
{ {
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile)) using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile))
{ {
Size[] sizes = ComponentUtils.CalculateJpegChannelSizes(decoder.Components, decoder.SubsampleRatio);
Assert.Equal(4, sizes.Length);
Size expected = decoder.Components[0].SizeInBlocks() * 8; Size expected = decoder.Components[0].SizeInBlocks() * 8;
foreach (OrigComponent component in decoder.Components) foreach (Size s in sizes)
{ {
Size actual = component.CalculateJpegChannelSize(decoder.SubsampleRatio); Assert.Equal(expected, s);
Assert.Equal(expected, actual);
} }
} }
} }

Loading…
Cancel
Save