PbIdea功能系列之PowerBuilder高级图像处理功能

PbIdea功能系列PowerBuilder高级图像处理功能

我们知道,PowerBuilder是CS桌面应用的开发利器,具方便、快捷、高效的特点。然而,PowerBuilder的特长在数据库方面,对于图像处理这块,功能几乎是一片空白,只有几个简单的图形形状,更谈不上图片处理与加工,甚至有些格式都不支持。

本文着重于介绍利用PbIdea扩展库,增强PB图片处理功能。

一、uo_image对象

uo_image对象着重于图片显示、转换、缩放等处理的一些基础功能,着重实现图片的工具性功能。

1、显示图片。uo_image本身是一个可视控件,直接拖放到窗口上,再使用打开图片功能即可以显示图片。支持的图片格式有:bmp,jpg,png,gif。例如:

uo_1.open(“test.bmp”)

参数可以是文件名,也可以是blob数据,数据可以是从数据库中取出,也可以是从网上下载等等:

Selectblob into :pic from … 然后 uo_1.open(pic)

扫描二维码关注公众号,回复: 13638000 查看本文章

httpclient.request(……)    然后 uo_1.open(httpclient.response.data)

均可以直接显示图片,不需要存为图片文件再显示。

对于一些下载通过base64编码的图片,可以直接打开显示,例如:

Ls_pic = “data:image/jpg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQ………..”

uo_1.open(ls_pic)

是不是感觉比PB自带的Picture控件强大了不少?

2、显示功能增强。我们显示图片文件到窗口的功能会了,支持的图片格式多,内容多。同时也支持一些增强功能。

增强一:uo_1. SetAlpha(180) 以 180/255的透明度显示。0为全透明,255为不透明。

 

增强二:使指定颜色变成透明。uo_3.SetMaskColor(RGB(255,255,255)),即让图片的白色背景变成透明颜色。

增强三:旋转图片角度。Uo_1. Rotate(15) ,即旋转15度。

 

增强四:基于上列一和三,实现渐变或者旋转动画显示效果。

增强五:支持动画gif播放

增强六:uo_1. Flip(),图片上下翻转

增强七:uo_1.Paint(…) ,将本控件的图片内容绘制到其他控件上去,本控件可以隐藏。可以由多个uo_image把图片绘制到同一个控件上,形成图片叠加效果,在使用带有透明效果png图片时,这个功能比较有用。比如下列这张图就是一个透明的蝴蝶被叠加到窗口背景上无缝对接。

3、图片处理功能。除了作为显示控件,uo_image 也可以直接做一些图片处理。在这些处理功能中,上面列出的大部分增强功能也都可以使用。同时还有额外功能。

uo_image img

img = create uo_image

img.open(…) //打开图片

img. GetSize(w,h) //获取图片宽度和高度

img. ReplaceColor(…)//实现颜色替换,有域值设置,比如张纸的背景有点脏点模糊,可以替换为纯白背景,或者其他颜色背景。如果存为png图片,也可以把背景替换为透明色,类似于PS的扣图。

Img.zoom(…) //图片缩放,可以指定大小尺寸进行缩放,也可以指定缩放比例进行缩放。

Img. Save(…) //另存为图片,格式由给定的图片名称的文件扩展名决定。

Open,然后再指定文件名Save,通常可以作为图片格式转换的通用方式。

4、二维码。二维码是现在比较常见的功能。Uo_image可以生成并显示二维码,也可以将生成的二维码存为图片文件。

uo_1.OpenQrCode("大自在 [email protected]", 1, 3,RGB(0,0,0), RGB(255,255,255), "..\demores\images\logo.png")

uo_1.save(…) 可另存为图片文件。

具体函数定义是:function boolean OpenBarCode(readonly string codeText,string barType, int nHeight,double scale,readonly string options) system library "PbIdea.dll" alias for "imageOpenBarCode"

