作者:李永春 msn:[email protected]转贴请写明出处 欢迎指正
1.1课题研制背景
随着国民经济社会信息化的发展,各企事业单位每天都要产生越来越多的大量业务单证,银行票据、保险报单、税务税单、政府文件、人事档案、法院诉讼、医院病历等面临着保存、分类、归档和查询的困难,同时还有大批的历史文档有待整理。而传统的手工处理方式存在如下问题:很容易令文档纸张污损或丢失;单位内各层次人员及客户很难对文档资料进行调阅和共享;由于手工查阅方式注定了效率不能跟上日益增长的“客户满意”的需求。
??? 图像存储主要针对各种单据、文件、传票、报表原件、法律文裆等以图像的形式进行存储。是替代传统的纸张、微缩胶片的一种全新概念。它利用图象采集设备把文档原件的图像信息存储转化成计算机可识别的数字信息,压缩处理后,存储到海量存储设备中,实现海量数据的在线存储。其特点是便于管理、查询,降低了存储成本。并利用计算机网络,通过打印机输出,也可以通过传真或电子邮件发出。其优点是图片以其形象性、纪实性、鲜明性特点比文字更能真实地反映现实生活,它能冲破语言和文字的隔阂,而为不同民族、不同文化程度的人们了解和喜爱。因此图像存储管理系统的应用需求日益迫切。?????
1.2课题研究现状分析
现在图像存储已应用于现代社会的许多领域。在所有这些领域中的使用方法和技术都很相似,下面列举若干研究现状分析的例子。
(1)卫星成像:地球或其他行星表面的图片是由宇宙飞船和人造卫星携带的摄像机拍摄得到。拍摄其他行星的图像的目的是研究它们的表面以便探索行星的性质或历史等。利用人造卫星对地球摄像的目的在于气象学、农业、环境保护和军事用途。
(2)空中成像:拍摄地球部分表面的图片,用于调查庄稼的收成或用于绘制地图等。
(3)打印和手写:识别打印的或手写的文字是图像处理的最早应用之一。自动阅读邮政编码和银行支票即为其应用例子。
(4)条形码:大多数超市的收银台上有一种设备,它能阅读并解释产品上的条形码。条形码也用于识别文件、生化样本和医院中的组织标本。
(5)放射学:在医学领域,放射学是图像处理技术的主要应用之一(参阅第9章)。不仅仅在常规X线检查中使用,其他如计算机断层扫描(CT)、磁共振成像(MRI)、正电子发射断层摄影术(PET)和超声诊断的成像过程中获得的许多图像都需要进行解释。在这些应用中,三维重建是特别感兴趣的主题。
(6)染色体:因为染色体图像具有相对简单的结构,染色体配对和染色体核型的自动化确定是图像处理在医学中的最早应用。
(7)胞学和组织学:显微镜成像(细胞和组织)的自动化或定量解释也是早期应用的例子
1.3本课题研究的应用前景
?? 可以应用在各行各业。尤其在医疗,档案管理,文物保护,生物,指纹鉴别系统,卫星领域等,目前这一应用主要集中在大量原始文件需要存储的领域,比如银行、税务单位的票据存储,机械行业的CAD图纸,植物图像数据库,医疗等
2.1 图像存储原理
从结构上讲,图形文件分为两种,即位图和矢量图。在位图中,图像由许多的屏幕小点(我们通常说的像素)组成,这些小点对应显存中的“位”,而就是这些“位”决定了像素的图形属性,如像素的颜色、灰度、明暗对比度等。当一个像素所占的位数多时,它所能表现的颜色就更多、更丰富,从整体上看,图像的色彩就更艳丽,分辨率就更高。位图中所分的二位图、八位图等正是指像素所占的位数。当位图被放大或缩小时,由于像素的数量没有改变,图像的分辨率就会降低,图像的外观自然就大打折扣。相信朋友们在Word或WPS当中插入图像,安排图文结构时,或多或少都会遇到这种情况。就这方面来看,位图的缺点是显而易见的——分辨率的固定导致大分辨率的清晰图像占用大量空间;像素的分散性使动态图像的表达显得困难,例如看VCD时出现马赛克现象,就是像素丢失造成的。
因此,研究人员开发出一种新的图形格式——矢量图。顾名思义,矢量图就是用矢量代替位图中的“位”。简单说来,矢量图不再给图的全部像素作统一的标记,而是用矢量给图的几何部分作标记。例如,一幅矢量图是绿色背景上,有一个黑色的圆圈。它的表达方式是先用语句调用调色板描述背景,再用带矢量的数学公式来描述圆圈的大小、形状等,这就使得图形的放大、缩小和移动变得十分简单,仅仅把公式中的矢量变量改一改就可以了,可以说矢量图的优点是很多的:能无限放大、缩小而不失真;不需要将图像每一点的状态记录下来,因而比相同质量和大小的位图占用的空间少得多,它甚至可以方便地通过更改内部公式制作动画,比位图省事多了。像Flash和CorelDraw等就是这样。
多样化的图像存储方式
我们现在所用的各式各样的图像存储方式,归根到底都离不开上面提到的两种最基本的原理。下面我就现在大家常见的几种图形存储方式作一个肤浅的介绍。
???
BMP(BitMap)——位图老祖宗
到现在为止,BMP还是Windows图形界面的基本构件之一,现在Windows的桌面依旧离不开它。BMP的颜色模式分为四种:2位(黑白)、4位(16色)、8位(256色)、24位(65535色)。由于这种格式无压缩,所以体积巨大。一张640×480的图,若色彩丰富的话,可高达1M~2M。即便如此,到现在它还得到不少人青睐的原因是,它不会丢失任何的图像细节,哪怕是一个细小的点,十分适合对图像要求严格的行业使用。
JPG、JPEG(Joined Photographic Experts Group)——静态图像专家组
这是位图的另一种。还记得当初第一次见到JPG格式时的情景——目瞪口呆,它竟能把一幅1.05M的BMP图压缩成119K,并且在显示器上看,和原来的没什么不同。这就是JPEG格式的过人之处,它提供2:1到40:1的压缩比例,在8×8面积像素单元内进行压缩,当单元颜色值较单一时,则输出一种颜色,也就是说,它在压缩时只储存单元内相差较大的颜色值,随着压缩比例的上升,这一储存值便相应减少,利用人的视觉的灵敏度,将一些常人不易察觉的颜色变化略去。因此,在使用相同压缩比的条件下,一些颜色较单一的图像失真度较少,相反的就大一些。所以朋友们在制作使用JPEG图时,不妨多试几次不同的压缩率,以找到压缩率与失真度之间的最佳结合点。一般说来,JPEG格式的位图可获得10:1的压缩率而我们却不觉得它有失真现象。凭借此两大法宝,JPG、 JPEG广泛应用于各种领域,尤其在因特网上,可以说它对缩减网页的大小功不可没。(JPEG格式的^03020101a^像)
GIF——动态位图开国元老
GIF包括三种格式,均为8位位图,最大支持256种颜色。一种是静态的GIF图,数据经过一定的压缩。另外两种是GIF89a和GIF87a。支持动画格式和透明效果,压缩方式与静态GIF图类似,可说是GIF的延续,但是由于它对颜色的支持不是很丰富,所以不论是动态的还是静态的GIF图,它都会使用真彩色的图像失真。因此,动态GIF图一般仅在网页中存在,而静态GIF图在JPEG及下面将提到的PNG格式的双重夹击下,越来越少人使用了。
PNG——GIF补丁版
PNG是一种较新的位图格式,比较少人用,由于它与GIF格式相类似,支持透明格式,可惜并不支持动画效果,但最大可支持24位真彩色,多少弥补了静态GIF的不足。PNG格式的压缩算法有其独到之处,对8位及以下位图的压缩能力比JPEG的压缩算法要好。在肉眼观察失真度相当的情况下,JPEG格式仅有20~25:1,某些8位图片用PNG格式存储可达40~50:1的压缩比!可见以前的JPEG还没有到孤独求败的地步。但是,用PNG格式储存24位真彩图时,由于其要保留对透明格式的支持,状况惨不忍睹,文件比BMP格式的还大,难以想像它是怎么计算的。
TIF、TIFF(Taggered Image File Format)——标记图像文件格式
TIF、TIFF主要用于页面排版的一种位图格式,用LZW编码压缩(与ARJ齐名的压缩方式),压缩比为2:1,这种格式通常使用在OCR软件识别扫描文档的存储中。
PCD ——PhotoShop 的专利
PhotoShop专用的位图储存格式,可以说,它的保真度和BMP没什么两样,但是因为它要记录层,而且每一个层就是一幅等大小的图像,体积自然就比BMP大多了。不过正是因为这个层的存在,使得它可以存储许多BMP所不能存储的效果,因此很多美工、图像编辑人员用它来存储作品。
WMF——Windows位元文件
Windows自定义的一种矢量图格式,Office剪辑库中的图形就使用这种格式。
CDR——另一种选择
CorelDRAW系列软件定义的矢量图格式,可导入位图并进行压缩。与其相似的还有PhotoShop、FreeHand等软件各自定义的矢量图格式,由于各自的压缩算法不同,只有在未压缩的情况下才能相互调用。
另外,还有一些常见但不常用的图形格式,如PCX、PIC、TAG等,这里就不再多说了
图像存储设计实现
3.1? 图像的存储策略
在数据库的开发过程中,经常需要在数据库中存储一些备注信息,而这些备注信息的内容一般较大,格式多样-如有可能是语音文件、视频文件、图片文件、文本文件等,怎样实现这些格式不同的备注文件的存取及预览,一直是开发人员比较关心的一个问题,本文系统的介绍了三种存取备注二进制信息的方法。?
对备注二进制信息的存储可以采用以下三种方式;?
方法一:文件保存在固定的路径下,数据库中存取文件路径和名称?
方法二:数据库中用blob类型或者varbinary类型字段存储备注文件
???? 方法三:在本地用PowerBuilder的OLE存储结构存储备注文件
三种方法的优缺点?
??? 方法一:文件保存在固定的路径下,数据库中存取文件路径和名称可以节省数据空间,避免了数据库过分膨胀,但备注文件必须在一定的目录下,不能丢失,且同一目录下文件不能重名,对文件的管理造成一定的困难,另外,在OLE控件中浏览显示备注文件时,由于每次都要调用服务器程序,所以速度较慢。?
??? 方法二:在数据库中用blob类型或者varbinary类型字段存储备注文件,当文件存储在数据库中以后,就可以删除硬盘上原来的临时文件,不需要复杂的二进制文件管理,且数据库可以存储在网络服务器上,对数据的共享非常方便。?
?? 方法三:在本地用OLE存储结构存储备注文件。可以把所有的二进制文件信息存储在一个OLE存储文件中,管理比较方便。当二进制文件信息存储后,可以删除原来的临时文件;因为打开存储文件后不需要每次执行服务器程序来显示存储信息,所以存取速度较快。?
?
3.2? SQL Server 2000存储图像数据库设计
图像数据库技术一直致力于解决海量数字图像的有效存储和管理问题。它是数据库技术的继承和发展,一方面,图像数据和文本数据存在着本质的区别,在文本数据领域得以成功应用的传统数据库技术,如果一成不变的照搬到图像数据库领域,结果往往是低效,甚至无效;另一方面,传统数据库的许多成果,如SQL语言、索引技术等都值得图像数据库借鉴。上述两个方面的结合成为目前图像数据库技术发展的主流。
1.1 BLOB数据类型
??? BLOB是非常巨大的不定的二进制或者字符型数据,通常是文档(.txt、.doc)和图片(.jpeg、.gif、.bmp),它可以存储在数据库中。在SQL Server中,BLOB可以是text、ntext或者image数据类型。 Image数据类型存储的是长度不确定的二进制数据,最大长度是2GB。
??? BLOB数据在SQL Server系统中的存储方式不同于普通的数据类型,对于普通类型的数据系统直接在用户定义的字段上存储数据值,而对于BLOB类型数据,系统开辟新的存储页面来存放这些数据,表中BLOB类型数据字段存放的仅是一个16个字节的指针,该指针指向存放该条记录的BLOB数据的页面。
1.2 BLOB的设计策略
??? BLOB数据是数据量很大的数据类型,它会占用大量的硬盘空间、内存和网络资源,因此合理地设计包含有BLOB数据类型的属性表,对提高存储效率、查询速度有很大的影响。一般BLOB的设计原则如下:
(1) 使用BLOB数据类型还是使用varchar或者varbinary数据类型
??? 二进制大对象并不一定要存储为text、ntext或者image数据类型,它们也可以作为varchar或者varbinary数据类型村处在表格中。数据类型的选择要根据将要存储的BLOB的实际大小。如果数据不会超过8K,那么就使用Varchar或者varbinary数据类型。如果这些大对象的尺寸超过8K,那么就使用text、ntext或者image数据类型。
(2) 存储BLOB在数据库中或者在文件系统中
??? 常见的设计问题是将图片存在数据库中还是存在文件系统中。在大多数情况下,最好把图片文件与其它数据一起存在数据库中。因为将影像数据文件存储在数据库中有许多优点:
??? 易于管理 当BLOB与其他数据一起存储在数据库中时,BLOB和表格是数据一起备份和恢复。这样就降低了表格数据与BLOB数据不同步的机会,而且降低了其他用户无意中删除了文件系统中BLOB数据位置的路径和风险。另外,将数据存储在数据库中BLOB和其他数据的插入、更新和删除都在同一个事务中实现。这样就确保了数据的一致性和文件与数据库之间的一致性。还有一点好处是不需要为文件系统中的文件单独设置安全性。
??? 可伸缩性 尽管文件系统被设计为能够处理大量不同大小的对象,但是文件系统不能对大量小文件进行优化。在这种情况下,数据库系统可以进行优化。
??? 可用性 数据库具有比文件系统更多的可用性。数据库复制允许在分布式环境中复制、分配和潜在的修改数据。在主系统失效的情况下,日志转移提供了保留数据库备用副本的方法。
?? 当然,在某些情况下,将图片存储在文件系统中将是更好的选择:
(1)使用图片的应用程序需要数据流性能,例如实时的视频重现。
(2)象Microsoft PhotoDraw或者Adobe Photoshop这样的应用程序经常访问BLOB,这些应用程序只知道怎样访问文件。
(3)需要使用一些NTFS文件系统中的特殊功能,例如远程存储。
1.3 存储图像数据的方法
建立具有image宇段的SQL Server数据库
??? 当需要在SQL Server数据库中存储图像数据时,首先应建立包含image数据类型字段的数据库关系表。SQL Server数据库平台支持的数据类型中,image数据类型主要用于存储图像数据等大段的二进制数据。SQL Server 7.0之后的版本,image类型可存储2GB的数据。
随着SQL Serve数据库管理系统功能的不断增强、性能的不断完善,将各类数据完全由数据库管理系统统一存储和管理,已成为技术发展的趋势。只有这样,SQL Serve数据库管理系统的强大功能才能得到充分发挥,数据的安全性才能得到充分的保障,使得诸如数据库复制、数据的转移等许多工作,变得非常简单容易。
?
3.3? PowerBuilder图像的存储技术
在Powerbuilder程序中有时要用到图象文件,比如人事系统中人员的相片、用扫描仪扫描进去的人事档案等等。但在Powerbuilder中,没有直接的方法将BMP文件读入内存并显示或写入到数据库中。但Powerbuilder支持二进制文件的读写操作,可将BMP文件整个读入BLOB类型的变量中来实现,现在经下面两个例子来讲解
一、在PowerBuilder中利用Picture控件存储及显示图像
步骤如下:
1 取得位图文件名。
2 取得文件长度。
计算要用fileread函数读文件的次数(一次最多只能读32K数据)
3 打开文件
使用FOR循环将文件中的数据读入到BLOB变量中
4 建立一Picture控件
5 使用SetPicture函数显示图象
现在编写程序代码
PowerBuilder要求每个应用程序的启动(Open)事件中具有一定代码,进入应用程序绘图器,在此例中我们为pic应用程序的Open事件中添加以下代码:
open(w_pic) //打开程序窗口
在W_pic窗体中建立一个“选择并显示位图”的按纽控件和建立P_1(Picture控件)
在“选择位图”的按纽控件的“open”事件中写入如下代码:
?? /* 本 段 代 码 将 读 取 一 个 超 过327680字 节 的 文 件, 这 个代 码 可 以 用 以 读 取Text 文 本 和Bitmap 图 象。*/
(“//------ //*****” 中间为注解的内容)
String Ls_path,ls_file,ls_parms,ls_dir,ls_command
integer ls_num,ls_cs,i
integer fh, ret
blob is_pic_blob
blob ls_blob //必须指明ls_blob的大小
string defext = "BMP"
string Filter = "bitmap Files (*.bmp), *.bmp"
ulong nbr,ls_len
ret = GetFileOpenName("Open Bitmap", ls_path,ls_name, defext, filter) //选择获取打开的位图文件
IF ret = 1 THEN
ls_len=filelength(ls_path) //取得文件的字节长度
//------计算出读取文件的次数
ls_cs=ls_len/(32*1024)
if mod(ls_len,32)=0 then
else
ls_cs=ls_cs+1
end if
//*****
ls_num=FileOpen(ls_path,StreamMode!) //打开选取的文件
//------循环将文件中的数据读入到BLOB变量中
IF ls_num >?32765 THEN
nbr=1
for i=1 to ls_cs
fileread(ls_num,is_pic_blob)
nbr = BlobEdit(ls_blob,nbr,is_pic_blob)
next
//*****
p_1.SetPicture(ls_blob) //显示位图
FileClose(ls_num)
end if
END IF
在程序中将照片存入数据库之中
数据库进行写入和后台数据库有关:以SQL Server 2000为例:一般用 UPDATEBLOB 和 SELECTBLOB 两个SQL语句来实现。 在本例中我们只是简单地执行位图的存入与取出操作,所以程序窗口也比较简单。其功能是通过“位图入库”按纽来选择写入数据库的图象,写入数据库的图象可以通过点击一旁的便列表来显视。
首先在应用脚本中连数据库及运动运行窗口:
open(w_pic)
在W_pic窗体中建立一个“位图入库”的按纽控件,数据窗口控件(用于选择显视的图片)和建立P_1(Picture控件)
在窗体W_pic的"OPEN"脚本中写入:
dw_1.settransobject(sqlca)
dw_1.retrieve()
在“位图入图”的按纽控件的“click"脚本中写入:
String Ls_path,ls_file,ls_parms,ls_dir,ls_command
integer ls_num,ls_cs,i
integer fh, ret
blob ls_blob
//-----选取图片进个BLOB类型的变量,这里读取的图片不大于32K
string defext = "BMP"
string Filter = "bitmap Files (*.bmp), *.bmp"
ulong nbr,ls_len,nbr1
ret = GetFileOpenName("Open Bitmap", ls_path,ls_file, defext, filter)
IF ret = 1 THEN
ls_num=FileOpen(ls_path,StreamMode!)
IF ls_num$#@60;$#@62; -1 THEN
fileread(ls_num,ls_blob)
FileClose(ls_num)
end if
END IF
//*******
//取得序列号
SELECT num
INTO :i
FROM number
where no=1
using sqlca;
//新增一条记录
INSERT INTO pic
( no )
VALUES ( :i ) using sqlca ;
//图片写入数据库
UPDATEBLOB pic
SET pics=:ls_blob
WHERE no=:i
using sqlca;
i=i+1
update number
set num=:i
where no=1
using sqlca;
dw_1.retrieve()
在“数据窗口DW_1”的按纽控件的“doubleclick"脚本中写入(实现显示双击选中的图片):
blob ls_blob
int i
i=int(this.getrow())
if i$#@62;0 then
messagebox("","fffff")
SELECTblob pics
INTO :ls_blob
FROM pic where no=:i using sqlca ;
messagebox(string(sqlca.sqlcode),string(len(ls_blob)))
p_1.SetPicture(ls_blob)
end if
二、在PowerBuilder中利用用OLE存取blob类型数据
1、? OLE的基本概念?
??? OLE是Object?Linking?Embedding(对象链结与嵌入)的缩写,它可以使windows应用程序共享数据和程序。?OLE控件?
在PB中OLE控件是一个OLE对象的包容器,可以使用服务器应用程序提供的功能和命令来编辑对象,也可以使用自动化OLE交互,在程序中激活对象和向服务器应用程序发送命令;在PB?的window画板中的OLE控件允许用户从多个应用程序嵌入和链结组件?
?? 2.1建立和设置OLE控件?
从window画板中选择OLE控件插入window。?
??? 当建立一个OLE控件并且插入一个对象时,PB将激活服务器应用程序以允许对对象进行编辑和修改;在使OLE中的对象称为非活动状态后,可以使用控件属性选项卡来设置控件的属性。?
??? 2.2?激活修改window画板中的OLE对象?
?? 在OLE控件的弹出菜单中选择open可以激活画板中OLE对象?
?? 使用服务器应用程序修改OLE对象?结束修改:使对象恢复为非活动状态,只要单击服务器应用对象之外的任何区域即可,也可以直接关闭服务器应用程序的窗口。?
? 2.3?嵌入和链结OLE控件?
?? 可以将OLE对象嵌入或者链结到自己的应用程序中。嵌入对象的数据放在应用程序中,在开发过程中这些数据放在应用程序的PBl库中,当生成应用后,这些数据将存放在exe或PBd文件中,虽然在程序的运行过程中可以修改,但修改的数据不会保存;链结对象的数据存放在PB应用程序以外,当链结一个对象时,在PB应用程序中不存放数据文件,而是存放引用数据的指针,?使用链结的数据,对数据的管理和保存都由服务器应用程序负责。这样可以用服务器应用程序修改处理数据,处理后的数据可以保存回原文件中。链结方式应用于需要多个应用程序共享的数据文件,任何一个应用程序修改了数据文件,都将影响到所有链结该文件的应用程序。?
?? 2.4?OLE控件的激活方式?
??? OLE控件的激活方式有offsite和in-place两种激活方式,offsite激活方式是指在PB应用程序的界面以外单独打开OLE对象,in-place激活方式是指PB应用程序的界面的原位置打开OLE对象。在数据窗口中的dbOLE默认的是offsite激活方式,而window中的OLE默认的激活方式是in-place。?
?在PB应用程序中可以用命令?
?? OLE_control.active(offsite)?或者OLE_control.active(in-place)设置OLE对象的以何种方式打开。?
? 2.5?设置和插入OLE对象?
? 在程序运行时可以用函数:?
? OLE_control.insertfile(soucefile)?插入象
??OLE_control.objectdata?=?blobvar?设置对象?
3、OLE存储?
3.1?OLE存储(OLEstorage)的概念?
??? OLE存储(OLEstorage)是OLE数据的一个仓库,存储就象磁盘上的目录结构,它可以是一个OLE对象,也可以包含在OLE对象中,每个对象都包含在OLE存储或者存储内的子存储内。保存在OLE存储中数据称作OLE流(OLE?stream),OLE流同OLE对象的关系就象文件同目录的关系。含有OLE对象的存储或子存储可以看做是属于特殊服务器的信息,在该层次之下的各部分都可以被相应的服务器程序操作。OLE存储对象是类用户对象,可以说明相应类型的变量,建立与之相应的实例和打开存储等,在使用完存储后需要关闭存储、释放分配的内存。
3.2?OLE存储的打开和保存?
? OLE存储可以用open函数打开,open函数的格式为:?
? Olecontrol.Open(OLEsourcefile),?
? 此函数在OLEsourcefile不存在时,自动创建该文件,所以创建OLE文件也用该函数;?OLE存储可以用save函数保存,save函数的格式为:
OLEcontrol.save()?//?保存OLE控件?
? OLEstorage.save()?//保存OLE存储?
4、处理blob类型数据?
对于大二进制数据,在PB?Script中是用blob数据类型表示并加以处理。标准SQL语句中的select、insert和update语句无法直接查询blob类型的数据,在PB中操作blob类型的数据只能用专用的语句,从数据库中查询blob类型的数据的命令是:?
selectblob?restofselectstatement?{using?transactionobject};?
//更新数据库中blob类型数据的格式是:?
updateblob?tablename?
set?blobcolumn?=?blobvarible?
restofupatestatement?{using?transctionobject};?
如连接的数据库是sybase或者Server 2000,则selectblob和updateblob语句要求数据库的自动提交方式为true,所以在在每次调用selectblob和updateblob语句以前必须用命令?Sqlca.autocommit=true,把数据库的自动提交方式设置为true,在updateblob语句的结束后,再用命令Sqlca.autocommit?=?false,把自动提交方式设置为false。?索数据的参数(如flag),然后在可修改列的Protect后的框中输入(user_name是该DataWindow中的一列,代表输入者的名称):?
5、数据窗口的blob列?
? 5.1?数据窗口blob列的功能?
??? 在PB?的datawindow画板中DBOLE控件允许用户利用这个控件浏览和操作数据库中的大二进制数据,即通过DBOLE控件可以作如下操作:?
??? 往数据库中存储大二进制数据,如:excel工作表、word文档、视频文件、图片文件等各种格式的文件;?
●?从数据库中检索数据到datawindow对象;?
●?使用OLE服务器程序察看修改数据;?
●?将修改后的数据保存回数据库;?
5.2?在数据窗口中添加blob列的的步骤?
1)?选择具有二进制字段的数据表作为数据源建立一新的数据窗口(该窗口可以至少需要包含非数据库表的标识列)?
??? 2)?选择insert?-control-OLE?database?blob?菜单,在数据窗口的detail节中要插入blob列的位置单击鼠标,这时将显示如图1所示的对话框?
?? 下面解释这些属性的具体含义?
1)?client?class:?客户类名,默认为datawindow?
2)?client?name:客户名,默认为untitled?
3)?table:?选择含有blob列的数据库表,所选表的字段将出现在右侧的large?binary/text?column列表框中。?
4)?large?binary/text?column:选择一个blob类型的字段列?
5)?key?clause:检索和更新blob数据的关键字表达式其中使用带冒号前缀的变量指出是数据窗口对象的列,如?表达式?id=:id,id是数据库表中的列,变量指出数据窗口对象的列?
6)?filetemplate?:如果需要OLE应用服务器每次打开相同的文件,则在filetemplate框中输入文件名。?
7)?OLE?class?:如果不需要OLE应用服务器每次打开相同的文件,则在OLE?class框中选择一个OLE类,如Pbrush。?
8)?Client?name?expression:显示在OLE服务器应用程序窗口标题的文字,可以输入为:"对应记录的id号是"+id?
单击ok按钮关闭对话框,将dbole列添加到适当的位置,保存数据窗口。?预览则可以对数据库中的blob数据进行存取,但是在新建的记录中只能存取OLE?class框中选择的一种格式的blob数据,不能存储多种格式的数据;但如果数据库中存有多种格式的数据,可以预览各种格式的数据。?
6、源程序建立?
1)?首先在数据库中建立如下结构的表blobsave:?
字段名称数据类型备注?
idchar(4)primairy?key?index?
s_pathchar(50)?
pic?binary?(50)?
2)?在PB建立PBl库blobsave.PBl?
3)?在PBl库blobsave.PBl中建立应用blobsave?
在应用的open事件中设置数据库连接程序(本程序中采用的是odbc方式连接数据库,读者可根据自己所建立的数据库的不同选用不同的连接方式,以下连接数据库的代码也有所改动,至于连接不同的数据库的方法,请参考有关资料,本文不做详细介绍):?
SQLCA.DBMS?=?"ODBC"?
SQLCA.AutoCommit?=?False?
SQLCA.DBParm?=?"Connectstring='DSN=blob'"?
connect;?
open(w_main)?
其中命令按钮cb_path的clicked中的代码格式如下:open(w_path)?
其中命令按钮cb_dbblob的clicked中的代码格式如下:open(w_dbblob)?
其中命令按钮cb_OLEblob的clicked中的代码格式如下:open(w_OLEblob)?
4)?建立数据窗口dw_blobsave?
按照上文中建立数据窗口的blob列的方法建立数据窗口dw_blobsave如图所示:?
其中:add,del,save,cancel,,retrieve等分别为数据窗口dw_blobsave的append?row,delete?row,update,retrieve动作按钮。?
首先创建实例变量?OLEstorage?stor1?
然后如图建立窗口w_path,其中数据窗口控件dw_1的rowfocuschanged中的代码如下:?
long?row_num?
row_num=dw_1.getrow()?
if?row_num?>0?then?
ole_1.insertfile(dw_1.object.s_path[row_num])?
end?if?
其中数据窗口dw_1的buttonclicked中的代码如下:?
if?dwo.name="cbselect"?then?
long?row_num?
row_num=dw_1.getrow()?
string?filepath,filename?
getfileopenname("请选择备注文件",filepath,filename)?
dw_1.object.s_path[row_num]=filepath?
ole_1.insertfile(filepath)?
end?if?
保存窗口w_path?
6)?建立窗口w_dbblob?
打开w_path,把其另存为w_dbblob,改变数据窗口dw_1的rowfocuschanged中的代码如下:?
blob?text1?
long?row_num?
row_num=dw_1.getrow()?
if?row_num>0?then?
string?id?
id?=?dw_1.object.id[row_num]?
sqlca.autocommit=true?
selectblob?pic?into?:text1?from?blobsave?where?id?=?:id;?
ole_1.objectdata=text1?
sqlca.autocommit=false?
end?if?
改变数据窗口dw_1的buttonclicked中的代码如下:?
long?row_num?
if?dwo.name="cbselect"?then?
row_num=dw_1.getrow()?
string?filepath,filename?
getfileopenname("请选择备注文件",filepath,filename)?
dw_1.object.s_path[row_num]=filepath?
ole_1.insertfile(filepath)?
end?if?
if?dwo.name="cbsave"?then?
string?id?
sqlca.autocommit?=?true
blob?text1?
text1?=?ole_1.objectdata?
dw_1.update()?
commit;?
row_num=dw_1.getrow()?
id=dw_1.object.id[row_num]?
updateblob?blobsave?
set?pic?=?:text1?
where?id?=?:id?;?
commit;?
sqlca.autocommit?=?FALSE?
dw_1.retrieve()?
dw_1.scrolltorow(row_num)?
end?if?
保存窗口w_dbblob
7)?建立窗口w_OLEblob?
打开w_path,把其另存为w_OLEblob,在窗口w_OLEblob的open事件中写入以下代码:?
stor1?=?create?olestorage?
stor1.open("c:/p1.ole")?//打开或创建ole文件?
在窗口w_OLEblob的close事件中写入以下代码:?
destroy?stor1
改变数据窗口dw_1的rowfocuschanged中的代码如下:?
blob?text1?
long?row_num?
row_num=dw_1.getrow()?
if?row_num>0?then?
string?id?
id?=?dw_1.object.id[row_num]?
ole_1.open(stor1,"w"+id)?
end?if?
改变数据窗口dw_1的buttonclicked中的代码如下:?
long?row_num?
if?dwo.name="cbselect"?then?
row_num=dw_1.getrow()?
string?filepath,filename?
getfileopenname("请选择备注文件",filepath,filename)?
dw_1.object.s_path[row_num]=filepath?
ole_1.insertfile(filepath)?
end?if?
if?dwo.name="cbsave"?then?
string?id?
row_num=dw_1.getrow()?
id=dw_1.object.id[row_num]?
ole_1.saveas(stor1,"w"+id)?
stor1.save()?
end?if?
保存窗口w_OLEblob,运行应用程序即可。?
3.4? PowerBuilder图像的扫描存储技术
开发信息管理系统时,常常要处理图象,这也是信息管理系统发展的必然趋势。怎样在PowerBuilder中通过扫描仪获得所需的图象信息呢?不外乎有三种基本的方法:?
1 通过图象处理软件,比如说Photoshop等,通过它们的扫描图象的功能,加工成一定格式的图象后再在自己的系统中利用;?
??? 2通过扫描仪接口Twain.DLL?。该接口是在安装扫描仪时提供的,它实际上是一个Plugin插件,它通过一系列函数来控制扫描仪;?
??? 3通过构件技术来控制扫描仪。?
?? ?利用第一种方法能减少编程的复杂度,但是系统的集成度不高,用户使用上也不方便;第二种方法能在驱动程序级直接控制扫描仪,能在编程上提供最大的灵活性和可控性;第三种方法能充分利用PowerBuilder的可视化构件技术,安全、灵活、自由地利用扫描仪。其实第三种方法也是建立在扫描仪接口Twain.DLL之上的。本文论述的方法就采用第三种。?
?? ?Windows9X中提供了“映象”可选件(Windows2000为Kadak),该附件是采用OCX构件来控制扫描仪的,共有imgEdit、imgAnntool、imgScan、imgAdmin?四个,有这四个构件基本上就能完全控制扫描仪。在PowerBuilder中的用法如下:?
??? 启动PowerBuilder,选择“Component”菜单项下的“Import?ActiveX?Control”,这时可以看到列表中有“Kadak?图象编辑控制、Kadak?图象扫描控制、Kadak?图象管理控制、Kadak?图象缩略图控制”,选中这四项,然后点击“Install”按钮,这时在构件面板上的ActiveX舌标下就可以看到这四个构件的图标。?
----?ImgScan?的主要属性:FileType:图象的文件类型(该构件支持三种:TIFF,BMP,AWD,jpg);?
? long CompressionInfo
? int CompressionType
??????? enum 0 -- NoCompression
??????? enum 1 -- CCITTGroup3_1d_Fax
??????? enum 2 -- CCITTGroup3_1d_ModifiedHuffman
??????? enum 3 -- PackedBits
??????? enum 4 -- CCITTGroup4_2d_Fax
??????? enum 5 -- JPEG
??????? enum 6 -- LZW
? string DestImageControl????????? //扫描图象接收控件名称
? int FileType???????????????????? //编程中不能设置
??????? enum 0 -- TIFF
??????? enum 1 -- AWD_MicrosoftFax
??????? enum 2 -- BMP_Bitmap
??? ????enum 3 -- JPG_File
? string Image??????????????????? //图象文件名
? boolean mULTIpAGE
? long Page
? long PageCount
? int PageOption
??????? enum 0 -- CreateNewFile
??????? enum 1 -- PromptToCreateNewFile
??????? enum 2 -- AppendPages
??????? enum 3 -- InsertPages
??????? enum 4 -- OverwritePages
??????? enum 5 -- PromptToOverwritePages
??????? enum 6 -- OverwriteAllPages
? int PageType????????????????????????? //编程中不能设置
??????? enum 0 -- BlackAndWhite
??????? enum 1 -- Gray16Shades
??????? enum 2 -- Gray256Shades
??????? enum 3 -- Color16Count
??????? enum 4 -- Color256Count
??????? enum 5 -- TrueColor24bit
??????? enum 6 -- HighColor24bit
? int ScanTo
??????? enum 0 -- DisplayOnly
??????? enum 1 -- DisplayAndFile
??????? enum 2 -- FileOnly
??????? enum 3 -- DisplayAndUseFileTemplate
??????? enum 4 -- UseFileTemplateOnly
??????? enum 5 -- FaxOnly
? boolean Scroll
? boolean ShowSetupBeforeScan
? long StatusCode
? boolean StopScanBox
? real Zoom
?
事件:
?
? PageDone(long PageNmuber)
? ScanDone()
? ScanStarted()
? ScanUIDone()
?
函数:
?
? AboutBox()
? long CloseScanner()
? int GetCompressionPreference()
? int GetpageTypeCompressionInfo(int ImageType)
? int GetpageTypeCompressionType(int ImageType)
? string GetVersion()
? long OpenScanner()
? long ResetScanner()
? boolean ScannerAvailable()
? SetExternallmageName(string szImageTitle)
? int SetPageTypeCompressionOpts(int Compref,int ImageType,int CompType,int ompInfo)
? SetScannerName(string szScannerName)
? long ShowScannerSetup()
? long ShowScanNew(any modal)???????? 扫描新图象设置,modal=true
? long ShowScanPage(any modal)
? long showscanPreferences()????????? 参数选择
? long ShowSelectScanner()??????????? 扫描仪选择
? long StartScan()?? 开始扫描
? long StopScan()??? 终止扫描
----?ImgEdit?的属性主要是控制扫描图象的分辨率、图象的宽高、是否允许对图象进行局部选?择等;其方法主要有拷贝、剪切图象到粘贴板,从粘贴板复制图象,旋转、放缩、?镜象图象;打印、保存、刷新图象等。?
----?关于上述四个OCX构件的详细使用说明可在PowerBuilder中查看其自带的帮助系统。?
注:如何在WindowsXP使用Kadak?扫描控件
在装有Win98电脑C:/WINDOWS/SYSTEM目录下的OIPRT400.DLL,OISLB400.DLL
,OISSQ400.DLL,OITWA400.DLL,OIUI400.DLL,IMGCMN.DLL,IMGADMIN.OCX,IMGEDIT.OCX,IMGSCAN.OCX,IMGTHUMB.OCX,OIADM400.DLL,OICOM400.DLL,OIDIS400.DLL,OIFIL400.DLL,OIGFS400.DLL, IMGSHL.DLL, IMGOCXD.HLP。如果找不到装有Win98的电脑,也可从Win98的安装光盘中提取上述文件,用WindowsXP中的搜索功能能很快地从Win98的安装光盘中找到所需文件所在的CAB包,例如IMGADMIN.OCX,IMGEDIT.OCX, IMGSCAN.OCX, IMGTHUMB.OCX等文件就在WIN98_74.CAB中。
??? 接下来需要对OCX文件进行注册,然后映象才能正常运行。为便于以后将其复制到其他WindowsXP上的电脑上运行,不妨在同一目录D:/KODAKIMG下建立一个批处理文件reg.bat, 然后用鼠标右键单击该reg.bat文件对其进行编辑输入以下命令:
regsvr32 imgadmin.ocx
regsvr32 imgedit.ocx
regsvr32 imgscan.ocx
regsvr32 imgthumb.ocx
保存并退出后,运行reb.bat, 屏幕上将出现弹出窗口“imgadmin.ocx中的DllRegisterServer成功”,点击“确定”后将同样依次出现“imgedit.ocx中的DllRegisterServer成功”
3.5? 本章总结
?? 在本章主要具体讲述PowerBuilder方式下的图像存储的关键技术,以及如何实现原理,为开发人员提供了PowerBuilder图像存储案实现的具体方案。,由此可快速建立自己的图像存储平台.
结论
? 通过本课题的研究,深入分析研究了PowerBuilder图像存储所遇的技术要点,并提出了相关的解决方案,
本课题以人事信息管理为研究背景,充分展现了PowerBuilder图像存储所遇的技术要点,通过系统测试,本系统已经达到了设计要求,完成了系统的功能目标和性能需求。基本符合课题的需求,能够适应一般性的扩展。到目前为止,系统尚且没有出现不可预料的错误,测试证明系统是可靠的。
参考文献
[1]柯建勋 《PowerBuilder?8.0基础篇》 2002.6.1?? 清华大学出版社
[2]柯建勋 《PowerBuilder 8.0进阶篇实例与技巧篇》2002.5.1 清华大学出版社
[3]崔巍?? 《PowerBuilder 7.0 参考手册》2000.11.1 ?清华大学出版社
[4]John W.FronckoWiak Edward Whalen Marcilina S.Garci《SQL Server 7.0 系统管理员手册》人民邮电出版社
?[5]丁宝康 《数据库原理》2000? 经济科学出版社
?[6]陆丽娜 《软件工程》 2000 经济科学出版社,
? ?