Example #1
0
        public static void WriteBits(
            ImageBinWriter s, ref BitBuffer32 bitBuf, ushort bs0, ushort bs1)
        {
            Debug.Assert(s != null);

            bitBuf.Count += bs1;
            bitBuf.Value |= bs0 << (24 - bitBuf.Count);

            while (bitBuf.Count >= 8)
            {
                byte c = (byte)((bitBuf.Value >> 16) & 0xff);
                s.WriteByte(c);
                if (c == 0xff)
                {
                    s.WriteByte(0);
                }

                bitBuf.Value <<= 8;
                bitBuf.Count  -= 8;
            }
        }
 private static void WriteDumpData(ImageBinWriter s, ReadOnlySpan <byte> data)
 {
     s.WriteByte((byte)((data.Length) & 0xff)); // lengthbyte
     s.Write(data);
 }
 private static void WriteRunData(ImageBinWriter s, int length, byte databyte)
 {
     s.WriteByte((byte)((length + 128) & 0xff)); // lengthbyte
     s.WriteByte(databyte);
 }
Example #4
0
        public static void WriteCore <TImage>(
            ImageBinWriter state, TImage image,
            bool useFloatPixels, int quality, bool allowSubsample, bool forceSubsample)
            where TImage : IPixelRowProvider
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            int width  = image.Width;
            int height = image.Height;
            int comp   = image.Components;

            if (width == 0 || (height == 0))
            {
                throw new ArgumentException("Invalid dimensions.", nameof(image));
            }
            if ((comp < 1) || (comp > 4))
            {
                throw new ArgumentException("Invalid component count.", nameof(image));
            }

            image.ThrowIfCancelled();

            Span <float> fdtbl_Y  = stackalloc float[64];
            Span <float> fdtbl_UV = stackalloc float[64];

            Span <byte> YTable  = stackalloc byte[64];
            Span <byte> UVTable = stackalloc byte[64];

            quality = quality != 0 ? quality : 90;
            quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
            quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
            bool subsample = forceSubsample || (allowSubsample && quality <= 90);

            ReadOnlySpan <byte> zigZag = ZigZag;

            for (int i = 0; i < 64; i++)
            {
                int yti = (YQT[i] * quality + 50) / 100;
                YTable[zigZag[i]] = (byte)(yti < 1 ? 1 : yti > 255 ? 255 : yti);

                int uvti = (UVQT[i] * quality + 50) / 100;
                UVTable[zigZag[i]] = (byte)(uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
            }

            for (int row = 0, k = 0; row < 8; row++)
            {
                for (int col = 0; col < 8; col++, k++)
                {
                    fdtbl_Y[k]  = 1 / (YTable[zigZag[k]] * aasf[row] * aasf[col]);
                    fdtbl_UV[k] = 1 / (UVTable[zigZag[k]] * aasf[row] * aasf[col]);
                }
            }

            {
                Span <byte> head1 = stackalloc byte[24] {
                    0xFF,
                    0xC0,
                    0,
                    0x11,
                    8,
                    (byte)(height >> 8),
                    (byte)((height) & 0xff),
                    (byte)(width >> 8),
                    (byte)((width) & 0xff),
                    3,
                    1,
                    (byte)(subsample ? 0x22 : 0x11),
                    0,
                    2,
                    0x11,
                    1,
                    3,
                    0x11,
                    1,
                    0xFF,
                    0xC4,
                    0x01,
                    0xA2,
                    0
                };

                state.Write(Head0);
                state.Write(YTable);
                state.WriteByte(1);
                state.Write(UVTable);
                state.Write(head1);

                state.Write(DefaultDcLuminanceNrcodes[1..DefaultDcChrominanceNrcodes.Length]);