Sign in Join

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

Mailing lists / fpc-pascal / 2015-10

Loading PNG files as OpenGL textures

33 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

I’m coming from the Mac and I’d like to replace some code that loads .png files into OpenGL textures using Apple libraries that aren’t cross platform compatible.

Does the FPC RTL contain any units for loading PNG files as bitmaps that I could extract the pixel data from and make textures for? I was using .png but I could use TIFF also or any other format which has an alpha channel.

I’ve found Vampyre Imaging Library but a) it’s huge and does far more than I need and b) I haven’t been able to find all it’s various dependancies, some of which use a newer version of OpenGL I’m not using. A small simple solution would be best if that’s possible.

Thanks.

Regards,
Ryan Joseph

Reply by email

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 5 lines
I’m coming from the Mac and I’d like to replace some code that loads .png files into OpenGL textures using Apple libraries that aren’t cross platform compatible. Does the FPC RTL contain any units for loading PNG files as bitmaps that I could extract the pixel data from and make textures for? I was using .png but I could use TIFF also or any other format which has an alpha channel. I’ve found Vampyre Imaging Library but a) it’s huge and does far more than I need and b) I haven’t been able to find all it’s various dependancies, some of which use a newer version of OpenGL I’m not using. A small simple solution would be best if that’s possible.

You can use the fpimage and fpreadpng units.
Check the packages/fcl-image sources.
There is a small demo program that shows how to do it.

Michael.

Reply by email

Ryan Joseph
to Michael Van Canneyt
On Oct 11, 2015, at 1:53 PM, Michael Van Canneyt wrote: You can use the fpimage and fpreadpng units. Check the packages/fcl-image sources. There is a small demo program that shows how to do it.

I see you can load an image as TFPCustomImage with TFPCustomImageReader then there is a canvas class (TFPCustomCanvas) which I assume I could draw the TFPCustomImage into and expose the pixels as a pointer to memory which I could then use to make the OpenGL texture.

I’m not able to see the references for TFPCustomCanvas in particular so I’m not sure how this would work. There is the guide I found but is there any more complete examples I could look at? Too much is missing to understand exactly how all these classes work together.

http://wiki.freepascal.org/fcl-image

Thanks.

Regards,
Ryan Joseph

Reply by email

Graeme Geldenhuys
to Ryan Joseph: I’m coming from the Mac and I’d like to replace some code that loads .png files into…
Ryan Joseph wrote
Does the FPC RTL contain any units for loading PNG files as bitmaps

As Michael mentioned, fpimage and fpreadpng can do this. Here is how I use it to populate fpGUI's TfpgImage class with image data.

https://github.com/graemeg/fpGUI/blob/develop/src/corelib/fpg_imgfmt_png.pas

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

Reply by email

Ryan Joseph
to Graeme Geldenhuys: As Michael mentioned, fpimage and fpreadpng can do this. Here is how I use it to populate…
Show quoted text 6 lines
On Oct 11, 2015, at 10:45 PM, Graeme Geldenhuys wrote: As Michael mentioned, fpimage and fpreadpng can do this. Here is how I use it to populate fpGUI's TfpgImage class with image data. https://github.com/graemeg/fpGUI/blob/develop/src/corelib/fpg_imgfmt_png.pas

But can I then access the pixel data so I can hand it to glTexImage2D and make the texture? I think the FPC RTL classes on http://wiki.freepascal.org/fcl-image would do this also but again it’s not clear how to get the pixel data for glTexImage2D

Thanks.

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Anthony Walter: You can write an interface to the quartz libs and have them load or save a variety of…
On Oct 12, 2015, at 3:46 AM, Anthony Walter wrote: You can write an interface to the quartz libs and have them load or save a variety of image formats such as bmp, jpg, gif, and png. I've done this with OpenGL on OSX with Free Pascal and I look for the code and post it to git sometime, maybe even Today.

This is what I do on Mac but I wanted to make some cross platform code so I need to kill lots of this Apple stuff.

Basically I loaded the image from file, made a CGImage wrapper to it (which understands PNG) and then draw it into a CGContext (like a bitmap canvas) then extracted the pixel data from the bitmap for use with glTexImage2D.

