Browse Source

Add option to encode Tiff's with jpeg compression

pull/1734/head
Brian Popow 5 years ago
parent
commit
fd957fae84
  1. 2
      src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs
  2. 49
      src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffJpegCompressor.cs
  3. 6
      src/ImageSharp/Formats/Tiff/Compression/TiffCompressorFactory.cs
  4. 2
      src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
  5. 2
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  6. 3
      src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
  7. 7
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs

2
src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsWriter.cs

@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
private static bool IsReplicateRun(ReadOnlySpan<byte> rowSpan, int startPos)
{
// We consider run which has at least 3 same consecutive bytes a candidate for a run.
var startByte = rowSpan[startPos];
byte startByte = rowSpan[startPos];
int count = 0;
for (int i = startPos + 1; i < rowSpan.Length; i++)
{

49
src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffJpegCompressor.cs

@ -0,0 +1,49 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
{
internal class TiffJpegCompressor : TiffBaseCompressor
{
public TiffJpegCompressor(Stream output, MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffPredictor predictor = TiffPredictor.None)
: base(output, memoryAllocator, width, bitsPerPixel, predictor)
{
}
/// <inheritdoc/>
public override TiffCompression Method => TiffCompression.Jpeg;
/// <inheritdoc/>
public override void Initialize(int rowsPerStrip)
{
}
/// <inheritdoc/>
public override void CompressStrip(Span<byte> rows, int height)
{
int pixelCount = rows.Length / 3;
int width = pixelCount / height;
using var memoryStream = new MemoryStream();
var image = Image.LoadPixelData<Rgb24>(rows, width, height);
image.Save(memoryStream, new JpegEncoder()
{
Subsample = JpegSubsample.Rgb
});
memoryStream.Position = 0;
memoryStream.WriteTo(this.Output);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
}
}
}

6
src/ImageSharp/Formats/Tiff/Compression/TiffCompressorFactory.cs

@ -25,7 +25,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression
// The following compression types are not implemented in the encoder and will default to no compression instead.
case TiffCompression.ItuTRecT43:
case TiffCompression.ItuTRecT82:
case TiffCompression.Jpeg:
case TiffCompression.OldJpeg:
case TiffCompression.OldDeflate:
case TiffCompression.None:
@ -34,6 +33,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression
return new NoCompressor(output, allocator, width, bitsPerPixel);
case TiffCompression.Jpeg:
DebugGuard.IsTrue(compressionLevel == DeflateCompressionLevel.DefaultCompression, "No deflate compression level is expected to be set");
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
return new TiffJpegCompressor(output, allocator, width, bitsPerPixel);
case TiffCompression.PackBits:
DebugGuard.IsTrue(compressionLevel == DeflateCompressionLevel.DefaultCompression, "No deflate compression level is expected to be set");
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");

2
src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs

@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression
TiffColorType colorType,
TiffPredictor predictor,
FaxCompressionOptions faxOptions,
byte[] jpegTables,
byte[] jpegTables,
TiffFillOrder fillOrder,
ByteOrder byteOrder)
{

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

@ -366,7 +366,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.ColorType,
this.Predictor,
this.FaxCompressionOptions,
this.JpegTables,
this.JpegTables,
this.FillOrder,
this.byteOrder);

3
src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs

@ -396,6 +396,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
case TiffCompression.Ccitt1D:
return (ushort)TiffCompression.Ccitt1D;
case TiffCompression.Jpeg:
return (ushort)TiffCompression.Jpeg;
}
return (ushort)TiffCompression.None;

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

@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Ccitt1D, TiffBitsPerPixel.Bit1, TiffCompression.Ccitt1D)]
[InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.ItuTRecT43, TiffBitsPerPixel.Bit24, TiffCompression.None)]
[InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.ItuTRecT82, TiffBitsPerPixel.Bit24, TiffCompression.None)]
[InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.Jpeg, TiffBitsPerPixel.Bit24, TiffCompression.None)]
[InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.Jpeg, TiffBitsPerPixel.Bit24, TiffCompression.Jpeg)]
[InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.OldDeflate, TiffBitsPerPixel.Bit24, TiffCompression.None)]
[InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.OldJpeg, TiffBitsPerPixel.Bit24, TiffCompression.None)]
public void EncoderOptions_SetPhotometricInterpretationAndCompression_Works(
@ -288,6 +288,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void TiffEncoder_EncodeRgb_WithPackBitsCompression_Works<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, TiffCompression.PackBits);
[Theory]
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeRgb_WithjpegCompression_Works<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, TiffCompression.Jpeg);
[Theory]
[WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)]
public void TiffEncoder_EncodeGray_Works<TPixel>(TestImageProvider<TPixel> provider)

Loading…
Cancel
Save