【发布时间】:2013-12-07 13:52:24
【问题描述】:
我有一些 c# 代码在 Vista 和 Windows 7 上运行良好,但在 Windows XP 上抛出 GDI+ 错误(安装了 service pack 3)。
在 XP 上抛出错误
System.Runtime.INteropServices.ExternalException(0x80004005):GDI+ 中出现一般错误 在 System.Drawing.Graphics.CheckErrorStatus(Int32Status) 在 System.Drawing.Graphics.DrawImage(图像图像,Int32 x,Int32 y) 在 System.Drawing.Graphics.DrawImageUnscaled(图像图像,Int32 x,Int 32 y) 在 mysolution.Core.ImageTools.ConvertToBitonal(位图原始,Int32 阈值)
这一行的代码中断:
using (var g = Graphics.FromImage(source))
{
g.DrawImageUnscaled(original, 0, 0); // Error Is Thrown Here
}
WpFAppTestingConvertToBitonalCS
....
下面是我调用的完整函数。
public static Bitmap ConvertToBitonal(Bitmap original, int threshold)
{
Bitmap source;
// If original bitmap is not already in 32 BPP, ARGB format, then convert
if (original.PixelFormat != PixelFormat.Format32bppArgb)
{
source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
source.SetResolution(original.HorizontalResolution, original.VerticalResolution);
using (var g = Graphics.FromImage(source))
{
g.DrawImageUnscaled(original, 0, 0);
}
}
else
{
source = original;
}
// Lock source bitmap in memory
var sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
// Copy image data to binary array
var imageSize = sourceData.Stride * sourceData.Height;
var sourceBuffer = new byte[imageSize];
Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
// Unlock source bitmap
source.UnlockBits(sourceData);
// Create destination bitmap
var destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);
destination.SetResolution(original.HorizontalResolution, original.VerticalResolution);
// Lock destination bitmap in memory
var destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
// Create destination buffer
imageSize = destinationData.Stride * destinationData.Height;
var destinationBuffer = new byte[imageSize];
var sourceIndex = 0;
var destinationIndex = 0;
var pixelTotal = 0;
byte destinationValue = 0;
var pixelValue = 128;
var height = source.Height;
var width = source.Width;
// Iterate lines
for (var y = 0; y < height; y++)
{
sourceIndex = y * sourceData.Stride;
destinationIndex = y * destinationData.Stride;
destinationValue = 0;
pixelValue = 128;
// Iterate pixels
for (var x = 0; x < width; x++)
{
// Compute pixel brightness (i.e. total of Red, Green, and Blue values) - Thanks murx
// B G R
pixelTotal = sourceBuffer[sourceIndex] + sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2];
if (pixelTotal > threshold)
{
destinationValue += (byte)pixelValue;
}
if (pixelValue == 1)
{
destinationBuffer[destinationIndex] = destinationValue;
destinationIndex++;
destinationValue = 0;
pixelValue = 128;
}
else
{
pixelValue >>= 1;
}
sourceIndex += 4;
}
if (pixelValue != 128)
{
destinationBuffer[destinationIndex] = destinationValue;
}
}
// Copy binary image data to destination bitmap
Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
// Unlock destination bitmap
destination.UnlockBits(destinationData);
// Dispose of source if not originally supplied bitmap
if (source != original)
{
source.Dispose();
}
// Return
return destination;
}
【问题讨论】:
-
你发了一百行:异常到底是在哪里引发的?
-
我们目前还不确定它在哪一行,我会在星期一检查一下,通过在 xp 机器上进行额外的登录和测试。
-
@Mario Vernari 它打破了这一行: using (var g = Graphics.FromImage(source)) { g.DrawImageUnscaled(original, 0, 0); }
-
一般问题:您的 XP 是否已经在 SP3 上?我有一些 .Net 代码在 SP2 下出现故障,在 SP3 下运行顺利。
-
GDI+ 在 Vista 中更新到 v1.10,对索引像素格式的支持有了很大改进。