Browse Source

Fix issue writing too large color palette

pull/1570/head
Brian Popow 5 years ago
parent
commit
8e85b1dd69
  1. 2
      src/ImageSharp/Configuration.cs
  2. 12
      src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
  3. 2
      tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs
  4. 4
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  5. 3
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
  6. 25
      tests/ImageSharp.Tests/TestImages.cs
  7. 3
      tests/Images/Input/Tiff/rgb_lzw_no_predictor.tiff

2
src/ImageSharp/Configuration.cs

@ -6,11 +6,11 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Experimental.Tiff;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Experimental.Tiff;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Processing;

12
src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

@ -6,9 +6,9 @@ using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Png.Zlib;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
@ -239,11 +239,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
public int WritePalettedRgb<TPixel>(Image<TPixel> image, IQuantizer quantizer, int padding, TiffEncoderCompression compression, out IExifValue colorMap)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorPaletteSize = 256 * 3 * 2;
int colorsPerChannel = 256;
int colorPaletteSize = colorsPerChannel * 3;
int colorPaletteBytes = colorPaletteSize * 2;
using IManagedByteBuffer row = this.AllocateRow(image.Width, 1, padding);
using IQuantizer<TPixel> frameQuantizer = quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration);
using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image.Frames.RootFrame, image.Bounds());
using IMemoryOwner<byte> colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(colorPaletteSize);
using IMemoryOwner<byte> colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(colorPaletteBytes);
Span<byte> colorPalette = colorPaletteBuffer.GetSpan();
ReadOnlySpan<TPixel> quantizedColors = quantized.Palette.Span;
@ -253,8 +255,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils
Span<Rgb48> quantizedColorRgb48 = MemoryMarshal.Cast<byte, Rgb48>(colorPalette.Slice(0, quantizedColorBytes));
PixelOperations<TPixel>.Instance.ToRgb48(this.configuration, quantizedColors, quantizedColorRgb48);
// It can happen that the quantized colors are less than the expected 256.
var diffToMaxColors = 256 - quantizedColors.Length;
// It can happen that the quantized colors are less than the expected 256 per channel.
var diffToMaxColors = colorsPerChannel - quantizedColors.Length;
// In a TIFF ColorMap, all the Red values come first, followed by the Green values,
// then the Blue values. Convert the quantized palette to this format.

2
tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs

@ -2,8 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using SixLabors.ImageSharp.Formats.Png.Zlib;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression;
using SixLabors.ImageSharp.Formats.Png.Zlib;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression

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

@ -60,8 +60,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
}
[Theory]
[InlineData(TestImages.Tiff.RgbLzw_NoPredictor_Multistrip, TiffByteOrder.LittleEndian)]
[InlineData(TestImages.Tiff.RgbLzw_NoPredictor_Multistrip_Motorola, TiffByteOrder.BigEndian)]
[InlineData(TestImages.Tiff.RgbLzwNoPredictorMultistrip, TiffByteOrder.LittleEndian)]
[InlineData(TestImages.Tiff.RgbLzwNoPredictorMultistripMotorola, TiffByteOrder.BigEndian)]
public void ByteOrder(string imagePath, TiffByteOrder expectedByteOrder)
{
var testFile = TestFile.Create(imagePath);

3
tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs

@ -93,6 +93,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
memStream.Position = 0;
using var encodedImage = (Image<TPixel>)Image.Load(memStream);
provider.Utility.SaveTestOutputFile(encodedImage, "tiff", encoder);
TiffTestUtils.CompareWithReferenceDecoder(provider, encodedImage);
}
@ -110,6 +111,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
memStream.Position = 0;
using var encodedImage = (Image<TPixel>)Image.Load(memStream);
provider.Utility.SaveTestOutputFile(encodedImage, "tiff", encoder);
TiffTestUtils.CompareWithReferenceDecoder(provider, encodedImage);
}
@ -127,6 +129,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
memStream.Position = 0;
using var encodedImage = (Image<TPixel>)Image.Load(memStream);
provider.Utility.SaveTestOutputFile(encodedImage, "tiff", encoder);
TiffTestUtils.CompareWithReferenceDecoder(provider, encodedImage);
}

25
tests/ImageSharp.Tests/TestImages.cs

