/// <summary>
 /// Get static cached instance of <see cref="ModifiedHuffmanCompressionAlgorithm"/>.
 /// </summary>
 /// <param name="fillOrder">The FillOrder tag specified in the image file directory.</param>
 /// <returns>A cached instance of <see cref="ModifiedHuffmanCompressionAlgorithm"/>.</returns>
 public static ModifiedHuffmanCompressionAlgorithm GetSharedInstance(TiffFillOrder fillOrder)
 {
     if (fillOrder != TiffFillOrder.LowerOrderBitsFirst)
     {
         return(HigherOrderBitsFirstInstance);
     }
     return(LowerOrderBitsFirstInstance);
 }
 /// <summary>
 /// Get static cached instance of <see cref="CcittGroup4Compression"/>.
 /// </summary>
 /// <param name="fillOrder">The FillOrder tag specified in the image file directory.</param>
 /// <returns>A cached instance of <see cref="CcittGroup4Compression"/>.</returns>
 public static CcittGroup4Compression GetSharedInstance(TiffFillOrder fillOrder)
 {
     if (fillOrder != TiffFillOrder.LowerOrderBitsFirst)
     {
         return(HigherOrderBitsFirstInstance);
     }
     return(LowerOrderBitsFirstInstance);
 }
Example #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ModifiedHuffmanTiffCompression" /> class.
        /// </summary>
        /// <param name="allocator">The memory allocator.</param>
        /// <param name="fillOrder">The logical order of bits within a byte.</param>
        /// <param name="width">The image width.</param>
        /// <param name="bitsPerPixel">The number of bits per pixel.</param>
        /// <param name="photometricInterpretation">The photometric interpretation.</param>
        public ModifiedHuffmanTiffCompression(MemoryAllocator allocator, TiffFillOrder fillOrder, int width, int bitsPerPixel, TiffPhotometricInterpretation photometricInterpretation)
            : base(allocator, width, bitsPerPixel)
        {
            this.FillOrder = fillOrder;
            bool isWhiteZero = photometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero;

            this.whiteValue = (byte)(isWhiteZero ? 0 : 1);
            this.blackValue = (byte)(isWhiteZero ? 1 : 0);
        }
        public static TiffBaseDecompressor Create(
            Configuration configuration,
            TiffDecoderCompressionType method,
            MemoryAllocator allocator,
            TiffPhotometricInterpretation photometricInterpretation,
            int width,
            int bitsPerPixel,
            TiffColorType colorType,
            TiffPredictor predictor,
            FaxCompressionOptions faxOptions,
            byte[] jpegTables,
            TiffFillOrder fillOrder,
            ByteOrder byteOrder)
        {
            switch (method)
            {
            case TiffDecoderCompressionType.None:
                DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
                DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
                return(new NoneTiffCompression(allocator, width, bitsPerPixel));

            case TiffDecoderCompressionType.PackBits:
                DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
                DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
                return(new PackBitsTiffCompression(allocator, width, bitsPerPixel));

            case TiffDecoderCompressionType.Deflate:
                DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
                return(new DeflateTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian));

            case TiffDecoderCompressionType.Lzw:
                DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
                return(new LzwTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian));

            case TiffDecoderCompressionType.T4:
                DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
                return(new T4TiffCompression(allocator, fillOrder, width, bitsPerPixel, faxOptions, photometricInterpretation));

            case TiffDecoderCompressionType.T6:
                DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
                return(new T6TiffCompression(allocator, fillOrder, width, bitsPerPixel, photometricInterpretation));

            case TiffDecoderCompressionType.HuffmanRle:
                DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
                return(new ModifiedHuffmanTiffCompression(allocator, fillOrder, width, bitsPerPixel, photometricInterpretation));

            case TiffDecoderCompressionType.Jpeg:
                DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");
                return(new JpegTiffCompression(configuration, allocator, width, bitsPerPixel, jpegTables, photometricInterpretation));

            default:
                throw TiffThrowHelper.NotSupportedDecompressor(nameof(method));
            }
        }
