Пример #1
0
        /// <summary>
        /// Decodes the image data for chunky encoded pixel data.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="frame">The image frame to decode data into.</param>
        /// <param name="rowsPerStrip">The rows per strip.</param>
        /// <param name="stripOffsets">The strip offsets.</param>
        /// <param name="stripByteCounts">The strip byte counts.</param>
        /// <param name="cancellationToken">The token to monitor cancellation.</param>
        private void DecodeStripsChunky <TPixel>(ImageFrame <TPixel> frame, int rowsPerStrip, Span <ulong> stripOffsets, Span <ulong> stripByteCounts, CancellationToken cancellationToken)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            // If the rowsPerStrip has the default value, which is effectively infinity. That is, the entire image is one strip.
            if (rowsPerStrip == TiffConstants.RowsPerStripInfinity)
            {
                rowsPerStrip = frame.Height;
            }

            int uncompressedStripSize = this.CalculateStripBufferSize(frame.Width, rowsPerStrip);
            int bitsPerPixel          = this.BitsPerPixel;

            using IMemoryOwner <byte> stripBuffer = this.memoryAllocator.Allocate <byte>(uncompressedStripSize, AllocationOptions.Clean);
            Span <byte>       stripBufferSpan     = stripBuffer.GetSpan();
            Buffer2D <TPixel> pixels = frame.PixelBuffer;

            using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create(
                      this.Configuration,
                      this.CompressionType,
                      this.memoryAllocator,
                      this.PhotometricInterpretation,
                      frame.Width,
                      bitsPerPixel,
                      this.ColorType,
                      this.Predictor,
                      this.FaxCompressionOptions,
                      this.JpegTables,
                      this.FillOrder,
                      this.byteOrder);

            TiffBaseColorDecoder <TPixel> colorDecoder = TiffColorDecoderFactory <TPixel> .Create(
                this.Configuration,
                this.memoryAllocator,
                this.ColorType,
                this.BitsPerSample,
                this.ColorMap,
                this.ReferenceBlackAndWhite,
                this.YcbcrCoefficients,
                this.YcbcrSubSampling,
                this.byteOrder);

            for (int stripIndex = 0; stripIndex < stripOffsets.Length; stripIndex++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                int stripHeight = stripIndex < stripOffsets.Length - 1 || frame.Height % rowsPerStrip == 0
                    ? rowsPerStrip
                    : frame.Height % rowsPerStrip;

                int top = rowsPerStrip * stripIndex;
                if (top + stripHeight > frame.Height)
                {
                    // Make sure we ignore any strips that are not needed for the image (if too many are present).
                    break;
                }

                decompressor.Decompress(
                    this.inputStream,
                    stripOffsets[stripIndex],
                    stripByteCounts[stripIndex],
                    stripHeight,
                    stripBufferSpan);

                colorDecoder.Decode(stripBufferSpan, pixels, 0, top, frame.Width, stripHeight);
            }
        }
Пример #2
0
        /// <summary>
        /// Decodes the image data for planar encoded pixel data.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="frame">The image frame to decode data into.</param>
        /// <param name="rowsPerStrip">The number of rows per strip of data.</param>
        /// <param name="stripOffsets">An array of byte offsets to each strip in the image.</param>
        /// <param name="stripByteCounts">An array of the size of each strip (in bytes).</param>
        /// <param name="cancellationToken">The token to monitor cancellation.</param>
        private void DecodeStripsPlanar <TPixel>(ImageFrame <TPixel> frame, int rowsPerStrip, Span <ulong> stripOffsets, Span <ulong> stripByteCounts, CancellationToken cancellationToken)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            int stripsPerPixel = this.BitsPerSample.Channels;
            int stripsPerPlane = stripOffsets.Length / stripsPerPixel;
            int bitsPerPixel   = this.BitsPerPixel;

            Buffer2D <TPixel> pixels = frame.PixelBuffer;

            var stripBuffers = new IMemoryOwner <byte> [stripsPerPixel];

            try
            {
                for (int stripIndex = 0; stripIndex < stripBuffers.Length; stripIndex++)
                {
                    int uncompressedStripSize = this.CalculateStripBufferSize(frame.Width, rowsPerStrip, stripIndex);
                    stripBuffers[stripIndex] = this.memoryAllocator.Allocate <byte>(uncompressedStripSize);
                }

                using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create(
                          this.Configuration,
                          this.CompressionType,
                          this.memoryAllocator,
                          this.PhotometricInterpretation,
                          frame.Width,
                          bitsPerPixel,
                          this.ColorType,
                          this.Predictor,
                          this.FaxCompressionOptions,
                          this.JpegTables,
                          this.FillOrder,
                          this.byteOrder);

                TiffBasePlanarColorDecoder <TPixel> colorDecoder = TiffColorDecoderFactory <TPixel> .CreatePlanar(
                    this.ColorType,
                    this.BitsPerSample,
                    this.ColorMap,
                    this.ReferenceBlackAndWhite,
                    this.YcbcrCoefficients,
                    this.YcbcrSubSampling,
                    this.byteOrder);

                for (int i = 0; i < stripsPerPlane; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    int stripHeight = i < stripsPerPlane - 1 || frame.Height % rowsPerStrip == 0 ? rowsPerStrip : frame.Height % rowsPerStrip;

                    int stripIndex = i;
                    for (int planeIndex = 0; planeIndex < stripsPerPixel; planeIndex++)
                    {
                        decompressor.Decompress(
                            this.inputStream,
                            stripOffsets[stripIndex],
                            stripByteCounts[stripIndex],
                            stripHeight,
                            stripBuffers[planeIndex].GetSpan());

                        stripIndex += stripsPerPlane;
                    }

                    colorDecoder.Decode(stripBuffers, pixels, 0, rowsPerStrip * i, frame.Width, stripHeight);
                }
            }
            finally
            {
                foreach (IMemoryOwner <byte> buf in stripBuffers)
                {
                    buf?.Dispose();
                }
            }
        }