Skip to content

Commit 0c45f37

Browse files
authored
Merge pull request #1 from SixLabors/master
Merge upstream changes
2 parents 08b0320 + bb72769 commit 0c45f37

File tree

10 files changed

+315
-98
lines changed

10 files changed

+315
-98
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
using SixLabors.ImageSharp.Advanced;
7+
using SixLabors.ImageSharp.PixelFormats;
8+
9+
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
10+
{
11+
/// <summary>
12+
/// On-stack worker struct to efficiently encapsulate the TPixel -> L8 -> Y conversion chain of 8x8 pixel blocks.
13+
/// </summary>
14+
/// <typeparam name="TPixel">The pixel type to work on</typeparam>
15+
internal ref struct LuminanceForwardConverter<TPixel>
16+
where TPixel : unmanaged, IPixel<TPixel>
17+
{
18+
/// <summary>
19+
/// The Y component
20+
/// </summary>
21+
public Block8x8F Y;
22+
23+
/// <summary>
24+
/// Temporal 8x8 block to hold TPixel data
25+
/// </summary>
26+
private GenericBlock8x8<TPixel> pixelBlock;
27+
28+
/// <summary>
29+
/// Temporal RGB block
30+
/// </summary>
31+
private GenericBlock8x8<L8> l8Block;
32+
33+
public static LuminanceForwardConverter<TPixel> Create()
34+
{
35+
var result = default(LuminanceForwardConverter<TPixel>);
36+
return result;
37+
}
38+
39+
/// <summary>
40+
/// Converts a 8x8 image area inside 'pixels' at position (x,y) placing the result members of the structure (<see cref="Y"/>)
41+
/// </summary>
42+
public void Convert(ImageFrame<TPixel> frame, int x, int y, ref RowOctet<TPixel> currentRows)
43+
{
44+
this.pixelBlock.LoadAndStretchEdges(frame.PixelBuffer, x, y, ref currentRows);
45+
46+
Span<L8> l8Span = this.l8Block.AsSpanUnsafe();
47+
PixelOperations<TPixel>.Instance.ToL8(frame.GetConfiguration(), this.pixelBlock.AsSpanUnsafe(), l8Span);
48+
49+
ref Block8x8F yBlock = ref this.Y;
50+
ref L8 l8Start = ref l8Span[0];
51+
52+
for (int i = 0; i < 64; i++)
53+
{
54+
ref L8 c = ref Unsafe.Add(ref l8Start, i);
55+
yBlock[i] = c.PackedValue;
56+
}
57+
}
58+
}
59+
}

src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Six Labors.
1+
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

44
namespace SixLabors.ImageSharp.Formats.Jpeg
@@ -20,5 +20,10 @@ internal interface IJpegEncoderOptions
2020
/// </summary>
2121
/// <value>The subsample ratio of the jpg image.</value>
2222
JpegSubsample? Subsample { get; }
23+
24+
/// <summary>
25+
/// Gets the color type.
26+
/// </summary>
27+
JpegColorType? ColorType { get; }
2328
}
24-
}
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
namespace SixLabors.ImageSharp.Formats.Jpeg
5+
{
6+
/// <summary>
7+
/// Provides enumeration of available JPEG color types.
8+
/// </summary>
9+
public enum JpegColorType : byte
10+
{
11+
/// <summary>
12+
/// YCbCr (luminance, blue chroma, red chroma) color as defined in the ITU-T T.871 specification.
13+
/// </summary>
14+
YCbCr = 0,
15+
16+
/// <summary>
17+
/// Single channel, luminance.
18+
/// </summary>
19+
Luminance = 1
20+
}
21+
}

src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,7 @@ private void ProcessStartOfFrameMarker(BufferedReadStream stream, int remaining,
912912
this.Frame.MaxHorizontalFactor = maxH;
913913
this.Frame.MaxVerticalFactor = maxV;
914914
this.ColorSpace = this.DeduceJpegColorSpace();
915+
this.Metadata.GetJpegMetadata().ColorType = this.ColorSpace == JpegColorSpace.Grayscale ? JpegColorType.Luminance : JpegColorType.YCbCr;
915916
this.Frame.InitComponents();
916917
this.ImageSizeInMCU = new Size(this.Frame.McusPerLine, this.Frame.McusPerColumn);
917918
}

src/ImageSharp/Formats/Jpeg/JpegEncoder.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public sealed class JpegEncoder : IImageEncoder, IJpegEncoderOptions
2525
/// </summary>
2626
public JpegSubsample? Subsample { get; set; }
2727

28+
/// <summary>
29+
/// Gets or sets the color type, that will be used to encode the image.
30+
/// </summary>
31+
public JpegColorType? ColorType { get; set; }
32+
2833
/// <summary>
2934
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
3035
/// </summary>
@@ -35,6 +40,7 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream)
3540
where TPixel : unmanaged, IPixel<TPixel>
3641
{
3742
var encoder = new JpegEncoderCore(this);
43+
this.InitializeColorType<TPixel>(image);
3844
encoder.Encode(image, stream);
3945
}
4046

@@ -50,7 +56,31 @@ public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, Cancellation
5056
where TPixel : unmanaged, IPixel<TPixel>
5157
{
5258
var encoder = new JpegEncoderCore(this);
59+
this.InitializeColorType<TPixel>(image);
5360
return encoder.EncodeAsync(image, stream, cancellationToken);
5461
}
62+
63+
/// <summary>
64+
/// If ColorType was not set, set it based on the given image.
65+
/// </summary>
66+
private void InitializeColorType<TPixel>(Image<TPixel> image)
67+
where TPixel : unmanaged, IPixel<TPixel>
68+
{
69+
// First inspect the image metadata.
70+
if (this.ColorType == null)
71+
{
72+
JpegMetadata metadata = image.Metadata.GetJpegMetadata();
73+
this.ColorType = metadata.ColorType;
74+
}
75+
76+
// Secondly, inspect the pixel type.
77+
if (this.ColorType == null)
78+
{
79+
bool isGrayscale =
80+
typeof(TPixel) == typeof(L8) || typeof(TPixel) == typeof(L16) ||
81+
typeof(TPixel) == typeof(La16) || typeof(TPixel) == typeof(La32);
82+
this.ColorType = isGrayscale ? JpegColorType.Luminance : JpegColorType.YCbCr;
83+
}
84+
}
5585
}
5686
}

0 commit comments

Comments
 (0)