当前位置: 首页 > news >正文

C# .NET开发图形图像程序时提示GDI+ 中发生一般性错误

今天突然收到一封信,说我那个极度复杂的Marshal的问题被解决了(http://www.cnblogs.com/hotcan/archive/2005/01/12/91007.html)。顿时感觉好久没有在这个blog上写东西了。想当年刚毕业没事情干的时候,还是写得很不亦乐乎的。所以决定炒炒冷饭,写一篇技术文章,以说明我还没有忘记这里。 

1.GDI+的前世今生

GDI+全称图形设备接口,Graphics Device Interface (GDI) ,他的爸爸叫做GDI, 用C写的。Windows XP出来以后用C++重新写了一下,变成了GDI+。从.NET Framework 1.0开始,GDI+就被正式封装在了.NET Framework里面,并被广泛地应用到了所有和图形图像相关的程序中。不幸的是,这个GDI+引入了微软有史以来最大的2个patch,造成了Microsoft IT, Support, Developer, Tester的无数麻烦。[1][2]

GDI+没有用显卡加速,所以Windows Vista推荐用Windows Display Driver Model (WDDM)了,支持渲染,3D加速。不过普通的应用程序,用GDI/GDI+其实是完全足够了,所以GDI+是在微软平台上开发图形图像程序的最好选择了。至少现在没有听说微软准备重新写GDI

GDI+ 可以用来做图形处理,也可以做图像处理。这里只分析几个使用.NET Framework容易出错的地方。 

2. GDI+一般性错误(A generic error occurred in GDI+)

这是使用GDI+的时候最滑稽的一个Exception,里面啥信息都没有。对于刚刚开始使用.NET Framework开发者来说,很难发现这个问题到底是为什么。

我们先来看看下面一段代码 

string fileName = "sample.jpg";
Bitmap bmp = new Bitmap(fileName);
bmp.Save(fileName, ImageFormat.Jpeg);

这段代码的目的是要打开一个Bitmap,然后保存。可惜这段代码一定会给你一个GDI+一般性错误:

System.Runtime.InteropServices.ExternalException

其中的Error Code是0x80004005, innerException是空。如果你查Windows的Error Code表,会发现这个错误原因是“Unspecified Error”,还是什么都不知道。这其实是.NET Framework封装不好的问题,我们可以调用

Marshal.GetLastWin32Error()

拿到Win32的Error, 32。这个错误代码就有点信息量了,在winerror.h里面,我们可以找到下面的定义:

//

// MessageId: ERROR_SHARING_VIOLATION

//

// MessageText:

//

//  The process cannot access the file because it is being used by another process.

//

#define ERROR_SHARING_VIOLATION          32L

原来是文件不能写。其实MSDN里面有一句话,The file remains locked until the Bitmap is disposed。所以文件读取以后是锁着的,没有办法写。那如果我想做点改动然后再保存原来的文件怎么办呢?

这里有个土办法可以搞定这个问题 

Bitmap bmpTemp = new Bitmap(image);
Bitmap bmp = new Bitmap(bmpTemp);
bmpTemp.Dispose();
bmp.Save(image, ImageFormat.Jpeg);

只要把当前的图像复制一份,然后把旧的Dispose掉,那个文件就不被锁住了,这样就可以放心覆盖原始文件了。

想想如果你要用GDI+写一个Painter,很容易你就会遇到这个问题。 此种情况是因为图片被占用导致锁定,保存前使用 Graphics.DrawImage() 复制一份,然后dispose释放掉锁定就ok了~

参考文献:

[1]. Microsoft Security Bulletin MS04-028 Buffer Overrun in JPEG Processing (GDI+) Could Allow Code Execution (833987) http://www.microsoft.com/technet/security/bulletin/MS04-028.mspx

[2].Microsoft Security Bulletin MS08-052 – Critical Vulnerabilities in GDI+ Could Allow Remote Code Execution (954593)http://www.microsoft.com/technet/security/bulletin/MS08-052.mspx

原文链接:

GDI+中常见的几个问题(1)

GDI+ 中发生一般性错误

相关文章:

  • centosx64 6.3安装firefox 17.0.1无法使用 flash
  • Linux下MySql安装配置方法总结
  • VC6.0入门使用
  • odbc备忘
  • C#实现网页表单自动提交
  • 分享:mahout in action ----分类的原理
  • CI框架 -- 核心文件 之 Input.php(输入数据处理文件)
  • 人人网 揭秘社交网络指开放平台技术
  • Android - 文字向上翻滚效果的实现
  • 大叔也学Xamarin系列
  • 从 相机 或者相册 获取图片显示在ImageView 上
  • 十年未变!安全,谁之责?(下)
  • linux的strace命令
  • 《锋利的jQuery》第1-3章
  • Python 远程操作文本转换excel
  • E-HPC支持多队列管理和自动伸缩
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • JavaScript HTML DOM
  • MySQL-事务管理(基础)
  • Mysql优化
  • SAP云平台里Global Account和Sub Account的关系
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • STAR法则
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 初识 webpack
  • 仿天猫超市收藏抛物线动画工具库
  • 力扣(LeetCode)965
  • 入门级的git使用指北
  • 使用Swoole加速Laravel(正式环境中)
  • 思考 CSS 架构
  • 用element的upload组件实现多图片上传和压缩
  • 主流的CSS水平和垂直居中技术大全
  • 《天龙八部3D》Unity技术方案揭秘
  • ​卜东波研究员:高观点下的少儿计算思维
  • #、%和$符号在OGNL表达式中经常出现
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (三)c52学习之旅-点亮LED灯
  • (四)Android布局类型(线性布局LinearLayout)
  • (转)http-server应用
  • (转)Linux下编译安装log4cxx
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .net反编译工具
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .net生成的类,跨工程调用显示注释
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @RunWith注解作用
  • [1] 平面(Plane)图形的生成算法
  • [2015][note]基于薄向列液晶层的可调谐THz fishnet超材料快速开关——
  • [④ADRV902x]: Digital Filter Configuration(发射端)