Skip to content

Commit 484ec85

Browse files
committed
Add support for horizontal predictor with 16 bit color tiff's
1 parent 78efd68 commit 484ec85

File tree

5 files changed

+93
-0
lines changed

5 files changed

+93
-0
lines changed

src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ public static void Undo(Span<byte> pixelBytes, int width, TiffColorType colorTyp
4343
case TiffColorType.Rgb888:
4444
UndoRgb24Bit(pixelBytes, width);
4545
break;
46+
case TiffColorType.Rgb161616:
47+
UndoRgb48Bit(pixelBytes, width, isBigEndian);
48+
break;
4649
}
4750
}
4851

@@ -236,5 +239,81 @@ private static void UndoRgb24Bit(Span<byte> pixelBytes, int width)
236239
}
237240
}
238241
}
242+
243+
private static void UndoRgb48Bit(Span<byte> pixelBytes, int width, bool isBigEndian)
244+
{
245+
int rowBytesCount = width * 6;
246+
int height = pixelBytes.Length / rowBytesCount;
247+
if (isBigEndian)
248+
{
249+
for (int y = 0; y < height; y++)
250+
{
251+
int offset = 0;
252+
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
253+
ushort r = TiffUtils.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
254+
offset += 2;
255+
ushort g = TiffUtils.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
256+
offset += 2;
257+
ushort b = TiffUtils.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
258+
offset += 2;
259+
260+
for (int x = 1; x < width; x++)
261+
{
262+
Span<byte> rowSpan = rowBytes.Slice(offset, 2);
263+
ushort deltaR = TiffUtils.ConvertToUShortBigEndian(rowSpan);
264+
r += deltaR;
265+
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, r);
266+
offset += 2;
267+
268+
rowSpan = rowBytes.Slice(offset, 2);
269+
ushort deltaG = TiffUtils.ConvertToUShortBigEndian(rowSpan);
270+
g += deltaG;
271+
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, g);
272+
offset += 2;
273+
274+
rowSpan = rowBytes.Slice(offset, 2);
275+
ushort deltaB = TiffUtils.ConvertToUShortBigEndian(rowSpan);
276+
b += deltaB;
277+
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, b);
278+
offset += 2;
279+
}
280+
}
281+
}
282+
else
283+
{
284+
for (int y = 0; y < height; y++)
285+
{
286+
int offset = 0;
287+
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
288+
ushort r = TiffUtils.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
289+
offset += 2;
290+
ushort g = TiffUtils.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
291+
offset += 2;
292+
ushort b = TiffUtils.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
293+
offset += 2;
294+
295+
for (int x = 1; x < width; x++)
296+
{
297+
Span<byte> rowSpan = rowBytes.Slice(offset, 2);
298+
ushort deltaR = TiffUtils.ConvertToUShortLittleEndian(rowSpan);
299+
r += deltaR;
300+
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, r);
301+
offset += 2;
302+
303+
rowSpan = rowBytes.Slice(offset, 2);
304+
ushort deltaG = TiffUtils.ConvertToUShortLittleEndian(rowSpan);
305+
g += deltaG;
306+
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, g);
307+
offset += 2;
308+
309+
rowSpan = rowBytes.Slice(offset, 2);
310+
ushort deltaB = TiffUtils.ConvertToUShortLittleEndian(rowSpan);
311+
b += deltaB;
312+
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, b);
313+
offset += 2;
314+
}
315+
}
316+
}
317+
}
239318
}
240319
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ public void TiffDecoder_CanDecode_42Bit<TPixel>(TestImageProvider<TPixel> provid
228228
public void TiffDecoder_CanDecode_48Bit<TPixel>(TestImageProvider<TPixel> provider)
229229
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
230230

231+
[Theory]
232+
[WithFile(FlowerRgb161616PredictorBigEndian, PixelTypes.Rgba32)]
233+
[WithFile(FlowerRgb161616PredictorLittleEndian, PixelTypes.Rgba32)]
234+
public void TiffDecoder_CanDecode_48Bit_WithPredictor<TPixel>(TestImageProvider<TPixel> provider)
235+
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
236+
231237
[Theory]
232238
[WithFile(FlowerRgb242424Contiguous, PixelTypes.Rgba32)]
233239
[WithFile(FlowerRgb242424ContiguousLittleEndian, PixelTypes.Rgba32)]

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,8 @@ public static class Tiff
573573
public const string FlowerRgb242424ContiguousLittleEndian = "Tiff/flower-rgb-contig-24_lsb.tiff";
574574
public const string FlowerRgb161616Contiguous = "Tiff/flower-rgb-contig-16.tiff";
575575
public const string FlowerRgb161616ContiguousLittleEndian = "Tiff/flower-rgb-contig-16_lsb.tiff";
576+
public const string FlowerRgb161616PredictorBigEndian = "Tiff/flower-rgb-contig-16_msb_zip_predictor.tiff";
577+
public const string FlowerRgb161616PredictorLittleEndian = "Tiff/flower-rgb-contig-16_lsb_zip_predictor.tiff";
576578
public const string FlowerRgb161616Planar = "Tiff/flower-rgb-planar-16.tiff";
577579
public const string FlowerRgb161616PlanarLittleEndian = "Tiff/flower-rgb-planar-16_lsb.tiff";
578580
public const string FlowerRgb141414Contiguous = "Tiff/flower-rgb-contig-14.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:eb465c21009def345d192319ba13ba2e1e537310eec3ab2cce680f0d111a4f18
3+
size 18256
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:c098beb9c8f250e9d4f6eb66a3a42f3852ad3ca86aabbdbacfa897d93ec8bc0d
3+
size 18254

0 commit comments

Comments
 (0)