Skip to content

Commit f8f0c10

Browse files
committed
Add support for horizontal predictor with 32 bit color tiff's
1 parent 484ec85 commit f8f0c10

File tree

5 files changed

+98
-0
lines changed

5 files changed

+98
-0
lines changed

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

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public static void Undo(Span<byte> pixelBytes, int width, TiffColorType colorTyp
4646
case TiffColorType.Rgb161616:
4747
UndoRgb48Bit(pixelBytes, width, isBigEndian);
4848
break;
49+
case TiffColorType.Rgb323232:
50+
UndoRgb96Bit(pixelBytes, width, isBigEndian);
51+
break;
4952
}
5053
}
5154

@@ -315,5 +318,81 @@ private static void UndoRgb48Bit(Span<byte> pixelBytes, int width, bool isBigEnd
315318
}
316319
}
317320
}
321+
322+
private static void UndoRgb96Bit(Span<byte> pixelBytes, int width, bool isBigEndian)
323+
{
324+
int rowBytesCount = width * 12;
325+
int height = pixelBytes.Length / rowBytesCount;
326+
if (isBigEndian)
327+
{
328+
for (int y = 0; y < height; y++)
329+
{
330+
int offset = 0;
331+
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
332+
uint r = TiffUtils.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
333+
offset += 4;
334+
uint g = TiffUtils.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
335+
offset += 4;
336+
uint b = TiffUtils.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
337+
offset += 4;
338+
339+
for (int x = 1; x < width; x++)
340+
{
341+
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
342+
uint deltaR = TiffUtils.ConvertToUIntBigEndian(rowSpan);
343+
r += deltaR;
344+
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, r);
345+
offset += 4;
346+
347+
rowSpan = rowBytes.Slice(offset, 4);
348+
uint deltaG = TiffUtils.ConvertToUIntBigEndian(rowSpan);
349+
g += deltaG;
350+
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, g);
351+
offset += 4;
352+
353+
rowSpan = rowBytes.Slice(offset, 4);
354+
uint deltaB = TiffUtils.ConvertToUIntBigEndian(rowSpan);
355+
b += deltaB;
356+
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, b);
357+
offset += 4;
358+
}
359+
}
360+
}
361+
else
362+
{
363+
for (int y = 0; y < height; y++)
364+
{
365+
int offset = 0;
366+
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
367+
uint r = TiffUtils.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
368+
offset += 4;
369+
uint g = TiffUtils.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
370+
offset += 4;
371+
uint b = TiffUtils.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
372+
offset += 4;
373+
374+
for (int x = 1; x < width; x++)
375+
{
376+
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
377+
uint deltaR = TiffUtils.ConvertToUIntLittleEndian(rowSpan);
378+
r += deltaR;
379+
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, r);
380+
offset += 4;
381+
382+
rowSpan = rowBytes.Slice(offset, 4);
383+
uint deltaG = TiffUtils.ConvertToUIntLittleEndian(rowSpan);
384+
g += deltaG;
385+
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, g);
386+
offset += 4;
387+
388+
rowSpan = rowBytes.Slice(offset, 4);
389+
uint deltaB = TiffUtils.ConvertToUIntLittleEndian(rowSpan);
390+
b += deltaB;
391+
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, b);
392+
offset += 4;
393+
}
394+
}
395+
}
396+
}
318397
}
319398
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,17 @@ public void TiffDecoder_CanDecode_96Bit<TPixel>(TestImageProvider<TPixel> provid
260260
image.DebugSave(provider);
261261
}
262262

263+
[Theory]
264+
[WithFile(FlowerRgb323232PredictorBigEndian, PixelTypes.Rgba32)]
265+
[WithFile(FlowerRgb323232PredictorLittleEndian, PixelTypes.Rgba32)]
266+
public void TiffDecoder_CanDecode_96Bit_WithPredictor<TPixel>(TestImageProvider<TPixel> provider)
267+
where TPixel : unmanaged, IPixel<TPixel>
268+
{
269+
// Note: because the MagickReferenceDecoder fails to load the image, we only debug save them.
270+
using Image<TPixel> image = provider.GetImage();
271+
image.DebugSave(provider);
272+
}
273+
263274
[Theory]
264275
[WithFile(GrayscaleDeflateMultistrip, PixelTypes.Rgba32)]
265276
[WithFile(RgbDeflateMultistrip, PixelTypes.Rgba32)]

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@ public static class Tiff
567567
public const string FlowerRgb323232ContiguousLittleEndian = "Tiff/flower-rgb-contig-32_lsb.tiff";
568568
public const string FlowerRgb323232Planar = "Tiff/flower-rgb-planar-32.tiff";
569569
public const string FlowerRgb323232PlanarLittleEndian = "Tiff/flower-rgb-planar-32_lsb.tiff";
570+
public const string FlowerRgb323232PredictorBigEndian = "Tiff/flower-rgb-contig-32_msb_zip_predictor.tiff";
571+
public const string FlowerRgb323232PredictorLittleEndian = "Tiff/flower-rgb-contig-32_lsb_zip_predictor.tiff";
570572
public const string FlowerRgb242424Planar = "Tiff/flower-rgb-planar-24.tiff";
571573
public const string FlowerRgb242424PlanarLittleEndian = "Tiff/flower-rgb-planar-24_lsb.tiff";
572574
public const string FlowerRgb242424Contiguous = "Tiff/flower-rgb-contig-24.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:3ed60ad91ea70db01789f9dd37745d8a5ab86f72b98637cf2007b4e28a71976f
3+
size 37632
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:1086c2ec568c5c3c2b08fcc66691fab017eb6fad109373a1dadd2e12fae86bc8
3+
size 37630

0 commit comments

Comments
 (0)