§§●ScanLine的怪问题!这种多出来的东西是哪来的???●§§ ( 积分: 50 )

  • 主题发起人 主题发起人 3333W
  • 开始时间 开始时间
3

3333W

Unregistered / Unconfirmed
GUEST, unregistred user!
我在bitmap上画了四个象素的点.分别是黑,兰,红,黄.排列方式如下:
黑,兰
红,黄
此图大小为4个象素.格式为24pf.
用scanline显示数据.
格式应该如下:
for y:=0 to bitmap.height-1 do<-----关键在这
begin
p:=bitmap.scanline[x]
for x:=0 to bitmap.width-1 do<-----关键在这
begin
str:=p[x*3]+p[x*3+1]+p[x*3+2]<--此处为输入方便请不要顾忌语法问题
str显示在文本里面.此处略去.....
end;
end;
按道理上面显示出来应该为:
0行:[ 0 0 0 ] [ 255 0 0 ]
1行:[ 0 0 255 ] [ 0 255 255 ]
这都没问题.结果无意中发现.将
for x:=0 to bitmap.width-1 do 中的 bitmap.width-1 改成bitmap.width+随便一个数.
非但没越界,而且还有一帮数据显示.我就郁闷这些数据哪里来的??
我改成加3后数据显示如下:
0行:[ 0 0 0 ] [ 255 0 0 ] [ 231 129 108 ] [ 0 0 160 ] [ 192 14 102 ] [ 206 89 0 ]
1行:[ 0 0 255 ] [ 0 255 255 ] [ 231 129 0 ] [ 0 0 255 ] [ 0 0 231 ] [ 129 108 0 ]
暴奇怪! 望高手指点!!!
 
我在bitmap上画了四个象素的点.分别是黑,兰,红,黄.排列方式如下:
黑,兰
红,黄
此图大小为4个象素.格式为24pf.
用scanline显示数据.
格式应该如下:
for y:=0 to bitmap.height-1 do<-----关键在这
begin
p:=bitmap.scanline[x]
for x:=0 to bitmap.width-1 do<-----关键在这
begin
str:=p[x*3]+p[x*3+1]+p[x*3+2]<--此处为输入方便请不要顾忌语法问题
str显示在文本里面.此处略去.....
end;
end;
按道理上面显示出来应该为:
0行:[ 0 0 0 ] [ 255 0 0 ]
1行:[ 0 0 255 ] [ 0 255 255 ]
这都没问题.结果无意中发现.将
for x:=0 to bitmap.width-1 do 中的 bitmap.width-1 改成bitmap.width+随便一个数.
非但没越界,而且还有一帮数据显示.我就郁闷这些数据哪里来的??
我改成加3后数据显示如下:
0行:[ 0 0 0 ] [ 255 0 0 ] [ 231 129 108 ] [ 0 0 160 ] [ 192 14 102 ] [ 206 89 0 ]
1行:[ 0 0 255 ] [ 0 255 255 ] [ 231 129 0 ] [ 0 0 255 ] [ 0 0 231 ] [ 129 108 0 ]
暴奇怪! 望高手指点!!!
 
To 3333W,
scanline 我不会,可能是画板是整个屏幕,您那里测试容易,您在试试看。
 
试过了.都设置成4象素了.还是这样
 
这个我也不是很了解,抱歉
 
To 3333W,
你这个问题不算问题

您可以贴出部分代吗我看看,看您上面的代码我这的不理解
 
以下为原代码.无删减!

unit Unit1;

interface

uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
StdCtrls,ExtCtrls;

type
TForm1=class(TForm)
Img_s:TImage;
Button1:TButton;
ListB_s:TMemo;
procedure Button1Click(Sender:TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1:TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender:TObject);
var
i,j:integer;
s:string;
ps:PByteArray;
begin
Img_s.Width:=2;
Img_s.Height:=2;
Img_s.Picture.Bitmap.Width:=2;
Img_s.Picture.Bitmap.Height:=2;
Img_s.Canvas.Pixels[0,0]:=clBlack;
Img_s.Canvas.Pixels[1,0]:=clBlue;
Img_s.Canvas.Pixels[0,1]:=clred;
Img_s.Canvas.Pixels[1,1]:=clYellow;
Img_s.Picture.Bitmap.PixelFormat:=pf24bit;
for i:=0 to Img_s.Height-1 do
begin
ps:=Img_s.Picture.Bitmap.ScanLine;
s:='';
for j:=0 to Img_s.Width+3 do
begin
s:=s+'[ '+inttostr(ps[j*3])+' '+inttostr(ps[j*3+1])+' '+inttostr(ps[j*3+2])+' ]'+' ';
end;
ListB_s.Lines.Add(inttostr(i)+': '+s);
end;
end;

