vb绘制图像
答案:5 悬赏:20 手机版
解决时间 2021-04-09 06:14
- 提问者网友:辞取
- 2021-04-08 15:22
在图片框里头填充渐变色的直线,直到铺满整个图片框。但是!一个像素一个像素填充很慢,要好几秒。能不能快点让它像显示图片那么迅速?注意每条渐变线条的颜色不是固定的也不是相同的,就是说不能先画成图片。有没有高人能解决?
最佳答案
- 五星知识达人网友:慢性怪人
- 2021-04-08 16:26
自盘古开天地以来(好像夸张了点),一直有人抱怨VB程序速度慢。特别是图像处理,被认为是VB的禁区。说起来也是,市面上的关于VB的图像处理的数据都是先讲计算公式,再直接用PSet(或API函数SetPixel)逐点画(至少我见过的书都是这样)。效果是办到了,但速度慢得离谱:对一幅640*480的图像进行半透明合并就需要10秒钟;而在PhotoShop中,只要一设置图层的透明度,半透明效果立即呈现。难怪有人说VB的闲话。
但这并不表示VB不能写高速的图像处理程序,速度慢是因为没有使用正确的方法。
从VB5开始,能以本机代码编译成exe文件,所以不存在代码执行速度的问题。那么,是什么拖慢了速度呢?就是PSet和SetPixel!PSet把浮点形式的坐标转为像素单位,再交给SetPixel处理。而SetPixel呢,坐标系转化、剪裁区域判断、将颜色匹配为设备支持的最接近的,最后还要根据不同的颜色格式寻址、为将颜色写入其所在位进行位运算。经过这么多层处理,速度不慢才怪。
那么,怎样才能提高处理速度呢?使用DIB,直接对位图所在内存进行操作,速度可以大大提高。现在看看范例程序,这只是一个简单的色彩演示程序。
CPU:赛扬333;内存:PC100(很老的概念了)的SDRAM,128MB;单位:毫秒 Windows 98 Windows XP 说 明
VB_PSet 1,199.4553 786.1885 在VB使用 PSet 画的
VB_SetPixel 872.3621 451.3712 在VB使用 SetPixelV 画的
VB_DIB 8.2218 8.2226 在VB使用 DIB 画的
VB_DIB_Ptr 9.6783 9.4420 在VB使用 DIBSection + 模拟指针 画的
VC(Debug) 6.6896 6.6503 VC写的(Debug版)
VC(Release) 3.2736 3.6247 VC写的(Release版)
从这个表中可看出:
1.VC比VB_DIB、VB_DIB_Ptr快两倍,这是因为SafeArray结构的数组比真正的指针慢,但也不是某些人所说的70~100倍;
2.VB_DIB_Ptr比VB_DIB慢一点,这是因为模拟指针本来就是靠SafeArray结构的数组,而且模拟指针需要对两个数组进行操作,所以速度慢一点;
3.真正差了70~100倍是VB_PSet和VB_SetPixel,特别是VB_PSet在Windows98下与VB_DIB差了145倍。
以上可证,速度慢的原因是SetPixel非常低效,而并不是VB的问题。虽然VC的的确比较快,但是我写这篇文章不是为了讨论速度极限(否则这篇文章会改名为《如何用汇编写高速的图像处理程序》),而是为了告诉大家如何在VB中写能够实时处理的图像处理程序。
未完>>
但这并不表示VB不能写高速的图像处理程序,速度慢是因为没有使用正确的方法。
从VB5开始,能以本机代码编译成exe文件,所以不存在代码执行速度的问题。那么,是什么拖慢了速度呢?就是PSet和SetPixel!PSet把浮点形式的坐标转为像素单位,再交给SetPixel处理。而SetPixel呢,坐标系转化、剪裁区域判断、将颜色匹配为设备支持的最接近的,最后还要根据不同的颜色格式寻址、为将颜色写入其所在位进行位运算。经过这么多层处理,速度不慢才怪。
那么,怎样才能提高处理速度呢?使用DIB,直接对位图所在内存进行操作,速度可以大大提高。现在看看范例程序,这只是一个简单的色彩演示程序。
CPU:赛扬333;内存:PC100(很老的概念了)的SDRAM,128MB;单位:毫秒 Windows 98 Windows XP 说 明
VB_PSet 1,199.4553 786.1885 在VB使用 PSet 画的
VB_SetPixel 872.3621 451.3712 在VB使用 SetPixelV 画的
VB_DIB 8.2218 8.2226 在VB使用 DIB 画的
VB_DIB_Ptr 9.6783 9.4420 在VB使用 DIBSection + 模拟指针 画的
VC(Debug) 6.6896 6.6503 VC写的(Debug版)
VC(Release) 3.2736 3.6247 VC写的(Release版)
从这个表中可看出:
1.VC比VB_DIB、VB_DIB_Ptr快两倍,这是因为SafeArray结构的数组比真正的指针慢,但也不是某些人所说的70~100倍;
2.VB_DIB_Ptr比VB_DIB慢一点,这是因为模拟指针本来就是靠SafeArray结构的数组,而且模拟指针需要对两个数组进行操作,所以速度慢一点;
3.真正差了70~100倍是VB_PSet和VB_SetPixel,特别是VB_PSet在Windows98下与VB_DIB差了145倍。
以上可证,速度慢的原因是SetPixel非常低效,而并不是VB的问题。虽然VC的的确比较快,但是我写这篇文章不是为了讨论速度极限(否则这篇文章会改名为《如何用汇编写高速的图像处理程序》),而是为了告诉大家如何在VB中写能够实时处理的图像处理程序。
未完>>
全部回答
- 1楼网友:枭雄戏美人
- 2021-04-08 19:36
描述有点乱,不好理解。
- 2楼网友:渊鱼
- 2021-04-08 18:58
我给你思路吧
1、解决数据的传递
1.1将数据存放在全局数组
全局数组可以在当前窗体定义(调用时需要用“窗体名.数组名(index)),也可以在模块里定义(调用时直接调用)
1.2将数据存放在文件中,在绘图时从文件读取数据,完后再删除文件
2、解决颜色问题
颜色直接在画的时候可以设置,如:picture1.line (0,0)-(0,100),vbblue
3、解决连接点问题
可以将前一个点保存在一个零时变量中,使用画线语句(picture1.line(x1,y1)-(x2,y2)),(x1,y1)就是零时变量保存的坐标,(x2,y2)就是当前的点的坐标
- 3楼网友:醉吻情书
- 2021-04-08 18:09
没有办法的,除非用高级技术来处理。
- 4楼网友:神的生死簿
- 2021-04-08 16:55
这种绘图问题来找我嘛……(分好寒酸。。)
传说中的GDI+隆重出场!……
GDI+是最快的。可以超过VB任何绘图语句
1.建立一个模块,复制下面代码:
Option Explicit
Public Type GdiplusStartupInput
GdiplusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Public 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
Public Enum LinearGradientMode
LinearGradientModeHorizontal ' 0
LinearGradientModeVertical ' 1
LinearGradientModeForwardDiagonal ' 2
LinearGradientModeBackwardDiagonal ' 3
End Enum
Public Enum WrapMode
WrapModeTile ' 0
WrapModeTileFlipX ' 1
WrapModeTileFlipY ' 2
WrapModeTileFlipXY ' 3
WrapModeClamp ' 4
End Enum
Public Type POINTL
x As Long
y As Long
End Type
Public Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As GpStatus
Public Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As GpStatus
Public Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, graphics As Long) As GpStatus
Public Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As GpStatus
Public Declare Function GdipGraphicsClear Lib "gdiplus" (ByVal graphics As Long, ByVal lColor As Long) As GpStatus
Public Declare Function GdipCreateLineBrushI Lib "gdiplus" (Point1 As POINTL, Point2 As POINTL, ByVal color1 As Long, ByVal color2 As Long, ByVal WrapMd As WrapMode, lineGradient As Long) As GpStatus
Public Declare Function GdipFillRectangleI Lib "gdiplus" (ByVal graphics As Long, ByVal Brush As Long, ByVal x As Long, ByVal y As Long, ByVal Width As Long, ByVal Height As Long) As GpStatus
Public Declare Function GdipDeleteBrush Lib "gdiplus" (ByVal Brush As Long) As GpStatus
Dim mToken As Long
Public Sub InitGDIPlus()
Dim uInput As GdiplusStartupInput
uInput.GdiplusVersion = 1
If GdiplusStartup(mToken, uInput) <> Ok Then
MsgBox "GDI+ 初始化错误。程序即将关闭。", vbCritical, "InitError"
End
End If
End Sub
Public Sub TerminateGDIPlus()
GdiplusShutdown mToken
End Sub
2.窗体上复制下面代码:
Option Explicit
Dim g As Long, Brush As Long
Dim p1 As POINTL, p2 As POINTL
Private Sub Form_Load()
Picture1.ScaleMode = 2
Picture1.AutoRedraw = True
Me.ScaleMode = 2
p1.x = Picture1.Left
p1.y = Picture1.Top
p2.x = p1.x + Picture1.Width
p2.y = p1.y + Picture1.Height
Call InitGDIPlus
GdipCreateFromHDC Picture1.hDC, g
GdipCreateLineBrushI p1, p2, &HFFFF00FF, &HFF00FF00, WrapModeTileFlipY, Brush
GdipFillRectangleI g, Brush, p1.x, p1.y, p2.x - p1.x, p2.y - p1.y
End Sub
Private Sub Form_Unload(Cancel As Integer)
GdipDeleteBrush Brush
GdipDeleteGraphics g
TerminateGDIPlus
End Sub
注意这一行 GdipCreateLineBrushI p1, p2, &HFFFF00FF, &HFF00FF00, WrapModeTileFlipY, Brush
&HFFFF00FF, &HFF00FF00分别是两个颜色,对应AlphaRedGreenBlue
即&HFFFF00FF代表Alpha=255,Red=255,Green=0,Blue=255
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