找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 11392|回复: 9

[交流] VB GdipLoadImageFromStream 内存问题

 火.. [复制链接]

21

主题

162

回帖

4

精华

论坛元老

Tokyo-Hot

积分
5945
QQ
发表于 2011-9-21 23:00:17 | 显示全部楼层 |阅读模式
本帖最后由 wszjljx 于 2011-9-21 23:00 编辑

Public Sub ByteDrawImage(ImageData() As Byte, ByVal DeviceHandle As Long, Optional ByVal Left As Long = 0, Optional ByVal Top As Long = 0, Optional ByVal Width As Long = 0, Optional ByVal Height As Long = 0)

On Error Resume Next

Dim GdiValue As Long
Dim DrawWidth As Long
Dim DrawHeight As Long
Dim ImageValue As Long
Dim StreamValue As Long
Dim GdiDeviceHandle As Long
Dim GdiObject As GdiplusStartupInput

If DeviceHandle = 0 Then Exit Sub

DrawWidth = Width
DrawHeight = Height

GdiObject.GdiplusVersion = 1

Call GdiplusStartup(GdiValue, GdiObject)
Call GdipCreateFromHDC(DeviceHandle, GdiDeviceHandle)
Call CreateStreamOnHGlobal(ImageData(0), 0, StreamValue)
Call GdipLoadImageFromStream(StreamValue, ImageValue)

If DrawWidth <= 0 Then Call GdipGetImageWidth(ImageValue, DrawWidth)
If DrawHeight <= 0 Then Call GdipGetImageHeight(ImageValue, DrawHeight)

Call GdipDrawImageRect(GdiDeviceHandle, ImageValue, Left, Top, DrawWidth, DrawHeight)

Call GdipDisposeImage(ImageValue)
Call GdipDeleteGraphics(GdiDeviceHandle)
Call GdiplusShutdown(GdiValue)

End Sub

利用此代码直接将字节数组图片绘制在窗体上 但是每绘制一次使用的内存就会增大 不清楚该如何释放
经检查 导致内存增加不释放的时CreateStreamOnHGlobal该API函数
求教如何释放此函数创建的流对象...
洗澡脱光衣服打开水才发现自己没带洗发水没带沐浴乳只带了一包洗衣粉 心酸的用洗衣粉把自己搓了一遍... ...

21

主题

162

回帖

4

精华

论坛元老

Tokyo-Hot

积分
5945
QQ
 楼主| 发表于 2011-9-21 23:00:52 | 显示全部楼层
API函数及类型定义:


Private Declare Function GdipDrawImageRect Lib "gdiplus" (ByVal graphics As Long, ByVal image As Long, ByVal x As Single, ByVal y As Single, ByVal Width As Single, ByVal Height As Single) As GpStatus
Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Sub CreateStreamOnHGlobal Lib "ole32.dll" (ByRef hGlobal As Any, ByVal fDeleteOnRelease As Long, ByRef ppstm As Any)
Private Declare Function GdipLoadImageFromStream Lib "gdiplus" (ByVal Stream As Long, ByRef image As Long) As Long
Private Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As GpStatus
Private Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As GpStatus
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As Long
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Long
Private Declare Sub GdiplusShutdown Lib "gdiplus" (ByVal token As Long)

Private Enum GpStatus
  Ok = 0
  GenericError = 1
  InvalidParameter = 2
  OutOfMemory = 3
  ObjectBusy = 4
  InsufficientBuffer = 5
  NotImplemented = 6
  Win32Error = 7
  WrongState = 8
  Aborted = 9
  FileNotFound = 10
  ValueOverflow = 11
  AccessDenied = 12
  UnknownImageFormat = 13
  FontFamilyNotFound = 14
  FontStyleNotFound = 15
  NotTrueTypeFont = 16
  UnsupportedGdiplusVersion = 17
  GdiplusNotInitialized = 18
  PropertyNotFound = 19
  PropertyNotSupported = 20
End Enum

Private Type GdiplusStartupInput
   GdiplusVersion As Long
   DebugEventCallback As Long
   SuppressBackgroundThread As Long
   SuppressExternalCodecs As Long
