好久不搞delphi一搞就出问题.问题解决立刻给分.

风平心境 2010-07-31 09:35:08

{-----------------------------------------------------------------------------
Unit Name: PublicFunction
Author:
Purpose: 图像处理公用函数
History:
-----------------------------------------------------------------------------}

unit PublicFunction;

interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics,Jpeg,GIFImage,Math;
type
TPixels = Array of array of TRGBTriple;
TPixelArray = Array of TRGBTriple;
TPixelChanncle=(tcRed,tcGreen,tcBlue);

procedure GraphicMedianFilter(var bit: TBitmap;matrix_x,matrix_y:integer);
procedure ReadPixelArray(Pic: Tbitmap;rec:TRect; var tPix: TPixelArray);
procedure SortPixelArray(var A: TPixelArray; iLo, iHi: Integer;c:TPixelChanncle );

implementation


{-----------------------------------------------------------------------------
Procedure: ReadPixelArray
Author:
Date: 31-七月-2010
Arguments: Pic: Tbitmap;rec:TRect; var tPix: TPixelArray
Result: None
Description: 读取图片内的矩形区域的像素 返回 TPixelArray 像素-维数组
-----------------------------------------------------------------------------}
procedure ReadPixelArray(Pic: Tbitmap;rec:TRect; var tPix: TPixelArray);
Var PixPtr:PbyteArray;
i,j,m,rec_H,rec_W,n,index,len :Integer;
begin
rec_H:=Min(rec.Bottom,Pic.Height-1);
rec_W:=Min(rec.Right,pic.Width-1);
len:=(rec_H+1-Max(rec.Top,0))*(rec_W+1-Max(rec.Left,0));
SetLength(tPix,len);
Pic.PixelFormat := pf24bit;
Pic.HandleType:=bmDIB;
index:=0;
For i :=Max(rec.Top,0) to rec_H do
begin
PixPtr:=Pic.ScanLine[i];
for j:= Max(rec.Left,0) to rec_W do
begin
m := j*3;
n:= index*rec_H+j;
tPix[n].rgbtBlue := PixPtr[m];
tPix[n].rgbtGreen := PixPtr[m+1];
tPix[n].rgbtRed := PixPtr[m+2];
end;
inc(index);
end;
end;

{-----------------------------------------------------------------------------
Procedure: GraphicMedianFilter
Author:
Date: 31-七月-2010
Arguments: var bit: TBitmap,matrix_x,matrix_y:integer
Result: None
Description: 区域中值滤波 按照:[matrix_x]*[matrix_y]矩阵大小
-----------------------------------------------------------------------------}
procedure GraphicMedianFilter(var bit: TBitmap;matrix_x,matrix_y:integer);
var
x, y: integer;
bitmap: Tbitmap;
p: pbyteArray;
pix:TRGBTriple;
procedure OffsetRect(var r:TRect;x,y:integer);
begin
r.Left :=r.Left +x;
r.Top :=r.Top +y;
r.Bottom:=r.Bottom +y;
r.Right :=r.Right +x;
end;
//求出区域的中值像素
function calMean(x,y:integer):TRGBTriple;
var pixels:TPixelArray;
r:TRect;
rpix:TRGBTriple;
len,x1,y1,n,m:integer;
begin
r:=Rect(x,y,x+matrix_x-1,y+matrix_y-1);
//平移
x1:=Round(matrix_x/2)-1;
y1:=Round(matrix_y/2)-1;
OffsetRect(r,-x1,-y1);

//读矩形内的像素到数组 pixels
ReadPixelArray(bit,r,pixels);

len:=high(pixels);
m:=Round(len/2);
//排序数组并取出中值
SortPixelArray(pixels,0,len,tcRed);
rpix.rgbtRed:=pixels[m].rgbtRed;
SortPixelArray(pixels,0,len,tcGreen);
rpix.rgbtGreen:=pixels[m].rgbtGreen;
SortPixelArray(pixels,0,len,tcBlue);
rpix.rgbtBlue:=pixels[m].rgbtBlue;
setLength(pixels,0);
pixels:=nil;
result:= rpix;
end;
begin
if (matrix_x<3) or (matrix_y<3) then exit;
bitmap:=TBitMap.Create;
bitmap.Assign(bit);
for y := 0 to bitmap.Height - 1 do
begin
P := bitmap.ScanLine[y];
for x := 0 to bitmap.Width - 1 do
begin
pix:= calMean(x,y);
p[3 * x + 2] := pix.rgbtRed;
p[3 * x + 1] := pix.rgbtGreen;
p[3 * x ] := pix.rgbtBlue;
end;
end;
bit.Assign(bitmap);
bitmap.Free;
end;

