コード例 #1
0
        /// <inheritdoc />
        public void Compress(TiffCompressionContext context, ReadOnlyMemory <byte> input, IBufferWriter <byte> outputWriter)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.PhotometricInterpretation != TiffPhotometricInterpretation.WhiteIsZero && context.PhotometricInterpretation != TiffPhotometricInterpretation.BlackIsZero)
            {
                throw new NotSupportedException("Modified Huffman compression does not support this photometric interpretation.");
            }

            if (context.BitsPerSample.Count != 1 || context.BitsPerSample[0] != 8)
            {
                throw new NotSupportedException("Unsupported bits per sample.");
            }

            context.BitsPerSample = TiffValueCollection.Single <ushort>(1);

            ReadOnlySpan <byte> inputSpan = input.Span;

            int width     = context.ImageSize.Width;
            int height    = context.ImageSize.Height;
            var bitWriter = new BitWriter2(outputWriter, 4096);

            // Process every scanline
            for (int row = 0; row < height; row++)
            {
                ReadOnlySpan <byte> rowSpan = inputSpan.Slice(0, width);
                inputSpan = inputSpan.Slice(width);

                CcittEncodingTable currentTable = CcittEncodingTable.WhiteInstance;
                CcittEncodingTable otherTable   = CcittEncodingTable.BlackInstance;

                // ModifiedHuffman compression assumes WhiteIsZero photometric interpretation is used.
                // Since the first run is white run, we look for black pixel in the first iteration.
                byte nextRunPixel = 255;

                while (!rowSpan.IsEmpty)
                {
                    // Get the length of the current run
                    int runLength = rowSpan.IndexOf(nextRunPixel);
                    if (runLength < 0)
                    {
                        runLength = rowSpan.Length;
                    }
                    currentTable.EncodeRun(ref bitWriter, runLength);
                    rowSpan = rowSpan.Slice(runLength);

                    // Switch to the other color
                    CcittHelper.SwapTable(ref currentTable, ref otherTable);
                    nextRunPixel = (byte)~nextRunPixel;
                }

                bitWriter.AdvanceAlignByte();
            }

            bitWriter.Flush();
        }
コード例 #2
0
        static public MemoryStream CompressToLZXStreamRAW(String FileToCompress)
        {
            using (Stream StreamToCompress = File.OpenRead(FileToCompress))
            {
                var OutputStream       = new MemoryStream();
                var OutputBinaryWriter = new BinaryWriter(OutputStream);

                while (!StreamToCompress.Eof())
                {
                    byte[] CompressedBytes;
                    long   Position          = StreamToCompress.Position;
                    var    UncompressedBytes = StreamToCompress.ReadBytesUpTo(0x8000);

                    {
                        var MS = new MemoryStream();

                        var BW = new BitWriter2(MS, 2, false);

                        if (Position == 0)
                        {
                            BW.WriteBits(1, 0);                             // Header
                            //BW.WriteBits(1, 1); // Header
                            //BW.WriteBits(16, 183);
                            //BW.WriteBits(16, 6912);
                        }

                        BW.WriteBits(3, 3);                         // Bits
                        BW.WriteBits(24, UncompressedBytes.Length);
                        BW.Align();
                        MS.WriteStruct((uint)0);
                        MS.WriteStruct((uint)0);
                        MS.WriteStruct((uint)0);
                        MS.WriteBytes(UncompressedBytes);

                        CompressedBytes = MS.ToArray();
                    }

                    if ((UncompressedBytes.Length != 0x8000))
                    {
                        OutputBinaryWriter.Write((byte)0xFF);
                        OutputBinaryWriter.WriteEndian((ushort)UncompressedBytes.Length, Endianness.BigEndian);
                        OutputBinaryWriter.WriteEndian((ushort)CompressedBytes.Length, Endianness.BigEndian);
                    }
                    else
                    {
                        OutputBinaryWriter.WriteEndian((ushort)CompressedBytes.Length, Endianness.BigEndian);
                    }

                    OutputStream.WriteBytes(CompressedBytes);
                }

                OutputStream.Position = 0;
                return(OutputStream);
            }
        }
