MixImages function help
BlitzPlus Forums/BlitzPlus Programming/MixImages function help
| ||
Hello everybody! I need an help. I need to speed up a little this function...can anyone help me? Thanks!Function MixImages(mix,ima1,ima2) b1=ImageBuffer(ima1) b2=ImageBuffer(ima2) bm=ImageBuffer(mix) LockBuffer b1 LockBuffer b2 LockBuffer bm For y=0 To Screen_Height For x=0 To Screen_Width c1=ReadPixelFast(x,y,b1) c2=ReadPixelFast(x,y,b2) WritePixelFast x,y,c1+c2,bm Next Next UnlockBuffer bm UnlockBuffer b2 UnlockBuffer b1 End Function |
| ||
right, you cant just add the 2 colors. what you are going to have to do is split the color into its red, green, and blue components, add these together, and write back. theres functions to split/combine colors in the archives :) |
| ||
Three thoughts on your dilemna. First: When you use the following line: WritePixelFast x,y,c1+c2,bm you have to remember that the red, green, and blue values each are limited to values of 0 to 255. If you do a straight across the board c1+c2, where if the sum of any red, green, or blue values could add together to more than 255, there could be unpredictable results. Try this to illustrate what I am saying: Graphics 800,600 c1=$ffaabbcc ;using red, green, blue values that will c2=$ffaabbcc ;overflow, that is, go greater than 255 each c3=c1+c2 Print Hex$(c3) ;this operation effectively halves the color Color $aa,$bb,$cc ;ie the original color Rect 100,100,200,200 Color (c3 And $ff0000) Shr 16,(c3 And $ff00) Shr 8,(c3 And $ff) ;ie the colors added togther Rect 400,100,200,200 MouseWait() End Second: I don't know what the effects are of using the lockbuffer command three times sequentially. Maybe some other voices can address this point. Third (to go faster): You could try reading the color values of the images into arrays, then instead of doing ReadPixelFast on-the-fly, the values could just be read back in from the array. It's a little more memory intensive, but is faster. In other words, put the following OUTSIDE the function: dim c1(Screen_Width-1,Screen_Height-1);arrays are global dim c2(Screen_Width-1,Screen_Height-1) For y=0 To Screen_Height For x=0 To Screen_Width c1(x,y)=ReadPixelFast(x,y,b1) c2(x,y)=ReadPixelFast(x,y,b2) Next Next Then you can access that info inside your Function: For y=0 To Screen_Height For x=0 To Screen_Width WritePixelFast x,y,c1(x,y)+c2(x,y),bm Next Next Of course, this latter bit of code still doesn't address the issue of summing RGB color values together when they can overflow past 255 within their 0-255 range. Depending on what you want to do, you might read in the red, green and blue values separately into intergers, add the integers together and divide by two (if an average is what you're looking for), or just let the color info max out at 255. Generally, these two concepts are illustrated thus: my_red = (c1_red+c2_red)/2 ;if averaging is what you want (OR) my_red = (c1_red+c2_red):if my_red>255 then my_red=255 |
| ||
I've tried to make something like what you said:Dim c1(Screen_Width-1,Screen_Height-1) Dim c2(Screen_Width-1,Screen_Height-1) Dim cm(Screen_Width-1,Screen_Height-1) Function MixImages(mix,ima1,ima2) buf1=ImageBuffer(ima1) buf2=ImageBuffer(ima2) bufm=ImageBuffer(mix) LockBuffer buf1 LockBuffer buf2 LockBuffer bufm For y=0 To Screen_Height-1 For x=0 To Screen_Width-1 c1(x,y)=ReadPixelFast(x,y,buf1) c2(x,y)=ReadPixelFast(x,y,buf2) Next Next For y=0 To Screen_Height-1 For x=0 To Screen_Width-1 red1=GetRed(c1(x,y)) : red2=GetRed(c2(x,y)) green1=GetGreen(c1(x,y)) : green2=GetGreen(c2(x,y)) blue1=GetBlue(c1(x,y)) : blue2=GetBlue(c2(x,y)) rm=red1+red2 : If rm>255 Then rm=255 gm=green1+green2 : If gm>255 Then gm=255 bm=blue1+blue2 : If bm>255 Then bm=255 cm(x,y)=Combine(rm,gm,bm) Next Next For y=0 To Screen_Height-1 For x=0 To Screen_Width-1 WritePixelFast x,y,cm(x,y),bufm Next Next UnlockBuffer bufm UnlockBuffer buf2 UnlockBuffer buf1 End Function But it is slower than what I wrote yesterday! I think that using all this arrays it isn't usefull. Is the code similar to what you thought? A last question: how can I wrote the codes in green in this forums? Thanks! |
| ||
What are the forum codes? |
| ||
Thanks Tiger! |
| ||
When you add the colors together, what effect are you trying to make happen? In other words, "why" are you adding the colors together? Depending on the effect, you might do better to logically "OR" them, or logically "AND" them. For example, instead of c3=c1+c2, use this:c3= (c1 OR c2).or use this: c3=(c1 AND c2) Whenever you are inside a loop, you always want the fastest possible operations occurring. The closer you can get to the LEAST number of operations occurring inside a loop, the faster will be the loop's total execution time. Also, certain operations are FASTER than others. IF you can logically OR/AND them, that will be faster than adding them together and then dividing by two (regarding the logical OR or the logical AND, either operation is only one(1) operation, thereby taking less time than adding and dividing, which are two operations which therefore use more time). Back to your original question, can the READPIXELFAST commands be executed outside the function, or are the graphics content in the imagebuffers going to be ever-changing and therefore have to be done inside the Function? If the latter, then don't bother with the arrays, because that becomes extra work for the CPU, and then of course that takes more time. If this is the situation, go back to your original code, and instead of doing a addition (ie c1+c2) operation, try the (c1 OR c2), or the (c1 AND c2). Ahh, nuts. It's hard to offer suggestions, because I'm not sure what effect you are going for. Could you enlighten me a wee bit? Thanks. |
| ||
I had to Mix two images with the OR operation (thanks, i didn't know that I could write "c1 OR c2") because I had to show the two views of a stereo-camera in only one screen! This is the problem! Yes, it could be written out of the function but since the 2 images change every frame, I must write the ReadPixelFast inside the main loop, and so I cant get any speed improvement... Otherwise I can texture 2 sprites (with alpha=0.5) with the images and then render them, but I dont know how far must they be from the camera, in order to render them in 1:1 scale factor. I should try with Orthographic Projection... mmh... let's try! |
| ||
Nothing to do... it works very fast but the sprites are shifted a little and the textures on them seem to be smaller than the screen width-height. Can anyone tell me how to solve this bug? (Texture size and offset from camera) |
| ||
Yes, the OR operation would blend two colors together, and there is no need to separate out the individual RGB values either to do it (time saver, there). Logical AND tends to subtract colors, rather than blend them together. In fact, logical AND is what is used to mask a graphics image so that the non-black portion of an image is rendered, but not the black portion (assuming of course that the default COLOR 0,0,0 is used for the transparent mask color). Back to your speed problem. After thinking about it a bit, I realized that you are doing the readpixelfast / writepixelfast on a LOT of pixels! At 640x480, you are reading 307200 pixels each for b1 and b2, and then OR-ing those together and writing 307200 pixels, for a total of 921600 pixels. At 800x600, the total jumps to 1440000 pixels! That's smokin'! If I understand your application, you are working in the Graphics3d mode (you mentioned Texture and Camera), and are trying to do a 3d-stereoscopic-type image. If this is the case, is it necessary to do the entire screen's area for each imagebuffer, or can you get away with a portion of the screen? If you MUST use the entire screen, take a look at the triple lockbuffer commands set you are using in your Function as I mentioned in point 2 of my original response. I don't know if using three lockbuffers is OK, or if they are in any way impeding each other. One way to find out, is to lockbuffer the first imagebuffer, read its color info into an array, then unlock it and lock the second imagebuffer, reading it into another array, unlock it, then lock the third imagebuffer, and writepixelfast (via logical OR) the two array values into it, finally unlocking it. See if that causes any speed increase. |
| ||
Hello, I was re=reading your original code. The following three lines are incorrect, I think:b1=ImageBuffer(ima1) b2=ImageBuffer(ima2) bm=ImageBuffer(mix) The docs show imagebuffer as a command to use with setbuffer, as in: Setbuffer Imagebuffer(handle) From the code Function MixImages(mix,ima1,ima2)I assume that you are supplying the Function with image handles. Therefore, if I understand the command properly, the proper way to use it inside your function would be like this: ;arrays are global, so they will be seen inside your function Global Const Screen_Width=640 Global Const Screen_Height=480 dim b1array(Screen_Width-1,Screen_Height-1) dim b2array(Screen_Width-1,Screen_Height-1) ;arrays are dimensioned minus one, because they start ;counting at 0, ie (0 to 639) x (0 to 479) for 640x480 ; Function MixImages(bm,b1,b2) ;where bm,b1 and b2 are the graphic images handles ;you are mixing together. LockBuffer Imagebuffer(b1) For y=0 To Screen_Height-1 For x=0 To Screen_Width-1 b1array(x,y)=ReadPixelFast(x,y) Next Next unLockBuffer Imagebuffer(b1) LockBuffer Imagebuffer(b2) For y=0 To Screen_Height-1 For x=0 To Screen_Width-1 b2array(x,y)=ReadPixelFast(x,y) Next Next unLockBuffer Imagebuffer(b2) LockBuffer Imagebuffer(bm) For y=0 To Screen_Height-1 For x=0 To Screen_Width-1 WritePixelFast x,y,(b1array(x,y) OR b2array(x,y)) Next Next unLockBuffer Imagebuffer(bm) End Function |
| ||
The commandsb1=ImageBuffer(ima1) b2=ImageBuffer(ima2) bm=ImageBuffer(mix) are ok, because the function "ImageBuffer()" return the handle of the image buffer, and so it is more quick use a variable (b1,b2,bm) instead calling every time ImageBuffer()... now I'll try your last code... wait! |
| ||
Nothing... FPS are the same! And so it means that lock 3 buffer it's allowed, too! I think the only way is to reduce the resolution (but it is about 11 Fps at 320x200!!!) to reduce the number of pixel that must be calculated, or use 2 sprites as I say yesterday. The last idea sounds very good, but I don't know how to apply it |
| ||
Don't forget to use Flag 2 for mixing images in Blitz+ 1.34. img1 = LoadImage("image1.bmp",2) img2 = LoadImage("image2.bmp",2) This will make the imagebuffers WAY faster! I discovered also that you should really never mix two different types of image buffers or your program will slow down drastically! [edit] Also, try out the 3 different graphics drivers in Blitz. Native, OpenGL and DirectDraw, and see which one is fastest. Use SetGfxDriver(1 - 3) [/edit] |
| ||
Thanks Cyberseth :) But now I managed to use 2 sprites in front of my camera to mix the 2 images...I need no more help! Anyway, thanks for the tips! :D |
| ||
Now I've added my code to the code archives, 3d section ("Stereoscopic Camera")! Thanks to all the persons who have helped me in this forum! And also thanks for having understood me even if I'm not good in english :D Bye |
| ||
A special thanks comes to Tobias Müller, who has written the "TEXTURE-HUD" code which has helped me a lot! |