检测图像是否为空的有效方法
我需要一种非常快速的方法来检测图像是否为空。就我而言,所有像素都是白色且透明的。 图像是 png 的。我当前的方法是将它们加载到内存位图中并检查每个像素值,但这种方法很慢。 有更有效的方法吗?
这是我当前的代码:
'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
I need a very fast method to detect if an image is empty. Im my case then all pixels are white and transparant.
The images are png's. My current method is to load them in a memory bitmap and check each pixel value, but this is way to slow.
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您可以将 GDI+ 位图“映射”到固定的
byte[]
(或int[]
甚至uint[]
)上,并通过此直接使用数组读写ARGB位图数据。以下 CodeProject 文章介绍了如何执行此操作:http://www.codeproject。 com/KB/GDI-plus/pointerlessimageproc.aspx
You can "map" a GDI+ bitmap onto a pinned
byte[]
(orint[]
or evenuint[]
) and by this directly use the array to read and write the ARGB bitmap data.The following CodeProject article explains how to do it: http://www.codeproject.com/KB/GDI-plus/pointerlessimageproc.aspx
当然,将图像除以一定数量,为每个集合启动一个新线程以仅检查非空白像素(例如,非白色/透明)。
创建一个仅在找到非空像素时才触发(并设置标志)的事件。让每个线程检查此标志(基本上是一个 while 循环)。
Sure, divide the image by a set amount, for each set start a new thread to only check for non blank pixels (eg not white/transparent).
Create an event that fires (and sets a flag) only if a non empty pixel is found. Have each thread to check this flag (basically a while loop).
使用 Marshal.ReadInt64() 将使您的速度立即提高 8 倍。不过,请注意宽度是否超出,您需要使用 ReadByte() 来读取扫描线中的最后几个像素。在辅助程序集中用 C# 编写此代码可能是最快的解决方法,它允许您使用指针。
Using Marshal.ReadInt64() will give you an immediate x 8 speed boost. Watch out for overshooting the Width though, you'll need ReadByte() for the last few pixels in a scan line. Writing this code in C# in a helper assembly is probably the quickest fix, it allows you to use a pointer.
使用 C#(我知道您的示例是在 VB.Net 中),您可以使用 unsafe 并非常快速地访问您的位图:
如果您不能使用 C#,那么最快的方法是使用 Marshal.Copy 作为块:
Using C# (I know you sample is in VB.Net), you can use unsafe and get very fast access to your bitmap:
If you can't use C#, then the fastest way would be to use Marshal.Copy as a block:
最有效的方法是手动解析文件,直接跳转到数据流并读取压缩的zLib流,直到找到非白色和透明的像素。
根据图片的来源以及它们使用各种 PNG“特殊”(滤镜、特殊调色板...)的程度,这可能需要付出很大的努力,因此将“高效”理解为“大量工作,但速度非常快” ”。
对此有用的资源是 PNG 数据流规范 和 ZLIB 规范(或者,更简单的是 zLib 库)。
The most efficient way would be to manually parse the file, directly jump to the datastream and read the compressed zLib stream until you find a pixel that is not white and transparent.
Depending on where the pictures come from and how much they make use of various PNG "specials" (filters, special palette...), this can be much effort, so read "efficient" as "a lot of work, but very fast".
Useful resources for this are the PNG datastream specification and the ZLIB specification (or, much easier, a zLib library).
Image Magick 有一个 c# 包装器:
http://sourceforge.net/projects/imagemagickapp/
使用ImageMagik CLI 的识别功能如下:
http://www.imagemagick.org/script/identify .php
使用命令:
identify -format "%#" source.png
如果颜色数为 1,则您有一个空白页。
您还可以使用命令:
identify -verbose source.png
对于空白图像,标准差、倾斜度和峰度将为 0。
There is a c# wrapper for Image Magick:
http://sourceforge.net/projects/imagemagickapp/
Use the identify feature of ImageMagik CLI as given here:
http://www.imagemagick.org/script/identify.php
With command:
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.
我会使用 GDI+ 将 PNG 文件转换为 BMP 并将其保存到临时位置。然后,我将利用其未压缩的性质,在标头之外寻找像素,准备一个充满零字节的中等大小(例如 16384 B)临时字符串,然后读取 16384B 块直到文件末尾,将它们与临时字符串进行比较。由于 Windows XP 及更高版本在读取超过文件末尾时给出零字节,因此不需要对末尾进行特殊处理,只需在上次迭代时读取末尾一点即可。
确保位图以 32 位模式保存,否则将无法检测到黑色不透明像素。此模式还将处理任何调色板和其他怪癖,以便您甚至可以寻求固定的后标题偏移。
I would use GDI+ to convert the PNG file to BMP and save it to a temporary location. Then I would leverage its uncompressed nature, seek beyond the header into the pixels, prepare a medium-sized (say 16384 B) temporary string full of zero bytes and then read 16384B chunks until the end of file, comparing them to the temporary string. Since Windows XP and higher gives zero bytes when reading past end of file, no special treatment of the end is needed, just read a bit over the end with your last iteration.
Make sure the bitmap is saved in 32-bit mode or black opaque pixels won't be detected. This mode will also take care of any palettes and other quirks so that you can even seek to a fixed post-header offset.