Delete alpha chanel on bitmap c# (Slicing image of solid color only)

Go To StackoverFlow.com

1

I want to get the difference between two images

I use this source code:

 public Bitmap GetDifference(Bitmap bm1, Bitmap bm2)
        {

            if (bm1.Size != bm2.Size)
                throw new ArgumentException("exception");


            var resultImage = new Bitmap(bm1.Width, bm1.Height);

            using (Graphics g = Graphics.FromImage(resultImage))
                g.Clear(Color.Transparent);


            for (int w = 0; w < bm1.Width; w++)
            {
                for (int h = 0; h < bm1.Height; h++)
                {
                    var bm2Color = bm2.GetPixel(w, h);
                    if (IsColorsDifferent(bm1.GetPixel(w, h), bm2Color))
                    {
                        resultImage.SetPixel(w, h, bm2Color);                    
                    }                  
                }
            }

            return resultImage;
        }


        bool IsColorsDifferent(Color c1, Color c2)
        {
            return c1 != c2;
        }

This source works good for me, but I have following issues:

For exaple if I choose image with a resolution 480x320 my resultImage has the same resolution (and this is corect, because I set in when created new Bitmap), but my Images have transparent color and I want to get result images with a solid color only.

Let us say - if the solid result images (solid color pixel) in 480x320 have 100x100 field I should to get just this solid Bitmap with a resolution 100x100.

To put it simply I need to get only rectangle that bordered with a solid color and cutt of alpha chanel.

Thanks!

2012-04-05 01:23
by Matrosov Alexander
You will need to scan the image and keep track of the boundaries as you encounter pixels where the alpha channel > 0 (assuming you have rectangular sections this is easy). Also be aware that GetPixel and SetPixel are slow as a dog. A really slow dog. If they are working for you and you know that your input images will always be very small, fine. If the size of the images is unknown I don't think it is premature optimization to delve into an unsafe context and get a pointer to the image's buffer via LockBits - Ed S. 2012-04-05 01:27
thanks, yes I know it. this is will be used for create an package and not be uses in runtime (only one-time calculations - Matrosov Alexander 2012-04-05 01:31
Oh, another image processing tip; scan the image row wise, not column wise as you do now. The assumption here is that your image data is stored in an array row wise (this is almost always true). Locality of data is important here. Your code will likely not result in a CPU cache full of adjacent data currently. You will be flushing and filling the cache on each iteration, which means longer trips to grab data from main memory. If you loop row wise it will - Ed S. 2012-04-05 01:35
@EdS. can you write your tips as an answer please? it can be usefull for other people. thank - Mustafa Ekici 2012-04-05 02:27


0

Please see the class that I wrote below:

class ProcessingImage
    {         
        public Bitmap GetDifference(Bitmap bm1, Bitmap bm2)
        {            
            if (bm1.Size != bm2.Size)
                throw new ArgumentException("Images must have one size");

            var resultImage = new Bitmap(bm1.Width, bm1.Height);

            using (Graphics g = Graphics.FromImage(resultImage))
                g.Clear(Color.Transparent);

            int min_height = int.MaxValue;
            int min_width = int.MaxValue;
            int max_height = -1;
            int max_width = -1;

            for (int w = 0; w < bm1.Width; w++)
                for (int h = 0; h < bm1.Height; h++)
                {
                    var bm2Color = bm2.GetPixel(w, h);
                    if (IsColorsDifferent(bm1.GetPixel(w, h), bm2Color))
                    {
                        resultImage.SetPixel(w, h, bm2Color);
                        if (h < min_height) min_height = h;
                        if (w < min_width) min_width = w;
                        if (h > max_height) max_height = h;
                        if (w > max_width) max_width = w;
                    }                    
                }

            max_height = max_height + 1;    //Needed for get valid max height point, otherwise we lost one pixel.
            max_width = max_width + 1;      //Needed for get valid max width point, otherwise we lost one pixel.


            // Calculate original size for image without alpha chanel.

            int size_h = max_height - min_height;
            int size_w = max_width - min_width;

            var resizeImage = new Bitmap(size_w, size_h); // Creaete bitmap with new size.

            for (int w = 0; w < resultImage.Width; w++)
                for (int h = 0; h < resultImage.Height; h++)
                {
                    var color = resultImage.GetPixel(w, h);
                    if (color.A != 0)
                    {
                        // Move each pixels at a distance calculate before.
                        int x = w - min_width;
                        int y = h - min_height;
                        resizeImage.SetPixel(x, y, color);
                    }
                }           

            return resizeImage;
        }

        bool IsColorsDifferent(Color c1, Color c2)
        {
            return c1 != c2;
        }
    }

I think, this class can be modified to optimize, but now it works good. If you need return image with original size and without alpha channel - this is one of many solutions how to do it.

2012-04-07 13:21
by Matrosov Alexander
Note: please see comments above about speed of execution - Matrosov Alexander 2012-04-07 13:23
Ads