Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-05

Questions regarding FPImage's TFPMemoryImage.FData variable

9 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

The internal FData field variable of TFPMemoryImage is of type FPFItegerArray and is defined as follows:

  TFPIntegerArray = array [0..(maxint-1) div sizeof(integer)-1] of integer;
  PFPIntegerArray = ^TFPIntegerArray;

Unfortunately the FPImage unit is not I have the
following questions regarding that field variable:

1) I'm assuming FData is the raw image buffer of TFPMemoryImage where all the image pixel data is stored?

2) Nowhere in TFPMemoryImage is the size of FData being set, it seem it is always a hard-coded size, based on the type declaration shown above. Isn't this inefficient? eg: a small 5x5 image and 4000x4000 image uses the same amount of memory for example. It is obviously possible that I'm misunderstanding TFPMemoryImage completely. ;-)

3) The FData image buffer (assuming (1) is correct) uses Integer instead of Byte as it's element size. So I'm assuming a singe Integer hold all the colour information for a single pixel?
But then again, I have noticed that TFPColor uses Word size data elements, thus the whole RGBA information per pixel will be 8 bytes of data, and Integer is only 4 bytes large.

4) What is the order in which the colour channel information is stored in memory? RGB, BGR, RGBA, BGRA, ARGB, ABGR etc?

5) Is the Alpha channel actually stored? I assume it is, because the Integer type is large enough to hold that information.

The reason for all these questions. I've got a image loaded in a TFPMemoryImage instance. I need to pass the the raw pixel data buffer to a 3rd party library for further processing. But I need to tell that 3rd party library a bit about the data I'm giving it (colour channel size, colour channel order etc).

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 14 lines
Hi, The internal FData field variable of TFPMemoryImage is of type FPFItegerArray and is defined as follows: TFPIntegerArray = array [0..(maxint-1) div sizeof(integer)-1] of integer; PFPIntegerArray = ^TFPIntegerArray; Unfortunately the FPImage unit is not I have the following questions regarding that field variable: 1) I'm assuming FData is the raw image buffer of TFPMemoryImage where all the image pixel data is stored?

Yes.

BUT:
depending on UsePalette, it contains indexes in the palette or RGB Data.

Show quoted text 6 lines
2) Nowhere in TFPMemoryImage is the size of FData being set, it seem it is always a hard-coded size, based on the type declaration shown above. Isn't this inefficient? eg: a small 5x5 image and 4000x4000 image uses the same amount of memory for example. It is obviously possible that I'm misunderstanding TFPMemoryImage completely. ;-)

It is definitely possible that you are wrong.
Line 512 of fpimage, and line 544

3) The FData image buffer (assuming (1) is correct) uses Integer instead of Byte as it's element size. So I'm assuming a singe Integer hold all the colour information for a single pixel?

No.

But then again, I have noticed that TFPColor uses Word size data elements, thus the whole RGBA information per pixel will be 8 bytes of data, and Integer is only 4 bytes large.

Yes. The Pixels array is a palette. The colors array is RGBA.

4) What is the order in which the colour channel information is stored in memory? RGB, BGR, RGBA, BGRA, ARGB, ABGR etc?

You should not worry about this. The whole idea is that you do not use the internal format, but just use the colors array:

       property  Colors [x,y:integer] : TFPColor read GetColor write SetColor; default;
5) Is the Alpha channel actually stored? I assume it is, because the Integer type is large enough to hold that information.

Alpha is stored.

Show quoted text 7 lines
The reason for all these questions. I've got a image loaded in a TFPMemoryImage instance. I need to pass the the raw pixel data buffer to a 3rd party library for further processing. But I need to tell that 3rd party library a bit about the data I'm giving it (colour channel size, colour channel order etc).

This is not supported for TFPMemoryImage.

The TFPCustomImage image component does not provide storage. It does not care about actual storage, and defines just an interface for getting/setting color data (possibly using a palette).

TFPMemoryImage is just a sample implementation of TFPCustomImage, which supports full 64-bit color specs (3 RGB, 1 Alpha, all of size 16 bit). The data is private, because it uses a private format, which will be unusable in most libraries.

