Different TBitmap.RawImage.Data behavior in Win32 and Linux lazarus / 39-Graphics ---------------------------------------------------------------------- dan59314 · 2009-10-27 01:18 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: [Select]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; 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 · 2009-10-27 09:38 Code: [Select]ptr1 := bmp1.RawImage.Data + bmp1.Width*3*i; 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 · 2009-10-28 02:51 Quote from: Marc on October 27, 2009, 10:38:58 amCode: [Select]ptr1 := bmp1.RawImage.Data + bmp1.Width*3*i; 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 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 · 2009-10-28 07:58 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 · 2009-10-28 09:21 Quote from: Vincent Snijders on October 28, 2009, 08:58:35 amYou 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? 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: [Select]                                                                                    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;                                                                                                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 ---------------------------------------------------------------------- Vincent Snijders · 2009-10-28 09:30 You are trying something different than I meant. You change description according to the way you copy the data. I suggested that you read the description of both bitmaps and adjust the way you copy the data accordingly. ---------------------------------------------------------------------- dan59314 · 2009-10-29 00:37 Quote from: Vincent Snijders on October 28, 2009, 10:30:27 amYou are trying something different than I meant. You change description according to the way you copy the data. I suggested that you read the description of both bitmaps and adjust the way you copy the data accordingly. With the following code, I got a more comfortable result. http://dan59314.myweb.hinet.net/LinuxImage1.jpg I suppose the raw data aligned in  BBBBBBBBBBBBBBBBBBBBB....(count: WidthxHeight) GGGGGGGGGGGGGGGGGGGGGGG.......RRRRRRRRRRRRRRRRRR from the start to end. Code: [Select]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;       bmp2.RawImage.Description.Init_BPP32_B8G8R8_BIO_TTB(bmp2.Width, bmp2.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;       bmp2.BeginUpdate(false);       {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;       }       // First assign a contiuos block for Blue ----------------------       ptr2 := bmp2.RawImage.Data;       for i:=0 to bmp1.Height-1 do       begin         ptr1 := bmp1.RawImage.Data+bmp1.Width*3*i;         for j:=0 to bmp1.Width-1 do         begin           Move(ptr1^, ptr2^, 1);           //Move((ptr1+1)^, (ptr2+bmp2.Width)^, 1);           //Move((ptr1+2)^, (ptr2+bmp2.Width*2)^, 1);           ptr1 := Pointer( integer(ptr1)+3);           ptr2 := Pointer( integer(ptr2)+1);         end;       end;       //  block for Green -----------------------------       ptr2 := bmp2.RawImage.Data+bmp2.Width*bmp2.Height;       for i:=0 to bmp1.Height-1 do       begin         ptr1 := bmp1.RawImage.Data+bmp1.Width*3*i;         for j:=0 to bmp1.Width-1 do         begin           //Move(ptr1^, ptr2^, 1);           //Move((ptr1+1)^, (ptr2+bmp2.Width)^, 1);           Move((ptr1+2)^, (ptr2)^, 1);           ptr1 := Pointer( integer(ptr1)+3);           ptr2 := Pointer( integer(ptr2)+1);         end;       end;       // block for Red -------------------------------------------       ptr2 := bmp2.RawImage.Data+bmp2.Width*bmp2.Height*2;       for i:=0 to bmp1.Height-1 do       begin         ptr1 := bmp1.RawImage.Data+bmp1.Width*3*i;         for j:=0 to bmp1.Width-1 do         begin           //Move(ptr1^, ptr2^, 1);           Move((ptr1+1)^, (ptr2)^, 1);           //Move((ptr1+2)^, (ptr2+bmp2.Width*2)^, 1);           ptr1 := Pointer( integer(ptr1)+3);           ptr2 := Pointer( integer(ptr2)+1);         end;       end;       bmp2.EndUpdate(false);       bmp2.SaveToFile('aa.bmp');     finally       bmp1.Free;       bmp2.Free;     end;   end; end; I wonder I am almost there. Any idea to get it work? Thanks, Daniel ---------------------------------------------------------------------- dan59314 · 2009-10-29 01:00 Also I just simply use BitBlt() to get desktop image on form1. It's a mass. http://dan59314.myweb.hinet.net/TempImage/BitBltImage1.jpg Is it possible there is a bug in raw data alignment, so cause the incorrect result in BitBlt() and my previous trying. Daniel Code: [Select]procedure TForm1.Button1Click(Sender: TObject); begin   BitBlt(Self.Canvas.Handle, 0,0,Self.ClientWidth, Self.ClientHeight,  GetDC(0), 0,0, 0); end; ---------------------------------------------------------------------- Marc · 2009-10-29 11:45 Does the following work ?Code: [Select]var   B: TBitmap;   DC: HDC; begin   B := TBitmap.Create;   DC := GetDC(0);   B.LoadFromDevice(DC);   ReleaseDC(0, DC);   ... end; ---------------------------------------------------------------------- dan59314 · 2009-10-30 00:39 Quote from: Marc on October 29, 2009, 12:45:42 pmDoes the following work ? Yes, it's perfect without missing any pixel. Do you have any idea on why BitBlt() don't work fine?  and mine. Daniel ---------------------------------------------------------------------- dan59314 · 2009-11-02 07:28 Any one ever success on using BitBlt() in Ubuntu Linux? ---------------------------------------------------------------------- dan59314 · 2009-11-09 09:38 May anyone help? BitBlt() can't work in ubuntu linux? ---------------------------------------------------------------------- dan59314 · 2009-11-27 00:53 Hi,    No one got the same problem on Linux ubuntu ?    Can anyone kindly help? Thanks, Daniel ---------------------------------------------------------------------- dan59314 · 2010-01-11 09:18 Hi,   This is an old post, still not solved, wonder someone may help now.   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: [Select]procedure TForm1.btnScan0TestClick(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('test24.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;  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 · 2010-01-11 10:08 Please, 1) if this is an old thread, respond to that thread 2) read my notes about rawimage.destription. You are assuming a dataformat which isn't correct. Merged.... ---------------------------------------------------------------------- LuizAmérico · 2010-01-11 14:48 You can use http://imaginglib.sourceforge.net/ it gives you any format you want both in win32 and linux ---------------------------------------------------------------------- marcov · 2010-01-11 15:33 Quote from: Marc on January 11, 2010, 11:08:38 amPlease, 1) if this is an old thread, respond to that thread 2) read my notes about rawimage.destription. You are assuming a dataformat which isn't correct. Merged.... Can't you specify how a bmp is to be loaded? Loading 24-bits bmps as 32-bit is not such a strange thing to expect. ---------------------------------------------------------------------- Marc · 2010-01-11 20:04 Quote from: marcov on January 11, 2010, 04:33:47 pmCan't you specify how a bmp is to be loaded? Loading 24-bits bmps as 32-bit is not such a strange thing to expect. Nope, loading a 24bpp bitmap will result in a 24bpp bitmap, independent of the pixelformat set before loading ---------------------------------------------------------------------- Marc · 2010-01-12 00:08 OK, I changed the code a bit since it is a bit faster and you should use begin/end update:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  bmp1, bmp2:TBitmap;  ptr1, ptr2:Pointer;  i:integer;  R1, R2: TRawImage;begin   //if OpenDialog1.Execute then  begin    try    bmp1:=TBitmap.Create;      bmp2:=TBitmap.Create;       bmp1.LoadFromFile('test24.bmp'); //OpenDialog1.FileName);      bmp2.PixelFormat := bmp1.PixelFormat;      bmp2.Width := bmp1.Width;    bmp2.Height := bmp1.Height;       R1 := bmp1.RawImage;      bmp2.BeginUpdate;      R2 := bmp2.RawImage;       for i:=0 to bmp1.Height-1 do      begin        // something else since this won't work        // ptr1 := R1.Data + bmp1.Width*3*i;        // ptr2 := R2.Data + bmp2.Width*3*i;         // Move(ptr1^, ptr2^, bmp1.Width*3);      end;       bmp2.EndUpdate;      bmp2.SaveToFile('aa.bmp');      finally      bmp1.Free;      bmp2.Free;    end;  end;end;  If you looked at the Rawimage.Description, you will notice the difference. The bitmap loaded has a bits per pixel of 24 while bitmap 2 has a bits per pixel of 32. While the depth of both bitmaps are 24bpp, the gtk widgetset internally prefers 4 bytes to store a pixel. therefore you cannot simply copy a whole line. R1.Description:Code: [Select]  FORMAT = RICFRGBA,   WIDTH = 480,   HEIGHT = 360,   DEPTH = 24,   BITORDER = RIBOBITSINORDER,   BYTEORDER = RIBOLSBFIRST,   LINEORDER = RILOTOPTOBOTTOM,   LINEEND = RILEDWORDBOUNDARY,   BITSPERPIXEL = 24,   REDPREC = 8,   REDSHIFT = 16,   GREENPREC = 8,   GREENSHIFT = 8,   BLUEPREC = 8,   BLUESHIFT = 0,   ALPHAPREC = 0,   ALPHASHIFT = 0,   MASKBITSPERPIXEL = 1,   MASKSHIFT = 0,   MASKLINEEND = RILEWORDBOUNDARY,   MASKBITORDER = RIBOBITSINORDER,   PALETTECOLORCOUNT = 0,   PALETTEBITSPERINDEX = 0,   PALETTESHIFT = 0,   PALETTELINEEND = RILETIGHT,   PALETTEBITORDER = RIBOBITSINORDER,   PALETTEBYTEORDER = RIBOLSBFIRST R2.Description:Code: [Select]  FORMAT = RICFRGBA,   WIDTH = 480,   HEIGHT = 360,   DEPTH = 24,   BITORDER = RIBOBITSINORDER,   BYTEORDER = RIBOLSBFIRST,   LINEORDER = RILOTOPTOBOTTOM,   LINEEND = RILEDWORDBOUNDARY,   BITSPERPIXEL = 32,   REDPREC = 8,   REDSHIFT = 16,   GREENPREC = 8,   GREENSHIFT = 8,   BLUEPREC = 8,   BLUESHIFT = 0,   ALPHAPREC = 0,   ALPHASHIFT = 0,   MASKBITSPERPIXEL = 1,   MASKSHIFT = 0,   MASKLINEEND = RILEBYTEBOUNDARY,   MASKBITORDER = RIBOBITSINORDER,   PALETTECOLORCOUNT = 0,   PALETTEBITSPERINDEX = 0,   PALETTESHIFT = 0,   PALETTELINEEND = RILETIGHT,   PALETTEBITORDER = RIBOBITSINORDER,   PALETTEBYTEORDER = RIBOLSBFIRST ---------------------------------------------------------------------- LuizAmérico · 2010-01-12 02:55 I had the same problems some years ago. With imaginglib this whould be done with few calls: LoadImageFromFile(FileName, Data); // -> you get the image data //after here you can work with Get/SetPixel32 independent of the data format //to ensure a data format do more one call: if Data.Format <> MyFormat then   ConvertImage(Data, MyFormat); You can use the Bits property to access directly the code. Here is one excerpt of a routine that masks a image data (FData) given a color. You can find good documentation in the site i mentioned earlier. procedure TCairoImagingPicture.Mask(const AMaskColor: TColor24Rec; ClearAlpha: Boolean); var   Pixel: PColor32Rec;   ByteCount: PtrUInt; begin   Pixel := FData.Bits;   ByteCount := FData.Size shr 2;   while ByteCount > 0 do   begin     //todo: optimize this comparation     with Pixel^ do     begin       if (R = AMaskColor.R) and         (G = AMaskColor.G) and         (B = AMaskColor.B) then         Color := $00000000       else         if ClearAlpha then           A := 255;     end;     Inc(Pixel);     Dec(ByteCount);   end; end; ---------------------------------------------------------------------- dan59314 · 2010-01-12 03:17 Quote from: Marc on January 12, 2010, 01:08:09 am Hi, Marc,     I knew they are different in Description, but I still don't know how to make the soucecode work. I will try harder to see if I can figure it out.     Btw, I got a stupid question. How you watch the TRawImage.Description, I never success on trace these information, and others. When I add it to watch dialog, it always show some kind of 'bmp2.RawImage.Description',  'A Syntax error in expression, near 'RawImage.Description'. Daniel ---------------------------------------------------------------------- dan59314 · 2010-01-12 03:31 Quote from: LuizAmérico on January 12, 2010, 03:55:08 amI had the same problems some years ago. With imaginglib this whould be done with few calls: LoadImageFromFile(FileName, Data); // -> you get the image data //after here you can work with Get/SetPixel32 independent of the data format //to ensure a data format do more one call: if Data.Format <> MyFormat then   ConvertImage(Data, MyFormat); You can use the Bits property to access directly the code. Here is one excerpt of a routine that masks a image data (FData) given a color. You can find good documentation in the site i mentioned earlier. procedure TCairoImagingPicture.Mask(const AMaskColor: TColor24Rec; ClearAlpha: Boolean); var   Pixel: PColor32Rec;   ByteCount: PtrUInt; begin   Pixel := FData.Bits;   ByteCount := FData.Size shr 2;   while ByteCount > 0 do   begin     //todo: optimize this comparation     with Pixel^ do     begin       if (R = AMaskColor.R) and         (G = AMaskColor.G) and         (B = AMaskColor.B) then         Color := $00000000       else         if ClearAlpha then           A := 255;     end;     Inc(Pixel);     Dec(ByteCount);   end; end; Hi, LuizAmerico,   Where can I get imagingLib? Daniel ---------------------------------------------------------------------- LuizAmérico · 2010-01-12 03:34 http://imaginglib.sourceforge.net/ ---------------------------------------------------------------------- dan59314 · 2010-01-12 04:53 With this revised piece, I can now get better result, but mono.        ptr1 := R1.Data + bmp1.Width*3*i;         ptr2 := R2.Data + bmp2.Width*4*i;  //  make it increase every 4 byte         Move(ptr1^, ptr2^, bmp1.Width*3); Code: [Select]procedure TForm1.Button2Click(Sender: TObject); var   bmp1, bmp2:TBitmap;   ptr1, ptr2:Pointer;   i:integer;   R1, R2: TRawImage; 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;       R1 := bmp1.RawImage;       bmp2.BeginUpdate;       R2 := bmp2.RawImage;       for i:=0 to bmp1.Height-1 do       begin         // something else since this won't work         ptr1 := R1.Data + bmp1.Width*3*i;         ptr2 := R2.Data + bmp2.Width*4*i;         Move(ptr1^, ptr2^, bmp1.Width*3);         // The following should do the same thing, but became whole black.         {(ptr2)^ :=  pByte(ptr1)^;         pByte(ptr2+1)^ :=  pByte(ptr1+1)^;         pByte(ptr2+2)^ :=  pByte(ptr1+2)^; }       end;       bmp2.EndUpdate;       bmp2.SaveToFile('../cc.bmp');     finally       bmp1.Free;       bmp2.Free;     end;   end; end;    And the weired one is         (ptr2)^ :=  pByte(ptr1)^;         pByte(ptr2+1)^ :=  pByte(ptr1+1)^;         pByte(ptr2+2)^ :=  pByte(ptr1+2)^; should same to Move(ptr1^, ptr2^, bmp1.Width*3); but not. I now know loaded bmp is 24 bit aligned, bmp2 is 32 bit aligned. I wonder the only problem now is I don't know how the RGB aligned in bmp2. Is it? Daniel ---------------------------------------------------------------------- Marc · 2010-01-12 11:06 Quote from: dan59314 on January 12, 2010, 05:53:59 amWith this revised piece, I can now get better result, but mono.        ptr1 := R1.Data + bmp1.Width*3*i;        ptr2 := R2.Data + bmp2.Width*4*i;  //  make it increase every 4 byte        Move(ptr1^, ptr2^, bmp1.Width*3); this is because you are moving one line, but the pixels are wider. If you look how the colors are stored:     bmp1: BGRBGRBGR   bmp2: xBGRxBgrxBgr so if you copy the 3 pixels above in one move, they are copied over the x QuoteAnd the weired one is         (ptr2)^ :=  pByte(ptr1)^;         pByte(ptr2+1)^ :=  pByte(ptr1+1)^;         pByte(ptr2+2)^ :=  pByte(ptr1+2)^; should same to Move(ptr1^, ptr2^, bmp1.Width*3); it is not the same. In the first case you only copy 1 pixel while with the move you copy "width" pixels ---------------------------------------------------------------------- dan59314 · 2010-01-15 00:55 Quote from: Marc on January 12, 2010, 12:06:29 pmQuote  bmp1: BGRBGRBGR   bmp2: xBGRxBgrxBgr And the weired one is         (ptr2)^ :=  pByte(ptr1)^;         pByte(ptr2+1)^ :=  pByte(ptr1+1)^;         pByte(ptr2+2)^ :=  pByte(ptr1+2)^; should same to Move(ptr1^, ptr2^, bmp1.Width*3); it is not the same. In the first case you only copy 1 pixel while with the move you copy "width" pixels Sorry, my mistake. I didn't notice that I only wrote one for-loop. I will revise it to double for-loop to mainpulate the single pixel each time.   >>bmp1: BGRBGRBGR   >>bmp2: xBGRxBgrxBgr This is what I want to know, now I will know how to copy data by byte. P.S. I can't watch the bmp.rawimage, description..... and most the variables. Can you show me how to watch them? That's why I can't trace to know.... bmp2: xBGRxBgrxBgr. Thanks, Daniel ---------------------------------------------------------------------- dan59314 · 2010-01-15 01:52 Hi, Marc,   I work it out. And the bmp2 should be aligned in BGRXBGRXBGRX or RGBXRGBX....., I am not sure since I can't watch the value.  X should be the last byte. Code: [Select]procedure TForm1.Button2Click(Sender: TObject);    var   bmp1, bmp2:TBitmap;   ptr1, ptr2:Pointer;   i,j:integer;   R1, R2: TRawImage;   strideBytes1, strideBytes2: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;       R1 := bmp1.RawImage;       bmp2.BeginUpdate;       R2 := bmp2.RawImage;       for i:=0 to bmp1.Height-1 do       begin         ptr1 := bmp1.RawImage.Data+bmp1.Width*3*i;         ptr2 := bmp2.RawImage.Data+bmp2.Width*4*i;         for j:=0 to bmp1.Width-1 do         begin                Move(ptr1^,ptr2^, 3);           ptr1 := Pointer( integer(ptr1)+3);   //BGRBGRBGR           ptr2 := Pointer( integer(ptr2)+4);   //BGRXBGRXBGRX         end;       end;       bmp2.EndUpdate;       bmp2.SaveToFile('../cc.bmp');     finally       bmp1.Free;       bmp2.Free;     end;   end; end;    Daniel ---------------------------------------------------------------------- User137 · 2010-02-06 15:14 As far as i see, RawImage has also palette and mask arrays but i don't know if you need them for exact result. Also you make assumption that everything in data is in bytes which it isn't. Rawimage seems to support well images with pixels of even 7 bits or something. You can directly copy Raw data to another if you use RawImage.DataSize property instead of image width and height things. I just yesterday made loading functions for OpenGL textures and gave small code hint there: http://www.lazarus.freepascal.org/index.php/topic,7532.msg41410.html#m sg41410 ---------------------------------------------------------------------- Marc · 2010-02-17 23:19 Palette isn't used/implemented yet