Is there a faster way to set pixels in an image than MEM2SPRITE

Previous topic - Next topic

backspace

Hi again,
I was curious to see if I would be able to make small images to be used for paintbrushes in a paint program that I have in mind. It's straight forward to make an image with a 2D painter, but wanted to try to dynamically make all kinds of "paint brushes", so that I do not have hundreds of brush images to clutter the place.

Background:
I wrote a little program that uses SPRITE2MEM and MEM2SPRITE just to see how things would work, since the documentation warns that GETPIXEL can be very slow. The program uses a linear-move (linear-swap without comparing) concept to play around with the pixels. It's a very crude program, but it's the speed of the program that has me a little concerned. The idea is to use a paintbrush image and mix it with a different image on another "screen/buffer" in order to get all sorts of fun filter brush effects.

Code (glbasic) Select
// --------------------------------- //
// Project: spritememToy
// --------------------------------- //

LOCAL pxl%[]
LOCAL res
LOCAL w
LOCAL h
LOCAL x
LOCAL y
LOCAL sw
LOCAL sh
LOCAL barrel%
LOCAL i
LOCAL offs1, offs2

LOADSPRITE "prettyImage.png",0
GETSPRITESIZE 0,w,h
GETSCREENSIZE sw,sh
res = SPRITE2MEM(pxl%[], 0)

WHILE 1
FOR y = 0 TO h-1
FOR i = 0 TO w-1
offs1 = (w/2 + i) + (y*h)
offs2 = (w/2 + i+1) +(y*h)
barrel% = pxl%[offs1]
pxl%[offs1] = pxl%[offs2]
pxl%[offs2] = barrel%
NEXT
MEM2SPRITE (pxl%[], 0, w, h)
NEXT
DRAWSPRITE 0, sw/2-w/2, sh/2-h/2

PRINT w+" "+h, 10,10
SHOWSCREEN
WEND


Question:
There are nothing wrong with the MEM functions, but they may be too slow for what I have in mind. Are MEM functions the fastest way to manipulate pixels in an image, or is there a faster way?  I could go the INLINE route, but then it moves out of the realm of what I want to teach the kids in my computer lessons. I hope there is a solution, else I may have to leave out this fun little exercise in my course.
My program itself may also be the problem, and it is perhaps just too crude for the mission.

Edit: I've included the image I used for my tests.

[attachment deleted by admin]
I came, I saw, I coded.

kanonet

There are two fast ways that i can imagine atm:
1. mem commands, what you already tried.
2. draw everything with polyvector
   a on screen and grab it or
   b on a offscreen

Dont draw all brushes every loop, just draw them when they get used, then grab the image and use the result as starting image for the next loop, draw some new brushes again, grab the result and use it as background for next loop...
Should be fast and looking fine, the only downside is that you cant undo drawn brushes without much work.
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

hardyx

There is a faster way to make thinks allways, like using INLINE code or assembler or some trick. But if you are teaching in a course, MEM2SPRITE is a good and fast way. Other way is using a "buffer" or auxiliar screen in memory, draw in memory and dump this screen to the real screen.

If you want to generate some sprites with functions in memory, you must to generate all once, assign to a sprite with MEM2SPRITE, and then use (draw) later. In your example, you can generate the sprite once, and you can draw many times in the WHILE loop. The secret is pre-generate all the data you can for aid in the drawing, and quit the calculus in the draw loop. This way is faster.

Code (glbasic) Select
// Generating sprites
// this code is out of the draw loop
FOR y = 0 TO h-1
FOR i = 0 TO w-1
offs1 = (w/2 + i) + (y*h)
offs2 = (w/2 + i+1) +(y*h)
barrel% = pxl%[offs1]
pxl%[offs1] = pxl%[offs2]
pxl%[offs2] = barrel%
NEXT
MEM2SPRITE (pxl%[], 0, w, h)
NEXT

// draw loop, less calculations = faster
WHILE 1
DRAWSPRITE 0, sw/2-w/2, sh/2-h/2

PRINT w+" "+h, 10,10
SHOWSCREEN
WEND

backspace

I wanted to update the whole screen in the game loop, which if you think of it is really very silly of me. I can see that I need to pre-create my brushes before the game loop, and then use them on a background screen to get the effect I want.

The thing is, that I need to be able to apply smudges, emboss, and a few other sort of fun effects at realtime with a brush, so I need to do this stuff from the draw loop.

I am now thinking of using the old "dirty rectangle" method, by grabbing only the small part of the screen under the brush, and then doing my MEM magic only on that captured part, and then replacing the result back onto the buffer.

Thanks very much for your input, it helped me to see where I was going wrong. I have some homework to do now that you have straightened out my thinking. 
I came, I saw, I coded.

Hemlos

Your classroom sounds like a lot of fun, where do i sign up   :D

Bing ChatGpt is pretty smart :O

backspace

I find that bright kids need a challenge, and they really do amazing things if you give them fun toys. I hate boring classes, so really do try my best to provided courses that the kids enjoy. The course is only for the kids in our school in Pretoria though.
As long as you don't laugh at my mistakes, if you like, I can post some of my classes here once I have the tricky stuff worked out. It may also be a great way for the kids to reference the material online, and maybe also learn more about GLBasic from you boffs.
I came, I saw, I coded.

Hemlos

Quote from: backspace on 2013-Jan-09
I find that bright kids need a challenge, and they really do amazing things if you give them fun toys. I hate boring classes, so really do try my best to provided courses that the kids enjoy. The course is only for the kids in our school in Pretoria though.
As long as you don't laugh at my mistakes, if you like, I can post some of my classes here once I have the tricky stuff worked out. It may also be a great way for the kids to reference the material online, and maybe also learn more about GLBasic from you boffs.

That would be a great use for the forums, and i would definetly encourage you to use it for all those reasons.
For your students to easily reference what you do here, title your threads with "Pretoria: project#1234" or "Pretoria: tutorial #1234" whatever your naming convention may be...
..from the root of the forums, they can search after they login, for "Pretoria" for a full list of your threads.

If you build it in the form of tutorials, feel free to use the tutorial section of the forum.
If its going to be just a bunch of code and projects, use any of the correlatiing codesnippet sections.

Bing ChatGpt is pretty smart :O

kanonet

Every forum account has a blog, you can also use this to publish there.
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

Moru

The tutorial forum can't have too many tutorials, we would love to see more there!

backspace

Thank you all for you most excellent suggestions. I shall certainly refer back to them when I am ready to post my lessons.
One very noob question though. A forum Blog? Where would I find this? Ok, that's 2 questions then :P
I came, I saw, I coded.

kanonet

To find it, just click on "blogs" left of "log out", or simply follow this link: http://www.glbasic.com/forum/index.php?blog=15572
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64