Example #5
0
 /// <summary>
 /// Initialize the middleware with the specified bit count and fill order.
 /// </summary>
 /// <param name="bitCount">The bit count.</param>
 /// <param name="fillOrder">The FillOrder tag.</param>
 public TiffWhiteIsZeroAny32Interpreter(int bitCount, TiffFillOrder fillOrder = TiffFillOrder.HigherOrderBitsFirst)
 {
     if ((uint)bitCount > 32)
     {
         throw new ArgumentOutOfRangeException(nameof(bitCount));
     }
     if (fillOrder == 0)
     {
         fillOrder = TiffFillOrder.HigherOrderBitsFirst;
     }
     _bitCount  = bitCount;
     _fillOrder = fillOrder;
 }
 /// <summary>
 /// Initialize the middleware with the specified bits per sample and fill order.
 /// </summary>
 /// <param name="bitsPerSample">The BitsPerSample flags.</param>
 /// <param name="fillOrder">The FillOrder tag.</param>
 public TiffChunkyRgbAny888Interpreter(TiffValueCollection <ushort> bitsPerSample, TiffFillOrder fillOrder = TiffFillOrder.HigherOrderBitsFirst)
 {
     if (bitsPerSample.Count != 3)
     {
         throw new ArgumentOutOfRangeException(nameof(bitsPerSample));
     }
     if ((uint)bitsPerSample[0] > 8 || (uint)bitsPerSample[1] > 8 || (uint)bitsPerSample[2] > 8)
     {
         throw new ArgumentOutOfRangeException(nameof(bitsPerSample));
     }
     if (fillOrder == 0)
     {
         fillOrder = TiffFillOrder.HigherOrderBitsFirst;
     }
     _bitsPerSample = bitsPerSample;
     _fillOrder     = fillOrder;
 }
Example #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="T4TiffCompression" /> class.
        /// </summary>
        /// <param name="allocator">The memory allocator.</param>
        /// <param name="fillOrder">The logical order of bits within a byte.</param>
        /// <param name="width">The image width.</param>
        /// <param name="bitsPerPixel">The number of bits per pixel.</param>
        /// <param name="faxOptions">Fax compression options.</param>
        /// <param name="photometricInterpretation">The photometric interpretation.</param>
        public T4TiffCompression(
            MemoryAllocator allocator,
            TiffFillOrder fillOrder,
            int width,
            int bitsPerPixel,
            FaxCompressionOptions faxOptions,
            TiffPhotometricInterpretation photometricInterpretation)
            : base(allocator, width, bitsPerPixel)
        {
            this.faxCompressionOptions = faxOptions;
            this.FillOrder             = fillOrder;
            this.width = width;
            bool isWhiteZero = photometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero;

            this.whiteValue = (byte)(isWhiteZero ? 0 : 1);
            this.blackValue = (byte)(isWhiteZero ? 1 : 0);
        }
Example #8
0
 /// <summary>
 /// Initialize the middleware with the specified bit count and fill order.
 /// </summary>
 /// <param name="colorMap">The color map.</param>
 /// <param name="bitCount">The bit count.</param>
 /// <param name="fillOrder">The FillOrder tag.</param>
 public TiffPaletteColorAny8Interpreter(ushort[] colorMap, int bitCount, TiffFillOrder fillOrder = TiffFillOrder.HigherOrderBitsFirst)
 {
     if ((uint)bitCount > 32)
     {
         throw new ArgumentOutOfRangeException(nameof(bitCount));
     }
     if (fillOrder == 0)
     {
         fillOrder = TiffFillOrder.HigherOrderBitsFirst;
     }
     _bitCount  = bitCount;
     _fillOrder = fillOrder;
     _colorMap  = colorMap ?? throw new ArgumentNullException(nameof(colorMap));
     if (_colorMap.Length < 3 * SingleColorCount)
     {
         throw new ArgumentException($"Color map requires {3 * SingleColorCount} elements.", nameof(colorMap));
     }
 }
 /// <summary>
 /// Initialize the middleware.
 /// </summary>
 /// <param name="isAlphaAssociated">Whether the alpha channel is associated.</param>
 /// <param name="undoColorPreMultiplying">Whether to undo color pre-multiplying.</param>
 /// <param name="bitsPerSample">The BitsPerSample flags.</param>
 /// <param name="fillOrder">The FillOrder tag.</param>
 public TiffChunkyRgbaAny8888Interpreter(bool isAlphaAssociated, bool undoColorPreMultiplying, TiffValueCollection <ushort> bitsPerSample, TiffFillOrder fillOrder = TiffFillOrder.HigherOrderBitsFirst)
 {
     _isAlphaAssociated       = isAlphaAssociated;
     _undoColorPreMultiplying = undoColorPreMultiplying;
     if (bitsPerSample.Count != 4)
     {
         throw new ArgumentOutOfRangeException(nameof(bitsPerSample));
     }
     if ((uint)bitsPerSample[0] > 8 || (uint)bitsPerSample[1] > 8 || (uint)bitsPerSample[2] > 8 || (uint)bitsPerSample[3] > 8)
     {
         throw new ArgumentOutOfRangeException(nameof(bitsPerSample));
     }
     if (fillOrder == 0)
     {
         fillOrder = TiffFillOrder.HigherOrderBitsFirst;
     }
     _bitsPerSample = bitsPerSample;
     _fillOrder     = fillOrder;
 }