End Type
洗澡脱光衣服打开水才发现自己没带洗发水没带沐浴乳只带了一包洗衣粉 心酸的用洗衣粉把自己搓了一遍... ...

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2011-9-22 14:52:11 | 显示全部楼层
  1.   函数原型:   WINOLEAPI CreateStreamOnHGlobal(
  2.   HGLOBAL hGlobal, // Memory handle for the stream object
  3.   BOOL fDeleteOnRelease, // Whether to free memory when the object is released
  4.   LPSTREAM *ppstm // Address of output variable that receives the IStream interface pointer   );
复制代码
看起来StreamValue这个参数是个指针,并且指向的是一个接口,如果这个接口被实现了,那就是一个对象.

用closehandle关闭这个句柄试试吧.
我就是嗷嗷叫的老马了......

21

主题

162

回帖

4

精华

论坛元老

Tokyo-Hot

积分
5945
QQ
 楼主| 发表于 2011-9-22 17:46:05 | 显示全部楼层
本帖最后由 wszjljx 于 2011-9-22 23:14 编辑

closehandle的话VB直接弹出内存不能为READ

那个问题我已经解决了 API的第二个参数为1就行...
又有了新的问题... Call GdiplusStartup(GdiValue, GdiObject)这行 也会每运行一次内存使用多4KB...
洗澡脱光衣服打开水才发现自己没带洗发水没带沐浴乳只带了一包洗衣粉 心酸的用洗衣粉把自己搓了一遍... ...

21

主题

162

回帖

4

精华

论坛元老

Tokyo-Hot

积分
5945
QQ
 楼主| 发表于 2011-9-22 23:13:17 | 显示全部楼层
问题已解决 ... 不要绘制一次就初始化一次GDI+库 再销毁一次
先初始化GDI+库 就可以画图了 不用销毁
程序Unload时再销毁就行... 内存使用终于不再彪了...
洗澡脱光衣服打开水才发现自己没带洗发水没带沐浴乳只带了一包洗衣粉 心酸的用洗衣粉把自己搓了一遍... ...

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2011-9-26 17:39:31 | 显示全部楼层
汗,哈哈.

内存泄漏啊内存泄漏!{:soso_e113:}
我就是嗷嗷叫的老马了......

21

主题

162

回帖

4

精华

论坛元老

Tokyo-Hot

积分
5945
QQ
 楼主| 发表于 2011-9-26 21:52:12 | 显示全部楼层
现在完美的解决方案模块我发一份 内存基本不产生问题
主要是GdiplusStartup初始化的GDI+库GdiplusShutdown不能完全释放掉
所以不要每次绘图加载一次卸载一次 只要第一次绘图时加载 在程序退出的时候卸载就好...

模块下载地址:http://www.m5home.com/bbs/thread-5952-1-1.html
洗澡脱光衣服打开水才发现自己没带洗发水没带沐浴乳只带了一包洗衣粉 心酸的用洗衣粉把自己搓了一遍... ...

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
发表于 2011-10-3 14:09:20 | 显示全部楼层
楼主的精华已经达到两篇,现在把你的用户组改为核心会员!

0

主题

1

回帖

0

精华

初来乍到

积分
13
发表于 2011-12-21 15:50:39 | 显示全部楼层
7 楼提供的模块也有问题,Steam 不能定义为 object 类型,在IDE 中调试会崩溃。应该是Iunknown 类型。这个模块帮了我不少忙啊。

21

主题

162

回帖

4

精华

论坛元老

Tokyo-Hot

积分
5945
QQ
 楼主| 发表于 2012-1-10 20:27:04 | 显示全部楼层
的确在IDE环境有时候会崩溃 那是因为你在程序退出时没有调用DestroyGDI来卸载GDI+库 如果正常卸载掉了 不会有问题的
洗澡脱光衣服打开水才发现自己没带洗发水没带沐浴乳只带了一包洗衣粉 心酸的用洗衣粉把自己搓了一遍... ...
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表