The FPC RTL on http://wiki.freepascal.org/fcl-image seems to do this but I don’t see the interface for TFPCustomCanvas so I don’t know if it’s possible to access the pixel data.

There’s code at http://www.sulaco.co.za/opengl_project_BMP_JPG_TGA_texture_loader.htm which follows a similar procedure but it’s Delphi and I couldn’t get it to run on FPC on my anyways.

Regards,
Ryan Joseph

Reply by email

Anthony Walter
to Ryan Joseph: But can I then access the pixel data so I can hand it to glTexImage2D and make the…

Okay, I looked at my Darwin sources which use minimal wrappers around the inbuilt Quartz classes to handle image loading, saving, and pixel data access.

To load any image (png, jpg, bmp, gif, ect) you use a CGImageSourceRef object.

From file:
ImageSource :=
CGImageSourceCreateWithURL(UrlRefCreateFromFileSystem(FileName).Handle,
nil);
From a stream:
ImageSource := CGImageSourceCreateWithData(DataRefCreate(Stream).Handle,
nil);

Then to access image data you need to create a bitmap context and tell the image source to populate the bitmap. My bitmap context create looks like this, which should give you a head start:

constructor TBitmapContextRef.Create(Image: IImageRef; ColorSpace:
TColorSpace = colorBGRA);
var
  R: CGRect;
begin
  Create(Image.Width, Image.Height);
  R.origin.x := 0;
  R.origin.y := 0;
  R.size.width := Image.Width;
  R.size.height := Image.Height;
  CGContextDrawImage(Handle, R, Image.Handle);
end;
constructor TBitmapContextRef.Create(Width, Height: Integer; ColorSpace:
TColorSpace = colorBGRA);
var
  PixelBytes: UIntPtr;
  C: CGColorSpaceRef;
  A: CGImageAlphaInfo;
  R: CGContextRef;
begin
  inherited Create(nil);
  PixelBytes := Width * Height * 4;
  FPixels := GetMem(PixelBytes);
  FillZero(FPixels^, PixelBytes);
  C := CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
  A := ColorSpaceToAlpha(ColorSpace);
  R := CGBitmapContextCreate(FPixels, Width, Height, 8, Width * 4, C, A);
  CGColorSpaceRelease(C);
  HandleOwn(R);
end;

https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGImageSource/ https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGBitmapContext/

You might be able to figure the rest out from there by yourself. If instead of figuring things out for yourself, you might to use want the Darwin graphics part of my library. For this you'll need two of my unit files:

The first unit wraps the ref object management pattern used by Darwin and includes plus a few extra helper routines.
The second unit wraps the Quartz 2D objects and also includes a few simple helper routines.

Let me know if you want to contribute and I can upload some code to a repository on github. But please I would ask that if you have any improvements to my code (such as wrapping more classes), that you share those changes with everyone using the same github repository. I'll need you github account names add you guys as contributors.

Reply by email

Ryan Joseph
to Anthony Walter
On Oct 12, 2015, at 9:47 AM, Anthony Walter wrote: Okay, I looked at my Darwin sources which use minimal wrappers around the inbuilt Quartz classes to handle image loading, saving, and pixel data access.

I have a good working implementation of loading OpenGL textures on Mac but I want to replace it with a cross platform solution that would run on Windows/Linux also that doesn’t rely on CoreGraphics libraries.

I think the classes in FPimage/FPCanvas from the RTL do this already so why do we need to use CoreGraphics and Apple-only libraries?

Regards,
Ryan Joseph

Reply by email

Anthony Walter
to Ryan Joseph

I tend to use OS core elements or well known open source libraries for a few reasons.

1) less code compiled and small programs
2) superior performance
3) more features

Example: When loading hundreds of textures you bet the Apple Quartz graphics libs are faster and more reliable. Same goes to WIC on Windows and Cario on linux.

Example: When processing XML, the power of the MSXML parser is going to be both lighter and faster than any other implementation on Windows. It's also includes the ability to do stylesheet transforms.

Example: When rendering video frames to textures you bet I am going to use ffmpeg libs rather than some native implementation.

This isn't meant to dissuade people from writing native implementations in Pascal. I wrote and maintain a game engine, but even so it's just a friendly interface to SDL2, OpenGL, SSL, XML, FFMPEG, and System graphics libs. I have no problem using that stuff when I write Pascal applications, and that's where I think Pascal excels, which is making friendly OO encapsulation wrappers around stuff using PME (objects with properties, methods, and events).

