Forum > Graphics
Different TBitmap.RawImage.Data behavior in Win32 and Linux
dan59314:
Hi,
I tried to manipulate TBitmap.RawImage.Data as following, load a bmp file, copy to a new TBitmap, and save to a new file. But get different result in Win32 and Linux.
With the same source code....
--- Code: ---procedure TForm1.Button1Click(Sender: TObject);
var
bmp1, bmp2:TBitmap;
ptr1, ptr2:Pointer;
i:integer;
begin
//if OpenDialog1.Execute then
begin
try
bmp1:=TBitmap.Create;
bmp2:=TBitmap.Create;
bmp1.LoadFromFile('test.bmp'); //OpenDialog1.FileName);
bmp2.PixelFormat := bmp1.PixelFormat;
bmp2.Width := bmp1.Width;
bmp2.Height := bmp1.Height;
for i:=0 to bmp1.Height-1 do
begin
ptr1 := bmp1.RawImage.Data + bmp1.Width*3*i;
ptr2 := bmp2.RawImage.Data+ bmp2.Width*3*i;
Move(ptr1^, ptr2^, bmp1.Width*3);
end;
bmp2.SaveToFile('aa.bmp');
finally
bmp1.Free;
bmp2.Free;
end;
end;
end;
--- End code ---
Got different result,
In Windows http://dan59314.myweb.hinet.net/WindowsImage.jpg
In Linux http://dan59314.myweb.hinet.net/LinuxImage.jpg
How to fix the problem? Is it a bug?
Thanks,
Regards,
Daniel
Marc:
--- Code: ---ptr1 := bmp1.RawImage.Data + bmp1.Width*3*i;
--- End code ---
the problems here are the assumptions you make:
Each pixel will take 3 bytes and each row is byte alligned
This is complete platform dependent, look at the rawimage.description how the data is layout in memory
dan59314:
--- Quote from: Marc on October 27, 2009, 10:38:58 am ---
--- Code: ---ptr1 := bmp1.RawImage.Data + bmp1.Width*3*i;
--- End code ---
the problems here are the assumptions you make:
Each pixel will take 3 bytes and each row is byte alligned
This is complete platform dependent, look at the rawimage.description how the data is layout in memory
--- End quote ---
Hi, Marc,
Thanks again.
Yes, I loaded the 24bit bmp file, size 480x360, 3 bytes per pixel, I guess the stridebytes should be bmp.Width*3 = 480*3 = 1440.
I search and found in GraphType.pp the TRawImageDescription, still don't know how the linux align the raw data.
Then I google 'Linux Raw Data format', 'Linux Raw Data mainpulate'.., can't find any hint can make the code work.
Then I wondered that may works if I add 'bmp2.RawImage.Description := bmp1.RawImage.Description;' after set bmp2 size. But still the same.
Didn't tried it out yet.
May you revise the code and show me how to make it works the same result in both linux and windows?
Regards,
Daniel
Vincent Snijders:
You must use the bmp1.RawImage.Description fields to determine how to copy the bytes. See http://lazarus-ccr.sourceforge.net/docs/lcl/graphtype/trawimagedescription.html for a explanation of the fields.
In your copying code you assume BitsPerPixel=24 and LineEnd=rileByteBoundary. Is that true?
dan59314:
--- Quote from: Vincent Snijders on October 28, 2009, 08:58:35 am ---You must use the bmp1.RawImage.Description fields to determine how to copy the bytes. See http://lazarus-ccr.sourceforge.net/docs/lcl/graphtype/trawimagedescription.html for a explanation of the fields.
In your copying code you assume BitsPerPixel=24 and LineEnd=rileByteBoundary. Is that true?
--- End quote ---
Thanks,
I read the explanation, and assign 3 fields.
bmp2.RawImage.Description.Format:= ricfRGBA;
bmp2.RawImage.Description.BitsPerPixel:=BitsPerPixel;
bmp2.RawImage.Description.LineEnd:=rileDWordBoundary;
--- Code: ---
function BytesPerScanline(PixelsPerScanline, BitsPerPixel,
Alignment: Integer): Longint;
begin
Dec(Alignment);
Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment;
Result := Result div 8;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
bmp1, bmp2:TBitmap;
ptr1, ptr2, p0:Pointer;
i,j,strideBytes,BYtesPerPixel,BitsPerPixel:integer;
begin
//if OpenDialog1.Execute then
begin
try
bmp1:=TBitmap.Create;
bmp2:=TBitmap.Create;
bmp1.LoadFromFile('test.bmp'); //OpenDialog1.FileName);
bmp2.PixelFormat := bmp1.PixelFormat;
bmp2.Width := bmp1.Width;
bmp2.Height := bmp1.Height;
BitsPerPixel :=24;
bmp2.RawImage.Description.Format:= ricfRGBA;
bmp2.RawImage.Description.BitsPerPixel:=BitsPerPixel;
bmp2.RawImage.Description.LineEnd:=rileDWordBoundary;
strideBytes := BytesPerScanline(bmp1.Width, BitsPerPixel, 32);
BytesPerPixel := BitsPerPixel div 8;
//bmp2.RawImage.Description := bmp1.RawImage.Description;
for i:=0 to bmp1.Height-1 do
begin
ptr1 := bmp1.RawImage.Data+strideBytes*i;
ptr2 := bmp2.RawImage.Data+strideBytes*i;
Move(ptr1^, ptr2^, strideBytes);
end;
bmp2.SaveToFile('aa.bmp');
finally
bmp1.Free;
bmp2.Free;
end;
end;
end;
--- End code ---
In Windows, I guess it's 32 bits aligned, means rileDWordBoundary. I suppose Linux also the same.
if I assign the
bmp2.RawImage.Description := bmp1.RawImage.Description;
and
copy the RawImage data with the for loop, increasing pointer.
The bmp2 should be as same as bmp1, isn't it?
BTW, in Windows, the Raw Image aligned in BGRBGRBGRBGR........
Is the Linux aligned in a different manner? EX BBBBBBBBBBBBB..... GGGGGGGG.... RRRRRR..., first Blue data block, then the Green, the Red... ? ( Because the image seems have multiple shifted image.)
Thanks,
Regards,
Daniel
Navigation
[0] Message Index
[#] Next page