Bitmap 初始化的奇怪问题

cardinal_508 2011-12-03 10:35:01
我在制作自定义控件的时候
使用Image对象作为图片容器存放对象,
使用Bitmap创建图片时有时会发生奇怪的报错问题
我制作的控件在事件引发时对图片今天重新绘制
总共要绘制三幅图片,这三幅图片尺寸依次变大,有时会在第三幅图片实例化的时候引发异常异常信息如下
----------------------------------------------------------------------------------
System.ArgumentException: Parameter is not valid
at System.Drawing.Bitmap.. ctor(Int32 width, Int32 height,PixelFormat format)
at System.Drawing.Bitmap.. ctor(Int32 width, Int32 height)
-----------------------------------------------------------------------------------
而我创建时用代码为
Bitmap bmp =null;
bmp = new Bitmap(_width, rowCount * m_distanceRow);

width值比较大而rowCount * m_distanceRow不会超过100,在出现异常时,我检测过代码应这两个数位正整数
而且使用这两个值在别的程序中直接创建Bitmap是有效的

我怀疑问题的引发可能原因如下:
1、资源释放问题,可是为什么会在Bitmap实例化时引发
2、尺寸过大,但是同一尺寸时在多次重新绘制图片时在绘制最大一张图图片时有时会引发此异常
...全文
1013 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
cardinal_508 2011-12-08
  • 打赏
  • 举报
回复
这个bug并不是多个对象引用所触发的,它的引发是在不涉及其他因素,仅在new一个Bitmap时发生的.
应该是Bitmap申请的内存存在上限,超过上限时将会引发无效参数异常,故而在频繁申请大尺寸Image对象时,需要手动释放资源,不能等待系统的垃圾回收。
待验证......
qldsrx 2011-12-08
  • 打赏
  • 举报
回复
如果是资源释放问题,那就检查代码中是否有非托管引用的存在,所谓的非托管引用,就是通过
Bitmap.GetHbitmap方法进行的操作。
例如:
  [System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);


private void DemonstrateGetHbitmap()
{
Bitmap bm = new Bitmap("Picture.jpg");
IntPtr hBitmap = bm.GetHbitmap();

// Do something with hBitmap.

DeleteObject(hBitmap);
}


另外要注意:
释放对 Image 的最后一个引用之前,始终应先调用 Dispose。 否则,在垃圾回收器调用 Image 对象的 Finalize 方法之前,该对象所使用的资源将不会被释放。
调用 Dispose 后,必须释放对 Image 的所有引用,这样垃圾回收器才能回收 Image 占用的内存。
lookcode 2011-12-06
  • 打赏
  • 举报
回复
图片是引用类型的,
同一个Bitmap在用过一次以后,如果改变也会影响到其他的Bitmap
再次引用同一个Bitmap最好是用COPY函数复制,重新定义一个Bitmap
cardinal_508 2011-12-06
  • 打赏
  • 举报
回复
我发现可能是我内存释放不及时所引起的
我在看别的贴子发现使用for循环循环创建Image时,申请到达一定数量时也会引发无效参数异常,
结合我的压力测试发现,new Bitmap时报错与传入两个参数还是三个参数无关,
一张Bitmap的初始化是有极限的,其极限与申请的资源数量有关,
我测试时单个程序中只初始化一个宽度达70w的图片也是没问题的,
怀疑与内存管理有关,现优化了资源的释放,还在测试中......
qldsrx 2011-12-04
  • 打赏
  • 举报
回复
引用
指定了名称不以 Format 开头的 PixelFormat 值。 例如,指定 Gdi 将导致一个 ArgumentException,但 Format48bppRgb 不会出现这种情况。


这里是PixelFormat引起的异常,和尺寸无关。
阿非 2011-12-04
  • 打赏
  • 举报
回复
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public Bitmap(int width, int height) : this(width, height, PixelFormat.Format32bppArgb)
{
}

public Bitmap(int width, int height, PixelFormat format)
{
IntPtr zero = IntPtr.Zero;
int status = SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0(width, height, 0, (int) format, NativeMethods.NullHandleRef, out zero);
if (status != 0)
{
throw SafeNativeMethods.Gdip.StatusException(status);
}
base.SetNativeImage(zero);
}
---------------------------------
case 2:
return new ArgumentException(SR.GetString("GdiplusInvalidParameter"));


应该是你传的参数在调用
SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0 这个方法时,没有返回0 返回了2


你可以搜索SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0 这个方法在什么情况下返回2


兔子-顾问 2011-12-04
  • 打赏
  • 举报
回复
如果位图较大,你又要经常创建,不用的时候记得要调用dispose。
cardinal_508 2011-12-04
  • 打赏
  • 举报
回复
我去查查pixelformat异常的相关问题
阿非 2011-12-04
  • 打赏
  • 举报
回复
Bitmap bmp =null;
int height=rowCount * m_distanceRow;
bmp = new Bitmap(_width, height);
cardinal_508 2011-12-04
  • 打赏
  • 举报
回复
我的控件并没有原图,都是在创建好的图片上绘制的
所以和图片路径无关
流程为先创建一个空白的bitmap并设置好bitmap的大小,如Bitmap bmp = new Bitmap(width,height);
然后再用画布绘制,而程序改变尺寸或引发事件时将重绘Bitmap

就是不明白为什么new 一个空白的Bitmap 只指定宽高都会引发无效参数异常
linwenlei 2011-12-03
  • 打赏
  • 举报
回复
上面错了。。
应该是用这个。。。参数为图片路径。
bmp = new Bitmap(ImagePath);

linwenlei 2011-12-03
  • 打赏
  • 举报
回复
在已定义bitmap的时候图片的大小已经确定了。你可以把里面的参数去掉试试。可能确定大小的图片无法赋值大小不等的图片的。
Bitmap bmp =null;
bmp = new Bitmap();

zzf2004 2011-12-03
  • 打赏
  • 举报
回复
没必要每次重绘都new。
你只有三幅图的话,先加载好。
得绘时选择要用的图就行。

111,118

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