dkprojektai 1 Posted March 6, 2020 Hello, need help. How can I find in Delphi pointer to memory buffer which contain image file data and size of memory buffer in bytes ? These are not correct: @Bitmap1 Bitmap1.ScanLine[0] Buffer size can be found: function GetGraphicSize(g: TGraphic): Integer; var ms: TStream; begin ms := TMemoryStream.Create; try g.SaveToStream(ms); Result := ms.Size; finally ms.Free; end; end; How can do it correctly ? Share this post Link to post
Vandrovnik 214 Posted March 6, 2020 Bitmap1.ScanLine[Bitmap1.Height-1] is start of the image buffer (raw image data, it is bottom up). Buffer size is not so easy; in VCL.Graphics, they have this function (Alignment=32; you need to multiply its result by Bitmap1.Height; look at TBitmap.GetScanLine in VCL.Graphics). function BytesPerScanline(PixelsPerScanline, BitsPerPixel, Alignment: Longint): Longint; begin Dec(Alignment); Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment; Result := Result div 8; end; Share this post Link to post
dkprojektai 1 Posted March 6, 2020 thanks, but for me is too complicated. Could you write an example? Share this post Link to post
Vandrovnik 214 Posted March 6, 2020 Do you need pointer to raw image data (say RGB bytes for 24 bit/px images - ScanLine), or pointer to data which you saved to ms in your example? tMemoryStream has property Memory (pointer to its data). Share this post Link to post
dkprojektai 1 Posted March 6, 2020 I have Tbitmap I need: * pBuffer - Pointer to memory buffer which contain image file data * bufferSize - size of memory buffer in bytes Share this post Link to post
Anders Melander 1782 Posted March 6, 2020 3 hours ago, dkprojektai said: pBuffer - Pointer to memory buffer which contain image file data You didn't really answer @Vandrovnik's question. For Windows bitmaps the bitmap file image (i.e. bitmap header and pixel data) isn't stored in memory. When TBitmap loads a bmp file it reads the header information then the pixel data. From this it stores the relevant meta data (width/height, color depth, palette, etc) and pixel data in memory. Of these you only have direct access to the raw pixel data. If you need the file bitmap image in memory then you will either have to save the bitmap to a memory stream or construct the image yourself in memory. btw, when I write "image" I don't mean in the picture/graphic/bitmap sense. Maybe you should try to explain what problem you are trying to solve. 1 Share this post Link to post
David Heffernan 2345 Posted March 6, 2020 What is your actual problem for which you need a solution? Because what you are asking doesn't actually make sense. 1 Share this post Link to post
dkprojektai 1 Posted March 6, 2020 I have Bitmap and want to pass it this function function ReadFromMemFile(hEngine: TENGINE; pBuffer: Pointer; bufferSize: Integer): TRESULT; Share this post Link to post
Anders Melander 1782 Posted March 6, 2020 2 hours ago, dkprojektai said: function ReadFromMemFile(hEngine: TENGINE; pBuffer: Pointer; bufferSize: Integer): TRESULT; You're not giving us much to work with here. Do you have any documentation about what kind of data ReadFromMemFile expect the input buffer to hold? Share this post Link to post
David Heffernan 2345 Posted March 6, 2020 Perhaps you know what this is. 2 hours ago, dkprojektai said: function ReadFromMemFile(hEngine: TENGINE; pBuffer: Pointer; bufferSize: Integer😞 TRESULT; We don't. Try to imagine that we can't see your screen. 1 Share this post Link to post
Remy Lebeau 1394 Posted March 6, 2020 (edited) 8 hours ago, Vandrovnik said: Bitmap1.ScanLine[Bitmap1.Height-1] is start of the image buffer (raw image data, it is bottom up). The TBitmap.ScanLine property getter handles top-down vs bottom-up differences for you. You can use scanline indexes as if the bitmap were always top-down, like a normal array, and the property getter will access the raw pixels as needed based on whether the bitmap is top-down or bottom-up. In other words, ScanLine[0] always represents the 1st line of pixels, ScanLine[1] always represents the 2nd line of pixels, and so on. function TBitmap.GetScanLine(Row: Integer): Pointer; begin Changing(Self); with FImage.FDIB, dsbm, dsbmih do begin if (Row < 0) or (Row >= bmHeight) then InvalidOperation(@SScanLine); DIBNeeded; GDIFlush; if biHeight > 0 then // bottom-up DIB Row := biHeight - Row - 1; Result := PByte(bmBits) + Row * BytesPerScanline(biWidth, biBitCount, 32); end; end; That means if you want a raw pointer to the entire image buffer as a whole, then you have to use ScanLine[0] for a top-down bitmap, and ScanLine[Height-1] for a bottom-up bitmap. But, if you just want to access the individual lines one at a time, then you can loop through ScanLine[0]..ScanLine[Height-1] without regard to whether the bitmap is top-down or bottom-up. Edited March 7, 2020 by Remy Lebeau 1 Share this post Link to post
Remy Lebeau 1394 Posted March 7, 2020 (edited) 4 hours ago, dkprojektai said: I have Bitmap and want to pass it this function function ReadFromMemFile(hEngine: TENGINE; pBuffer: Pointer; bufferSize: Integer): TRESULT; Without knowing exactly what that function actually is or where it comes from, and given how few parameters it takes, it MOST LIKELY is expecting the WHOLE bitmap, header and everything, not just the raw pixel data by itself. If so, you would just have to load your BMP file or TBitmap object into a TMemoryStream first, and then you can pass its Memory and Size properties to that function's parameters, eg: MS := TMemoryStream.Create; try MS.LoadFromFile('image.bmp'); or BmpObj.SaveToStream(MS); Result := ReadFromMemFile(hEngine, MS.Memory, MS.Size); finally MS.Free; end; Edited March 7, 2020 by Remy Lebeau 2 Share this post Link to post
dkprojektai 1 Posted March 7, 2020 12 hours ago, Remy Lebeau said: Without knowing exactly what that function actually is or where it comes from, and given how few parameters it takes, it MOST LIKELY is expecting the WHOLE bitmap, header and everything, not just the raw pixel data by itself. If so, you would just have to load your BMP file or TBitmap object into a TMemoryStream first, and then you can pass its Memory and Size properties to that function's parameters, eg: MS := TMemoryStream.Create; try MS.LoadFromFile('image.bmp'); or BmpObj.SaveToStream(MS); Result := ReadFromMemFile(hEngine, MS.Memory, MS.Size); finally MS.Free; end; That is what I wanted and it helped. Thanks Remy Lebeau Share this post Link to post