{-----------------------------------------------------------------------------
Procedure: SortArray
Author:
Date: 31-七月-2010
Arguments: var A: array of Integer; iLo, iHi: Integer;c:TPixelChanncle
Result: None
Description: 像素数组排序
-----------------------------------------------------------------------------}
procedure SortPixelArray(var A: TPixelArray; iLo, iHi: Integer;c:TPixelChanncle );
var
Lo, Hi, Mid, T: Integer;
begin
Lo := iLo;
Hi := iHi;
case c of
tcRed: Mid := A[(Lo + Hi) div 2].rgbtRed;
tcGreen:Mid := A[(Lo + Hi) div 2].rgbtGreen;
tcBlue: Mid := A[(Lo + Hi) div 2].rgbtBlue;
end;
repeat
case c of
tcRed:
begin
while A[Lo].rgbtRed < Mid do Inc(Lo);
while A[Hi].rgbtRed > Mid do Dec(Hi);
if Lo <= Hi then
begin
T := A[Lo].rgbtRed;
A[Lo].rgbtRed := A[Hi].rgbtRed;
A[Hi].rgbtRed := T;
Inc(Lo);
Dec(Hi);
end;
end;
tcGreen:
begin
while A[Lo].rgbtGreen < Mid do Inc(Lo);
while A[Hi].rgbtGreen > Mid do Dec(Hi);
if Lo <= Hi then
begin
T := A[Lo].rgbtGreen;
A[Lo].rgbtGreen := A[Hi].rgbtGreen;
A[Hi].rgbtGreen := T;
Inc(Lo);
Dec(Hi);
end;
end;
tcBlue:
begin
while A[Lo].rgbtBlue < Mid do Inc(Lo);
while A[Hi].rgbtBlue > Mid do Dec(Hi);
if Lo <= Hi then
begin
T := A[Lo].rgbtBlue;
A[Lo].rgbtBlue := A[Hi].rgbtBlue;
A[Hi].rgbtBlue :=T;
Inc(Lo);
Dec(Hi);
end;
end;
end;
until Lo > Hi;
if Hi > iLo then SortPixelArray(A, iLo, Hi,c);
if Lo < iHi then SortPixelArray(A, Lo, iHi,c);
end;
end.


窗口端调用

procedure TForm1.Button9Click(Sender: TObject);
var bmp:TBitmap;
begin
bmp:=TBitmap.Create();
bmp.Assign(image1.Picture.Bitmap);
GraphicMedianFilter(bmp,3,3);
image2.Picture.Bitmap:=bmp;
end;


以上setLength(pixels,0);是出错的地方.地址错误.而且这个错误每张图片都是不固定的.
按正常一个局部动态数组在函数调用结束会调用用_DnyArrayClear清理函数. 错误就发生这个函数: Invalid pointer operation 奇怪.用的好好的,系统清理动态数组就出错.那位好心人帮我调调. 郁闷想多给分都不行



...全文
317 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
风平心境 2010-08-16
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 mwy654321 的回复:]

好久不搞delphi一搞就出问题。

出问题与你是否经常搞delphi无关。
[/Quote]
我也想知道自己的问题出来在哪里?
风平心境 2010-08-16
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 iamduo 的回复:]

if (matrix_x<3) or (matrix_y<3) then exit;
bitmap:=TBitMap.Create;
bitmap.Assign(bit);
for y := 0 to bitmap.Height - 1 do
begin
P := bitmap.ScanLine[y];
for ……
[/Quote]
这个有什么区别吗?
bit.Assign(bitmap);
能所一下原因吗?代码我已经改成TList了. 原来版本就没保存了.不好意思
风平心境 2010-08-16
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 weirdman 的回复:]