@ -526,14 +526,15 @@ namespace SixLabors.ImageSharp.Tests
public const string GrayscaleUncompressed = "Tiff/grayscale_uncompressed.tiff";
public const string PaletteDeflateMultistrip = "Tiff/palette_grayscale_deflate_multistrip.tiff";
public const string PaletteUncompressed = "Tiff/palette_uncompressed.tiff";
public const string RgbDeflate_Predictor = "Tiff/rgb_deflate.tiff";
public const string RgbDeflatePredictor = "Tiff/rgb_deflate.tiff";
public const string RgbDeflateMultistrip = "Tiff/rgb_deflate_multistrip.tiff";
public const string RgbJpeg = "Tiff/rgb_jpeg.tiff";
public const string RgbLzw_Predictor = "Tiff/rgb_lzw_predictor.tiff";
public const string RgbLzw_NoPredictor_Multistrip = "Tiff/rgb_lzw_noPredictor_multistrip.tiff";
public const string RgbLzw_NoPredictor_Multistrip_Motorola = "Tiff/rgb_lzw_noPredictor_multistrip_Motorola.tiff";
public const string RgbLzw_NoPredictor_Singlestrip_Motorola = "Tiff/rgb_lzw_noPredictor_singlestrip_Motorola.tiff";
public const string RgbLzwMultistrip_Predictor = "Tiff/rgb_lzw_multistrip.tiff";
public const string RgbLzwPredictor = "Tiff/rgb_lzw_predictor.tiff";
public const string RgbLzwNoPredictor = "Tiff/rgb_lzw_no_predictor.tiff";
public const string RgbLzwNoPredictorMultistrip = "Tiff/rgb_lzw_noPredictor_multistrip.tiff";
public const string RgbLzwNoPredictorMultistripMotorola = "Tiff/rgb_lzw_noPredictor_multistrip_Motorola.tiff";
public const string RgbLzwNoPredictorSinglestripMotorola = "Tiff/rgb_lzw_noPredictor_singlestrip_Motorola.tiff";
public const string RgbLzwMultistripPredictor = "Tiff/rgb_lzw_multistrip.tiff";
public const string RgbPackbits = "Tiff/rgb_packbits.tiff";
public const string RgbPackbitsMultistrip = "Tiff/rgb_packbits_multistrip.tiff";
public const string RgbUncompressed = "Tiff/rgb_uncompressed.tiff";
@ -544,7 +545,7 @@ namespace SixLabors.ImageSharp.Tests
public const string RgbUncompressedTiled = "Tiff/rgb_uncompressed_tiled.tiff";
public const string MultiframeDifferentSizeTiled = "Tiff/multipage_ withPreview_differentSize_tiled.tiff";
public const string MultiframeLzw_Predictor = "Tiff/multipage_lzw.tiff";
public const string MultiframeLzwPredictor = "Tiff/multipage_lzw.tiff";
public const string MultiframeDeflateWithPreview = "Tiff/multipage_deflate_withPreview.tiff";
public const string MultiframeDifferentSize = "Tiff/multipage_differentSize.tiff";
public const string MultiframeDifferentVariants = "Tiff/multipage_differentVariants.tiff";
@ -554,20 +555,20 @@ namespace SixLabors.ImageSharp.Tests
public static readonly string[] All =
{
Calliphora_PaletteUncompressed, Calliphora_RgbPackbits,
Calliphora_GrayscaleDeflate_Predictor, Calliphora_RgbDeflate_Predictor, RgbDeflate_Predictor,
Calliphora_RgbLzw_Predictor, RgbLzw_Predictor, // TODO: Undoing the horizontal prediction seems to fail for lzw. Do we need to do something different for lzw?
Calliphora_GrayscaleDeflate_Predictor, Calliphora_RgbDeflate_Predictor, RgbDeflatePredictor,
Calliphora_RgbLzw_Predictor, RgbLzwPredictor, // TODO: Undoing the horizontal prediction seems to fail for lzw. Do we need to do something different for lzw?
Calliphora_BiColor, Calliphora_RgbUncompressed, Calliphora_HuffmanCompressed, Calliphora_Fax3Compressed, CcittFax3AllTermCodes, CcittFax3AllMakeupCodes,
HuffmanRleAllTermCodes, HuffmanRleAllMakeupCodes, GrayscaleDeflateMultistrip, Calliphora_GrayscaleDeflate, Calliphora_GrayscaleUncompressed,
GrayscaleUncompressed, PaletteDeflateMultistrip, PaletteUncompressed, RgbDeflateMultistrip, /*RgbJpeg,*/ /* RgbLzwMultistrip_Predictor,*/
RgbLzw_NoPredictor_Multistrip, RgbLzw_NoPredictor_Multistrip_Motorola, RgbLzw_NoPredictor_Singlestrip_Motorola, RgbPackbits, RgbPackbitsMultistrip, RgbUncompressed,
/* MultiframeLzw_Predictor, MultiFrameDifferentVariants, SampleMetadata,*/ SmallRgbDeflate, SmallRgbLzw,
RgbLzwNoPredictorMultistrip, RgbLzwNoPredictorMultistripMotorola, RgbLzwNoPredictorSinglestripMotorola, RgbPackbits, RgbPackbitsMultistrip, RgbUncompressed,
/* MultiframeLzw_Predictor, MultiFrameDifferentVariants, SampleMetadata,*/ SmallRgbDeflate, SmallRgbLzw, RgbLzwNoPredictor
};
public static readonly string[] Multiframes = { MultiframeDeflateWithPreview /*MultiframeLzw_Predictor, MultiFrameDifferentSize, MultiframeDifferentSizeTiled, MultiFrameDifferentVariants,*/ };
public static readonly string[] Metadata = { SampleMetadata };
public static readonly string[] NotSupported = { Calliphora_RgbJpeg, RgbLzwMultistrip_Predictor, RgbJpeg, RgbUncompressedTiled, MultiframeLzw_Predictor, MultiframeDifferentSize, MultiframeDifferentVariants };
public static readonly string[] NotSupported = { Calliphora_RgbJpeg, RgbLzwMultistripPredictor, RgbJpeg, RgbUncompressedTiled, MultiframeLzwPredictor, MultiframeDifferentSize, MultiframeDifferentVariants };
}
}
}

3
tests/Images/Input/Tiff/rgb_lzw_no_predictor.tiff

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:facf3ccfa0d01803e2eead6dfa6fb95133382c15cb991eb6a097678ca31b50dc
size 131081
Loading…
Cancel
Save