5、条码。支持多种条码。其中也包括二维码。(文档https://www.zint.org.uk/manual)

//条码类型定义

CONSTANT int BARCODE_CODE11 = 1

CONSTANT int BARCODE_C25MATRIX = 2

CONSTANT int BARCODE_C25INTER = 3

CONSTANT int BARCODE_C25IATA = 4

CONSTANT int BARCODE_C25LOGIC = 6

CONSTANT int BARCODE_C25IND = 7

CONSTANT int BARCODE_CODE39 = 8

CONSTANT int BARCODE_EXCODE39 = 9

CONSTANT int BARCODE_EANX = 13

CONSTANT int BARCODE_EAN128 = 16

CONSTANT int BARCODE_CODABAR = 18

CONSTANT int BARCODE_CODE128 = 20

CONSTANT int BARCODE_DPLEIT = 21

CONSTANT int BARCODE_DPIDENT = 22

CONSTANT int BARCODE_CODE16K = 23

CONSTANT int BARCODE_CODE49 = 24

CONSTANT int BARCODE_CODE93 = 25

CONSTANT int BARCODE_FLAT = 28

CONSTANT int BARCODE_RSS14 = 29

CONSTANT int BARCODE_RSS_LTD = 30

CONSTANT int BARCODE_RSS_EXP = 31

CONSTANT int BARCODE_TELEPEN = 32

CONSTANT int BARCODE_UPCA = 34

CONSTANT int BARCODE_UPCE = 37

CONSTANT int BARCODE_POSTNET = 40

CONSTANT int BARCODE_MSI_PLESSEY = 47

CONSTANT int BARCODE_FIM = 49

CONSTANT int BARCODE_LOGMARS = 50

CONSTANT int BARCODE_PHARMA = 51

CONSTANT int BARCODE_PZN = 52

CONSTANT int BARCODE_PHARMA_TWO = 53

CONSTANT int BARCODE_PDF417 = 55

CONSTANT int BARCODE_PDF417TRUNC = 56

CONSTANT int BARCODE_MAXICODE = 57

CONSTANT int BARCODE_QRCODE = 58

CONSTANT int BARCODE_CODE128B = 60

CONSTANT int BARCODE_AUSPOST = 63

CONSTANT int BARCODE_AUSREPLY = 66

CONSTANT int BARCODE_AUSROUTE = 67

CONSTANT int BARCODE_AUSREDIRECT = 68

CONSTANT int BARCODE_ISBNX = 69

CONSTANT int BARCODE_RM4SCC = 70

CONSTANT int BARCODE_DATAMATRIX = 71

CONSTANT int BARCODE_EAN14 = 72

CONSTANT int BARCODE_CODABLOCKF = 74

CONSTANT int BARCODE_NVE18 = 75

CONSTANT int BARCODE_JAPANPOST = 76

CONSTANT int BARCODE_KOREAPOST = 77

CONSTANT int BARCODE_RSS14STACK = 79

CONSTANT int BARCODE_RSS14STACK_OMNI = 80

CONSTANT int BARCODE_RSS_EXPSTACK = 81

CONSTANT int BARCODE_PLANET = 82

CONSTANT int BARCODE_MICROPDF417 = 84

CONSTANT int BARCODE_ONECODE = 85

CONSTANT int BARCODE_PLESSEY = 86

CONSTANT int BARCODE_TELEPEN_NUM = 87

CONSTANT int BARCODE_ITF14 = 89

CONSTANT int BARCODE_KIX = 90

CONSTANT int BARCODE_AZTEC = 92

CONSTANT int BARCODE_DAFT = 93

CONSTANT int BARCODE_MICROQR = 97

CONSTANT int BARCODE_HIBC_128 = 98

CONSTANT int BARCODE_HIBC_39 = 99

CONSTANT int BARCODE_HIBC_DM = 102

CONSTANT int BARCODE_HIBC_QR = 104

CONSTANT int BARCODE_HIBC_PDF = 106

CONSTANT int BARCODE_HIBC_MICPDF = 108

CONSTANT int BARCODE_HIBC_BLOCKF = 110

CONSTANT int BARCODE_HIBC_AZTEC = 112

CONSTANT int BARCODE_AZRUNE = 128

CONSTANT int BARCODE_CODE32 = 129

CONSTANT int BARCODE_EANX_CC = 130

CONSTANT int BARCODE_EAN128_CC = 131

CONSTANT int BARCODE_RSS14_CC = 132

CONSTANT int BARCODE_RSS_LTD_CC = 133

CONSTANT int BARCODE_RSS_EXP_CC = 134

CONSTANT int BARCODE_UPCA_CC = 135

CONSTANT int BARCODE_UPCE_CC = 136

CONSTANT int BARCODE_RSS14STACK_CC = 137

CONSTANT int BARCODE_RSS14_OMNI_CC = 138

CONSTANT int BARCODE_RSS_EXPSTACK_CC = 139

CONSTANT int BARCODE_CHANNEL = 140

CONSTANT int BARCODE_CODEONE = 141

CONSTANT int BARCODE_GRIDMATRIX = 142

/*

条码参数说明:

bind      选项,添加绑定条

hidetext  选项,不显示文字

show_hrt  选项,删除人类可读文本

bold      选项,使用粗体文本

box       选项,在符号周围加一个方框

cymk      选项,在EPS符号中使用cmyk颜色

dotty     选项,多蒂用点代替方块来表示矩阵符号

dmre      选项,允许数据矩阵矩形扩展

esc       选项,处理输入数据中的转义字符

gs1       选项,将输入视为与gs1兼容的数据

small     选项,在图像中使用小文本

square    选项,平方力数据矩阵符号为平方

type   =  n ,条码类型数(默认为20 (=Code128))

bg     =  ffffff,指定背景色,十六进制方式,6个字符长, ,默认白色

fg     =  000000,指定前景色,十六进制方式,6个字符长, ,默认黑色

align  = left / right ,文本居左,居右,默认居中

border = n, 边框的宽度

cols   = n, 设置符号中的数据列数

rows   = n, 设置符号中的数据行数

dotsize = n ,点在dotty模式下的数量设置半径

eci     = n, 设置原始数据的eci模式

filetype = PNG/EPS/SVG/PNG/EPS/GIF/TXT,设置输出文件类型

height   = n ,设置高度

mode     = n,设置编码模式(Maxicode/组合)

output  = out.png ,文件发送输出到文件。(缺省为out.png)

primary = STRING Set结构化主消息(Maxicode/Composite)

secure  = NUMBER ,Set error correct level

scale   = n,缩放比例,默认为1

rotate  = 0/90/180/270,旋转角度,(PNG/BMP/PCX)

vers    = n,设置符号版本(二维码/Han Xin)

whitesp = n,维数倍数下空格的数量设置宽度

*/

function boolean OpenBarCode(readonly string codeText,string barType, int nHeight,double scale,readonly string options) system library "PbIdea.dll" alias for "imageOpenBarCode"

uo_barcode.OpenBarCode("12345678901234567890123456789012345678901234567890", “code128”, ai_height,1.0," hidetext ") 通过成不显示文本内容的128码

uo_barcode.save(…) 可另存为图片文件。

uo_json jsBar

jsBar = create uo_json

jsBar.set("width",180)

jsBar.set("height",24)

jsBar.set("text","1234567890123456789012345678901234567890")

jsBar.set("fontsize",48)

jsBar.set("type",20) //或"code128"

//jsBar.set("type",58) //或"qrcode"

//jsBar.set("vers",5)

//jsBar.set("secure",3)

jsBar.set("show_hrt",1)

jsBar.set("scale",1.0)

img.OpenBarCode(jsBar)

destroy jsBar

二、uo_painter对象

在开始本章节前,我们先闭上眼睛做一个瞑想:假如你是一位画师,你要准备画画了,你得有一些基本元素,首先你得有一大张纸(或者是空白墙壁),上面有底色,或者是有现成的底案图纹,然后你往上面安置你想到的各种图片元素(各种类型的图片),或者各种图形元素(圆、矩、文字等),绘制结束后,你可以把成果保存起来,成为一幅画或图片文件。具体到PC里面,你会想到,这不就是windows操作系统自带的“画图”工具吗?我们打开画图工具,可以拉伸图片大小、填底色、粘贴图片、放文字、放各种图形元素,最后我们还可以另存为各种格式的图片文件。

没错,uo_painter就是windows操作系统自带的“画图”工具一样神奇工具,由于是用程序实现这些功能,可以通过计算机强大计算功能实现更加复杂的功能。接下来,我们按照上面暝想的步骤来实现一些基本功能。本章介绍所函数,都是uo_painter的成员函数,需要先对uo_painter实例化才能使用,例如:

uo_painter p;

p = create uo_painter;

p. SetCanvas(this,”ue_paint”);

destroy p;

 

(一)先了解图形的基本元素

1、画板。画板可以是窗口,可以是HDC,可以是一张图,可以是内存的一块区域。

(1)对于窗口,绝大多数很好理解 ,就是把内容画到一个窗口上面,我们可以看得到显示效果。

(2)HDC是什么呢?这个东西有点难理解,微软文档里就这个名词,也没有很好的办法去翻译这个缩写。我们可以把它看作是一个指向硬件的绘图句柄,它可以根据窗口句柄创建一个指向屏幕或桌面的绘图句柄,它也可以是根据打印机创建的一个指向打印机的绘图句柄,也可以是指向绘图仪或其他什么硬件的绘图句柄。我们常用的就2个:屏幕和打印机。同一句绘图语句,当HDC指向屏的时候,会显示显示到窗口,指向指印机时,操作系统会把这些内容输出到打印机上。

(3)一张图,可以是内存的一块区域。图片在内存里加载的时候,其实它就是一块连续的内存区域。也就是我们可以创建一张空白图,或者使用一张现有的图,只不过这些图不显示 ,只是加载在内存里,然后在这个图上进行绘图。就象画家在纸上作画一样。

2、图片。我们知道图片有各种格式,常见的有bmp、jpg(jpeg)、png、gif等等。各种图片格式,只是图片保存时使用,当一张图片加载到内存里后,实际上都是bmp点阵图,使用一块内存区域保存。uo_painter里使用CacheImage/CacheImageBase64函数,对图片加载,缓存到内存里面,缓存后返回一个唯一ID号代表被缓存的这张图,后面需要用到这张图时,以这人ID作为图片参数传入即可。用完后可以使用RemoveImage函数把这张缓存的图片从内存里释放掉。那么为什么我们要缓存图片到内存里呢,完全可以需要时直接传递文件名,从硬盘读取的呀?是的,这想法也没错。但我们为了追求高效率,就得使用缓存方式。比如在一个窗口的存在周期里,使用一张图上作为绘制背景,每次刷新时如果都要从硬盘读文件,这将是一个非常低效率的事情,甚至导致背景绘制停滞或者闪烁,而缓存到内存,就非常高效。

3、背景、前景色与透明度。这些颜色为大家所熟知。除了背景色与前景色,还有一个透明度。当使用png图片的时候,自然这张图片就有一部分是透明,一部分不透明,当把它叠加在其他图片上时,透明部分就不会遮住底图相应部分。此外,还有整图透明度形成上图与下图你中有我、我中有你的那种朦胧感。绘图函数中经常会需要指定背景色、前景色和透明度。

4、形状元素。

(1)点,是线的基础。多点可以连成线。函数:AddPoint

(2)直线,多直线可以连成固定形状。函数:DrawLines

(3)弧线,DrawCurve和DrawBezier。

(4)多边形,函数:DrawPolygon

(5)矩形条状,函数DrawBar

(6)圆角矩形,函数DrawRoundRect

(7)菱形,函数DrawRhombus

(8)箭头,函数DrawArrow 

(9)椭圆,函数:DrawEllipse

(10)扇形,其实也是圆形,函数DrawPie

5、文字。绘制文本,可以有前景色、背景色、字体名称、字号等各种属性,可以计算指定字体属性前提下的相应文本所占位置大小等等。函数DrawText、CalcTextSize、InstallFontPlus

(二)准备一张“白纸”,为所有的绘图做准备。

1、在窗口或控件上绘制。在窗口或控件上绘制内容,并不象我们想像的那么容易,下面我简称UI绘制。UI绘制由操作系统负责调度,什么时候需要绘制,什么时候不需要绘制,完全由操作系统管理、控制,所以,我们只能响应操作系统的绘制请求,做出正确绘制,才是有效的,否则绘制无效,看不到结果。

UI有背景擦除时,操作系统会发送WM_ERASEBKGND消息,有刷新绘制需求时,会发送WM_PAINT消息。作为控件绘图,我们默认忽略WM_ERASEBKGND消息,只响应WM_PAINT消息就可以了。具体到PB里面,有个pbm_paint消息对应于WM_PAINT。但是,这个消息与其他消息不同,这个消息只能响应一次,PB内部因绘制需要已响应过一次,我们再去自定义事件响应这个消息是无效的。因此,uo_painter提供了SetCanvas函数响应绘制消息。

步骤一、为窗口或可视自定义控件声明一个实例变量

uo_painter p;

步骤二、open事件,或者的Constructor事件里对控件实例化,并且将当前UI对象变成可响应消息画板:

p = create uo_painter;

p. SetCanvas(this,”ue_paint”);

步骤三、close事件,或者的Destructor事件里销毁实例,释放资源

destroy p;

步骤四然后再给这个窗口或控件添加一个事件,命名为ue_paint,给它一个 ulong类型的参数,命名为hdc。

经过以上4个步骤,当前窗口或控件就具备在ue_paint事件里响应绘制动作,并且显示绘制效果即可。我们可以直接使用 hdc 参数:

p.BeginPaint(hdc,RGB(255,255,255))  //以白色背景开始绘制

………. //接下来可以完成自己的绘制任务

由于Uo_painter采用了双缓存绘图机制,这时候绘制的内容实际上是在内存里创建的一个虚拟屏幕上,我们要将内容显示到实际hdc上,最后还必要须:

p. EndPaint() //将绘制内容刷新到物理屏幕上,形成可视效果

2、在现在图片上绘制。前面我们说过缓存存图,在这个基础上进行图片绘制。可以在一张图片上添加水印、文字等。

Long li_image

Li_image = p.CacheImage(“back.bmp”) //加载一张图开缓存

p. BeginPaintImage(li_image) //以上面加载的图为底图,开始绘制

………. //接下来可以完成自己的绘制任务

p. SaveMemoryImage (“new.bmp”) //将内容另存为图,释放资源

或者

Blob pic

Pic = p.GetMemoryImage(“jpg”) //以JPG格式返回BLOB数据,自己另行使用。

p.RemoveImage(li_image) //原背景不用了要释放掉

3、开启空白图片进行绘制。可以开启一张底色为指定颜色的空白图片,然后在这个基础上绘制,就和系统的画图工具一样的功能。

p. BeginPaintImage(400,600,RGB(255,255,255)) //开启一张宽400高600背景色为白色的空白图

………. //接下来可以完成自己的绘制任务

或者

Blob pic

Pic = p.GetMemoryImage(“jpg”) //以JPG格式返回BLOB数据,自己另行使用。

(三)绘图命令

具体绘图命令,就不一一介绍了,可以直接打开 uo_painter对象,切换到Local External Functions看函数声明,都有具体中文注释。

有一点请注意,图片处理同时支持文件操作和内存BLOB操作,不是必须要存为文件或者从文件加载。甚至直接支持打开图片base64编码,内部自动进行解码还原为图片数据。

(四)一些常用功能示例操作

1、图片格式转换

uo_painter p; p = create uo_painter

long image

image = p.CacheImage(“test.bmp”) //加载原图

p.SaveImage(image,”test.png”) //另存为png格式

p.SaveImage(image,”test.jpg”) //另存为jpg格式

p.RemoveImage(image)

destroy p

2、图片缩放

uo_painter p; p = create uo_painter

long image1,image2

image1 = p. CacheImageThumb (“test.bmp”,200,0.5) //加载图片,透明度为200,宽和高缩小50%

image2 = p. CacheImageThumb (“test.bmp”,200,1.5) //加载图片,透明度为200,宽和高放大150%

p.SaveImage(image1,”test.png”)

p.SaveImage(image,2”test.jpg”)

p.RemoveImage(image1)

p.RemoveImage(image2)

destroy p

3、图片拼接

将a.bmp和b.bmp按左右方式进行拼接,生成新图

uo_painter p; p = create uo_painter

long a,b

int width,height,wa,ha,wb,hb

a = p. CacheImage ("a.bmp") //加载图片

b = p. CacheImage ("b.bmp") //加载图片

p.GetImageSize(a,wa,ha) //获取A图片大小

p.GetImageSize(b,wb,hb) //获取图片大小

width = wa + wb //计算合并后的宽度

height = ha

if ha < hb then height = hb //以最大高度为新图片的高度

p.BeginPaintImage(width,height,RGB(255,255,255)) //开启一张新图

p.DrawImage(0,(height - ha)/2,wa,ha,a,0) //把A图片绘制到指定位置

p.DrawImage(wa,(height - hb)/2,wb,hb,b,0) //把B图片绘制到指定位置

p.SaveMemoryImage ("c.png") //合并后的图片另存为c.png

p.RemoveImage(a)

p.RemoveImage(b)

destroy p

合并后效果如下:

4、图片拼接2

Uo_painter也提供了现成拼接函数

uo_painter p; p = create uo_painter

p. MergeImageInit(8, 0, true, 2, 1, RGB(255,255,255), “back.jpg”, 180, false,”c.png”)//边距为8,边距有效,2行,2列,背景为白色,背景图片back.jpg透明度为180,不进行缩放,拼完后存为c.png

p. MergeImageAdd(1, 1, 1, 1, “a.bmp”,255,0)  //添加b.bmp放到第1行第1列,只占1行1列范围

p. MergeImageAdd(2, 1, 1, 1, “hd.png”,255,0) //添加b.bmp放到第2行第1列,只占1行1列范围

p. MergeImage()//完成合并

destroy p

效果如下图

5、图片上写字和加水印

uo_painter p; p = create uo_painter

long image,water,dzz

int width,height

image = p.cacheImage("tmp/f.jpg")

water = p.cacheImage("tmp/hd.png")

dzz   = p.cacheImage("tmp/dzz.png")

p.GetImageSize(image,width,height)

p.BeginPaintImage(image)

p.DrawImage(200,236,64,64,water,0)

p.DrawImage(8,height - 84,84,84,dzz,0)

p.DrawText(0,8,width,32,"漂亮美女人人爱","黑体",28,RGB(250,250,250),1)

p.DrawText(0,height - 38,width,32,string(datetime(today(),now()),"yyyy-mm-dd hh:mm_ss"),"黑体",28,RGB(255,0,0),2)

p.SaveMemoryImage ("tmp/new.png")

p.removeImage(image)

destroy p

效果图如下:

6、更多其他功能,请加参考 PbIdea DEMO 之uo_painter部分。

                                              大自在 于2022年元旦假日

                                            QQ:781770213 QQ群:624409252

猜你喜欢

转载自blog.csdn.net/lxbin2003/article/details/122290643