Browse Source

Add optimised implementation for 8-bit RGB images

pull/119/head
Andrew Wilkinson 9 years ago
parent
commit
933f54b148
  1. 50
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs
  2. 5
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
  3. 5
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  4. 10
      tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/PhotometricInterpretation/RgbTiffColorTests.cs
  5. 4
      tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs

50
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgb888TiffColor.cs

@ -0,0 +1,50 @@
// <copyright file="Rgb888TiffColor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats.Tiff
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp;
using ImageSharp.PixelFormats;
/// <summary>
/// Implements the 'RGB' photometric interpretation (optimised for 8-bit full color images).
/// </summary>
internal static class Rgb888TiffColor
{
/// <summary>
/// Decodes pixel data using the current photometric interpretation.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="data">The buffer to read image data from.</param>
/// <param name="pixels">The image buffer to write pixels to.</param>
/// <param name="left">The x-coordinate of the left-hand side of the image block.</param>
/// <param name="top">The y-coordinate of the top of the image block.</param>
/// <param name="width">The width of the image block.</param>
/// <param name="height">The height of the image block.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Decode<TPixel>(byte[] data, PixelAccessor<TPixel> pixels, int left, int top, int width, int height)
where TPixel : struct, IPixel<TPixel>
{
TPixel color = default(TPixel);
uint offset = 0;
for (int y = top; y < top + height; y++)
{
for (int x = left; x < left + width; x++)
{
byte r = data[offset++];
byte g = data[offset++];
byte b = data[offset++];
color.PackFromBytes(r, g, b, 255);
pixels[x, y] = color;
}
}
}
}
}

5
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs

@ -59,5 +59,10 @@ namespace ImageSharp.Formats.Tiff
/// RGB Full Color.
/// </summary>
Rgb,
/// <summary>
/// RGB Full Color. Optimised implementation for 8-bit images.
/// </summary>
Rgb888
}
}

5
src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

@ -395,7 +395,7 @@ namespace ImageSharp.Formats
{
if (this.BitsPerSample[0] == 8 && this.BitsPerSample[1] == 8 && this.BitsPerSample[2] == 8)
{
this.ColorType = TiffColorType.Rgb;
this.ColorType = TiffColorType.Rgb888;
}
else
{
@ -529,6 +529,9 @@ namespace ImageSharp.Formats
case TiffColorType.Rgb:
RgbTiffColor.Decode(data, this.BitsPerSample, pixels, left, top, width, height);
break;
case TiffColorType.Rgb888:
Rgb888TiffColor.Decode(data, pixels, left, top, width, height);
break;
case TiffColorType.PaletteColor:
PaletteTiffColor.Decode(data, this.BitsPerSample, this.ColorMap, pixels, left, top, width, height);
break;

10
tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/PhotometricInterpretation/RgbTiffColorTests.cs

@ -147,5 +147,15 @@ namespace ImageSharp.Tests
RgbTiffColor.Decode(inputData, bitsPerSample, pixels, left, top, width, height);
});
}
[Theory]
[MemberData(nameof(Rgb8_Data))]
public void Decode_WritesPixelData_8Bit(byte[] inputData, uint[] bitsPerSample, int left, int top, int width, int height, Rgba32[][] expectedResult)
{
AssertDecode(expectedResult, pixels =>
{
Rgb888TiffColor.Decode(inputData, pixels, left, top, width, height);
});
}
}
}

4
tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs

@ -202,8 +202,8 @@ namespace ImageSharp.Tests
[InlineData(true, TiffPhotometricInterpretation.PaletteColor, new[] { 1 }, TiffColorType.PaletteColor)]
[InlineData(false, TiffPhotometricInterpretation.Rgb, new[] { 4, 4, 4 }, TiffColorType.Rgb)]
[InlineData(true, TiffPhotometricInterpretation.Rgb, new[] { 4, 4, 4 }, TiffColorType.Rgb)]
[InlineData(false, TiffPhotometricInterpretation.Rgb, new[] { 8, 8, 8 }, TiffColorType.Rgb)]
[InlineData(true, TiffPhotometricInterpretation.Rgb, new[] { 8, 8, 8 }, TiffColorType.Rgb)]
[InlineData(false, TiffPhotometricInterpretation.Rgb, new[] { 8, 8, 8 }, TiffColorType.Rgb888)]
[InlineData(true, TiffPhotometricInterpretation.Rgb, new[] { 8, 8, 8 }, TiffColorType.Rgb888)]
public void ReadImageFormat_DeterminesCorrectColorImplementation(bool isLittleEndian, ushort photometricInterpretation, int[] bitsPerSample, int colorType)
{
Stream stream = CreateTiffGenIfd()

Loading…
Cancel
Save