Fast, direct pixel access? lazarus / 8-Other ---------------------------------------------------------------------- idog · 2009-10-21 18:49 Hi, I'm looking for the fastest way to access on-screen pixels. I know there's OpenGL and other third-party components, but since it's an educational project I'm looking for the "purest" and leanest solution within the basic LCL. In essence, I want to have some component on a form (TPaintBox?), and some pixel-compatible arrays in memory, and to be able to copy these arrays directly to [x,y] locations in that component. Is there a safe way to access the memory used by a TCanvas, or a similar option? Thanks in advance. ---------------------------------------------------------------------- idog · 2009-10-23 23:16 ok... if nobody knows then I guess I'll just have to find the solution myself! After digging through many an obscure sourcecodes and webpages, and doing some hair-raising experimentation, I came up with something that runs fairly quick. Can someone at least tell me if its safe, or will it crash other systems (and why)? I'm running this with Lazarus 0.9.29, Vista 32 bit. 1. I have a TImage component on the form called Image. 2. At form's OnCreate, I do:     Image.Picture.Bitmap.SetSize(SomeX, SomeY);     Image.Picture.Bitmap.PixelFormat :=pf24Bit; // for simple, 3-byte R/G/B pixels 3. For drawing:    var p : PByte; j : Integer; b : Byte;     Image.Picture.Bitmap.BeginUpdate;     p := Image.Picture.Bitmap.RawImage.Data;     // Example of filling raw image with data     for j := 1 to SomeY do       begin          b := Random(256);          FillChar(p^, SomeX * 3, b);          inc(p, SomeX * 3);       end;     Image.Picture.Bitmap.EndUpdate;     4. And voila - gray lines run like crazy. I estimate ~200 fps for a 640x400 image. [Edit: Discovered one more important thing that got me worried: this only works if something is painted on the canvas in the "normal" manner afterwards. Otherwise, the image remains empty. ??] ---------------------------------------------------------------------- skalogryz · 2009-10-23 23:29 Are you sure that this code is portable between platforms. Even R,G,B(,A) order might be different on each widgetset. Though, it's protable enough for graylines. ---------------------------------------------------------------------- idog · 2009-10-23 23:38 My question percisely, Skalogryyz! I'm having a hard time figuring out the inner workings of these graphic classes. I trial-and-errored until I came up with this solution, so now I'm asking the experts here - is this safe? cross- platform-able? Of course, the gray lines are just for the example. in my application I'll use colored pixels, images etc. ---------------------------------------------------------------------- felipemdc · 2009-10-28 18:06 Why not using TLazIntfImage? Here is an example (the second code, not the first one which is for Delphi): http://wiki.lazarus.freepascal.org/Developing_with_Graphics#A_fading_e xample ---------------------------------------------------------------------- idog · 2009-10-28 21:13 If I'm not mistaken, this will only add a buffer between my data and the canvas and slow things down. How is accessing a Canvas' pixels using the Canvas properties different from accessing the LazintfImage pixels and then copying it to the canvas? And again, I intend to write an educational application that demonstrated programming techniques, not "how to use a ready made tool" :-) ---------------------------------------------------------------------- theo · 2009-10-28 21:48 Afaik, Canvas.Pixels is calling the interface for every single pixel, like gdk_draw_point(DC.Drawable, DC.GC, X, Y); in case of GTK while a LazIntfImage is filling the pixels in an array and only copy the whole thing to the interface when the image is completed. The latter should be much faster when changing a lot of pixels. ---------------------------------------------------------------------- tk · 2009-10-28 22:19 You must use lazintfimage for this with appropriate raw image format. But beware it is still little bit buggy or incomplete depending on lazarus version you use. If running the app on different platforms you might get wrong results e.g. for alpha blending etc. - depending on lazarus version you use. ---------------------------------------------------------------------- idog · 2009-10-28 22:46 Ok, thanks all. I guess it's the price one has to pay for cross- platform compatibility  Theo: Indeed, if TLazInfImage pixels are just a direct-access array then that solves my major problem. tk: In this particular case, I'm actually using only simple pixel color assignments, so hopefully there won't be any problems... We'll see. ---------------------------------------------------------------------- Marc · 2009-10-29 11:40 BTW, if oyu want to manipulate the pixels of a TRasterImage (=bitmap/png/jpeg/..) then you can also use:Code: [Select]var   bmp: TBitmap;   RI: TRawImage; begin   ...   bmp.BeginUpdate(..);   RI := bmp.RawImage;     //do your stuff   bmp.EndUpdate(..)    ... end; See sample ---------------------------------------------------------------------- idog · 2009-10-29 12:36 Thanks Marc. Actually, that's more or less what I did to begin with - I have my pixel data stored at some allocated DataPtr, and I -   Move(DataPtr^, Pointer(Bmp.RawImage.Data)^, SizeInBytes);  From what I understand now, to make the program cross-platform-able I need to take into considerations the parameters of the RawImage.Description... and this is what TLazIntfImage already does. Correct? ---------------------------------------------------------------------- Marc · 2009-10-29 12:57 Quote from: idog on October 29, 2009, 01:36:57 pmFrom what I understand now, to make the program cross-platform-able I need to take into considerations the parameters of the RawImage.Description... and this is what TLazIntfImage already does. Correct? Yes and no. If you Move() the data, TLazIntfImage doesn't help you. But if you Move() the data in a TLazIntfImage according its description and you assign that TLazIntfImage to another TLazIntfImage with another (maybe platform dependent) description is helps, but.... it copies the data pixel by pixel, converting it from the first description to the latter. If you generate your data according to the Bmp.Rawimage.Description, then you don't need a TLazIntfImage adn it works cross platform. ---------------------------------------------------------------------- idog · 2009-10-30 02:40 Yes, I believe that's the method I was looking for. Thanks Marc! The problem is, I only have Windows 32 bit to test and debug this on... so I'm counting on the Lazarus community to test it when it's finished and yell at me if it crashes their OSs