diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index 80aab1cc4..192bf5a73 100644 --- a/src/ImageSharp/Configuration.cs +++ b/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; diff --git a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs b/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs index dbaeac7e6..774273b07 100644 --- a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs +++ b/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(Image image, IQuantizer quantizer, int padding, TiffEncoderCompression compression, out IExifValue colorMap) where TPixel : unmanaged, IPixel { - 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 frameQuantizer = quantizer.CreatePixelSpecificQuantizer(this.configuration); using IndexedImageFrame quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image.Frames.RootFrame, image.Bounds()); - using IMemoryOwner colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(colorPaletteSize); + using IMemoryOwner colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(colorPaletteBytes); Span colorPalette = colorPaletteBuffer.GetSpan(); ReadOnlySpan quantizedColors = quantized.Palette.Span; @@ -253,8 +255,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils Span quantizedColorRgb48 = MemoryMarshal.Cast(colorPalette.Slice(0, quantizedColorBytes)); PixelOperations.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. diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs index 65d31dbcc..0f0b867f7 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs +++ b/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 diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 11a01d50f..09f1c8d0c 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/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); diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs index d7d0f4b0f..99d9a10d5 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs @@ -93,6 +93,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff memStream.Position = 0; using var encodedImage = (Image)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)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)Image.Load(memStream); + provider.Utility.SaveTestOutputFile(encodedImage, "tiff", encoder); TiffTestUtils.CompareWithReferenceDecoder(provider, encodedImage); } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 9f7516fe2..8913fee1e 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/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 }; } } } diff --git a/tests/Images/Input/Tiff/rgb_lzw_no_predictor.tiff b/tests/Images/Input/Tiff/rgb_lzw_no_predictor.tiff new file mode 100644 index 000000000..1fa09b5e2 --- /dev/null +++ b/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