http://www.baregame.org/#bare_game (SDL wrappers)
http://www.getlazarus.org/videos/crossgraphics/
(Quartz,Cairo,Direct2D,GdiPlus wrappers)
http://www.getlazarus.org/interfaces/xml/ (MSXML,libXML2 wrappers)

Reply by email

Ryan Joseph
to Anthony Walter
Show quoted text 10 lines
On Oct 12, 2015, at 10:57 AM, Anthony Walter wrote: I tend to use OS core elements or well known open source libraries for a few reasons. 1) less code compiled and small programs 2) superior performance 3) more features Example: When loading hundreds of textures you bet the Apple Quartz graphics libs are faster and more reliable. Same goes to WIC on Windows and Cario on linux.

So your advice would be to keep my Apple libraries I use on Mac and something else for Windows? What would be the equivalent libraries on Windows for CGImage and CGBitmapContext be?

Loading PNG’s into a bitmap seems like a pretty thing for single unit but I could do the native route also if it was easier. I just wanted to get started on cross platform basically and I’m looking for the easiest strategy.

Here’s an example function to load a texture on Mac (given a CGImageRef you load from CGImageCreateWithURL). Pretty easy using Apple frameworks and I assume those would have some FPC RTL equivalents.

function GenerateTextureFromImage (image: CGImageRef): GLuint;
var
	textureWidth, textureHeight: integer;
	textureName: GLuint;
	bounds: CGRect;
	bitmapData: pointer;
	colorSpace: CGColorSpaceRef;
	context: CGContextRef;
begin
	result := 0;
	// generate texture
	textureWidth := CGImageGetWidth(image);
	textureHeight := CGImageGetHeight(image);
	bounds := CGRectMake(0, 0, textureWidth, textureHeight);
	bitmapData := GetMem(textureHeight * (textureWidth * 4));
	if bitmapData  nil then
		begin
			colorSpace := CGColorSpaceCreateDeviceRGB;
		  context := CGBitmapContextCreate(bitmapData, textureWidth, textureHeight, 8, 4 * textureWidth, colorSpace, kCGImageAlphaPremultipliedLast);
			if context  nil then
				begin
					CGContextFlipVertically(context, bounds);
					CGContextClearRect(context, bounds);
					CGContextDrawImage(context, bounds, image);
					glGenTextures(1, @result);
					glBindTexture(GL_TEXTURE_2D, result);
					glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
					glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapData);
					//writeln('generated texture ', result, ' (', textureWidth, 'x', textureHeight,')');
					CGContextRelease(context);
				end;
			FreeMemory(bitmapData);
			CFRelease(colorSpace);
		end;
end;

Regards,
Ryan Joseph

Reply by email

Michael Van Canneyt
to Anthony Walter: I tend to use OS core elements or well known open source libraries for a few reasons. 1)…
Anthony Walter wrote 6 lines
I tend to use OS core elements or well known open source libraries for a few reasons. 1) less code compiled and small programs 2) superior performance 3) more features

1. is not true for image code if you're using lazarus. The code will already be there.
2. May be true, depends on what it is.
3. May be true, depends on what it is.

But the downside is that you will need to write glue code for all libraries. Which can be a real pain for cross-platform apps. Look at lazarus itself. As a consequence your application may behave differently on each OS. (XML is a sore point there, or Unicode)

So I would never recommend your route, unless there is no native pascal implementation.

For the specific case of image loading, only 2 holds true;
so unless you really need great performance I see no reason to go this route.

Michael.

Reply by email

Anthony Walter
to Ryan Joseph: So your advice would be to keep my Apple libraries I use on Mac and something else for…

I would abstract all platform specific code. I define a encapsulating set of interfaces for any platform specific stuff. Interface types also provide a nice layer of abstraction.

In such a way I have at least IDocument, IBitmap, IAudio, and IVideo; where the last three type define methods for loading and decompressing images, audio, and video frames in that order. Then for each platform I map the interfaces to whatever native OS functions work best (or perhaps easiest). On OSX I use the QuickTime objects to decode video and on Linux it would be ffmpeg. On Windows I use MSXML parser, on Linux it would be libxml2 (I use my own libxml wrapper which has better xpath encapsulation), and so on.