前几天我也遇到过相同问题
我的是图片像素读错了,导致存进数组的为空值
所以虽然他提示是setLength(pixels,0)
建议你检查下前面的像素读取有没错误
[/Quote]
像素数组读取是没错的.用这个方法读出来的像素数组实现其他的filter了.我改成TList就没这个问题了.所以才抓狂.
gusman 2010-08-16
  • 打赏
  • 举报
回复
学习!
iamduo 2010-08-03
  • 打赏
  • 举报
回复
if (matrix_x<3) or (matrix_y<3) then exit;
bitmap:=TBitMap.Create;
bitmap.Assign(bit);
for y := 0 to bitmap.Height - 1 do
begin
P := bitmap.ScanLine[y];
for x := 0 to bitmap.Width - 1 do
begin
pix:= calMean(x,y);
p[3 * x + 2] := pix.rgbtRed;
p[3 * x + 1] := pix.rgbtGreen;
p[3 * x ] := pix.rgbtBlue;
end;
end;
bit.Assign(bitmap);
bitmap.Free;


试试看,把bitmap 变量删掉。直接用 bit 是否会错?
无条件为你 2010-08-03
  • 打赏
  • 举报
回复
好久不搞delphi一搞就出问题。

出问题与你是否经常搞delphi无关。
weirdman 2010-08-03
  • 打赏
  • 举报
回复
前几天我也遇到过相同问题
我的是图片像素读错了,导致存进数组的为空值
所以虽然他提示是setLength(pixels,0)
建议你检查下前面的像素读取有没错误
风平心境 2010-08-02
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 wdonghai 的回复:]

楼主去看一下DELPHI数字图像处理这本书中的第五章,里面就有个中值滤波处理
[/Quote] 问题不是在这里.那个不是我想要的代码.
这里主要问题是想知道为什么这样使用动态数组会有这样的错误.
  • 打赏
  • 举报
回复
帮你顶吧,那么多代码不敢看,发现你写的代码好工整!!!!!!!
奔雷手 2010-08-02
  • 打赏
  • 举报
回复
膜拜~~~~
wdonghai 2010-08-02
  • 打赏
  • 举报
回复
楼主去看一下DELPHI数字图像处理这本书中的第五章,里面就有个中值滤波处理
sghff110 2010-08-02
  • 打赏
  • 举报
回复
我也顶一下。
风平心境 2010-08-01
  • 打赏
  • 举报
回复
算了把数组改成Tlist 了. 想必是由于动态数组释放时候它里面的某些项目已经释放了.
风平心境 2010-08-01
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 sqldebug_fan 的回复:]
PixPtr:PbyteArray改成PixPtr:TbyteArray,SetLength接收的数组定义,不是动态数组指针,你试试。
[/Quote]

可是 PixPtr:=Pic.ScanLine[i]; 返回的是数组的指针再转成数组 应该不是这个问题吧.
我把
PixPtr:=Pic.ScanLine[i];
改成
PixPtr:= TbyteArray(Pic.ScanLine[i]^);
转不了啊...出错: EAccessViolation 地址访问错误.

"SetLength接收的数组定义" 由于是不定大小的矩形区域所以无法固定接收数组的大小.

SQLDebug_Fan 2010-08-01
  • 打赏
  • 举报
回复
PixPtr:PbyteArray改成PixPtr:TbyteArray,SetLength接收的数组定义,不是动态数组指针,你试试。
风平心境 2010-08-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 tjianliang 的回复:]
在这一句上面设个断点,看看pixels内容
[/Quote]
谢谢你的回答.
pixels 是可以访问,pixels前面用的好的. 错误出现在系统函数@DnyArrayClear里面. 在cpu里看出来的.

问题出现在这个子函数里面红色字.也就是函数结束部分
function calMean(x,y:integer):TRGBTriple;
var pixels:TPixelArray;
r:TRect;
rpix:TRGBTriple;
len,x1,y1,n,m:integer;
begin
r:=Rect(x,y,x+matrix_x-1,y+matrix_y-1);
//平移
x1:=Round(matrix_x/2)-1;
y1:=Round(matrix_y/2)-1;
OffsetRect(r,-x1,-y1);

//读矩形内的像素到数组 pixels
ReadPixelArray(bit,r,pixels);

