2

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;
LuFang
  • 191
  • 3
  • 12
  • Apart from the question, wouldn't it be much easier to use a TArray or TArray instead of a blank pointer? – Rudy Velthuis Jan 31 '19 at 11:25
  • @RudyVelthuis , I use this pointer further in the code to get indexed access to each line of pixels, to fast copy a small image into specific coordinates of a large image. See `RenderMemoryToBitmap32` procedure in the added part of my question. What are the benefits of using TArray or TArray? – LuFang Jan 31 '19 at 13:28
  • 1
    The benefits are automatic memory management. No need to think when you must free the memory. And instead of an untyped Pointer, use a PByte or PRGBQuad for access. Much easier. – Rudy Velthuis Jan 31 '19 at 13:50
  • 1
    Since this doesn't answer the question, and in a comment, I can't show how I would do this, you'll have to find out. I would return a TArray and use that from there on. Hardly any need for Pointers, no need to cast, no need for GetMem, etc. no need to think about when to use FreeMem, etc. Why do things the hard and low level way when using the high-level way is in no way slower and much easier to use? – Rudy Velthuis Jan 31 '19 at 13:55

2 Answers2

2

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);
Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
MBo
  • 77,366
  • 5
  • 53
  • 86
1

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.

CWBudde
  • 1,783
  • 1
  • 24
  • 28
  • I agree, I have to revise my code so that it will be more optimize for bitmap manipulation. Graphics32 is a great library, thank you. – LuFang Feb 01 '19 at 05:48