Skip to content

Commit a1ee0d6

Browse files
committed
Decoding 16bit rgb planar now also respects byte order
1 parent cc16677 commit a1ee0d6

File tree

9 files changed

+95
-5
lines changed

9 files changed

+95
-5
lines changed

src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb161616TiffColor{TPixel}.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the Apache License, Version 2.0.
33

44
using System;
5-
using System.Buffers.Binary;
65
using SixLabors.ImageSharp.Formats.Tiff.Utils;
76
using SixLabors.ImageSharp.Memory;
87
using SixLabors.ImageSharp.PixelFormats;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System.Buffers;
5+
using SixLabors.ImageSharp.Formats.Tiff.Utils;
6+
using SixLabors.ImageSharp.Memory;
7+
using SixLabors.ImageSharp.PixelFormats;
8+
9+
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
10+
{
11+
/// <summary>
12+
/// Implements the 'RGB' photometric interpretation with 'Planar' layout for all 16 bit.
13+
/// </summary>
14+
internal class Rgb16PlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel>
15+
where TPixel : unmanaged, IPixel<TPixel>
16+
{
17+
private readonly bool isBigEndian;
18+
19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="Rgb16PlanarTiffColor{TPixel}" /> class.
21+
/// </summary>
22+
/// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
23+
public Rgb16PlanarTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian;
24+
25+
/// <inheritdoc/>
26+
public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
27+
{
28+
var color = default(TPixel);
29+
30+
System.Span<byte> redData = data[0].GetSpan();
31+
System.Span<byte> greenData = data[1].GetSpan();
32+
System.Span<byte> blueData = data[2].GetSpan();
33+
34+
int offset = 0;
35+
var rgba = default(Rgba64);
36+
for (int y = top; y < top + height; y++)
37+
{
38+
for (int x = left; x < left + width; x++)
39+
{
40+
ulong r = TiffUtils.ConvertToShort(redData.Slice(offset, 2), this.isBigEndian);
41+
ulong g = TiffUtils.ConvertToShort(greenData.Slice(offset, 2), this.isBigEndian);
42+
ulong b = TiffUtils.ConvertToShort(blueData.Slice(offset, 2), this.isBigEndian);
43+
44+
offset += 2;
45+
46+
rgba.PackedValue = r | (g << 16) | (b << 32) | (0xfffful << 48);
47+
color.FromRgba64(rgba);
48+
pixels[x, y] = color;
49+
}
50+
}
51+
}
52+
}
53+
}

src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColor{TPixel}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
1212
/// <summary>
1313
/// Implements the 'RGB' photometric interpretation with 'Planar' layout (for all bit depths).
1414
/// </summary>
15-
internal class RgbPlanarTiffColor<TPixel>
15+
internal class RgbPlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel>
1616
where TPixel : unmanaged, IPixel<TPixel>
1717
{
1818
private readonly float rFactor;
@@ -47,7 +47,7 @@ public RgbPlanarTiffColor(TiffBitsPerSample bitsPerSample)
4747
/// <param name="top">The y-coordinate of the top of the image block.</param>
4848
/// <param name="width">The width of the image block.</param>
4949
/// <param name="height">The height of the image block.</param>
50-
public void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
50+
public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
5151
{
5252
var color = default(TPixel);
5353

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System.Buffers;
5+
using SixLabors.ImageSharp.Memory;
6+
using SixLabors.ImageSharp.PixelFormats;
7+
8+
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
9+
{
10+
/// <summary>
11+
/// The base class for planar color decoders.
12+
/// </summary>
13+
/// <typeparam name="TPixel">The pixel format.</typeparam>
14+
internal abstract class TiffBasePlanarColorDecoder<TPixel>
15+
where TPixel : unmanaged, IPixel<TPixel>
16+
{
17+
/// <summary>
18+
/// Decodes source raw pixel data using the current photometric interpretation.
19+
/// </summary>
20+
/// <param name="data">The buffers to read image data from.</param>
21+
/// <param name="pixels">The image buffer to write pixels to.</param>
22+
/// <param name="left">The x-coordinate of the left-hand side of the image block.</param>
23+
/// <param name="top">The y-coordinate of the top of the image block.</param>
24+
/// <param name="width">The width of the image block.</param>
25+
/// <param name="height">The height of the image block.</param>
26+
public abstract void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height);
27+
}
28+
}

src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,17 @@ public static TiffBaseColorDecoder<TPixel> Create(TiffColorType colorType, TiffB
145145
}
146146
}
147147