Instead, you can use use one of the TFPCompactImgBase descendants: they store their data in more compact (and common) formats than TFPMemoryImage.

TFPCompactImgRGBA8Bit
TFPCompactImgRGB8Bit

etc. The data pointer is protected, so you can create a descendent and access it directly.

Or write your own imaga storage. You just need to override 5 methods.

Michael.

Graeme Geldenhuys
to Graeme Geldenhuys: The internal FData field variable of TFPMemoryImage is of type FPFItegerArray and is…

Playing around further I've managed to get something kinda working. See attached image. Left is what I now render via my 3rd party image library, right is what it is supposed to look like.

Two points to note about the attached image:
1. The colours are obviously wrong.
2. The image seems stretched horizontally. I'm not sure if this is due to the TFPColor being Word size elements instead of Byte size elements.

Graeme Geldenhuys wrote
1) I'm assuming FData is the raw image buffer of TFPMemoryImage where all the image pixel data is stored?

I seem to have answered this myself by simply trying it and casting TFPMemoryImage to a "friend class" (hack) so I can access the protected FData field variable.

2) Nowhere in TFPMemoryImage is the size of FData being set, it seem it is always a hard-coded size, based on the type declaration shown above. Isn't this inefficient?

Afterwards I found the TFPMemoryImage.SetSize() which reallocates memory based on the image dimensions. So memory usage is not hard-coded as I first thought.

My earlier questions 3, 4 and 5 I still don't have answers to.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Graeme Geldenhuys
to Michael Van Canneyt: Yes. BUT: depending on UsePalette, it contains indexes in the palette or RGB Data. It is…
Michael Van Canneyt wrote
BUT: depending on UsePalette, it contains indexes in the palette or RGB Data.

Oh, I forgot about Palette usage. I’ll have to check for that in my code. Does setting UsePalette := False at runtime auto convert palette data to RGB data? I had a () but it
is not immediately obvious what it does at runtime (after image data was already loaded).

It is definitely possible that you are wrong.

:-) Definitely not the first time that happened.

Yes. The Pixels array is a palette. The colors array is RGBA.

Good to know the difference, thanks.

Show quoted text 5 lines
> 4) What is the order in which the colour channel information is stored > in memory? RGB, BGR, RGBA, BGRA, ARGB, ABGR etc? You should not worry about this. The whole idea is that you do not use the internal format, but just use the colors array:

But that would be super slow.

Show quoted text 7 lines
> The reason for all these questions. I've got a image loaded in a > TFPMemoryImage instance. I need to pass the the raw pixel data buffer to > a 3rd party library for further processing. But I need to tell that > 3rd party library a bit about the data I'm giving it (colour channel > size, colour channel order etc). This is not supported for TFPMemoryImage.

Well, I seem to have it almost working (see my other message with attached image). I didn’t know about the TFPCompactImgBase descendants - I’ll give them a try instead. That seems more like what I need.

Many thanks for all the information Michael.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 9 lines
On 2016-05-26 12:08, Michael Van Canneyt wrote: > BUT: > depending on UsePalette, it contains indexes in the palette or RGB Data. Oh, I forgot about Palette usage. I’ll have to check for that in my code. Does setting UsePalette := False at runtime auto convert palette data to RGB data? I had a () but it is not immediately obvious what it does at runtime (after image data was already loaded).

Yes it does, but this is very slow.

Show quoted text 18 lines
> It is definitely possible that you are wrong. :-) Definitely not the first time that happened. > Yes. The Pixels array is a palette. The colors array is RGBA. Good to know the difference, thanks. >> 4) What is the order in which the colour channel information is stored >> in memory? RGB, BGR, RGBA, BGRA, ARGB, ABGR etc? > > You should not worry about this. The whole idea is that you do not use the > internal format, but just use the colors array: But that would be super slow.

Yes. But sometimes it is all you've got; e.g. when drawing on an image.