Example #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="T4BitReader" /> class.
        /// </summary>
        /// <param name="input">The compressed input stream.</param>
        /// <param name="fillOrder">The logical order of bits within a byte.</param>
        /// <param name="bytesToRead">The number of bytes to read from the stream.</param>
        /// <param name="allocator">The memory allocator.</param>
        /// <param name="eolPadding">Indicates, if fill bits have been added as necessary before EOL codes such that EOL always ends on a byte boundary. Defaults to false.</param>
        public T4BitReader(Stream input, TiffFillOrder fillOrder, int bytesToRead, MemoryAllocator allocator, bool eolPadding = false)
        {
            this.fillOrder = fillOrder;
            this.Data      = allocator.Allocate <byte>(bytesToRead);
            this.ReadImageDataFromStream(input, bytesToRead);

            this.DataLength           = bytesToRead;
            this.BitsRead             = 0;
            this.Value                = 0;
            this.CurValueBitsRead     = 0;
            this.Position             = 0;
            this.IsWhiteRun           = true;
            this.isFirstScanLine      = true;
            this.isStartOfRow         = true;
            this.terminationCodeFound = false;
            this.RunLength            = 0;
            this.eolPadding           = eolPadding;

            if (this.eolPadding)
            {
                this.maxCodeLength = 24;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ModifiedHuffmanBitReader"/> class.
 /// </summary>
 /// <param name="input">The compressed input stream.</param>
 /// <param name="fillOrder">The logical order of bits within a byte.</param>
 /// <param name="bytesToRead">The number of bytes to read from the stream.</param>
 /// <param name="allocator">The memory allocator.</param>
 public ModifiedHuffmanBitReader(Stream input, TiffFillOrder fillOrder, int bytesToRead, MemoryAllocator allocator)
     : base(input, fillOrder, bytesToRead, allocator)
 {
 }
 /// <summary>
 /// Initialize the middleware with the specified fill order.
 /// </summary>
 /// <param name="fillOrder">The FillOrder tag.</param>
 public TiffWhiteIsZero1Interpreter(TiffFillOrder fillOrder)
 {
     _shouldReverseBits = fillOrder == TiffFillOrder.LowerOrderBitsFirst;
 }
Example #13
0
        public void GetFillOrder_ReturnsValue(ByteOrder byteOrder, TiffType type, int?data, TiffFillOrder expectedResult)
        {
            var ifd = TiffIfdBuilder.GenerateIfd(TiffTags.FillOrder, type, data, byteOrder).Ifd;

            var result = ifd.GetFillOrder(byteOrder);

            Assert.Equal(expectedResult, result);
        }
Example #14
0
 /// <summary>
 /// Get static cached instance of <see cref="CcittGroup3OneDimensionalCompressionAlgorithm"/>.
 /// </summary>
 /// <param name="fillOrder">The FillOrder tag specified in the image file directory.</param>
 /// <returns>A cached instance of <see cref="CcittGroup3OneDimensionalCompressionAlgorithm"/>.</returns>
 public static CcittGroup3OneDimensionalCompressionAlgorithm GetSharedInstance(TiffFillOrder fillOrder)
 {
     if (fillOrder != TiffFillOrder.LowerOrderBitsFirst)
     {
         return(HigherOrderBitsFirstInstance);
     }
     return(LowerOrderBitsFirstInstance);
 }
Example #15
0
 /// <summary>
 /// Initialize the middleware with the specified fill order.
 /// </summary>
 /// <param name="fillOrder">The FillOrder tag.</param>
 public TiffTransparencyMask1Interpreter(TiffFillOrder fillOrder)
 {
     _shouldReverseBits = fillOrder == TiffFillOrder.LowerOrderBitsFirst;
 }
        /// <summary>
        /// Determines the TIFF compression and color types, and reads any associated parameters.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <param name="exifProfile">The exif profile of the frame to decode.</param>
        /// <param name="frameMetadata">The IFD entries container to read the image format information for current frame.</param>
        public static void VerifyAndParse(this TiffDecoderCore options, ExifProfile exifProfile, TiffFrameMetadata frameMetadata)
        {
            if (exifProfile.GetValueInternal(ExifTag.TileOffsets) is not null || exifProfile.GetValueInternal(ExifTag.TileByteCounts) is not null)
            {
                TiffThrowHelper.ThrowNotSupported("Tiled images are not supported.");
            }

            if (exifProfile.GetValueInternal(ExifTag.ExtraSamples) is not null)
            {
                TiffThrowHelper.ThrowNotSupported("ExtraSamples is not supported.");
            }

            TiffFillOrder fillOrder = (TiffFillOrder?)exifProfile.GetValue(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst;

            if (fillOrder == TiffFillOrder.LeastSignificantBitFirst && frameMetadata.BitsPerPixel != TiffBitsPerPixel.Bit1)
            {
                TiffThrowHelper.ThrowNotSupported("The lower-order bits of the byte FillOrder is only supported in combination with 1bit per pixel bicolor tiff's.");
            }

            if (frameMetadata.Predictor == TiffPredictor.FloatingPoint)
            {
                TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported.");
            }

            TiffSampleFormat[] sampleFormats = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray();
            TiffSampleFormat?  sampleFormat  = null;

            if (sampleFormats != null)
            {
                sampleFormat = sampleFormats[0];
                foreach (TiffSampleFormat format in sampleFormats)
                {
                    if (format != TiffSampleFormat.UnsignedInteger && format != TiffSampleFormat.Float)
                    {
                        TiffThrowHelper.ThrowNotSupported("ImageSharp only supports the UnsignedInteger and Float SampleFormat.");
                    }
                }
            }

            ushort[] ycbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value;
            if (ycbcrSubSampling != null && ycbcrSubSampling.Length != 2)
            {
                TiffThrowHelper.ThrowImageFormatException("Invalid YCbCrSubsampling, expected 2 values.");
            }

            if (ycbcrSubSampling != null && ycbcrSubSampling[1] > ycbcrSubSampling[0])
            {
                TiffThrowHelper.ThrowImageFormatException("ChromaSubsampleVert shall always be less than or equal to ChromaSubsampleHoriz.");
            }

            if (exifProfile.GetValue(ExifTag.StripRowCounts)?.Value != null)
            {
                TiffThrowHelper.ThrowNotSupported("Variable-sized strips are not supported.");
            }

            VerifyRequiredFieldsArePresent(exifProfile, frameMetadata);

            options.PlanarConfiguration       = (TiffPlanarConfiguration?)exifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration;
            options.Predictor                 = frameMetadata.Predictor ?? TiffPredictor.None;
            options.PhotometricInterpretation = frameMetadata.PhotometricInterpretation ?? TiffPhotometricInterpretation.Rgb;
            options.SampleFormat              = sampleFormat ?? TiffSampleFormat.UnsignedInteger;
            options.BitsPerPixel              = frameMetadata.BitsPerPixel != null ? (int)frameMetadata.BitsPerPixel.Value : (int)TiffBitsPerPixel.Bit24;
            options.BitsPerSample             = frameMetadata.BitsPerSample ?? new TiffBitsPerSample(0, 0, 0);
            options.ReferenceBlackAndWhite    = exifProfile.GetValue(ExifTag.ReferenceBlackWhite)?.Value;
            options.YcbcrCoefficients         = exifProfile.GetValue(ExifTag.YCbCrCoefficients)?.Value;
            options.YcbcrSubSampling          = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value;
            options.FillOrder                 = fillOrder;
            options.JpegTables                = exifProfile.GetValue(ExifTag.JPEGTables)?.Value;

            options.ParseColorType(exifProfile);
            options.ParseCompression(frameMetadata.Compression, exifProfile);
        }