Пример #1
0
        public static void SaveImageData(Stream stream, FreeImageBitmap image)
        {
            byte[] imageData = new byte[image.Width * image.Height / 2];
            int    o         = 0;

            for (int y = 0; y < image.Height; y++)
            {
                if (image.ColorDepth == 4)
                {
                    var scanline = image.GetScanlineFromTop4Bit(y);
                    for (int x = 0; x < image.Width; x += 2)
                    {
                        int p1 = scanline[x];
                        int p2 = scanline[x + 1];
                        imageData[o++] = (byte)((p1 << 4) + p2);
                    }
                }
                else if (image.ColorDepth == 8)
                {
                    var scanline = image.GetScanlineFromTop8Bit(y);
                    for (int x = 0; x < image.Width; x += 2)
                    {
                        int p1 = scanline[x] & 0x0F;
                        int p2 = scanline[x + 1] & 0x0F;
                        imageData[o++] = (byte)((p1 << 4) + p2);
                    }
                }
            }
            byte[] bytes = new byte[imageData.Length];

            int[] lengths = new int[9];

            TransformImage(bytes, imageData, image.Width, image.Height);
            int height = image.Height;

            //encode the bytes
            for (int i = 0; i < bytes.Length; i++)
            {
                int x = i / image.Height;
                int p = x & 3;

                Array.Clear(lengths, 0, lengths.Length);
                lengths[0] = MeasureRleRun(bytes, i, height);
                lengths[1] = MeasureRleRun2(bytes, i, height);
                lengths[2] = MeasurePreviousColumnRun(bytes, i, height, height * 4, 0);
                if (p >= 1)
                {
                    lengths[3] = MeasurePreviousColumnRun(bytes, i, height, height * p, 0);
                    lengths[6] = MeasurePreviousColumnRun(bytes, i, height, height * p, 255);
                }
                if (p >= 2)
                {
                    lengths[4] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 1), 0);
                    lengths[7] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 1), 255);
                }
                if (p >= 3)
                {
                    lengths[5] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 2), 0);
                    lengths[8] = MeasurePreviousColumnRun(bytes, i, height, height * (p - 2), 255);
                }
                int maxIndex;
                int max = lengths.Max(out maxIndex);

                byte b = bytes[i];
                if (max < 2)
                {
                    maxIndex = -1;
                }
                else if (max == 2)
                {
                    if (b >= 0x08)
                    {
                        maxIndex = -1;
                    }
                    else
                    {
                        if (maxIndex < 2 || maxIndex >= 6)
                        {
                            maxIndex = -1;
                        }
                    }
                }
                else if (max == 3)
                {
                    //don't compress 3 bytes to 3 bytes unless first byte would be a literal
                    if (b >= 0x08 && maxIndex < 2 || maxIndex >= 6)
                    {
                        maxIndex = -1;
                    }
                }

                switch (maxIndex)
                {
                default:
                {
                    //No compression - raw byte or escaped literal
                    if (b >= 0x08)
                    {
                        //raw byte
                        stream.WriteByte((byte)b);
                    }
                    else
                    {
                        //encode a literal as 2 bytes
                        stream.WriteByte((byte)0x07);
                        stream.WriteByte((byte)b);
                    }
                    i++;
                }
                break;

                case 0:
                {
                    //RLE - 01
                    stream.WriteByte(0x01);
                    stream.WriteByte((byte)(max - 1));
                    stream.WriteByte(b);
                    i += max;
                }
                break;

                case 1:
                {
                    //Alternating RLE - 02
                    stream.WriteByte(0x02);
                    stream.WriteByte((byte)(max / 2 - 1));
                    stream.WriteByte(b);
                    stream.WriteByte(bytes[i + 1]);
                    i += max;
                }
                break;

                case 2:
                {
                    //from previous column (same plane) - 00
                    stream.WriteByte(0x00);
                    stream.WriteByte((byte)(max - 1));
                    i += max;
                }
                break;

                case 3:
                {
                    //from plane 0 without mask - 03
                    stream.WriteByte(0x03);
                    stream.WriteByte((byte)(max - 1));
                    i += max;
                }
                break;

                case 6:
                {
                    //from plane 0 with mask - 06 03
                    stream.WriteByte(0x06);
                    stream.WriteByte(0x03);
                    stream.WriteByte((byte)(max - 1));
                    i += max;
                }
                break;

                case 4:
                {
                    //from plane 1 without mask - 04
                    stream.WriteByte(0x04);
                    stream.WriteByte((byte)(max - 1));
                    i += max;
                }
                break;

                case 7:
                {
                    //from plane 1 with mask - 06 04
                    stream.WriteByte(0x06);
                    stream.WriteByte(0x04);
                    stream.WriteByte((byte)(max - 1));
                    i += max;
                }
                break;

                case 5:
                {
                    //from plane 2 without mask - 05
                    stream.WriteByte(0x05);
                    stream.WriteByte((byte)(max - 1));
                    i += max;
                }
                break;

                case 8:
                {
                    //from plane 2 with mask - 06 05
                    stream.WriteByte(0x06);
                    stream.WriteByte(0x05);
                    stream.WriteByte((byte)(max - 1));
                    i += max;
                }
                break;
                }
                i--;
            }
        }