protected override void EncodeStrip(int y, int height, TiffBaseCompressor compressor)
        {
            if (this.rowBuffer == null)
            {
                this.rowBuffer = this.MemoryAllocator.Allocate <byte>(this.BytesPerRow * height);
            }

            this.rowBuffer.Clear();

            Span <byte> outputRowSpan = this.rowBuffer.GetSpan().Slice(0, this.BytesPerRow * height);

            int width = this.Image.Width;

            using IMemoryOwner <TPixel> stripPixelBuffer = this.MemoryAllocator.Allocate <TPixel>(height * width);
            Span <TPixel> stripPixels       = stripPixelBuffer.GetSpan();
            int           lastRow           = y + height;
            int           stripPixelsRowIdx = 0;

            for (int row = y; row < lastRow; row++)
            {
                Span <TPixel> stripPixelsRow = this.Image.PixelBuffer.GetRowSpan(row);
                stripPixelsRow.CopyTo(stripPixels.Slice(stripPixelsRowIdx * width, width));
                stripPixelsRowIdx++;
            }

            this.EncodePixels(stripPixels, outputRowSpan);
            compressor.CompressStrip(outputRowSpan, height);
        }
Example #2
0
        public virtual void Write(TiffBaseCompressor compressor, int rowsPerStrip)
        {
            DebugGuard.IsTrue(this.BytesPerRow == compressor.BytesPerRow, "bytes per row of the compressor does not match tiff color writer");
            int stripsCount = (this.Image.Height + rowsPerStrip - 1) / rowsPerStrip;

            uint[] stripOffsets    = new uint[stripsCount];
            uint[] stripByteCounts = new uint[stripsCount];

            int stripIndex = 0;

            compressor.Initialize(rowsPerStrip);
            for (int y = 0; y < this.Image.Height; y += rowsPerStrip)
            {
                long offset = compressor.Output.Position;

                int height = Math.Min(rowsPerStrip, this.Image.Height - y);
                this.EncodeStrip(y, height, compressor);

                long endOffset = compressor.Output.Position;
                stripOffsets[stripIndex]    = (uint)offset;
                stripByteCounts[stripIndex] = (uint)(endOffset - offset);
                stripIndex++;
            }

            DebugGuard.IsTrue(stripIndex == stripsCount, "stripIndex and stripsCount should match");
            this.AddStripTags(rowsPerStrip, stripOffsets, stripByteCounts);
        }
        /// <inheritdoc />
        protected override void EncodeStrip(int y, int height, TiffBaseCompressor compressor)
        {
            int width = this.Image.Width;

            if (this.BitsPerPixel == 4)
            {
                int halfWidth            = width >> 1;
                int excess               = (width & 1) * height; // (width % 2) * height
                int rows4BitBufferLength = (halfWidth * height) + excess;
                this.indexedPixelsBuffer ??= this.MemoryAllocator.Allocate <byte>(rows4BitBufferLength);
                Span <byte> rows4bit    = this.indexedPixelsBuffer.GetSpan();
                int         idx4bitRows = 0;
                int         lastRow     = y + height;
                for (int row = y; row < lastRow; row++)
                {
                    ReadOnlySpan <byte> indexedPixelRow = this.quantizedImage.DangerousGetRowSpan(row);
                    int idxPixels = 0;
                    for (int x = 0; x < halfWidth; x++)
                    {
                        rows4bit[idx4bitRows] = (byte)((indexedPixelRow[idxPixels] << 4) | (indexedPixelRow[idxPixels + 1] & 0xF));
                        idxPixels            += 2;
                        idx4bitRows++;
                    }

                    // Make sure rows are byte-aligned.
                    if (width % 2 != 0)
                    {
                        rows4bit[idx4bitRows++] = (byte)(indexedPixelRow[idxPixels] << 4);
                    }
                }

                compressor.CompressStrip(rows4bit.Slice(0, idx4bitRows), height);
            }
            else
            {
                int stripPixels = width * height;
                this.indexedPixelsBuffer ??= this.MemoryAllocator.Allocate <byte>(stripPixels);
                Span <byte> indexedPixels       = this.indexedPixelsBuffer.GetSpan();
                int         lastRow             = y + height;
                int         indexedPixelsRowIdx = 0;
                for (int row = y; row < lastRow; row++)
                {
                    ReadOnlySpan <byte> indexedPixelRow = this.quantizedImage.DangerousGetRowSpan(row);
                    indexedPixelRow.CopyTo(indexedPixels.Slice(indexedPixelsRowIdx * width, width));
                    indexedPixelsRowIdx++;
                }

                compressor.CompressStrip(indexedPixels.Slice(0, stripPixels), height);
            }
        }
Example #4
0
        /// <inheritdoc/>
        protected override void EncodeStrip(int y, int height, TiffBaseCompressor compressor)
        {
            int width = this.Image.Width;

            if (compressor.Method == TiffCompression.CcittGroup3Fax || compressor.Method == TiffCompression.Ccitt1D)
            {
                // Special case for T4BitCompressor.
                int stripPixels = width * height;
                this.pixelsAsGray ??= this.MemoryAllocator.Allocate <byte>(stripPixels);
                Span <byte> pixelAsGraySpan = this.pixelsAsGray.GetSpan();
                int         lastRow         = y + height;
                int         grayRowIdx      = 0;
                for (int row = y; row < lastRow; row++)
                {
                    Span <TPixel> pixelsBlackWhiteRow = this.imageBlackWhite.GetPixelRowSpan(row);
                    Span <byte>   pixelAsGrayRow      = pixelAsGraySpan.Slice(grayRowIdx * width, width);
                    PixelOperations <TPixel> .Instance.ToL8Bytes(this.Configuration, pixelsBlackWhiteRow, pixelAsGrayRow, width);

                    grayRowIdx++;
                }

                compressor.CompressStrip(pixelAsGraySpan.Slice(0, stripPixels), height);
            }
            else
            {
                // Write uncompressed image.
                int bytesPerStrip = this.BytesPerRow * height;
                this.bitStrip ??= this.MemoryAllocator.Allocate <byte>(bytesPerStrip);
                this.pixelsAsGray ??= this.MemoryAllocator.Allocate <byte>(width);
                Span <byte> pixelAsGraySpan = this.pixelsAsGray.GetSpan();

                Span <byte> rows = this.bitStrip.Slice(0, bytesPerStrip);
                rows.Clear();

                int outputRowIdx = 0;
                int lastRow      = y + height;
                for (int row = y; row < lastRow; row++)
                {
                    int           bitIndex            = 0;
                    int           byteIndex           = 0;
                    Span <byte>   outputRow           = rows.Slice(outputRowIdx * this.BytesPerRow);
                    Span <TPixel> pixelsBlackWhiteRow = this.imageBlackWhite.GetPixelRowSpan(row);
                    PixelOperations <TPixel> .Instance.ToL8Bytes(this.Configuration, pixelsBlackWhiteRow, pixelAsGraySpan, width);

                    for (int x = 0; x < this.Image.Width; x++)
                    {
                        int shift = 7 - bitIndex;
                        if (pixelAsGraySpan[x] == 255)
                        {
                            outputRow[byteIndex] |= (byte)(1 << shift);
                        }

                        bitIndex++;
                        if (bitIndex == 8)
                        {
                            byteIndex++;
                            bitIndex = 0;
                        }
                    }

                    outputRowIdx++;
                }

                compressor.CompressStrip(rows, height);
            }
        }
Example #5
0
 protected abstract void EncodeStrip(int y, int height, TiffBaseCompressor compressor);