From 0327e1d332179fea4e051a14c2ec275c36d69035 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 5 Nov 2022 17:33:20 +0100 Subject: [PATCH] Avoid some code duplication --- .../Formats/Tiff/TiffDecoderCore.cs | 77 +++++++++++-------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 0324759824..6d55d9981c 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -323,13 +323,35 @@ internal class TiffDecoderCore : IImageDecoderInternals int tilesAcross = (width + tileWidth - 1) / tileWidth; int tilesDown = (height + tileLength - 1) / tileLength; + Array tilesOffsetsArray; + Array tilesByteCountsArray; + IExifValue tilesOffsetsExifValue = tags.GetValueInternal(ExifTag.TileOffsets); + IExifValue tilesByteCountsExifValue = tags.GetValueInternal(ExifTag.TileByteCounts); + if (tilesOffsetsExifValue is null) + { + // Note: This is against the spec, but libTiff seems to handle it this way. + // TIFF 6.0 says: "Do not use both strip- oriented and tile-oriented fields in the same TIFF file". + tilesOffsetsExifValue = tags.GetValueInternal(ExifTag.StripOffsets); + tilesByteCountsExifValue = tags.GetValueInternal(ExifTag.StripByteCounts); + tilesOffsetsArray = (Array)tilesOffsetsExifValue.GetValue(); + tilesByteCountsArray = (Array)tilesByteCountsExifValue.GetValue(); + } + else + { + tilesOffsetsArray = (Array)tilesOffsetsExifValue.GetValue(); + tilesByteCountsArray = (Array)tilesByteCountsExifValue.GetValue(); + } + + using IMemoryOwner tileOffsetsMemory = this.ConvertNumbers(tilesOffsetsArray, out Span tileOffsets); + using IMemoryOwner tileByteCountsMemory = this.ConvertNumbers(tilesByteCountsArray, out Span tileByteCounts); + if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar) { - this.DecodeTilesPlanar(tags, frame, tileWidth, tileLength, tilesAcross, tilesDown, cancellationToken); + this.DecodeTilesPlanar(frame, tileWidth, tileLength, tilesAcross, tilesDown, tileOffsets, tileByteCounts, cancellationToken); } else { - this.DecodeTilesChunky(tags, frame, tileWidth, tileLength, tilesAcross, tilesDown, cancellationToken); + this.DecodeTilesChunky(frame, tileWidth, tileLength, tilesAcross, tilesDown, tileOffsets, tileByteCounts, cancellationToken); } } @@ -475,14 +497,23 @@ internal class TiffDecoderCore : IImageDecoderInternals /// Decodes the image data for Tiff's which arrange the pixel data in tiles and the planar configuration. /// /// The pixel format. - /// The IFD tags. /// The image frame to decode into. /// The width in pixels of the tile. /// The height in pixels of the tile. /// The number of tiles horizontally. /// The number of tiles vertically. + /// The tile offsets. + /// The tile byte counts. /// The token to monitor cancellation. - private void DecodeTilesPlanar(ExifProfile tags, ImageFrame frame, int tileWidth, int tileLength, int tilesAcross, int tilesDown, CancellationToken cancellationToken) + private void DecodeTilesPlanar( + ImageFrame frame, + int tileWidth, + int tileLength, + int tilesAcross, + int tilesDown, + Span tileOffsets, + Span tileByteCounts, + CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { Buffer2D pixels = frame.PixelBuffer; @@ -490,11 +521,6 @@ internal class TiffDecoderCore : IImageDecoderInternals int height = pixels.Height; int bitsPerPixel = this.BitsPerPixel; - Array tilesOffsetsArray = (Array)tags.GetValueInternal(ExifTag.TileOffsets).GetValue(); - Array tilesByteCountsArray = (Array)tags.GetValueInternal(ExifTag.TileByteCounts).GetValue(); - using IMemoryOwner tileOffsetsMemory = this.ConvertNumbers(tilesOffsetsArray, out Span tileOffsets); - using IMemoryOwner tileByteCountsMemory = this.ConvertNumbers(tilesByteCountsArray, out Span tileByteCounts); - int bytesPerRow = ((width * bitsPerPixel) + 7) / 8; int bytesPerTileRow = ((tileWidth * bitsPerPixel) + 7) / 8; int uncompressedTilesSize = bytesPerTileRow * tileLength; @@ -559,14 +585,23 @@ internal class TiffDecoderCore : IImageDecoderInternals /// Decodes the image data for Tiff's which arrange the pixel data in tiles and the chunky configuration. /// /// The pixel format. - /// The IFD tags. /// The image frame to decode into. /// The width in pixels of the tile. /// The height in pixels of the tile. /// The number of tiles horizontally. /// The number of tiles vertically. + /// The tile offsets. + /// The tile byte counts. /// The token to monitor cancellation. - private void DecodeTilesChunky(ExifProfile tags, ImageFrame frame, int tileWidth, int tileLength, int tilesAcross, int tilesDown, CancellationToken cancellationToken) + private void DecodeTilesChunky( + ImageFrame frame, + int tileWidth, + int tileLength, + int tilesAcross, + int tilesDown, + Span tileOffsets, + Span tileByteCounts, + CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { Buffer2D pixels = frame.PixelBuffer; @@ -574,26 +609,6 @@ internal class TiffDecoderCore : IImageDecoderInternals int height = pixels.Height; int bitsPerPixel = this.BitsPerPixel; - Array tilesOffsetsArray; - Array tilesByteCountsArray; - IExifValue tilesOffsetsExifValue = tags.GetValueInternal(ExifTag.TileOffsets); - IExifValue tilesByteCountsExifValue = tags.GetValueInternal(ExifTag.TileByteCounts); - if (tilesOffsetsExifValue is null) - { - tilesOffsetsExifValue = tags.GetValueInternal(ExifTag.StripOffsets); - tilesByteCountsExifValue = tags.GetValueInternal(ExifTag.StripByteCounts); - tilesOffsetsArray = (Array)tilesOffsetsExifValue.GetValue(); - tilesByteCountsArray = (Array)tilesByteCountsExifValue.GetValue(); - } - else - { - tilesOffsetsArray = (Array)tilesOffsetsExifValue.GetValue(); - tilesByteCountsArray = (Array)tilesByteCountsExifValue.GetValue(); - } - - using IMemoryOwner tileOffsetsMemory = this.ConvertNumbers(tilesOffsetsArray, out Span tileOffsets); - using IMemoryOwner tileByteCountsMemory = this.ConvertNumbers(tilesByteCountsArray, out Span tileByteCounts); - int bytesPerRow = ((width * bitsPerPixel) + 7) / 8; int bytesPerTileRow = ((tileWidth * bitsPerPixel) + 7) / 8; int uncompressedTilesSize = bytesPerTileRow * tileLength;