Interfaces go into standard units such as YourCompany.Graphics, and implementations go into YourCompany.Platform.Darwin.Graphics or YourCompany.Platform.Linux.Graphics. Then in code I only reference YourCompany.Graphics, which has code like this:

unit YourCompany.Graphics;
type IBitmap = interface ... end;
function CreateBitmap(const FileName: string): IBitmap; overload;
function CreateBitmap(Stream: TStream): IBitmap; overload;

So then to your example. In my engine I have a TTextures asset manager class (exposed as a singleton):

TTextures = class(TAssetManager)
  procedure Add(const FileName: string; const Name: string); overload;
  procedure Add(Stream: TStream; const Name: string); overload;
  procedure Bind(const Name: string);
  property Texture[Name: string]: TTexture read GetTexture; default;
  ...
function Textures: TTextures;

The actual TTextures.Add methods uses an IBitmap interface which can to load, save, give dimensions, and provide access to pixel data.

procedure TTextures.Add(Stream: TStream; const Name: string);
var
  B: IBitmap;
  T: Texture;
begin
  if Texture[Name]  nil then Exit;
  B := CreateBitmap(Stream);
  T := TTexture.Create;
  T.Name := Name;
  T.Width := B.Width;
  T.Height := B.Height;
  glGenTextures(1, @T.FId);
  // B.Pixels has the pixel data which will be freed with the interface
  ...
end;

You get the idea I hope.

For stuff which might need a different implementation on platforms: define interfaces.
For stuff which is unaffected by platforms, encapsulate that using types like records, classes, enums, and sets.

Reply by email

Michael Van Canneyt
to Ryan Joseph: I see you can load an image as TFPCustomImage with TFPCustomImageReader then there is a…
Ryan Joseph wrote 6 lines
> On Oct 11, 2015, at 1:53 PM, Michael Van Canneyt wrote: > > You can use the fpimage and fpreadpng units. Check the packages/fcl-image sources. There is a small demo program that shows how to do it. I see you can load an image as TFPCustomImage with TFPCustomImageReader then there is a canvas class (TFPCustomCanvas) which I assume I could draw the TFPCustomImage into and expose the pixels as a pointer to memory which I could then use to make the OpenGL texture.

You don't need TFPCustomCanvas.

TFPCustomImage is an abstract image class, it provides no storage for the data. It can have several descendants such as TFPMemoryImage and TFPCompactImgRGBA8Bit. If you just want the raw data, create a TFPMemoryImage and access the Colors array property.

Michael.

Reply by email

Anthony Walter
to Michael Van Canneyt: 1. is not true for image code if you're using lazarus. The code will already be there. 2.…

Michael,

I've written a whole lot of OpenGL demos (demoscene) using both C and Pascal. I can tell you there is a huge difference between the Delphi image decompression performance and the performance of the image libs ones provided by the OS (WIC and Quartz especially). The OS imaging libs are orders of magnitudes faster than TFPImage, especially when it comes to loading 100s of textures during the start of a demo or game. Speed aside, all the OS imaging libs also provide vastly superior image manipulation including scaling, blending, and all support matrix color operations on pixels.

I find it ridiculous to reinvent a worse version the wheel in Pascal. Yeah sure I love Pascal, but mostly for the friendly wrappers it creates out of everything, which was how Delphi started.

Button.Caption := 'Hello World';

See: http://www.getlazarus.org/language/pme/

Reply by email

Michael Van Canneyt
to Anthony Walter
Anthony Walter wrote 11 lines
Michael, I've written a whole lot of OpenGL demos (demoscene) using both C and Pascal. I can tell you there is a huge difference between the Delphi image decompression performance and the performance of the image libs ones provided by the OS (WIC and Quartz especially). The OS imaging libs are orders of magnitudes faster than TFPImage, especially when it comes to loading 100s of textures during the start of a demo or game. Speed aside, all the OS imaging libs also provide vastly superior image manipulation including scaling, blending, and all support matrix color operations on pixels.

As I said: performance is the only reason IMHO.
If all you need to do is load an image to display it somewhere, then your method is complete overkill and not worth the hassle.

