How to create Bitmap32 from Bits array?

635 Views Asked by At

I have a function that returns a pointer to the memory where the image is stored as Bitmap32.Bits:

function FileToMemoryAsBitmap32Bits: pointer;
var
  bmp32: TBitmap32;
  wic: TWICImage;
begin
  Result := nil;

  bmp32 := TBitmap32.Create();
  try
    wic := TWICImage.Create;
    try
      wic.LoadFromFile('256x256.jpg');
      bmp32.Assign(wic);
      GetMem(Result, 256*256*4);
      Move(bmp32.Bits^, Result^, 256*256*4);
    finally
      FreeAndNil(wic);
    end;
  finally
    FreeAndNil(bmp32);
  end;
end;

Somewhere further in the code I need to create a new Bitmap32 from this Bits in memory. How to do it correctly?
I tried to do the following:

var 
  p: Pointer;
  NewBitmap32: TBitmap32;
// ...
p := FileToMemoryAsBitmap32Bits;
// ... do something with Bits in memory
NewBitmap32 := TBitmap32.Create(256, 256);
NewBitmap32.Bits := p;  

but I get an error:

E2129 Cannot assign to a read-only property

ADDED for @RudyVelthuis:

procedure RenderMemoryToBitmap32(Output: TBitmap32; p: pointer; const x, y: integer);
var
  d, i,j: integer;
  OutputRowRGBA, RowRGBA: PColor32Array;
begin
  RowRGBA := PColor32Array(p);
  for j := 0 to 255 do begin
    OutputRowRGBA := Output.Scanline[y+j]; // row in large bitmap

    for i := 0 to 255 do begin
      d := i + x;            // offset
      TColor32Entry(OutputRowRGBA[d]).B := TColor32Entry(RowRGBA[i]).B;
      TColor32Entry(OutputRowRGBA[d]).G := TColor32Entry(RowRGBA[i]).G;
      TColor32Entry(OutputRowRGBA[d]).R := TColor32Entry(RowRGBA[i]).R;
      TColor32Entry(OutputRowRGBA[d]).A := TColor32Entry(RowRGBA[i]).A;
    end;

    inc(longword(RowRGBA), 256*4); // next row
  end;
end;
2

There are 2 best solutions below

3
MBo On BEST ANSWER

You cannot change address of data using this way, memory is already allocated and bitmap32 doesn't allow to replace its address.

But you can move stored data in this location like (but in reverse direction) you already did for storing, but in reverse direction:

 Move(p^, NewBitmap32.Bits^,  256*256*4);
1
CWBudde On

While I don't want to question your needs in regards of storing the bitmap as bitstream, it should also be possible to clone the original bitmap like this:

NewBitmap32 := TBitmap32.Create;
NewBitmap32.Assign(OriginalBitmap);

This will clone the bitmap perfectly in terms of preserving the width and height of the bitmap (which otherwise gets lost). The overhead of having a TBitmap32 in memory instead of a pure bitstream is minimal.