Image.Clone 出现 OutOfMemoryException - 仅在 Windows 2003 上
这是我的问题。我有一张需要缩小的图像。原始图像是灰度 PNG,这并不是一个大问题,只是当我缩小它时,热敏标签打印机会拾取伪影并将其打印在标签上。所以,我所做的就是将图像更改为黑色和白色。调整大小之前为白色(Format1bppIndexed),如下所示:
Dim bte() As Byte = System.Convert.FromBase64String(imgStr)
Dim ms As New IO.MemoryStream(bte)
Dim bmp As New System.Drawing.Bitmap(ms)
Dim monoImage As Drawing.Bitmap = New Drawing.Bitmap(1200, 1800, Drawing.Imaging.PixelFormat.Format1bppIndexed)
Dim rect As New Drawing.Rectangle(0, 0, 1200, 1800)
monoImage = bmp.Clone(rect, Drawing.Imaging.PixelFormat.Format1bppIndexed)
然后调整它的大小。这段代码在我的 Windows 7 机器上运行良好,但是当我在它称为“家”的 Windows 2003 Server 机器上运行它时,它在遇到 bmp.Clone 行时总是抛出 OutOfMemoryException。
关于正在发生的事情有什么想法,或者也许有更好的解决方案将图像转换为黑白?
So here's my issue. I have an image that I need to shrink. The original image is a grayscale PNG, which isn't a huge issues except that when I shrink it down, the thermal label printers pickup the artifacts and print them on the label. So, what I did was change the image to black & white (Format1bppIndexed) before resizing, like this:
Dim bte() As Byte = System.Convert.FromBase64String(imgStr)
Dim ms As New IO.MemoryStream(bte)
Dim bmp As New System.Drawing.Bitmap(ms)
Dim monoImage As Drawing.Bitmap = New Drawing.Bitmap(1200, 1800, Drawing.Imaging.PixelFormat.Format1bppIndexed)
Dim rect As New Drawing.Rectangle(0, 0, 1200, 1800)
monoImage = bmp.Clone(rect, Drawing.Imaging.PixelFormat.Format1bppIndexed)
And then I resize it. This code works fine on my Windows 7 machine, but when I run it on the Windows 2003 Server box that it calls home, it always throws an OutOfMemoryException when it hits the bmp.Clone line.
Any ideas as to what's happening, or perhaps a better solution to converting the image to B&W?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
以下是本文中的一些转换后的源代码:
使用以下方式调用它:
Here's some converted source code from this article:
Call it using:
GDI+ 异常消息非常糟糕,如果您传递的矩形超出图像边界,则 Clone() 方法中可能会引发 OutOfMemoryException。与内存不足无关。这里很容易发生这种情况,源位图不太可能是 1200 x 1800。让您的代码如下所示:
不太确定生成的位图看起来不错或可用,GDI+ 对索引像素格式的支持很差。 Win7 的 gdiplus.dll 版本与 Windows 2003 不同。我仅在 Win7 上测试了此代码。
GDI+ exception messages are pretty miserable, OutOfMemoryException can be raised in the Clone() method if the rectangle you pass is outside of the image bounds. Nothing to do with running out of memory. Which could easily happen here, it isn't that likely that the source bitmap is 1200 x 1800. Make your code look like this:
Not so sure the resulting bitmap would look good or is usable, GDI+ has poor support for indexed pixel formats. Win7 has a different version of gdiplus.dll than Windows 2003. I tested this code only on Win7.
看看这个: http:// msdn.microsoft.com/en-us/library/system.windows.media.imaging.formatconvertedbitmap.aspx
但将
PixelFormats.Gray32Float
更改为PixelFormats.BlackWhite
Take a look at this: http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.formatconvertedbitmap.aspx
But change
PixelFormats.Gray32Float
toPixelFormats.BlackWhite
我立即发现的一个问题是您的代码存在资源泄漏:
您正在创建一个全新的位图并将其分配给
monoImage
,然后几乎立即将其丢弃,而无需处理原始位图位图。如果您经常这样做,则会泄漏大量 GDI 资源,并可能因此收到各种错误(包括 OOM)。只需将声明移至与“新”赋值相同的行即可:
您还需要确保正在处理其他
Bitmap
和MemoryStream
等等等;所有这些都实现了IDisposable
,因此只需将它们包装在Using
中即可。One problem I see right away is that your code has a resource leak:
You're creating a brand-new bitmap and assigning it to
monoImage
, and then almost immediately throwing it away without ever disposing of the originalBitmap
. If you're doing this often, you're leaking a lot of GDI resources and can receive all sorts of errors as a result (including OOMs).Just move the declaration to the same line as the "new" assignment:
You also need to make sure you're disposing the other
Bitmap
, and theMemoryStream
, and so on and so forth; all of these implementIDisposable
so just wrap them inUsing
.