Пример #1
0
        private static byte[] GetBGRFromBitmap(FreeImageBitmap bitmap, int w, int h)
        {
            byte[] pic = new byte[(w + 10) * (h + 10) * 3];

            int o = 0;

            //get pic from bitmap
            for (int y = 0; y < h; y++)
            {
                var scanline = bitmap.GetScanlineFromTop8Bit(y);
                if (bitmap.ColorDepth == 24)
                {
                    for (int x = 0; x < w; x++)
                    {
                        //get image data from RGB to BGR
                        pic[o++] = scanline[x * 3 + 2];
                        pic[o++] = scanline[x * 3 + 1];
                        pic[o++] = scanline[x * 3 + 0];
                    }
                }
                else if (bitmap.ColorDepth == 32)
                {
                    for (int x = 0; x < w; x++)
                    {
                        //get image data from RGB to BGR
                        pic[o++] = scanline[x * 4 + 2];
                        pic[o++] = scanline[x * 4 + 1];
                        pic[o++] = scanline[x * 4 + 0];
                    }
                }
            }
            return(pic);
        }
Пример #2
0
 private static bool AllPixelsOpaque(FreeImageBitmap existingAlphaChannel)
 {
     //all pixels opaque?
     for (int y = 0; y < existingAlphaChannel.Height; y++)
     {
         var scanline = existingAlphaChannel.GetScanlineFromTop8Bit(y);
         for (int x = 0; x < existingAlphaChannel.Width; x++)
         {
             if (scanline[x] != 255)
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Пример #3
0
        private static byte[] GetAlphaFromBitmap(FreeImageBitmap bitmap, int w, int h)
        {
            byte[] pic = new byte[(w + 10) * (h + 10)];
            int    o   = 0;

            //get pic from bitmap
            for (int y = 0; y < h; y++)
            {
                var scanline = bitmap.GetScanlineFromTop8Bit(y);
                for (int x = 0; x < w; x++)
                {
                    //get alpha channel
                    pic[o++] = scanline[x * 4 + 3];
                }
            }
            return(pic);
        }
Пример #4
0
        internal static void SaveImageData8Bit(Stream stream, FreeImageBitmap bitmap)
        {
            int width  = bitmap.Width;
            int height = bitmap.Height;

            byte[] pic = new byte[width * height];

            int o = 0;

            for (int y = 0; y < height; y++)
            {
                var scanline = bitmap.GetScanlineFromTop8Bit(y);
                for (int x = 0; x < width; x++)
                {
                    pic[o++] = scanline[x];
                }
            }
            SaveImageData8Bit(stream, pic, width, height);
        }
Пример #5
0
        public static unsafe void RemapPalette(FreeImageBitmap bitmap, FreeImageBitmap referenceImage, int numberOfColors)
        {
            using (FreeImageBitmap bitmap32 = bitmap.GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP))
            {
                if (referenceImage.Height < bitmap.Height || referenceImage.Width < bitmap.Width)
                {
                    int h2 = referenceImage.Height;
                    if (h2 < bitmap.Height)
                    {
                        h2 = bitmap.Height;
                    }
                    int w2 = referenceImage.Width;
                    if (w2 < bitmap.Width)
                    {
                        w2 = bitmap.Width;
                    }
                    referenceImage.EnlargeCanvas <byte>(0, 0, w2 - referenceImage.Width, h2 - referenceImage.Height, 0);
                }

                //FreeImageBitmap reference32 = bitmap.GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP);

                if (bitmap.ColorDepth != 8)
                {
                    bitmap.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP);
                }
                int *newPalette = (int *)(referenceImage.Palette.BaseAddress);

                int h = bitmap.Height;
                int w = bitmap.Width;

                //Ties are broken in ColorToIndex by popularity in the original image
                Dictionary <int, int> ColorToIndex = new Dictionary <int, int>();
                int[] ColorHistogram = new int[256];
                for (int y = 0; y < h; y++)
                {
                    byte *srcScanline = (byte *)(referenceImage.GetScanlineFromTop8Bit(y).BaseAddress);
                    for (int x = 0; x < w; x++)
                    {
                        int c = srcScanline[x];
                        ColorHistogram[c]++;
                    }
                }

                //add each palette color to the dictionary
                for (int i = 0; i < numberOfColors; i++)
                {
                    int c = newPalette[i] & 0xFFFFFF;
                    if (ColorToIndex.ContainsKey(c))
                    {
                        int otherIndex = ColorToIndex[c];
                        if (ColorHistogram[i] > ColorHistogram[otherIndex])
                        {
                            ColorToIndex[c] = i;
                        }
                    }
                    else
                    {
                        ColorToIndex[c] = i;
                    }
                }

                for (int y = 0; y < h; y++)
                {
                    int * trueColorScanline = (int *)(bitmap32.GetScanlineFromTop32Bit(y).BaseAddress);
                    byte *srcScanline       = (byte *)(bitmap.GetScanlineFromTop8Bit(y).BaseAddress);
                    byte *referenceScanline = (byte *)(referenceImage.GetScanlineFromTop8Bit(y).BaseAddress);

                    for (int x = 0; x < w; x++)
                    {
                        int srcColor = trueColorScanline[x] & 0xFFFFFF;
                        int refIndex = referenceScanline[x];
                        int refColor = newPalette[refIndex] & 0xFFFFFF;
                        if (srcColor == refColor)
                        {
                            srcScanline[x] = (byte)refIndex;
                        }
                        else
                        {
                            if (ColorToIndex.ContainsKey(srcColor))
                            {
                                int newColorIndex = ColorToIndex[srcColor];
                                if (refColor == (newPalette[newColorIndex] & 0xFFFFFF))
                                {
                                    srcScanline[x] = (byte)refIndex;
                                }
                                else
                                {
                                    srcScanline[x] = (byte)newColorIndex;
                                }
                            }
                            else
                            {
                                float minDistance = float.MaxValue;
                                int   minIndex    = 0;
                                for (int i = 0; i < numberOfColors; i++)
                                {
                                    int   c        = newPalette[i] & 0xFFFFFF;
                                    float distance = GetDistanceF(srcColor, c);
                                    if (distance < minDistance)
                                    {
                                        minIndex    = i;
                                        minDistance = distance;
                                    }
                                    else if (distance == minDistance && ColorHistogram[i] > ColorHistogram[minIndex])
                                    {
                                        minIndex = i;
                                    }
                                }
                                if (refColor == (newPalette[minIndex] & 0xFFFFFF))
                                {
                                    srcScanline[x] = (byte)refIndex;
                                }
                                else
                                {
                                    srcScanline[x] = (byte)minIndex;
                                }
                                ColorToIndex.Add(srcColor, minIndex);
                            }
                        }
                    }
                }
                bitmap.Palette.AsArray = referenceImage.Palette.AsArray;
            }
        }
Пример #6
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--;
            }
        }