VB6 GDI+ 入门教程[9] Bitmap魔法(2):数据读写
本文转自
http://vistaswx.com/blog/article/category/tutorial/page/2
导读:
本节介绍了一下Gdi+中进行数据直接读写的方法
1.GdipBitmapGetPixel
2.GdipBitmapSetPixel
3.GdipBitmapLockBits & GdipBitmapUnlockBits
1.GdipBitmapGetPixel
我们似乎一直在纳闷,GDI+中怎么拿到图片的数据呢?(我们之前一直都是绘制)。这一节,你就会拿数据了。
拿数据,无非就是取得一个点的ARGB值,而且往往我们要获取所有的点的值。
纵观GDI+的模块中的API,我们寻觅到了这个API:GdipBitmapGetPixel。如名,它是用于得到像素(点)的,事实上的确是。这个函数传出的变量包含了指定点的颜色值(AARRGGBB[16])。
此函数用起来及其方便,像VB中的Point(X,Y)函数一样。
例如:
Dim color As Long GdipBitmapGetPixel bitmap, 0, 0, color Debug.Print Hex(color) |
这样我们就拿到了bitmap中点(0,0)的颜色。
再说回来,怎么拿到所有颜色呢?无非如此罢了:
Dim color() As Long Dim i As Long , j As Long ReDim color(BitmapWidth - 1, BitmapHeight - 1) For i = 0 To BitmapWidth - 1 For j = 0 To BitmapHeight - 1 GdipBitmapGetPixel bitmap, i, j, color(i, j) Next Next |
注意:
其中,bitmap就是拿颜色的位图;
BitmapWidth,BitmapHeight分别是用GdipGetImageWidth,GdipGetImageHeight得到的Bitmap的尺寸。
2.GdipBitmapSetPixel
类比着,我们设置Bitmap中的某一个点也是很容易的,API是GdipBitmapSetPixel。代码类似于GdipBitmapGetPixel。
例如:
GdipBitmapSetPixel bitmap, 0, 0, &HFF000000 |
这句把bitmap位图中点(0,0)设置为黑色。
3.GdipBitmapLockBits & GdipBitmapUnlockBits
看看名字,LockBits,锁定……锁定是什么呢……这个先不要管他。不知你有没有发现前面2个得到颜色/设置颜色的GDI+函数巨慢无比?(不过貌似比VB中的Point快)。为什么呢?其实我也不知道(怎么可能呢?)
在我这台破烂电脑上,一幅800*800左右的图片,Get所有的Pixel花费了约1s……,那么1024*768怎么办?更大的怎么办?有没有更快的?
答案是,有。用什么?就是这个——GdipBitmapLockBits。
GdipBitmapLockBits,GdipBitmapUnlockBits是一对函数,他们可以将Bitmap上数据映射到内存和将内存中位图数据写回Bitmap,这个函数是一整块的,非常适合处理一大片的点——例如整个图像。
演示代码:
Option Explicit Dim bitmap As Long , rc As RECTL Dim data() As Long Dim graphics As Long Private Sub Form_Load() InitGDIPlus GdipCreateBitmapFromFile StrPtr( "c:TestImg.png" ), bitmap GdipGetImageWidth bitmap, rc.Right GdipGetImageHeight bitmap, rc.Bottom ReDim data(rc.Right - 1, rc.Bottom - 1) Dim BmpData As BitmapData With BmpData .Width = rc.Right .Height = rc.Bottom .PixelFormat = GpPixelFormat.PixelFormat32bppARGB .scan0 = VarPtr(data(0, 0)) .stride = 4 * CLng (rc.Right) End With GdipBitmapLockBits bitmap, rc, ImageLockModeUserInputBuf Or ImageLockModeWrite Or ImageLockModeRead, GpPixelFormat.PixelFormat32bppARGB, BmpData Dim i As Long , j As Long , s As String For i = 0 To rc.Bottom - 1 For j = 0 To rc.Right - 1 data(j, i) = data(j, i) + data(j, i) Next Next GdipBitmapUnlockBits bitmap, BmpData GdipCreateFromHDC Me .hDC, graphics GdipDrawImageRectI graphics, bitmap, 0, 0, rc.Right, rc.Bottom GdipDeleteGraphics graphics GdipDisposeImage bitmap End Sub Private Sub Form_Unload(Cancel As Integer ) TerminateGDIPlus End Sub |
我们先注意BmpData结构体,它实际上就是数据的设置。
scan0内存地址我们写的是VarPtr(data(0,0))。
stride = 4 * CLng(rc.Right):扫描宽度,这一个实际上就是二维数组每隔多少字节增加第一维,其中4是Long的存储长度,4个字节。
我们可以把数组的存储想象为一个矩形,gdi+放数据就是从左到右放,放到了边界则从下一行的第一个再从左向右放……
GdipBitmapLockBits:
我们首先用它来得到位图数据,方式是ImageLockModeWrite Or ImageLockModeRead(ImageLockModeUserInputBuf必须写)。即我们传给他的data(),它将把位图数据写入;而在GdipBitmapUnlockBits时候将data()数据写入位图。注意:如果只是Write模式,那么你将得不到原始数据。
data(j, i) = data(j, i) + data(j, i) 这句是一句简单的颜色处理变换,让我们能看到处理效果
GdipBitmapUnlockBits:完成最后的写入&释放工作。后面几句是绘制这个新图片用。
注意:这里LockBits得到的数据data()是data(y,x),即顺序是(列,行)。Lockbits时候也要按照传入长度和宽度,不然VB会抛给你“Visual Basic 遇到问题需要关闭……
VB6 GDI+ 入门教程[9] Bitmap魔法(2):数据读写的更多相关文章
- VB6 GDI+ 入门教程[8] Bitmap魔法(1):创建
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[8] Bitmap魔法(1):创建 2009 年 9 月 ...
- VB6 GDI+ 入门教程[7] Graphics 其他内容
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[7] Graphics 其他内容 2009 年 9 月 ...
- VB6 GDI+ 入门教程[1] GDI+介绍
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[1] GDI+介绍 2009 年 6 月 18 日 17 ...
- VB6 GDI+ 入门教程[2] GDI+初始化
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[2] GDI+初始化 2009 年 6 月 18 日 7 ...
- VB6 GDI+ 入门教程[3] 笔、刷子、矩形、椭圆绘制
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[3] 笔.刷子.矩形.椭圆绘制 2009 年 6 月 1 ...
- VB6 GDI+ 入门教程[4] 文字绘制
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[4] 文字绘制 2009 年 6 月 18 日 7条评论 ...
- VB6 GDI+ 入门教程[5] 基础绘图小结
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[5] 基础绘图小结 2009 年 6 月 18 日 4条 ...
- VB6 GDI+ 入门教程[6] 图片
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[6] 图片 2009 年 6 月 19 日 15条评论 ...
- testng入门教程16数据驱动(把数据写在xml)
testng入门教程16数据驱动(把数据写在xml) testng入门教程16数据驱动(把数据写在xml)把数据写在xml文件里面,在xml文件右键选择runas---testng执行 下面是case ...
随机推荐
- 双4G LTE
我们即将上市的Xplay3S将支持双4G LTE(TDD-LTE+FDD-LTE),那什么是4G LTE呢,今天来给大家科普下4G LTE网络知识. 什么是TDD-LTE/FDD-LTE? LTE是通 ...
- 【leetcode❤python】27. Remove Element
#-*- coding: UTF-8 -*- class Solution(object): def removeElement(self, nums, val): "& ...
- BZOJ 3534 重建
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3534 题意:给定一个无向图,每条边有选择概率P:求选出的边恰是一棵生成树的概率. 思路: ...
- [CF353C]Find Maximum(贪心)
题目链接:http://codeforces.com/contest/353/problem/C 题意:给你一串数字a[]和一个二进制串,要求找一个不超过m的二进制数,使得与对应a[]上的数字的乘积和 ...
- 20150203一些移动端H5小bug解决
都是一些我也不知道为什么会有的bug. 1. 在三星note2,小米2,页面加载后,页面有黑块. 那么提高被盖住的部分z-index. 2. iphone5 ,ios7.0.4,上文字显示不出 那么就 ...
- GitHub上不错的Android开源项目(二)
收集相关系列资料,自己用作参考,练习和实践.小伙伴们,总有一天,你也能写出 Niubility 的 Android App :-) 系列文章如下: GitHub上不错的Android开源项目(一):h ...
- 一个封装较好的删除方法(Delete)
前台的引用 @Html.ActionLink(“删除字样”,“后台的删除方法”,new{绑定id},new{@style="样式"});方法,如何要独立使用的话,一般还要使用到相应 ...
- 2013/7/16 HNU_训练赛4
CF328B Sheldon and Ice Pieces 题意:给定一个数字序列,问后面的数字元素能够组成最多的组数. 分析:把2和5,6和9看作是一个元素,然后求出一个最小的组数就可以了. #in ...
- sgu-508 Black-white balls 概率-贝叶斯公式
题意:有n个球,其中有0.1.2...n个黑球的概率是相等的,现在从中取出L个球,p个黑球q个白球.现在问猜一个黑球的区间,使得落在这个区间的概率大于给定的一个数值. 详见代码: #include & ...
- E2 2014.5.8 更新日志
增加功能 增加报价单功能,可以针对指定客户生成报价单,可以直接生成一个在线地址,直接把地址发给客户在线打开 传统的报价,先生成一个EXCEL,再传给客户,使用E2,这一切都变得简单,你可生成一个在线地 ...