And everyone is reinventing the wheel anyway, every gaming library I've encountered out there reinvents all the image routines, be it as wrappers or native.

The main reason TFPImage exists is to be free of external dependencies.

Michael.

Reply by email

Graeme Geldenhuys
to Ryan Joseph: But can I then access the pixel data so I can hand it to glTexImage2D and make the…
Ryan Joseph wrote
But can I then access the pixel data so I can hand it to glTexImage2D and make the texture?

Yes, look at line 61. Simply use the Colors[] array property.

The code I suggested was not meant as a complete implementation for you, but as an example of how to use the fpImage and FPReadPNG units. Like I said, once the PNG file is loaded, use the Colors[] array property to access the pixel data.

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

Reply by email

Graeme Geldenhuys
to Anthony Walter: I've written a whole lot of OpenGL demos (demoscene) using both C and Pascal. I can tell…
Anthony Walter wrote
The OS imaging libs are orders of magnitudes faster than TFPImage, especially when it comes to loading 100s of textures during the start of a demo or game.

Indeed, FPImage is not very fast... This was also extensively proven and compared against many other image libraries. The convenience is that you have NO 3rd party dependencies and your code is 100% cross-platform. So you need to trade up the options. If you one need to load a handful of textures, then FPImage will do perfectly and you probably wouldn't notice any speed penalties.

http://members.upc.nl/h.speksnijder4/software/fpGUI/imagesread.html http://members.upc.nl/h.speksnijder4/software/fpGUI/pngloader.html

Speed aside, all the OS imaging libs also provide vastly superior image manipulation including scaling, blending, and all support matrix color operations on pixels.

Sorry, but it is definitely not that black & white. I know of many libraries that perform better than native OS libraries, and have better rendering results too. AGG vs GDI+ is one such example - the AGG library renders much better anti-aliasing and font rendering than anything Microsoft has created. See the documentation and research sections on this website:

http://antigrain.com/

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

Reply by email

Ryan Joseph
to Michael Van Canneyt: You don't need TFPCustomCanvas. TFPCustomImage is an abstract image class, it provides no…
On Oct 12, 2015, at 2:25 PM, Michael Van Canneyt wrote: TFPCustomImage is an abstract image class, it provides no storage for the data. It can have several descendants such as TFPMemoryImage and TFPCompactImgRGBA8Bit. If you just want the raw data, create a TFPMemoryImage and access the Colors array property.

Sorry for the silence.

I’ve learned that the FPImage classes are pretty slow but I’d like to try them anyways first to see if they’re acceptable.

I don’t use Delphi so the FPC docs are a little confusing for me. There is a colors/pixels property but from what I can tell they map to getting a single pixel/color at a specific location, but the docs aren’t clear because the method arguments are never shown.

Do I need to loop through all the pixels or something and pack them into a pointer? There should be some a single continuous block of memory in this class but I can’t seem to find it using the colors/pixels property. What am I missing?

==========

http://lazarus-ccr.sourceforge.net/docs/fcl/fpimage/tfpmemoryimage.html http://lazarus-ccr.sourceforge.net/docs/fcl/fpimage/tfpcustomimage.html

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Reimar Grabowski: On Sun, 11 Oct 2015 16:36:56 +0700 http://sourceforge.net/p/asmoday/code/HEAD/tree/trunk/a…
Show quoted text 5 lines
On Oct 12, 2015, at 8:39 PM, Reimar Grabowski wrote: http://sourceforge.net/p/asmoday/code/HEAD/tree/trunk/asmtypes.pas#l203 Not an example but a straightforward texture class implementation based on TFPCustomImage. Should work as is for bmp, jpg, png, tga, xpm, if not drop me a line.

Thanks, this is really helpful.

I see how you populated TFPCustomImage and generated “Data” to store the color values.

Is it necessary to build an entire subclass or can I just use TFPMemoryImage to achieve the same effect? I understand now TFPCustomImage is an abstract class but TFPMemoryImage apparently has stored values so I should be able to access the “Data” property but these seem to be accessors to getting single pixel values so I can’t just pass the entire block into glTexImage2D like you did.

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Graeme Geldenhuys: Indeed, FPImage is not very fast... This was also extensively proven and compared against…
On Oct 12, 2015, at 5:52 PM, Graeme Geldenhuys wrote: http://members.upc.nl/h.speksnijder4/software/fpGUI/pngloader.html