Show quoted text 12 lines
>> The reason for all these questions. I've got a image loaded in a >> TFPMemoryImage instance. I need to pass the the raw pixel data buffer to >> a 3rd party library for further processing. But I need to tell that >> 3rd party library a bit about the data I'm giving it (colour channel >> size, colour channel order etc). > > This is not supported for TFPMemoryImage. Well, I seem to have it almost working (see my other message with attached image). I didn’t know about the TFPCompactImgBase descendants - I’ll give them a try instead. That seems more like what I need.

It probably is.

For completeness, in fpImage: when doing 16 bit image, then (16-bit color value)=(8-bit color value) shl 8 + (8-bit color value)

Michael.

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote
Yes it does, but this is very slow.

Probably due to Colors array usage. ;-)

Yes. But sometimes it is all you've got; e.g. when drawing on an image.

Just so that others know, the 3rd party image library I’m using is AggPas. AggPas (like most other image libraries I would guess) uses ScanLine or pointers to bytes to speed up the manipulation of pixel data.

With FPImage’s Colors array the pixel offsets in FData need to be calculated with every pixel accessed. That is a huge speed penalty.

For completeness, in fpImage: when doing 16 bit image, then (16-bit color value)=(8-bit color value) shl 8 + (8-bit color value)

Ah, so it duplicates the 8-bit value to fill the 16-bit Word. That also explains the rendered output I see - why my current code is partially working with AggPas.

ps:
Is anybody working, on or started at least, documenting FPImage yet?

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 14 lines
On 2016-05-26 13:22, Michael Van Canneyt wrote: > Yes it does, but this is very slow. Probably due to Colors array usage. ;-) > Yes. But sometimes it is all you've got; e.g. when drawing on an image. Just so that others know, the 3rd party image library I’m using is AggPas. AggPas (like most other image libraries I would guess) uses ScanLine or pointers to bytes to speed up the manipulation of pixel data. With FPImage’s Colors array the pixel offsets in FData need to be calculated with every pixel accessed. That is a huge speed penalty.

The same is true for every array access ?

When drawing e.g. a red circle circle with given center and radius on an image canvas, you have no choice but to calculate X,Y and from there position in a scanline, which is an array etc. I suppose aggpas does the same.

When moving data in bulk, then the colors array is slow, but for all other access, I doubt it makes a huge difference.

Show quoted text 9 lines
> For completeness, in fpImage: when doing 16 bit image, then > (16-bit color value)=(8-bit color value) shl 8 + (8-bit color value) Ah, so it duplicates the 8-bit value to fill the 16-bit Word. That also explains the rendered output I see - why my current code is partially working with AggPas. ps: Is anybody working, on or started at least, documenting FPImage yet?

Not to my knowledge.

Michael.

Mattias Gaertner
to Graeme Geldenhuys: The internal FData field variable of TFPMemoryImage is of type FPFItegerArray and is…
[...] 3) The FData image buffer (assuming (1) is correct) uses Integer instead of Byte as it's element size. So I'm assuming a singe Integer hold all the colour information for a single pixel?

No, TFPMemoryImage uses one TFPColor per pixel (48bit). TFPCompactImgGray8Bit uses 8bit.
TFPCompactImgGray16Bit uses 16bit.
TFPCompactImgRGB8Bit uses 24bit.
TFPCompactImgRGBA8Bit uses 32bit.
and so forth...

But then again, I have noticed that TFPColor uses Word size data elements, thus the whole RGBA information per pixel will be 8 bytes of data, and Integer is only 4 bytes large.

The integer is only the palette index.

4) What is the order in which the colour channel information is stored in memory? RGB, BGR, RGBA, BGRA, ARGB, ABGR etc?

Each memory image uses a packed record. For example TFPMemoryImage uses TFPColor, TFPCompactImgRGBA8Bit uses TFPCompactImgRGBA8BitValue. It is typically RGBA.

5) Is the Alpha channel actually stored? I assume it is, because the Integer type is large enough to hold that information.

See above.

Mattias

Graeme Geldenhuys
to Mattias Gaertner
Mattias Gaertner wrote
TFPCompactImgRGBA8Bit uses 32bit.

Thanks for the information Mattias. In the end I managed with the TFPCompactImgRGBA8Bit image type. From what I can remember, after some experimentation, the internal channel information in memory was in BGRA format. It was easily adapted for AggPas usage though.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp