版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://vistaswx.blogbus.com/logs/48404882.html
话说有没有注意我把所有教程名字改了呢?呵呵为了增加收录率呗。
话说有没有注意我修改过Gdi+模块了呢?赶快看看,哦,多出来好多Sub/Function哟。其实这些都是为了方便大家而写的 :)。
其实呢图片保存应该放在Image部分,但是Bitmap中用到图片保存也不少,所以我就单独开辟一个来讲这个“文件保存”的问题,这里演示就用Bitmap来演示。
1.Clsid,Encode
图片怎么保存的呢?我们先研究BMP。众所周知,BMP是无损图像格式,BMP就是老老实实把图片上每一个点保存下来,因此同样尺寸的2份BMP大小是一样的。
由于它没有压缩,但是压缩需求一定是有的,于是出现了形形色色其他图片储存格式,例如GIF,JPG,PNG。图片要保存为这些格式的文件,都要经过一定的算法变换来压缩储存。在GDI+中我们无需知道图片保存的算法,但是怎么表示他们呢?就有了Clsid。GDI+由于某个目的只认Clsid,即类标识符,但是Clsid是一个字节数组,表示不方便,所以就有了相应的字符型表示方法Encode——我们给GDI+的Clsid首先通过一个API转换成相应格式才能用:ClsidFromString。
附:Clsid from MSDN
CLSID 是类标识符的缩写,同样 GUID 是全局唯一标识符的缩写。这两种缩写都是指一个 128 位的整数,其重复的统计概率很小,因此可以用作计算机和网络中的唯一标识符。此标识符通常表示为一个由 16 个成员组成的字节数组,或者表示为由十六进制数字组成的特殊格式字符串(其中字符 a-f 或 A-F 表示十进制数 10-15)。此字符串表示形式由 32 个连续的十六进制数字组成,或者由分别包含 8 个、4 个、4 个、4 个和 12 个十六进制数字的组组成,各组之间用连字符分隔。以连字符连接的字符串表示形式也可以用圆括号或大括号 ({}) 括起来。
2.Params
Param,即参数,保存图片也有参数,例如众所周知的JPEG有一个压缩比的参数。同样的,Params参数的传递也要通过Clsid,不过正是因为这样所以代码有点麻烦。
3.GdipSaveImageToFile
现在是真正的保存图像函数,先来看我写在模块中的一个已完成的函数。
Public Function SaveImageToPNG(ByVal Image As Long, ByVal Path As String) As GpStatus
Dim Params As EncoderParameters, EncParams() As Byte
ReDim EncParams(Len(Params) - 1)
SaveImageToPNG = GdipSaveImageToFile(Image, StrPtr(Path), GetImageEncoderClsid(PNG), EncParams(0))
Erase EncParams
End Function
其中GetImageEncoderClsid(PNG)为获取PNG的Clsid的一个函数。我们保存32位PNG不需要任何参数,因此可以看见我们仅仅是传递给他一片空白数据而已(起始位EncParams(0)),由于数据有长度,即使是空白数据我们也要有足够的空白,因此我们之前重定义这片空白大小为Len(Params)即EncoderParameters结构体的长度。
我们再来看看有参数保存是怎么回事。
Public Function SaveImageToJPG(ByVal Image As Long, ByVal Path As String, ByVal Quality As Long) As GpStatus
Dim Params As EncoderParameters, EncParams() As Byte
Params.count = 1
CLSIDFromString StrPtr(EncoderQuality), Params.Parameter.Guid
Params.Parameter.NumberOfValues = 1
Params.Parameter.type = 4
Params.Parameter.value = VarPtr(Quality)
ReDim EncParams(Len(Params) - 1)
CopyMemory EncParams(0), Params, Len(Params)
SaveImageToJPG = GdipSaveImageToFile(Image, StrPtr(Path), GetImageEncoderClsid(JPG), EncParams(0))
Erase EncParams
End Function
我们首先设置了Params.count,这里储存了你传入的参数个数,本例中只设置了Quality一个参数,因此Params.count = 1。Params.Parameter.type = 4这个怎么理解呢?这个4其实是EncoderParameterValueTypeLong,Long字节长度,这个值其实跟Value有关系,因为Value可能接受不同的数据类型,它们长度不一样,因此我们要事先传给他Value数据长度,当然这里只能是4……如果你希望VB IDE出错或程序崩溃你可以写大一点,可惜不能BSOD呵呵(Blue Screen)……最后我们还要CopyMemory,因为我们传给他是一个Byte数组,而我们的Params是一个结构体,所以我们要复制这个结构体数据到这个Byte数组中,这样才能传递这个Byte数组给GDI+函数。
4.[封装]SaveImageTo的使用
我在模块中已经封装好几个常用的东西:GetImageEncoderClsid用于获取图像编码的Clsid;而SaveImageTo是一组我为了方便大家使用而写的函数,功能是保存Image/Bitmap以一个指定格式到一个文件。
具体函数列表:
Public Function SaveImageToPNG(ByVal Image As Long, ByVal Path As String) As GpStatus Public Function SaveImageToJPG(ByVal Image As Long, ByVal Path As String, ByVal Quality As Long) As GpStatus Public Function SaveImageToGIF(ByVal Image As Long, ByVal Path As String) As GpStatus Public Function SaveImageToBMP(ByVal Image As Long, ByVal Path As String) As GpStatus
Image为传入的Image/Bitmap地址,Path为保存文件的路径,SaveImageToJPG中Quality为保存图像的质量(0~100)。返回值为GdipSaveImageToFile的返回值,代表保存文件的状态,0表示OK(成功)。
我还在模块中加入了CreateBitmap和CreateBitmapWithGraphics函数,两者都是从内存创建位图,后者在创建位图后还将这个位图与Graphics绑定并传回。
接下来演示我加入的这几个函数怎么使用。例:以不同格式保存图片
Option Explicit
Private Sub Form_Load()
Dim Bitmap As Long, Graphics As Long, Brush As Long
InitGDIPlus
CreateBitmapWithGraphics Bitmap, Graphics, 50, 50
GdipCreateSolidFill &H80FF0000, Brush '半透明红色。保存后仅在PNG中有半透明效果。
GdipFillRectangleI Graphics, Brush, 0, 0, 50, 50
GdipDeleteBrush Brush
GdipDeleteGraphics Graphics
SaveImageToPNG Bitmap, "c:\1.png"
SaveImageToJPG Bitmap, "c:\1.jpg", 100
SaveImageToGIF Bitmap, "c:\1.gif"
SaveImageToBMP Bitmap, "c:\1.bmp"
GdipDisposeImage Bitmap
End Sub
Private Sub Form_Unload(Cancel As Integer)
TerminateGDIPlus
End Sub





评论
請問該在哪邊作修改呢
謝謝
1.从内存创建Bitmap
2.GdipGetImageGraphicsContext将Bitmap与Graphics绑定。
参见本教程最后一个代码(以上两步已被封装为CreateBitmapWithGraphics)
... 初始化 GDI+ ...
GdipCreateBitmapFromScan0 W, H, 0, PixelFormat32bppARGB, ByVal 0&, bitmap
GdipGetImageGraphicsContext bitmap, graphics
GdipSetInterpolationMode graphics, InterpolationModeHighQualityBicubic
... 对场景 graphics 绘制内容 ...
... 使用这个位图 bitmap (如绘制或保存) ... <- 在这步如果使用多次 bitmap 将会给出 ObjectBusy 错误
... 清理所有对象 ...
... 卸载 GDI+ ...