Thanks for the links. BeRoPNG seems to load a PNG and the author states it’s fast and has no external dependancies. Fantastic.

According to Reimar’s code the raw image data is sufficient for glTexImage2D so I wonder if the data pointer returned from BeRoPNG would work also?

In my Apple CoreGraphics code I was drawing the image into a bitmap context and getting pixel data from the bitmap but that seems to be an extra step now.

Regards,
Ryan Joseph

Reply by email

Michael Van Canneyt
to Ryan Joseph: Thanks, this is really helpful. I see how you populated TFPCustomImage and generated…
Ryan Joseph wrote 17 lines
> On Oct 12, 2015, at 8:39 PM, Reimar Grabowski wrote: > > http://sourceforge.net/p/asmoday/code/HEAD/tree/trunk/asmtypes.pas#l203 > > Not an example but a straightforward texture class implementation based on TFPCustomImage. Should work as is for bmp, jpg, png, tga, xpm, if not drop me a line. Thanks, this is really helpful. I see how you populated TFPCustomImage and generated “Data” to store the color values. Is it necessary to build an entire subclass or can I just use TFPMemoryImage to achieve the same effect? I understand now TFPCustomImage is an abstract class but TFPMemoryImage apparently has stored values so I should be able to access the “Data” property but these seem to be accessors to getting single pixel values so I can’t just pass the entire block into glTexImage2D like you did.

If you need access to the actual memory block, then you must create another subclass of TFPCustomImage. TFPMemoryImage stores rgba in 4 word values which is the 'maximum' storage allowed by the API. There are other subclasses with more common formats, see my other mail.

Michael.

Reply by email

Michael Van Canneyt
to Ryan Joseph: Sorry for the silence. I’ve learned that the FPImage classes are pretty slow but I’d…
Ryan Joseph wrote 16 lines
> On Oct 12, 2015, at 2:25 PM, Michael Van Canneyt wrote: > > TFPCustomImage is an abstract image class, it provides no storage for the data. It can have several descendants such as TFPMemoryImage and TFPCompactImgRGBA8Bit. > If you just want the raw data, create a TFPMemoryImage and access the Colors array property. Sorry for the silence. I’ve learned that the FPImage classes are pretty slow but I’d like to try them anyways first to see if they’re acceptable. I don’t use Delphi so the FPC docs are a little confusing for me. There is a colors/pixels property but from what I can tell they map to getting a single pixel/color at a specific location, but the docs aren’t clear because the method arguments are never shown. Do I need to loop through all the pixels or something and pack them into a pointer? There should be some a single continuous block of memory in this class but I can’t seem to find it using the colors/pixels property. What am I missing?

Your are not missing anything, you saw correct.
TFPCompactImgRGBA8Bit is probably what you need, you'll need to subclass it to get direct access to the

   FData: PFPCompactImgRGBA8BitValue;

field, which is the memory buffer.

Michael.

Reply by email

Michael Van Canneyt
to Michael Van Canneyt
Michael Van Canneyt wrote 32 lines
On Wed, 14 Oct 2015, Ryan Joseph wrote: > >> On Oct 12, 2015, at 2:25 PM, Michael Van Canneyt >> wrote: >> >> TFPCustomImage is an abstract image class, it provides no storage for the >> data. It can have several descendants such as TFPMemoryImage and >> TFPCompactImgRGBA8Bit. >> If you just want the raw data, create a TFPMemoryImage and access the >> Colors array property. > > Sorry for the silence. > > I’ve learned that the FPImage classes are pretty slow but I’d like to try > them anyways first to see if they’re acceptable. > > I don’t use Delphi so the FPC docs are a little confusing for me. There is > a colors/pixels property but from what I can tell they map to getting a > single pixel/color at a specific location, but the docs aren’t clear > because the method arguments are never shown. > Do I need to loop through all the pixels or something and pack them into a > pointer? There should be some a single continuous block of memory in this > class but I can’t seem to find it using the colors/pixels property. What > am I missing? Your are not missing anything, you saw correct. TFPCompactImgRGBA8Bit is probably what you need, you'll need to subclass it to get direct access to the FData: PFPCompactImgRGBA8BitValue; field, which is the memory buffer.
Type
TMyImage = Class(TFPCompactImgRGBA8Bit)
Public
   property Data :  PFPCompactImgRGBA8BitValue read FData;