コード例 #3
0
        /// <inheritdoc />
        public void Compress(TiffCompressionContext context, ReadOnlyMemory <byte> input, IBufferWriter <byte> outputWriter)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.PhotometricInterpretation != TiffPhotometricInterpretation.WhiteIsZero && context.PhotometricInterpretation != TiffPhotometricInterpretation.BlackIsZero)
            {
                throw new NotSupportedException("Modified Huffman compression does not support this photometric interpretation.");
            }

            if (context.BitsPerSample.Count != 1 || context.BitsPerSample[0] != 8)
            {
                throw new NotSupportedException("Unsupported bits per sample.");
            }

            context.BitsPerSample = TiffValueCollection.Single <ushort>(1);

            ReadOnlySpan <byte> inputSpan = input.Span;

            int width     = context.ImageSize.Width;
            int height    = context.ImageSize.Height;
            var bitWriter = new BitWriter2(outputWriter, 4096);

            ReferenceScanline referenceScanline = new ReferenceScanline(whiteIsZero: true, width);

            // Process every scanline
            for (int row = 0; row < height; row++)
            {
                ReadOnlySpan <byte> scanline = inputSpan.Slice(0, width);
                inputSpan = inputSpan.Slice(width);

                Encode2DScanline(ref bitWriter, referenceScanline, scanline);

                referenceScanline = new ReferenceScanline(whiteIsZero: true, scanline);
            }

            bitWriter.Flush();
        }
コード例 #4
0
        private static void Encode2DScanline(ref BitWriter2 bitWriter, ReferenceScanline referenceScanline, ReadOnlySpan <byte> scanline)
        {
            int width = scanline.Length;
            CcittEncodingTable currentTable   = CcittEncodingTable.WhiteInstance;
            CcittEncodingTable otherTable     = CcittEncodingTable.BlackInstance;
            CodingScanline     codingScanline = new CodingScanline(whiteIsZero: true, scanline);

            byte a0Byte = 0;
            int  a0     = -1;

            while (true)
            {
                int a1 = codingScanline.FindA1(a0, a0Byte);
                int b1 = referenceScanline.FindB1(a0, a0Byte);
                int b2 = referenceScanline.FindB2(b1);

                if (b2 < a1)
                {
                    EncodePassCode(ref bitWriter);
                    a0 = b2;
                }
                else
                {
                    int a1b1 = b1 - a1;
                    if (a1b1 >= -3 && a1b1 <= 3)
                    {
                        // Vertical mode coding
                        switch (a1b1)
                        {
                        case 3:
                            EncodeVerticalL3Code(ref bitWriter);
                            break;

                        case 2:
                            EncodeVerticalL2Code(ref bitWriter);
                            break;

                        case 1:
                            EncodeVerticalL1Code(ref bitWriter);
                            break;

                        case 0:
                            EncodeVertical0Code(ref bitWriter);
                            break;

                        case -1:
                            EncodeVerticalR1Code(ref bitWriter);
                            break;

                        case -2:
                            EncodeVerticalR2Code(ref bitWriter);
                            break;

                        case -3:
                            EncodeVerticalR3Code(ref bitWriter);
                            break;

                        default:
                            break;
                        }

                        CcittHelper.SwapTable(ref currentTable, ref otherTable);
                        a0 = a1;
                    }
                    else
                    {
                        int a2 = codingScanline.FindA2(a1);
                        EncodeHorizontalCode(ref bitWriter);

                        currentTable.EncodeRun(ref bitWriter, a1 - a0);
                        otherTable.EncodeRun(ref bitWriter, a2 - a1);

                        a0 = a2;
                    }
                }

                if (a0 >= width)
                {
                    break;
                }
                a0Byte = scanline[a0];
            }
        }
コード例 #5
0
 private static void EncodeVerticalL3Code(ref BitWriter2 writer)
 {
     writer.Write(0b0000010, 7);
 }
コード例 #6
0
 private static void EncodeVerticalL1Code(ref BitWriter2 writer)
 {
     writer.Write(0b010, 3);
 }
コード例 #7
0
 private static void EncodeVerticalR2Code(ref BitWriter2 writer)
 {
     writer.Write(0b000011, 6);
 }
コード例 #8
0
 private static void EncodeVertical0Code(ref BitWriter2 writer)
 {
     writer.Write(0b1, 1);
 }
コード例 #9
0
 private static void EncodeHorizontalCode(ref BitWriter2 writer)
 {
     writer.Write(0b001, 3);
 }
コード例 #10
0
 private static void EncodePassCode(ref BitWriter2 writer)
 {
     writer.Write(0b0001, 4);
 }