148-
public static RgbPlanarTiffColor<TPixel> CreatePlanar(TiffColorType colorType, TiffBitsPerSample bitsPerSample, ushort[] colorMap)
148+
public static TiffBasePlanarColorDecoder<TPixel> CreatePlanar(TiffColorType colorType, TiffBitsPerSample bitsPerSample, ushort[] colorMap, ByteOrder byteOrder)
149149
{
150150
switch (colorType)
151151
{
152152
case TiffColorType.RgbPlanar:
153153
DebugGuard.IsTrue(colorMap == null, "colorMap");
154+
if (bitsPerSample.Channel0 == 16 && bitsPerSample.Channel1 == 16 && bitsPerSample.Channel2 == 16)
155+
{
156+
return new Rgb16PlanarTiffColor<TPixel>(byteOrder == ByteOrder.BigEndian);
157+
}
158+
154159
return new RgbPlanarTiffColor<TPixel>(bitsPerSample);
155160

156161
default:

src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ private void DecodeStripsPlanar<TPixel>(ImageFrame<TPixel> frame, int rowsPerStr
266266

267267
using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, frame.Width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions);
268268

269-
RgbPlanarTiffColor<TPixel> colorDecoder = TiffColorDecoderFactory<TPixel>.CreatePlanar(this.ColorType, this.BitsPerSample, this.ColorMap);
269+
TiffBasePlanarColorDecoder<TPixel> colorDecoder = TiffColorDecoderFactory<TPixel>.CreatePlanar(this.ColorType, this.BitsPerSample, this.ColorMap, this.byteOrder);
270270

271271
for (int i = 0; i < stripsPerPlane; i++)
272272
{

tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ public void TiffDecoder_CanDecode_42Bit<TPixel>(TestImageProvider<TPixel> provid
166166
[Theory]
167167
[WithFile(FlowerRgb161616Contiguous, PixelTypes.Rgba32)]
168168
[WithFile(FlowerRgb161616Planar, PixelTypes.Rgba32)]
169+
[WithFile(FlowerRgb161616PlanarLittleEndian, PixelTypes.Rgba32)]
169170
[WithFile(Issues1716Rgb161616BitLittleEndian, PixelTypes.Rgba32)]
170171
public void TiffDecoder_CanDecode_48Bit<TPixel>(TestImageProvider<TPixel> provider)
171172
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ public static class Tiff
563563
public const string RgbPaletteDeflate = "Tiff/rgb_palette_deflate.tiff";
564564
public const string FlowerRgb161616Contiguous = "Tiff/flower-rgb-contig-16.tiff";
565565
public const string FlowerRgb161616Planar = "Tiff/flower-rgb-planar-16.tiff";
566+
public const string FlowerRgb161616PlanarLittleEndian = "Tiff/flower-rgb-planar-16_lsb.tiff";
566567
public const string FlowerRgb141414Contiguous = "Tiff/flower-rgb-contig-14.tiff";
567568
public const string FlowerRgb141414Planar = "Tiff/flower-rgb-planar-14.tiff";
568569
public const string FlowerRgb101010Contiguous = "Tiff/flower-rgb-contig-10.tiff";
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:46a60552a7ff37f2c16c43e030e7180872af712f5d9c9c7673e2547049af3da9
3+
size 19168

0 commit comments

Comments
 (0)