Effective way to detect if image is empty

I need a very fast method to determine if an image is blank. Im my case, then all the pixels are white and transparent. Images are png. My current method is to load them into a memory bitmap and check each pixel value, but this is a way to slow things down. Is there a more efficient way?

This is my current code:

'Lock the bitmap bits. Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(rectBmp, _ Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat) Try Dim x As Integer Dim y As Integer For y = 0 To bmpData.Height - 1 For x = 0 To bmpData.Width - 1 If System.Runtime.InteropServices.Marshal.ReadByte(bmpData.Scan0, (bmpData.Stride * y) + (4 * x) + 3) <> 0 Then Return True Exit For End If Next Next Finally bmp.UnlockBits(bmpData) End Try 
+4
source share
7 answers

Of course, divide the image by a specified amount, for each set, start a new stream to check only non-empty pixels (for example, not white / transparent).

Create an event that fires (and sets a flag) only if a nonblank pixel is found. Ask each thread to check this flag (basically a while loop).

+1
source

You can "match" a GDI + bitmap with a fixed byte[] (or int[] or even uint[] ) and use the array directly to read and write ARGB bitmap data.

The following CodeProject article explains how to do this: http://www.codeproject.com/KB/GDI-plus/pointerlessimageproc.aspx

+2
source

Using Marshal.ReadInt64 () will give you an immediate acceleration of x 8. Watch for excess width, but for the last few pixels in the scan line you will need ReadByte (). Writing this code in C # in an auxiliary assembly is probably the fastest fix; it allows you to use a pointer.

+1
source

With C # (I know that you are using a sample in VB.Net), you can use insecure and very quick access to your bitmap:

  const int ALPHA_PIXEL = 3; const int RED_PIXEL = 2; const int GREEN_PIXEL = 1; const int BLUE_PIXEL = 0; try { BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat); int bytesPerPixel = (bmp.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4); int stride = bmData.Stride; unsafe { byte* pixel = (byte*)(void*)bmData.Scan0; for (int y = 0; y < bmp.Height; y++) { int yPos = y * stride; for (int x = 0; x < bmp.Width; x++) { int pos = yPos + (x * bytesPerPixel); if (pixel[pos + RED_PIXEL] != 255 || pixel[pos + GREEN_PIXEL] != 255 || pixel[pos + BLUE_PIXEL] != 255 || pixel[pos + ALPHA_PIXEL] != 0) { return true; } } } } } finally { bmp.UnlockBits(bmData); } return false; 

If you cannot use C #, then the fastest way would be to use Marshal.Copy as a block:

  Dim bmData As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat) Try Dim bytesPerPixel As Integer = If(bmp.PixelFormat = PixelFormat.Format24bppRgb, 3, 4) Dim stride As Integer = bmData.Stride Dim imageSize As Integer = stride * bmp.Height Dim pixel As Byte() ReDim pixel(imageSize) Marshal.Copy(bmData.Scan0, pixel, 0, imageSize) For y As Integer = 0 To bmp.Height - 1 Dim yPos As Integer = y * stride For x As Integer = 0 To bmp.Width - 1 Dim pos As Integer = yPos + (x * bytesPerPixel) If pixel(pos + RED_PIXEL) <> 255 OrElse pixel(pos + GREEN_PIXEL) <> 255 OrElse pixel(pos + BLUE_PIXEL) <> 255 OrElse pixel(pos + ALPHA_PIXEL) <> 0 Then Return End If Next Next Finally bmp.UnlockBits(bmData) End Try Return 
+1
source

The most effective way would be to manually analyze the file, go directly to the data stream and read the zLib compressed stream until you find a pixel that is not white and transparent.

Depending on where the photos came from and how much they use various โ€œspecialโ€ PNGs (filters, a special palette ...), this can be a big effort, so read โ€œeffectivelyโ€ as โ€œa lot of work, but really fast.โ€

Useful resources for this are the specification of the PNG and ZLIB data stream (or, much simpler, the zLib library).

0
source

There is a C # wrapper for Image Magick:

http://sourceforge.net/projects/imagemagickapp/

Use the ImageMagik CLI authentication function as indicated here:

http://www.imagemagick.org/script/identify.php

With the team:

identify -format "%#" source.png

If the number of colors is 1, you have a blank page.

You can also use the command:

identify -verbose source.png

The standard deviation, skew and kurtosis will be 0 for a blank image.

0
source

I would use GDI + to convert the PNG file to BMP and save it in a temporary place. Then I will use an uncompressed character, search for the heading in pixels, prepare a medium-sized temporary line (e.g. 16384 B), full of zero bytes, and then read 16384B fragments to the end of the file, comparing them with the time line. Since Windows XP and above give zero bytes when reading the last end of the file, no special end processing is required, just read the bit at the end with your last iteration. Make sure that the bitmap is saved in 32-bit mode or that black opaque pixels are not detected. This mode will also take care of any palettes and other quirks so you can even look for a fixed offset after the header.

0
source

Source: https://habr.com/ru/post/1311626/


All Articles