end.
 
内存是连续的,你多出来的东西是垃圾数据,但是是可以访问的。只要不是往里面写东西一般不会产生访问冲突。你甚至可以访问任意地址的值也不会出现错误。
 
按照楼上说的话.scanline这函数.扫描的数据不全是当前图片的数据??
我总觉的这个解释有点牵强. 如果是连续的为什么多出来的数据也能凑成颜色值.而不是别的东西呢?
 
To 3333W,
Canvas 是Delphi用临界区自己维护的,
一般情况下Pixels[x,y]:= -1
也就是后面出现的那些数据
 
to:老人家
你说的比较高深,我不太明白.可否说的详细白话一点. 哈哈,麻烦你了!
 
To 3333W,
你定义一个数组 array[0..10] of String;
array[0] := '100';
array[1] := '200';
现在 array[2] = ?
我认为array[2] = ''
 
要知道这个问题,你要跟踪调试一下,看看Graphics.CopyBitmap函数的代码。
TBitmap的Bits数据的存储地址是操作系统分配的(当然也可以提供一个FileMapping内存映射句柄来指定Bits数据存放在什么地方),操作系统分配内存时不是说你这个Bitmap需要16个字节,就给你分配16个字节,它是按页分配的,也就是说一分配就是4096字节的。
对pf24bit的2x2的Bitmap,有用的只有12字节(但地址边界对齐的缘故,实际上占用了14字节),不过在存放Bits的这个内存页,其他地址的内容也是可以访问的,只不过因为Bits数据没有设定,是随机值而已,估计是系统为了提高效率,分配之后整页一次性全部Commit了吧。另外,还有一点,Scanline读取的数据的存储是跟我们0..Height-1的先后顺序是倒的(可能这么表达不合适[:D]),就是说Scanline[Height-1]才是Bits数据存储的开始地址,而不是Scanline[0],因此,p:=Scanline[Height-1],那么p[4095]可以访问,p[4096]就不可以访问啦
 
你看看Fastbmp
 
unit FastBMP;

interface // TFastBMP v1.1
// Gordon Alex Cowie <gfody@jps.net>
uses Windows, // www.jps.net/gfody
FastRGB; //
// This unit is Freeware. Comments, Ideas,
const // Optimizations, Corrections, and Effects
{$IFDEF VER90} // are welcome. See readme.rtf for a brief
hSection=nil; // documentation. (2/8/99)
{$ELSE}
hSection=0;
{$ENDIF}

type

TFastBMP=class (TFastRGB)
private
procedure Initialize;
public
Handle,
hDC: Integer;
bmInfo: TBitmapInfo;
bmHeader: TBitmapInfoHeader;
// constructors
constructor Create(cx,cy:Integer);
constructor CreateFromFile(lpFile:string);
constructor CreateFromhBmp(hBmp:Integer);
constructor CreateFromRes(hInst:Integer;lpName:string);
constructor CreateCopy(hBmp:TFastBMP);
destructor Destroy; override;
// gdi routines
procedure Draw(hDst,x,y:Integer);
procedure Stretch(hDst,x,y,cx,cy:Integer);
procedure DrawRect(hDst,x,y,sx,sy,cx,cy:Integer);
procedure TileDraw(hDst,x,y,cx,cy:Integer);
// software (non gdi) routines
procedure Resize(Dst:TFastBMP);
procedure SmoothResize(Dst:TFastBMP);
procedure CopyRect(Dst:TFastBMP;x,y,sx,sy,cx,cy:Integer);
procedure Tile(Dst:TFastBMP);
end;

implementation