len:=high(pixels);
m:=Round(len/2);
//排序数组并取出中值
SortPixelArray(pixels,0,len,tcRed);
rpix.rgbtRed:=pixels[m].rgbtRed;
SortPixelArray(pixels,0,len,tcGreen);
rpix.rgbtGreen:=pixels[m].rgbtGreen;
SortPixelArray(pixels,0,len,tcBlue);
rpix.rgbtBlue:=pixels[m].rgbtBlue;
setLength(pixels,0);
pixels:=nil;
result:= rpix;

end;
风平心境 2010-08-01
  • 打赏
  • 举报
回复
windows 单元 自带的.
  tagRGBTRIPLE = packed record
rgbtBlue: Byte;
rgbtGreen: Byte;
rgbtRed: Byte;
end;
TRGBTriple = tagRGBTRIPLE;
wxieyang 2010-08-01
  • 打赏
  • 举报
回复
TRGBTriple 结构是什么样子?
亮剑_ 2010-07-31
  • 打赏
  • 举报
回复
在这一句上面设个断点,看看pixels内容
没有的请发邮件给我:jacdfb@163.com,qq:505689211 一直也没接触到什么复杂的报表,都是一些简单的报表,在DelphI下使用QuickReport一般也就能满足需要了,由于公司现在需求的变化,对条码扫描提了新的要求,主要是扫码要包含更多地内容,以前的一维码显然不能完全满足,再说二维码也是一种趋势,故而需要解决二维码的问题,网上搜了一下,方式有多种多样,我花了3天时间找了很多,也尝试了很多。也经历了很多失败!总结一下在Delphi下实现二维码主要有三种方法: 1、使用PtImageRW.dll和PtQREncode.dll动态连接库,使用uQRCode生成二维码图像,如此就可以在报表中予以打印了,具体如何用uQRCode实现绘制二维码,本人水平太低,无法参透;结合QuikReport就可以实现打印二维码了,但此种有一个问题就是不支持中文,如source1(整合到FastReport中也无法实现对中文的支持); 2、还有一种就是生成控件,利用ZINT制作的控件,如source2;此种有个问题就是无法在报表中使用(也许是我不会用),只可在窗体上显示,当然理论上说能在窗体上使用就完全可以用于打印报表了,可问题时我不会,哎,还是技术水平太低。还有一种叫Han-sof 2D Barcodes的控件,我可以安装,但却无法使用,无法生成二维码到图片。可上网搜索一下下载这个控件安装一下,有定的与我共享一下。 3、用ZINT整合到FastReport中,也是下面我要叙述的形式:source3。完全可以满足我的需求。 例子实现了对采购入库数据的组批量打印,加入了二维码的使用,当然实际工作当中制作入库单基本上用不到批量打印的,一般都是一单一打,但在我这里没办法,必须设计这样的功能,历史遗留问题吧,这里也牢骚一下吧! 如做一些延伸,很多的打印都和这个有很多的类似之处,我说的是并不太复杂的应用,至于什么更复杂得我想FS也能的定,这里做一个总结是希望对和我一样水平的人提供一些帮助吧,也许现在很多人根本不用Delphi了,权且当作自己的一个笔记吧! *********压缩文件内容如下********************************* 1、fastreport for 2010是我用的,可以正常使用也是例子里用到的4.9版本 2、fastreport5 for delphi7,已经好久不用7了,故也没测试,这是下载到的!测试成功的告诉我一下! 3、fastreport5 for xe8,我朋友测试通过的,也是他发给我的,但在我的xe8下就是不行,可以看到控件,但一运行,就报错,还没时间研究,我记得在装XE8的时候是自带了fastreport5的,但并没有二维码的选项,我是卸载了自带的,然后再安装的,然后现了一系列的问题,实在没时间,因为大部程序是在2010下的,还没时间向XE8切换,不知道是不在安装的时候不能安装自带的FS5,我朋友在第一次安装的时候就没有选择,然后手动安装的,效果很好! 有知道fastreport5如何在2010下用的,麻烦指教一下! 4、source1-3,前面有说过了,主要是一些例子,我所总结的三种方法,也不知道对不对! 5、zinBarcode文件里也是一个例子,也是用fastreport,可以比较完美的显示中文fastreport,但二维码不能显示中文,设置成中文即报错。

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