loop_in_codes

低调做技术__欢迎移步我的独立博客 codemaro.com 微博 kevinlynx

GDI+中从内存读取图片/保存图片到内存

要给项目中增加一个新的模块,需要先在服务器端做一些图片处理相关的工作。本来,对图片

做一些诸如ALPHA混合旋转缩放的操作,在游戏客户端应该是很容易的事。但是这事要在服务

器做,就不得不引入一些第三方库。反正我们的服务器运行于WINDOWS下,这里又需要处理

JPG图片的加载,我就考虑到了GDI+。

 

在这之前对GDI+没有过任何接触。直接翻了MSDN,还好居然有个一系列的usage。GDI+的Image

本身支持JPG的直接载入。但是并没有我理想中的CreateFromMemory( const void *buf )接口。

看起来唯一可以从内存创建Gdiplus::Image对象的方法是从一个叫IStream*的COM东西。我揣摩

微软为什么没有提供我理想中的那个接口,或者说要把GDI+设计成这样,可能还是考虑到对多语

言的支持。于是问题转换为如何将一个C语言的const void*转换为IStream*。我甚至在开始的时候

感觉到是不是要自己实现个Stream。后来在google上找到了一个似乎是标准的方法:首先创建个

HGLOBAL对象,然后通过GlobalLock就可以将一个C的const void*直接memcpy到这个HGLOBAL

里,最后,通过CreateStreamOnHGlobal这样的接口就可以得到一个IStream。

 

恶心的是,基于之前对服务器内存使用的优化,我现在对于内存的使用非常敏感(谁说现在内存

大了就可以任意malloc了??)。上面那个过程对于资源的管理在MSDN文档中似乎显得有点

模糊。CreateStreamOnHGlobal函数的第二个参数指定当IStream->Release的时候,是否会自动

删除这个HGLOBAL对象。我虽然对COM不懂,但也知道它的对象是基于一种引用计数的管理方式。

逐字看了下文档,发现一个final单词,原来是IStream->Release最后一次释放时,会同时释放掉

这个HGLOBAL对象。更让人发指的是,我猜测Image( IStream * )来创建Image时,Image又

会对这个IStream进行一次AddRef。我发觉MSDN对于Gdiplus::Image::FromStream函数的说明

也有点模糊。我揣摩使用FromStream获得的Image*,是否需要手动去delete?这个地方的内存

资源管理,一定得搞个水落石出。结果是,FromStream的实现就是简单地new了个Image。而

Image内部肯定会对IStream进行AddRef,并且,如果在Image销毁前销毁这个HGLOBAL,这个

Image基本也就废了。

 

也就是说,Image本身不对HGLOBAL中的图片数据进行复制。囧。别想让我再写个wrap class把

HGLOBAL和Image纠结在一起,简单考虑,将CreateStreamOnHGlobal第二个参数设为TRUE。

 

要将一个Image保存为一段内存,也比较麻烦。我的方法和google上的相同。当然,微软的库依

然让我在很多细节上栽跟斗(如前所说,可能这是基于多语言支持的考虑)。首先需要创建个空

的IStream,即CreateStreamOnHGlobal第一个参数为NULL。然后将Image Save到这个IStream。

再根据该IStream::Seek获取其大小,自己再分配段内存,最后IStream::Read读取进来。同样,

需要注意相关内存资源的管理。

 

下午简单把以上两个过程简单封装了下。

下载代码。

posted on 2009-05-28 20:23 Kevin Lynx 阅读(11883) 评论(4)  编辑 收藏 引用 所属分类: 通用编程

评论

# re: GDI+中从内存读取图片/保存图片到内存 2009-05-28 23:10 expter

呵呵,牛啊!

还是顶下,你QQ好多,ZM!
我加你。。。
  回复  更多评论   

# re: GDI+中从内存读取图片/保存图片到内存 2009-06-01 10:13 zwp

可以采用freeimage来从内存解编码图像数据的。
此外,IStream提供给用户更多选择,你可以直接从网络读取图像数据创建image,甚至在将保存出来的图片保存到网络上去。只要自己简单实现下该接口即可。而这样的灵活性不是简单的一个void*可以实现的:)
不过微软既然提供了从文件名打开和保存的方法,作为经常出现的内存打开和保存需求似乎也应该提供相关的方法。
  回复  更多评论   

# re: GDI+中从内存读取图片/保存图片到内存 2009-06-19 15:08 mike7734@sina.com

大哥,有完整DEMO么,我完全不懂GDI
发一份给我看看行么,我只会C,不会C++
mike7734@sina.com  回复  更多评论   

# re: GDI+中从内存读取图片/保存图片到内存 2009-06-20 10:58 Kevin Lynx

@mike7734@sina.com
你最好找人发一份c++ primer给你。:)  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理