What's an efficient way to tell if a bitmap is entirely black?

前端 未结 12 907
清酒与你
清酒与你 2021-02-05 05:40

I\'m wondering if there\'s a super-efficient way of confirming that an Image object references an entirely black image, so every pixel within the bitmap is ARGB(255, 0, 0, 0).

相关标签:
12条回答
  • 2021-02-05 06:14

    Draw the bitmap with a ColorMatrix that has 3 x 255 in the diagonal, that will blow any non-black pixel to pure white. Then draw that bitmap to a smaller one whose width is a multiple of 4 and has the Format24bppRgb format. That eliminates the alpha, reduces the size and leaves only zeros if the bitmap is truly black.

    You'll have to experiment to see how small you can make the bitmap, use a sample one that has only one white pixel to see when the interpolator makes it disappear. I'm guessing you can go pretty far.

    0 讨论(0)
  • 2021-02-05 06:17

    Just some random thoughts:

    • Maybe you could apply a ColorMatrix to the original bitmap (to completely turn it to black). Then compare the result with the original.
    • Or create a bitmap of identical size (filled with pure black) and then compare to the original bitmap.
    0 讨论(0)
  • 2021-02-05 06:21

    The first answer to this post is Awesome. I modified the code to more generically determine if the image is all one color(all black, all white, all magenta, etc...). Assuming you have a bitmap with 4 part color values ARGB, compare each color to the color in the top left if any is different then the image isn't all one color.

    private bool AllOneColor(Bitmap bmp)
    {
        // Lock the bitmap's bits.  
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
    
        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;
    
        // Declare an array to hold the bytes of the bitmap.
        int bytes = bmpData.Stride * bmp.Height;
        byte[] rgbValues = new byte[bytes];
    
        // Copy the RGB values into the array.
    
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
    
        bool AllOneColor = true;
        for (int index = 0; index < rgbValues.Length; index++)
        {
            //compare the current A or R or G or B with the A or R or G or B at position 0,0.
            if (rgbValues[index] != rgbValues[index % 4])
            {
                AllOneColor= false;
                break;
            }
        }
        // Unlock the bits.
        bmp.UnlockBits(bmpData);
        return AllOneColor;
    }
    
    0 讨论(0)
  • 2021-02-05 06:22

    I have an idea that's outside the box.

    What about a CRC checksum? You could first check the dimensions of the image, then calculate the checksum and compare that to known (precalculated) checksums of an all-black image of the same dimensions.

    EDIT: I doubt this would be any faster than @leonard's method. The only reason it might is if the original file was not a bitmap, but was a compressed image format. That way, the CRC checksum algorithm wouldn't have to uncompress the image before running.

    0 讨论(0)
  • 2021-02-05 06:23

    Using AForgeNET library (http://www.aforgenet.com) could also be a solution:

    public bool IsNotBlackImage()
    {
        Assembly assembly = this.GetType().Assembly;
        var imgTest = new Bitmap(assembly.GetManifestResourceStream("TestImage.png"));
        var imgStatistics = new ImageStatistics(imgTest);             
        return imgStatistics.PixelsCountWithoutBlack != 0;
    }
    

    For ImageStatistics class reference AForge.Imaging.dll in your project.

    http://code.google.com/p/aforge/source/browse/trunk/Sources/Imaging/ImageStatistics.cs

    0 讨论(0)
  • 2021-02-05 06:23

    A reasonably reliable method would be to check the file size of the image. That is, if the images that are not all black have a relatively normal distribution of colors.

    If you know the file type, you know some basic things about the average compression ratios. And you can determine the dimensions of the file pretty readily without cycling through the whole file.

    An all black image, of any dimension, using a compressed file format, is going to have a very small file size compared to an image of identical dimensions with a fairly normal distribution of colors.

    This method would take a little bit of time to test and build up a knowledge base of just what the file size of an all-black image should be compared to a non-all-black image, but it would be very fast.

    If you have many instances where the non-all-black images are pretty close to all-black, obviously then this method would not work.

    0 讨论(0)
提交回复
热议问题