end;

Should do it. Or if you don't need Alpha:

TMyImage = Class(TFPCompactImgRGB8Bit)
Public
   property Data :  PFPCompactImgRGB8BitValue read FData;
end;

You could throw in a property to get a direct pointer to a scanline. I should maybe add that to the base classes...

Michael.

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt

Hello Michael,

Michael Van Canneyt wrote
You could throw in a property to get a direct pointer to a scanline. I should maybe add that to the base classes...

+1

fpGUI's Image class has both ImageData and ScanLine[] properties, and they are very useful for fast access to the actual pixel data. When I work with FPImage, I always have to go via Pixels[] array which I assume will have a speed penalty.

ps:
Thanks for the subclass idea to surface the Data property - that will be very useful too.

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

Reply by email

Graeme Geldenhuys
to Ryan Joseph: Thanks for the links. BeRoPNG seems to load a PNG and the author states it’s fast and…

Hello Ryan,

Ryan Joseph wrote
According to Reimar’s code the raw image data is sufficient for glTexImage2D so I wonder if the data pointer returned from BeRoPNG would work also?

I assume it should work. I guess there is only one way to found out. ;-)

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

Reply by email

Ryan Joseph
to Graeme Geldenhuys
On Oct 14, 2015, at 4:59 PM, Graeme Geldenhuys wrote: I assume it should work. I guess there is only one way to found out. ;-)

Yes it did work which is nice.

I didn’t do any speed tests yet but from what I read this unit is faster than FPImage and it's easier to implement also, being just a single function.

Thanks.

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Michael Van Canneyt: Type TMyImage = Class(TFPCompactImgRGBA8Bit) Public property Data : …
Show quoted text 17 lines
On Oct 14, 2015, at 1:49 PM, Michael Van Canneyt wrote: Type TMyImage = Class(TFPCompactImgRGBA8Bit) Public property Data : PFPCompactImgRGBA8BitValue read FData; end; Should do it. Or if you don't need Alpha: TMyImage = Class(TFPCompactImgRGB8Bit) Public property Data : PFPCompactImgRGB8BitValue read FData; end; You could throw in a property to get a direct pointer

TFPCompactImgRGBA8Bit descends from TFPMemoryImage I assume? I need to draw text as textures also and I found an example at http://wiki.freepascal.org/fcl-image#Drawing_text which uses TFPMemoryImage.

Thanks for the example, I’ll give this a try.

Regards,
Ryan Joseph

Reply by email

Mattias Gaertner
to Ryan Joseph
Show quoted text 20 lines
> On Oct 14, 2015, at 1:49 PM, Michael Van Canneyt wrote: > > Type > TMyImage = Class(TFPCompactImgRGBA8Bit) > Public > property Data : PFPCompactImgRGBA8BitValue read FData; > end; > > > Should do it. Or if you don't need Alpha: > > TMyImage = Class(TFPCompactImgRGB8Bit) > Public > property Data : PFPCompactImgRGB8BitValue read FData; > end; > > You could throw in a property to get a direct pointer TFPCompactImgRGBA8Bit descends from TFPMemoryImage I assume?

Actually it works like TFPMemoryImage and descends from TFPCustomImage. The only difference is that it uses 4*8=32bit per pixel instead of 4*16bit.

It is only a few lines of code, so if you need a different pixel format or scan lines it is really easy to create your own image class.

I need to draw text as textures also and I found an example at http://wiki.freepascal.org/fcl-image#Drawing_text which uses TFPMemoryImage.

Mattias

Reply by email

Ryan Joseph
to Mattias Gaertner
Show quoted text 5 lines
On Oct 15, 2015, at 4:38 PM, Mattias Gaertner wrote: Actually it works like TFPMemoryImage and descends from TFPCustomImage. The only difference is that it uses 4*8=32bit per pixel instead of 4*16bit.

Are any of these FPImage classes documented or should I just try to dig around the FPC sources to find these things? There are dozens of classes available at http://wiki.freepascal.org/fcl-image but I don’t know what any of them do.

Regards,
Ryan Joseph

Reply by email