constructor TFastBMP.Create(cx,cy:Integer);
begin
Width:=cx;
Height:=cy;
with bmHeader do
begin
biSize:=SizeOf(bmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
bmInfo.bmiHeader:=bmHeader;
Handle:=CreateDIBSection(0,
bmInfo,
DIB_RGB_COLORS,
Bits,
hSection,
0);
Initialize;
end;

constructor TFastBMP.CreateFromFile(lpFile:string);
var
Bmp: TBITMAP;
memDC,
hBmp: Integer;
begin
hBmp:=LoadImage(0,PChar(lpFile),IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
GetObject(hBmp,SizeOf(Bmp),@Bmp);
Width:=Bmp.bmWidth;
Height:=Bmp.bmHeight;
Size:=((Width*3)+(Width mod 4))*Height;
// this conversion is to make sure bpp:=24
// bmp files are usually saved upside-down
// so to make sure that pixels[0,0] is the
// top left corner, I have to put -height.
with bmHeader do
begin
biSize:=SizeOf(bmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
bmInfo.bmiHeader:=bmHeader;
Handle:=CreateDIBSection(0,
bmInfo,
DIB_RGB_COLORS,
Bits,
hSection,
0);
memDC:=GetDC(0);
GetDIBits(memDC,hBmp,0,Height,Bits,bmInfo,DIB_RGB_COLORS);
ReleaseDC(0,memDC);
DeleteObject(hBmp);
Initialize;
end;

constructor TFastBMP.CreateFromhBmp(hBmp:Integer);
var
Bmp: TBITMAP;
memDC: Integer;
begin
GetObject(hBmp,SizeOf(Bmp),@Bmp);
Width:=Bmp.bmWidth;
Height:=Bmp.bmHeight;
Size:=((Width*3)+(Width mod 4))*Height;
with bmHeader do
begin
biSize:=SizeOf(bmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
bmInfo.bmiHeader:=bmHeader;
Handle:=CreateDIBSection(0,
bmInfo,
DIB_RGB_COLORS,
Bits,
hSection,
0);
memDC:=GetDC(0);
GetDIBits(memDC,hBmp,0,Height,Bits,bmInfo,DIB_RGB_COLORS);
ReleaseDC(0,memDC);
Initialize;
end;

constructor TFastBMP.CreateFromRes(hInst:Integer;lpName:string);
var
Bmp: TBITMAP;
memDC,
hBmp: Integer;
begin
hBmp:=LoadImage(hInst,PChar(lpName),IMAGE_BITMAP,0,0,0);
GetObject(hBmp,SizeOf(Bmp),@Bmp);
Width:=Bmp.bmWidth;
Height:=Bmp.bmHeight;
Size:=((Width*3)+(Width mod 4))*Height;
with bmHeader do
begin
biSize:=SizeOf(bmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
bmInfo.bmiHeader:=bmHeader;
Handle:=CreateDIBSection(0,
bmInfo,
DIB_RGB_COLORS,
Bits,
hSection,
0);
memDC:=GetDC(0);
GetDIBits(memDC,hBmp,0,Height,Bits,bmInfo,DIB_RGB_COLORS);
ReleaseDC(0,memDC);
DeleteObject(hBmp);
Initialize;
end;

constructor TFastBMP.CreateCopy(hBmp:TFastBMP);
begin
bmHeader:=hBmp.bmHeader;
bmInfo:=hBmp.bmInfo;
Width:=hBmp.Width;
Height:=hBmp.Height;
Size:=hBmp.Size;
Handle:=CreateDIBSection(0,
bmInfo,
DIB_RGB_COLORS,
Bits,
hSection,
0);
CopyMemory(Bits,hBmp.Bits,Size);
Initialize;
end;

destructor TFastBMP.Destroy;
begin
DeleteDC(hDC);
DeleteObject(Handle);
FreeMem(Pixels);
inherited;
end;

procedure TFastBMP.Initialize;
var
i: Integer;
x: Longint;
begin
GetMem(Pixels,Height*SizeOf(PLine));
Gap:=Width mod 4;
RowInc:=(Width*3)+Gap;
Size:=RowInc*Height;
x:=Integer(Bits);
for i:=0 to Height-1 do
begin
Pixels:=Pointer(x);
Inc(x,RowInc);
end;
hDC:=CreateCompatibleDC(0);
SelectObject(hDC,Handle);
end;

procedure TFastBMP.Draw(hDst,x,y:Integer);
begin
BitBlt(hDst,x,y,Width,Height,hDC,0,0,SRCCOPY);
end;

procedure TFastBMP.Stretch(hDst,x,y,cx,cy:Integer);
begin
// some video drivers don't implement stretching dibs
// very well. (diamond stealth fails when the scaling
// factor is greater then 255). for reliable resizing
// use the native 'resize' method.
SetStretchBltMode(hDst,STRETCH_DELETESCANS);
StretchBlt(hDst,x,y,cx,cy,hDC,0,0,Width,Height,SRCCOPY);
end;

procedure TFastBMP.DrawRect(hDst,x,y,sx,sy,cx,cy:Integer);
begin
BitBlt(hDst,x,y,cx,cy,hDC,sx,sy,SRCCOPY);
end;

procedure TFastBMP.TileDraw(hDst,x,y,cx,cy:Integer);
var
w,h,
hBmp,
memDC: Integer;
begin
memDC:=CreateCompatibleDC(hDst);
hBmp:=CreateCompatibleBitmap(hDst,cx,cy);
SelectObject(memDC,hBmp);
Draw(memDC,0,0);
w:=Width;
h:=Height;
while w<cx do
begin
BitBlt(memDC,w,0,w*2,cy,memDC,0,0,SRCCOPY);
Inc(w,w);
end;
while h<cy do
begin
BitBlt(memDC,0,h,w,h*2,memDC,0,0,SRCCOPY);
Inc(h,h);
end;
BitBlt(hDst,x,y,cx,cy,memDC,0,0,SRCCOPY);
DeleteDC(memDC);
DeleteObject(hBmp);
end;

procedure TFastBMP.Resize(Dst:TFastBMP);
var
xCount,
yCount,
x,y,xP,yP,
xD,yD,
yiScale,
xiScale: Integer;
xScale,
yScale: Single;
Read,
Line: PLine;
Tmp: TFColor;
pc: PFColor;
begin
if(Dst.Width=0)or(Dst.Height=0)then Exit;
if(Dst.Width=Width)and(Dst.Height=Height)then
begin
CopyMemory(Dst.Bits,Bits,Size);
Exit;
end;

xScale:=Dst.Width/Width;
yScale:=Dst.Height/Height;
if(xScale<1)or(yScale<1)then
begin // shrinking
xiScale:=(Width shl 16) div Dst.Width;
yiScale:=(Height shl 16) div Dst.Height;
yP:=0;
for y:=0 to Dst.Height-1 do
begin
xP:=0;
read:=Pixels[yP shr 16];
pc:=@Dst.Pixels[y,0];
for x:=0 to Dst.Width-1 do
begin
pc^:=Read[xP shr 16];
Inc(pc);
Inc(xP,xiScale);
end;
Inc(yP,yiScale);
end;
end
else // zooming
begin
yiScale:=Round(yScale+0.5);
xiScale:=Round(xScale+0.5);
GetMem(Line,Dst.Width*3);
for y:=0 to Height-1 do
begin
yP:=Trunc(yScale*y);
Read:=Pixels[y];
for x:=0 to Width-1 do
begin
xP:=Trunc(xScale*x);
Tmp:=Read[x];
for xCount:=0 to xiScale-1 do
begin
xD:=xCount+xP;
if xD>=Dst.Width then Break;
Line[xD]:=Tmp;
end;
end;
for yCount:=0 to yiScale-1 do
begin
yD:=yCount+yP;
if yD>=Dst.Height then Break;
CopyMemory(Dst.Pixels[yD],Line,Dst.Width*3);
end;
end;
FreeMem(Line);
end;
end;

// huge thanks to Vit Kovalcik for this awesome function!
// performs a fast bicubic interpolation <vkovalcik@iname.com>
procedure TFastBMP.SmoothResize(Dst:TFastBMP);
var
x,y,xP,yP,
yP2,xP2: Integer;
Read,Read2: PLine;
t,z,z2,iz2: Integer;
pc:PFColor;
w1,w2,w3,w4: Integer;
Col1,Col2: PFColor;
begin
if(Dst.Width<1)or(Dst.Height<1)then Exit;
if Width=1 then
begin
Resize(Dst);
Exit;
end;
if(Dst.Width=Width)and(Dst.Height=Height)then
begin
CopyMemory(Dst.Bits,Bits,Size);
Exit;
end;
xP2:=((Width-1)shl 15)div Dst.Width;
yP2:=((Height-1)shl 15)div Dst.Height;
yP:=0;
for y:=0 to Dst.Height-1 do
begin
xP:=0;
Read:=Pixels[yP shr 15];
if yP shr 16<Height-1 then
Read2:=Pixels[yP shr 15+1]
else
Read2:=Pixels[yP shr 15];
pc:=@Dst.Pixels[y,0];
z2:=yP and $7FFF;
iz2:=$8000-z2;
for x:=0 to Dst.Width-1 do
begin
t:=xP shr 15;
Col1:=@Read[t];
Col2:=@Read2[t];
z:=xP and $7FFF;
w2:=(z*iz2)shr 15;
w1:=iz2-w2;
w4:=(z*z2)shr 15;
w3:=z2-w4;
pc.b:=
(Col1.b*w1+PFColor(Integer(Col1)+3).b*w2+
Col2.b*w3+PFColor(Integer(Col2)+3).b*w4)shr 15;
pc.g:=
(Col1.g*w1+PFColor(Integer(Col1)+3).g*w2+
Col2.g*w3+PFColor(Integer(Col2)+3).g*w4)shr 15;
pc.r:=
(Col1.r*w1+PFColor(Integer(Col1)+3).r*w2+
Col2.r*w3+PFColor(Integer(Col2)+3).r*w4)shr 15;
Inc(pc);
Inc(xP,xP2);
end;
Inc(yP,yP2);
end;
end;

procedure TFastBMP.CopyRect(Dst:TFastBMP;x,y,sx,sy,cx,cy:Integer);
var
n1,n2: Pointer;
i: Integer;
begin
if cy+sy>Height then cy:=cy-((cy+sy)-Height);
if cx+sx>Width then cx:=cx-((cx+sx)-Width);
if cy+y>Dst.Height then cy:=cy-((cy+y)-Dst.Height);
if cx+x>Dst.Width then cx:=cx-((cx+x)-Dst.Width);

n1:=@Dst.Pixels[y,x];
n2:=@Pixels[sy,sx];
for i:=0 to cy-1 do
begin
CopyMemory(n1,n2,cx*3);
n1:=Ptr(Integer(n1)+Dst.RowInc);
n2:=Ptr(Integer(n2)+RowInc);
end;
end;

procedure TFastBMP.Tile(Dst:TFastBMP);
var
w,h,cy,cx: Integer;
begin
CopyRect(Dst,0,0,0,0,Width,Height);
w:=Width; h:=Height;
cx:=Dst.Width; cy:=Dst.Height;
while w<cx do
begin
Dst.CopyRect(Dst,w,0,0,0,w*2,cy);
Inc(w,w);
end;
while h<cy do
begin
Dst.CopyRect(Dst,0,h,0,0,w,h*2);
Inc(h,h);
end;
end;

end.
 
unit FastRGB;

// TFastRGB v1.0
// Gordon Alex Cowie <gfody@jps.net>
// www.jps.net/gfody
// shared properties for TFastBMP and TFastDDB
// see readme.rtf for documentation.

interface

type
TFColor = record b,g,r:Byte end;
PFColor =^TFColor;
TLine = array[0..0]of TFColor;
PLine =^TLine;
TPLines = array[0..0]of PLine;
PPLines =^TPLines;

TFastRGB=class
Gap, // space between scanlines
RowInc, // distance to next scanline
Size, // size of Bits
Width,
Height: Integer;
Pixels: PPLines;
Bits: Pointer;
end;

function FRGB(r,g,b:Byte):TFColor;
function IntToByte(i:Integer):Byte;
function TrimInt(i,Min,Max:Integer):Integer;

implementation

function FRGB(r,g,b:Byte):TFColor;
begin
Result.b:=b;
Result.g:=g;
Result.r:=r;
end;

function IntToByte(i:Integer):Byte;
begin
if i>255 then Result:=255
else if i<0 then Result:=0
else Result:=i;
end;

function TrimInt(i,Min,Max:Integer):Integer;
begin
if i>Max then Result:=Max
else if i<Min then Result:=Min
else Result:=i;
end;

end.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
488
import
I
I
回复
0
查看
641
import
I
后退
顶部