pb处理图片的问题
不要在程序中使用PB的自带的编辑图片的OLE,用那东西会损坏二进制信息的,我就遇到过图片的问题。所以要是数据库中的图片你用PB自带的OLE编辑过就可能已经损坏,selectblob可能就会出问题(据说OLE会加密图片信息,使得数据库中的图片只能用OLE控件显示和编辑)。解决办法如下:保存图片时,不要使用OLE,而是直接用FileRead()来读取图片文件到一个BLOB变量,再用UPDATEBOLB直接存储到数据库去,这样就不会造成数据被修改。下面是我写的批量读取图片文件的程序,是根据项目代号来读取其对应工程图到数据库的程序,项目代号和工程图是一一对应的。
blob lbl_pic , lbl_tem
string ls_path,ls_xmdh,ls_filename
long ll_loop,ll_count,ll_return,ll_flen,ll_filertn,ll_fopen,ll_fopenrtn
long ll_floop,i,ll_bz
ls_path = trim(sle_path.text) // 除去字符串前后的空格
if ls_path = '' or isnull(ls_path)then
messagebox("提示","对不起,请先选择好图片文件夹路径!")
return
end if
sqlca.autocommit =true
select count(dataxh) into:ll_loop from temp where ljxmdhis not null using gtr_sqlcb ;
ll_count = 0
for ll_count = 1 to ll_loop//循环取刚才导入的数据项目代号名
ls_xmdh = ''
setnull(ll_fopen)
setnull(lbl_pic)
select ljxmdh into :ls_xmdh from temp where dataxh = :ll_count using gtr_sqlcb ;
if ls_xmdh = '' then
continue
else
ls_filename = trim(ls_xmdh) + '.bmp'
ll_flen = FileLength(ls_path + ls_filename)
if ll_flen = -1 then
ll_filertn = messagebox('提示','未找到图片文件:'+ls_filename +'是否继续?',Question!,yesno!)
if ll_filertn = 2 then
return
else
continue
end if
else
if ll_flen > 32765 then
if Mod(ll_flen, 32765) = 0 then
ll_floop = ll_flen/32765
else
ll_floop = (ll_flen/32765) + 1
end if
else
ll_floop = 1
end if
ll_fopen = FileOpen(ls_path + ls_filename, StreamMode!, Read!)
if ll_fopen = -1 then
ll_fopenrtn = messagebox('提示','读取图片文件:'+ls_filename +'失败,是否继续?',Question!,yesno!)
if ll_fopenrtn = 1 then
return
else
continue
end if
else
for i = 1 to ll_floop
FileRead(ll_fopen, lbl_tem)
if i = 1 then
lbl_pic = lbl_tem
else
lbl_pic = lbl_pic + lbl_tem
end if
end for
FileClose(ll_fopen)
end if
end if
end if
UPDATEBLOB pgll_jcsj
SET ljgyjt = :lbl_pic
WHERE ljxmdh = :ls_xmdh
USING sqlca;
end for
if sqlca.sqlcode = 0 then
messagebox('提示','图片数据转换成功!')
commit using sqlca;
else
rollback using sqlca;
messagebox('提示','图片数据转换失败!')
end if
编辑图片时,先生成一个临时图片TEMP.BMP(当然你要是保存的其它格式,如JPG也可以),再调用外部工具,如PHOTOSHOP或WIN画图板等编辑,不要使用OLE!
直接使用API
定义API:Function Long ShellExecuteA(Long hwnd,String lpOperation,String lpFile,String lpParameters, String lpDirectory,Long nShowCmd) Library "shell32.dll"
编辑图片:
long ll_return
if is_bjms = '1' then
ll_return = ShellExecuteA(0,'open',gs_path + "\bmptem\temp.bmp",'','',1)
else
ll_return = ShellExecuteA(0,'edit',gs_path + "\bmptem\temp.bmp",'','',1)
end if
if ll_return = 2 then
messagebox('信息提示','未找到临时文件:'+gs_path + '\bmptem\temp.bmp')
return
elseif ll_return = 31 then
messagebox('信息提示','您还未给位图文件设置编辑工具!')
return
end if
this.enabled = false
ii_bjbs = 1
外部工具打开后,要监控外部程序的状态,同步刷新图片信息。
然后是保存:
long ll_flen,ll_floop,ll_fopen,i
blob lbl_pic,lbl_tem
ii_bjbs = 0
ll_flen = FileLength(gs_path + "\bmptem\temp.bmp")
if ll_flen = -1 then
messagebox('提示','未找到图片文件,保存失败!')
return
else
if ll_flen > 32765 then
if Mod(ll_flen, 32765) = 0 then
ll_floop = ll_flen/32765
else
ll_floop = (ll_flen/32765) + 1
end if
else
ll_floop = 1
end if
ll_fopen = FileOpen(gs_path + "\bmptem\temp.bmp", StreamMode!, Read!)
for i = 1 to ll_floop
FileRead(ll_fopen, lbl_tem)
if i = 1 then
lbl_pic = lbl_tem
else
lbl_pic = lbl_pic + lbl_tem
end if
end for
FileClose(ll_fopen)
end if
UPDATEBLOB pgll_jcsj
SET ljgyjt = :lbl_pic
WHERE ljxmdh = :is_xmdh
USING sqlca;
if sqlca.sqlcode = 0 then
messagebox('提示','保存成功!')
commit;
else
messagebox('提示','保存失败!')
return
end if
保存完成就可以用FileDelete()删除临时图片文件。
显示图片则可以使用数据窗口的DispalyASPicture属性来显示生成的临时图片
使用以上方法处理图片应该不会再有问题。
/////////
在pb中用selectblob取image类型的数据时,在调试的时候发现变量值是空的,还有可能,图片就没有存进数据库,或者数据损坏了。
BlobMid()
功能从Blob变量中提取出一段数据。提取之后,原Blob变量内容不变。
语法BlobMid ( data, n {, length } )
参数data:Blob类型的数据n:指定要提取数据的起始位置,有效值在1到4,294,967,295之间length:可选项,指定要提取数据的长度,以字节为单位,有效值在1到4,294,967,295之间。缺省时提取从指定位置n到末尾的所有数据返回值Blob。函数执行成功时返回指定字节数的数据。如果n的值大于data的字节数,函数返回空。如果n与length的和超过了data数据的字节数,那么BlobMid()函数返回剩下的数据,数据长度将小于参数length的值。如果任何参数的值为NULL,则BlobMid()函数返回NULL。
尽量不要使用blobmid来处理文件,因为返回值有长度限制,而且很不稳定。希望楼主能进一步说清需求,要如何处理图片,大家可以帮你想办法。
//////////////
三楼你说的是怎么样把图片文件显示出来,但是我现在遇到的问题是要从sql数据库中把image类型的数据读出来,并且能够赋给图片控件。注:是大图片
blob bphoto
int id_no=6,len
selectblob photo into :bphoto from phototable where id = :idno using sqlca;
len = len(bphoto)
这条数据的photo字段在数据库中明明有数据,但就是读不出来,调试跟踪时发现lb_photo为空值,len返回为空,用但是换用下面的语句后,
select photo into :bphoto from phototable where id = :idno using sqlca;
len = len(bphoto)
ifmod(len/32765) then
write = mod(len/32765)
else
write = mod(len/32765) + 1
end if
for cnt = to write
btemep = blobmid(bphoto,(write-1)*32765+1,32765)
next
len却有返回值,而且有50000000多字节,然后我就用循环读取数据,但是在执行到blobmid这句时就死机了。
/////////////////
总结如下:
1.
selectblob photo into :bphoto from phototable where id = :idno using sqlca;
这句有问题啊,你的变量是这样定义的:int id_no = 6,但是你的条件是where id = :idno
变量名字写错了啊,不应该是idno ,而应该是 id_no
2.
len变量不要用int类型,int类型的长度太小,可能图片太大越界了,最好使用long型
3.
图片过大会导致数据提取时得不稳定现象,尽量不要存取太大的图像。
4.
直接把blob赋给图片控件是不可能显示出图片的,我已试验过了,我前面也说了,你如果用PB的OLE编辑过图片,把编辑过的数据存在数据库后,图片的二进制数据会被PB串改加密,同样,pb图片控件也只认这种加密后的二进制数据,直接存在数据库的图片显示是有问题的。所以才告诉你要生成临时图片文件来显示。
4.
不明确你的数据库,我使用
selectblob 图片字段 into:BLOB字段 from 图片表
的方法在ORACLE、informix和ASA中都没有出过问题。
如果你使用的SQL Server 数据库
实在不行就把IMAGE字段的字段类型改为TEXT,再试。
下面一段取图片的程序在我的软件了一直很正常,用户使用了很久了:
selectblob ljgyjt into:lb_image from pgll_jcsj
WHERE ljxmdh = :is_xmdh using sqlca;
ll_flen = len(lb_image)
if ll_flen > 32765 then
if Mod(ll_flen, 32765) = 0 then
ll_floop = ll_flen/32765
else
ll_floop = (ll_flen/32765) + 1
end if
else
ll_floop = 1
end if
ll_fopen = FileOpen(gs_path + "\bmptem\temp.bmp", StreamMode!, Write!, Shared! , Append!)
for i = 1 to ll_floop
setnull(lbl_tem)
if i = 1 then
lbl_tem = blobmid(lb_image,1,32765)
else
j = 32765*(i - 1) + 1
if i = ll_floop then
lbl_tem = blobmid(lb_image,j,ll_flen)
else
lbl_tem = blobmid(lb_image,j,j+32765)
end if
end if
FileWrite(ll_fopen, lbl_tem)
end for
FileClose(ll_fopen)
你的图片不要大于32K,不然会超过PB处理的界限。不行就分成几个字段存储。
学习学习!!!! 感謝樓主分享 感謝樓主分享
页:
[1]