pixelmap mirror.

BlitzMax Forums/BlitzMax Beginners Area/pixelmap mirror.

ssdw(Posted 2010) [#1]
hello everyone,

it is possible to turn (mirror) a pixelmap (horizontal).
it must be fast, because many pictures must be mirrored!
does anyone know my answer?

Thanks!


ima747(Posted 2010) [#2]
If you're talking about when you draw an image itself I think the fastest and easiest method is likely using SetScale(-1, 1) which will draw the image inverted along the X axis but still normally along the Y (basically left/right are reversed).

If you actually want to invert the pixmap data itself the easiest way would be to do the mirrored drawing of an image and then use GrabPixmap() to pickup the mirror into a new pixmap.

A less graphics-centric method would be to create a new pixmap and copy the existing pixmap into it 1 pixel at a time but inverting the x offset of either source or destination.

A less memory intensive verison of the pixel copy could go line by line through a pixmap, store the value of a pixel along X, copy it's contents from the oposite side, then place the stored value in that oposite side postion, this will be less memory intensive as you wouldn't need 2 pixmaps...

I'm sure there are plenty of other methods as well these just come to mind.

But I suspect all you want to do it draw an image mirrored in which case just SetScale() :0) This also means you won't need a normal AND flipped copy of the image in memory (and then texture memory as well), and it's fully accelerated by the graphics card so it will be fast. I suspect that's the easiest/fastest/least resource intensive way to do what I think you want to do.


Oddball(Posted 2010) [#3]
Or use the function
XFlipPixmap(yourpixmap)


Last edited 2010


ssdw(Posted 2010) [#4]
they do it all, but it's about the speed.
The game uses a camera, the frames are loaded as a pixelmap, but it can also be an image. because it must can detect movements, I chose pixelmap.
Each frame should be mirrored, hence the speed is important.

Now I use XFlipPixmap, unless someone has a faster way.
Thanks for the help!

Last edited 2010


ima747(Posted 2010) [#5]
Wow, never even noticed XFlipPixmap() before... then again I've never had to flip one myself before... still nice to know :0)


ziggy(Posted 2010) [#6]
If you use the setscale -1,1 it'll be faster than fliping the pixmap.


ima747(Posted 2010) [#7]
Ya, but depends on what you want it flipped for... Drawing you're best off with images for speed, but saving editing etc you may need pixmaps... Good to have options, just gotta think through what's best for a given goal.


ssdw(Posted 2010) [#8]
how do I put SetScale -1,-1 in the code?
I put SetScale -1,-1 in the loop but nothing happened!


Jesse(Posted 2010) [#9]
it doesn't work for Tpixmap only for Timage.

Last edited 2010


ssdw(Posted 2010) [#10]
then I use XFlipPixmap()
thanks


ima747(Posted 2010) [#11]
if you go the image route (query: why are you drawing pixmaps directly especially if speed is a concern?) you want SetScale(-1,1). SetScale(-1,-1) would invert along both X and Y...


ssdw(Posted 2010) [#12]
is there another way to draw a pixelmap? a faster way.


ima747(Posted 2010) [#13]
make a timage out of it... images are stored in vram and have full graphics acceleration, and can be modified when drawn through all the max2d commands (setscale, setrotation, etc.) but since they exist on the graphics card essentially they are harder to manipulate on the pixel level. Pixmaps have to essentialy be pushed through the graphics card every time they are drawn, additionally they don't draw as reliably since how you get them to the screen varies from os to os and graphics system (opengl vs. directx). and they don't respond to the graphics commands (as you've seen with setscale not working). So they take much longer to draw, and are much harder to manipulate on the fly. However since you have pixel level access, and they exist in normal memory space you can easily modify them on a pixel level, and do other things with the raw data (like save it).

You can make an image out of a pixmap with LoadImage(a_pixmap_as_the_source), and if you create an "editable" image, you can also extract the pixmap back from the image if needed with LockImage(an_editable_TImage). You can load images directly from files as well... To generalize pixmaps are intended for editing pixels, images are intended for drawing.


ssdw(Posted 2010) [#14]
I need pixelmap, because each time must (a few) pixels read.
If I use an image for the screen. and use SetScale(-1,1) to mirron it.
and use the pixelmap for the information, is that faster?
The pixelmap need not be mirrored!


ima747(Posted 2010) [#15]
Should be much faster since you won't be drawing the pixmap. It will be higher memory usage since you will essentially have 2 copies of the data in memory. Depends which resource you have more room with, CPU or ram as to which would be better.


ziggy(Posted 2010) [#16]
Pixmax = Fast pixel information for calculations, etc. SLOW draw operations
Image = Fast accelerated draw operations, including alpha, scales, transforms, rotations, etc. Not valid for pixel information requests.
If you need both, you would be better off using both at the same time.


ima747(Posted 2010) [#17]
My clarifications can get... muddied :0)
Thanks ziggy, sums it up nicely.


TomToad(Posted 2010) [#18]
haven't tested anything, but I would think that using a TImage, and then LockImage()/UnlockImage() whenever you need to read or modify pixel data would be best.


TomToad(Posted 2010) [#19]
Just ran some tests. On a test program I wrote, I got 74 FPS with Pixmaps only. I got 120 FPS using Pixmaps, then LoadImage(Pixmap) to draw the pixmap. I got 247 FPS by using TImage and LockImage(Image) to modify the pixels.


Oddball(Posted 2010) [#20]
If you are only reading the pixel data then it's much faster to keep a copy of the pixmap and the image. Just use the pixmap for reading pixels and the image for rendering to the screen. No need to lock/unlock anything.

Also on another note unlock doesn't actually do anything. It's just an empty function. You only need to lock a TImage there is no need to unlock it again. Also, if you keep a pixmap reference of the TImages pixmap, that's the one you get from lock, then you don't even need to lock it before altering the pixmap. You only need to lock it at some point before you draw it. I occasionally do this if I'm performing lots of pixel pushing on an image. When it comes time to draw the image I check if the pixmap has changed and if it has I perform the LockImage before I draw it.


ima747(Posted 2010) [#21]
re tom:
I wouldn't suggest using LoadImage(pixmap) every frame (implication I got from your post) but it's interesting that even that is faster than drawing pixmaps directly...

If you want maximum speed, and you don't need to MODIFY the pixmaps, only read them (i.e. no visible changes), and you can afford the overhead then having a pixmap to "look at", and a seperate TImage (loaded once at startup) is going to be fastest since you are only loading once, and drawing only TImages.

Also interesting how fast the lock/unlock swapping apparently is for taking a peak, but it's still going to create overhead vs. just having a pixmap (disconnected) ready to go at all times.


re oddball:
despite unlock being empty I would personally still follow the documented "flow" since all of bmax's graphics functions are interface masks for driver/os specific things, you never know when the substructure might change in the future... e.g. this might be totally 100% fine for windows directx7, but what about dx 9, or opengl, or linux opengl? etc. If speed right now is your concern it's an interesting optimization but it could come back to cause some serious headaches down the road...


ssdw(Posted 2010) [#22]
The image must be repeatedly loaded, because The picture is always different. therefore the speed is important..
If I use loadimage() and nothing happens. no error and no picture on the screen.
Timage and Tpixmap works, but is not faster.


Jesse(Posted 2010) [#23]
if you can post the code maybe we can figure out the best way or an alternative route.


Oddball(Posted 2010) [#24]
@ima747: All LockImage does is remove the texture from graphics memory so that next time it is drawn it must be recreated from the edited pixmap. In that respect it is not so unlike LoadImage(pixmap) the main difference being that with LoadImage the pixmap is copied and resized first which accounts for it being slower. The way Max2D handles image textures means that the LockImage internal code is unlikely to change dramatically. I'd consider UnlockImage deprecated at this point. I don't quite get your point about it working differently with each driver as there is absolutely no code at all in the UnlockImage source. I don't see how no code can run differently on different systems.


ima747(Posted 2010) [#25]
Not having dipped into the source proper in many many months I'll defer to your assessment. My interest in sticking with the prescribed cycle is for future proofing. There's nothing in unlock image now, but what about bmax 1.5? Maybe there will be to support some new improvements etc. It could also be overridden in future. Basically it's the old "it's probably there for a reason" syndrome, but I've gotten myself in trouble in the past for ignoring that :0) if it gets officially depreciated I'll be revising all my code accordingly.


TomToad(Posted 2010) [#26]
I'm not certain that LoadImage(pixmap) is faster than drawing pixmaps directly. My test would load a png, modify 10 pixels each frame, flip the image then draw it. Drawing pixmaps directly, I need to first use XFlipPixmap(), but using LoadImage, I can just use SetScale -1,1 instead. That probably explains why it is faster.

As for using LoadImage() each frame, I was under the impression that the pixmap will need to be modified every frame, so my test reflects that.

For using UnlockImage(), it's true that it is an empty do-nothing function, but I tend to use it anyway for the same reason that ima747 does. Just in case in the future, it actually does something.


ima747(Posted 2010) [#27]
Regardless of what's being done it's pretty clear that drawing images (even if they have to be modified through lock, or for some reason re-loaded entirely) is way faster than drawing pixmaps (also more reliable, and gives you access to more modifications such as scaling, rotation, etc. and of course collision detection etc. etc. etc.) So long story short, no matter how much you're messing with things it seems faster to draw with images and do your flipping there.

And just to re-state, if you don't need to MODIFY the pixmap, but just peek at the data, having an image for drawing and a pixmap for looking at is going to be the fastest option as there will be no overhead at all compared to any other method (even the very very quick lockimage() is going to cause the data to get re-loaded because that's kind of it's purpose).

I think without code from ssdw to see exactly what he's trying to do, and why he's not seeing improvements we're just playing with applied theory that Tom already tested out :0)


ssdw(Posted 2010) [#28]
Here is the code,



I'll do what ima747 says it's faster.
Thanks everyone!


ima747(Posted 2010) [#29]
Aaah, it looks like you're actually grabbing a fresh pixmap to use as a drawing source via captureframe every cycle. What you have is probably the best combination of simplicity and speed given that. One option that might give slightly better performance (or maybe worse I don't know) would be to just keep one timage, lock it and overwrite it's pixmap every frame, but you will need a very fast method of copying the pixmap data and at best it would not give a huge improvement as the image is still going to have to be pushed to the graphics card.


ssdw(Posted 2010) [#30]
I think this is best!
thanks