From 1b32629e30c13fe7e27afec1cfefbb3d13198bb9 Mon Sep 17 00:00:00 2001 From: Ildar Khayrutdinov Date: Sun, 11 Aug 2019 16:33:21 +0300 Subject: [PATCH] Improve performance of Tiff decoders --- .../PhotometricInterpretation/BlackIsZero1TiffColor.cs | 5 +++-- .../PhotometricInterpretation/BlackIsZero4TiffColor.cs | 7 +++++-- .../PhotometricInterpretation/BlackIsZero8TiffColor.cs | 5 ++++- .../Tiff/PhotometricInterpretation/BlackIsZeroTiffColor.cs | 4 +++- .../Tiff/PhotometricInterpretation/PaletteTiffColor.cs | 4 +++- .../Tiff/PhotometricInterpretation/Rgb888TiffColor.cs | 5 ++++- .../Tiff/PhotometricInterpretation/RgbPlanarTiffColor.cs | 5 ++++- .../Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs | 5 ++++- .../PhotometricInterpretation/WhiteIsZero1TiffColor.cs | 7 +++++-- .../PhotometricInterpretation/WhiteIsZero4TiffColor.cs | 7 +++++-- .../PhotometricInterpretation/WhiteIsZero8TiffColor.cs | 5 ++++- .../Tiff/PhotometricInterpretation/WhiteIsZeroTiffColor.cs | 4 +++- 12 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs index e317a7af7f..df7d8aa483 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero1TiffColor.cs @@ -33,17 +33,18 @@ public static void Decode(byte[] data, Buffer2D pixels, int left for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); for (int x = left; x < left + width; x += 8) { byte b = data[offset++]; int maxShift = Math.Min(left + width - x, 8); - for (int shift = 0; shift < maxShift; shift++) + for (int shift = 0, index = x; shift < maxShift; shift++, index++) { int bit = (b >> (7 - shift)) & 1; byte intensity = (bit == 1) ? (byte)255 : (byte)0; color.FromRgba32(new Rgba32(intensity, intensity, intensity, 255)); - pixels[x + shift, y] = color; + buffer[index] = color; } } } diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs index 62fff4737c..521023ff26 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero4TiffColor.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -33,17 +34,19 @@ public static void Decode(byte[] data, Buffer2D pixels, int left for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width - 1; x += 2) { byte byteData = data[offset++]; byte intensity1 = (byte)(((byteData & 0xF0) >> 4) * 17); color.FromRgba32(new Rgba32(intensity1, intensity1, intensity1, 255)); - pixels[x, y] = color; + buffer[x] = color; byte intensity2 = (byte)((byteData & 0x0F) * 17); color.FromRgba32(new Rgba32(intensity2, intensity2, intensity2, 255)); - pixels[x + 1, y] = color; + buffer[x + 1] = color; } if (isOddWidth) diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs index 949549d17b..272ca5feac 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero8TiffColor.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -32,11 +33,13 @@ public static void Decode(byte[] data, Buffer2D pixels, int left for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { byte intensity = data[offset++]; color.FromRgba32(new Rgba32(intensity, intensity, intensity, 255)); - pixels[x, y] = color; + buffer[x] = color; } } } diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColor.cs index 689a305ca7..7fdc3a32f8 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZeroTiffColor.cs @@ -36,12 +36,14 @@ public static void Decode(byte[] data, uint[] bitsPerSample, Buffer2D buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { int value = bitReader.ReadBits(bitsPerSample[0]); float intensity = ((float)value) / factor; color.FromVector4(new Vector4(intensity, intensity, intensity, 1.0f)); - pixels[x, y] = color; + buffer[x] = color; } bitReader.NextRow(); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/PaletteTiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/PaletteTiffColor.cs index 6c4bb56127..a5d8ad299f 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/PaletteTiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/PaletteTiffColor.cs @@ -37,10 +37,12 @@ public static void Decode(byte[] data, uint[] bitsPerSample, uint[] colo for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { int index = bitReader.ReadBits(bitsPerSample[0]); - pixels[x, y] = palette[index]; + buffer[x] = palette[index]; } bitReader.NextRow(); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs index 7582220f7b..b48e0a493d 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -32,13 +33,15 @@ public static void Decode(byte[] data, Buffer2D pixels, int left for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { byte r = data[offset++]; byte g = data[offset++]; byte b = data[offset++]; color.FromRgba32(new Rgba32(r, g, b, 255)); - pixels[x, y] = color; + buffer[x] = color; } } } diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColor.cs index df7671d760..55b197532a 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbPlanarTiffColor.cs @@ -40,13 +40,16 @@ public static void Decode(byte[][] data, uint[] bitsPerSample, Buffer2D< for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { float r = ((float)rBitReader.ReadBits(bitsPerSample[0])) / rFactor; float g = ((float)gBitReader.ReadBits(bitsPerSample[1])) / gFactor; float b = ((float)bBitReader.ReadBits(bitsPerSample[2])) / bFactor; color.FromVector4(new Vector4(r, g, b, 1.0f)); - pixels[x, y] = color; + + buffer[x] = color; } rBitReader.NextRow(); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs index ec33417998..fb59db6b01 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs @@ -38,13 +38,16 @@ public static void Decode(byte[] data, uint[] bitsPerSample, Buffer2D buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { float r = ((float)bitReader.ReadBits(bitsPerSample[0])) / rFactor; float g = ((float)bitReader.ReadBits(bitsPerSample[1])) / gFactor; float b = ((float)bitReader.ReadBits(bitsPerSample[2])) / bFactor; color.FromVector4(new Vector4(r, g, b, 1.0f)); - pixels[x, y] = color; + + buffer[x] = color; } bitReader.NextRow(); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs index 2d9914de71..c3d4c7bb44 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero1TiffColor.cs @@ -33,17 +33,20 @@ public static void Decode(byte[] data, Buffer2D pixels, int left for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x += 8) { byte b = data[offset++]; int maxShift = Math.Min(left + width - x, 8); - for (int shift = 0; shift < maxShift; shift++) + for (int shift = 0, index = x; shift < maxShift; shift++, index++) { int bit = (b >> (7 - shift)) & 1; byte intensity = (bit == 1) ? (byte)0 : (byte)255; color.FromRgba32(new Rgba32(intensity, intensity, intensity, 255)); - pixels[x + shift, y] = color; + + buffer[index] = color; } } } diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs index 965abec819..60665cf4f6 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero4TiffColor.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -33,17 +34,19 @@ public static void Decode(byte[] data, Buffer2D pixels, int left for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width - 1; x += 2) { byte byteData = data[offset++]; byte intensity1 = (byte)((15 - ((byteData & 0xF0) >> 4)) * 17); color.FromRgba32(new Rgba32(intensity1, intensity1, intensity1, 255)); - pixels[x, y] = color; + buffer[x] = color; byte intensity2 = (byte)((15 - (byteData & 0x0F)) * 17); color.FromRgba32(new Rgba32(intensity2, intensity2, intensity2, 255)); - pixels[x + 1, y] = color; + buffer[x + 1] = color; } if (isOddWidth) diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs index fb209cecbc..6e463368ef 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -32,11 +33,13 @@ public static void Decode(byte[] data, Buffer2D pixels, int left for (int y = top; y < top + height; y++) { + Span buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { byte intensity = (byte)(255 - data[offset++]); color.FromRgba32(new Rgba32(intensity, intensity, intensity, 255)); - pixels[x, y] = color; + buffer[x] = color; } } } diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColor.cs index 8bb720bb9c..f46919bf24 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColor.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZeroTiffColor.cs @@ -36,12 +36,14 @@ public static void Decode(byte[] data, uint[] bitsPerSample, Buffer2D buffer = pixels.GetRowSpan(y); + for (int x = left; x < left + width; x++) { int value = bitReader.ReadBits(bitsPerSample[0]); float intensity = 1.0f - (((float)value) / factor); color.FromVector4(new Vector4(intensity, intensity, intensity, 1.0f)); - pixels[x, y] = color; + buffer[x] = color; } bitReader.NextRow();