Raw Image Structure (BGRA) to TBitmap - Fastest way lazarus / 39-Graphics ---------------------------------------------------------------------- gabriemarcelo · 2019-09-04 13:05 Hi guys... Lets say that I have a raw image structure in memory where each pixel is stored in BGRA (4 bytes per pixel). I can get the pointer to that buffer. I need to print or draw it on a Canvas. To draw that raw image, I create a TBitmap with the same Width & Height and then loop through each raw pixel BGRA values and set it to the TBitmap. A snipped code is below... My question is... can I avoid looping through the raw structure and instead just set the new TBitmap.RawImage.Data to that pointer? I'd like to avoid creating two buffers in order to I need to speed up this code... any hints on this? thanks in advance 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  // bmpPage is the BGRA structure in memory... bmp := TBitmap.Create;bmp.Width := bmpPage.Width;bmp.Height := bmpPage.Height; bmp.BeginUpdate(); bytesPerPixel := bmp.RawImage.Description.BitsPerPixel div 8;redOffset := bmp.RawImage.Description.RedShift div 8;greenOffset := bmp.RawImage.Description.GreenShift div 8;blueOffset := bmp.RawImage.Description.BlueShift div 8; ptr := bmpPage.GetBuffer; for Y := 0 to bmp.Height - 1 dobegin        LinePixs := bmp.RawImage.GetLineStart(Y);        for X := 0 to bmp.Width - 1 do        begin                b := PByte(ptr)^;              inc(ptr);                g := PByte(ptr)^;                inc(ptr);                r := PByte(ptr)^;                inc(ptr);              a := PByte(ptr)^;                inc(ptr);               (LinePixs+blueOffset)^ := b;                (LinePixs+greenOffset)^ := g;                (LinePixs+redOffset)^ := r;                inc(LinePixs, bytesPerPixel);        end;end; bmp.EndUpdate(); ---------------------------------------------------------------------- BeanzMaster · 2019-09-05 16:10 Hi, this is the method i'm using in my library 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 function TBZCustomBitmap.ExportToBitmap : Graphics.TBitmap;var  Temp:     Graphics.TBitmap;  RawImage: TRawImage;  BitmapHandle, MaskHandle: HBitmap;  W,H : Integer;  Buffer : PByte;Begin  result := nil;  BitmapHandle := 0;  MaskHandle := 0;  w := Self.Width;  h:=  Self.Height;  Buffer := PByte(GetSurfaceBuffer);   RawImage.Init;  RawImage.Description.Init_BPP32_R8G8B8A8_BIO_TTB(W,H);  RawImage.Data := Buffer;  RawImage.DataSize:= Self.Size;   if not RawImage_CreateBitmaps(RawImage, BitmapHandle, MaskHandle, False) then  begin    raise EBZBitmapException.Create('Failed to create bitmap handle');  end  else  begin   Temp := Graphics.TBitmap.Create;   Temp.Handle := BitmapHandle;   Temp.MaskHandle := MaskHandle;   Result := Temp;  end;  if (Result=nil) then Raise EBZBitmapException.Create('Erreur de conversion vers TBitmap');End; "GetSurfaceBuffer" return my raw buffer in (bgra or rgba format depend the os) Cheers ---------------------------------------------------------------------- gabriemarcelo · 2019-09-05 21:47 thanks for sharing the code. I tested it but it does not work as expected because my raw image format is BGRA and your code assumes it's RGBA as in your code you call Init_BPP32_R8G8B8A8_BIO_TTB The code runs but the output image has wrong pixel values as expected because again, my source is BGRA. If I change that call to this one (which should be the correct for BGRA format)  Init_BPP32_B8G8R8A8_M1_BIO_TTB then the code fails at that procedure (error Image attached). Do you know why? ---------------------------------------------------------------------- BeanzMaster · 2019-09-06 18:13 Hi, in your code Size is incorrect. It's (w*h) *4 (4 is for BGRA or RGBA. One byte per channel  ) so try an tell us And also becarefull with your "Buffer" it must be a PByte. I don't known what is your structure exactly. Cheers ---------------------------------------------------------------------- gabriemarcelo · 2019-09-06 19:28 That did the trick! Thanks a lot. Regards, ---------------------------------------------------------------------- gabriemarcelo · 2019-09-06 21:36 Bad news... the code fails in macOS compiling to Cocoa 64bit apps... the code fails in the RawImage_CreateBitmaps (in the cocoalclintf.inc) more precisely in the RawImage_DescriptionToBitmapType which is not implemented for BGRA as it's not listed in the TCocoaBitmapType ... Did you test your code in macOS cocoa? ---------------------------------------------------------------------- BeanzMaster · 2019-09-09 19:13 Hi, sorry ,i can't test actually with Mac and don't know how Cocoa64 scheme. But perhaps the trick will be to create an RGBA raw image, and so you'll must swap R&B of your buffer before export it. This how i swap R&B 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 // Fast Red-Blue channel color swappingType   TBZColor =record // Very simplified record of my solution  Case Integer of     //0 : (Red, Green, Blue, Alpha : Byte); For Linux, Mac and other     0 : (Blue, Green, Red, Alpha : Byte); //For Windows     1 : (AsInteger : Cardina)l;  end;   PBZColor = ^TBZColor;   procedure SwapRB(Buf: PBZColor; pixelCount: Integer);  var    Pixptr: PBZColor;    AIntColor : Cardinal;  begin    PixPtr := Buf;    while pixelCount > 0 do    begin      AIntColor := PixPtr^.AsInteger;      PixPtr^.AsInteger := AIntColor and $FF00FF00 or (AintColor and $000000FF SHL 16) or (AIntColor and $00FF0000 SHR 16);      Inc(PixPtr);      Dec(pixelCount);    end;  end;