Possible bug in CopyPixelFast (Blitz 2D)

BlitzPlus Forums/BlitzPlus Programming/Possible bug in CopyPixelFast (Blitz 2D)

Foppy(Posted 2003) [#1]
There's no bug forum for Blitz 2D anymore, so I thought I would post this here to see if anyone can tell me I am doing something wrong, or that this is indeed a bug. It's about the CopyPixelFast command. I keep getting a "Memory Access Violation" when trying to copy a pixel from an ImageBuffer to the FrontBuffer (or BackBuffer, it doesn't seem to matter, the critical part seems to be the ImageBuffer part). The Help file says this should be "used on a locked buffer" but this is somewhat cryptic as the command works on two buffers. Also, the first buffer in their example is an "ImageBuffer'ed" buffer as well. These can't be locked as far as I know. My own code I have reduced to the following lines. (The image used should of course be at least of size 11*11 as I am reading from position 10,10.) Does anyone have an idea?
Graphics 640,480,16
pic = LoadImage("Graphics/wall_2.png")

LockBuffer

CopyPixelFast 10,10,ImageBuffer(pic),10,10

UnlockBuffer

WaitKey
End
Note that normally I would use brackets and stuff but I changed this to look like the online example (in the end you try everything...). Edit: it's not a case of the image not being loaded, I tested this by adding a DrawImage and WaitKey right after the LoadImage command. It's also not a problem with a wrong video mode (as far as I can tell), I tried removing the 16 in the Graphics command and it doesn't help. Also tried different resolutions.


Floyd(Posted 2003) [#2]
The 'Fast' commands operate on locked buffers.

CopyPixelFast uses two buffers and *both* must be locked.
So you need a 'LockBuffer ImageBuffer(pic)', and Unlock when done.


Foppy(Posted 2003) [#3]
But ImageBuffer(pic) is a call to a function, so I can't use LockBuffer on that can I (or am I mistaken about ImageBuffer?). Or should I do:
mybuffer = ImageBuffer(pic)
LockBuffer(mybuffer)
CopyPixelFast 10,10,mybuffer,10,10
Hmmm...

In the meanwhile here's a picture of the project that I am trying to use this in, it's a raycaster. Currently it uses rectangles to draw the wall slices, but I want to use texture mapping (although if it doesn't work out in the end, the rectangles look nice too and are really fast!). That texturing stuff is working but very slow, and CopyPixelFast could be of some help (maybe it would go from 3 fps to 4 or 5 fps...).



joncom2000(Posted 2003) [#4]
You can Lock any imagebuffer as well as the front and back buffers


Foppy(Posted 2003) [#5]
Ok, thanks to both of you for helping me with this! I will try something like the following (but only by tomorrow as it is quite late here already).
SetBuffer(ImageBuffer(pic))
LockBuffer
Actually that makes a lot of sense, I am using this SetBuffer(ImageBuffer(pic)) idea in other parts of my code as well... Still the example in the Help file under CopyPixelFast appears to be wrong.


injeevious(Posted 2003) [#6]
floppy, i had trouble with my engine to and found it faster to copy images to an array containing their argb values, then read the array and use write pixel fast this got my fps up to 60 fps at 640*480


Foppy(Posted 2003) [#7]
Hey injeevious it took me a few days to realize what you meant but of course you are right, why am I locking things and using "readPixelFast" on an image that will never change anyway, to get those rgb values, it makes no sense... so I will try the array approach. Thanks!


Foppy(Posted 2003) [#8]
There was quite an improvement using an array instead of the image, FPS rate for the textured version went from something like 10/15 to 20/25. That may not sound like much but it is about good enough for a game. But for now I stick to plain walls.


WolRon(Posted 2003) [#9]
from something like 10/15 to 20/25. That may not sound like much


Yes it does, that's a 100% increase!


injeevious(Posted 2003) [#10]
is there a reason that blitz dosen't use arrays for images?


BlitzSupport(Posted 2003) [#11]
I know this is sorta resolved, but for the record (as Floyd said) for the example up there to work ImageBuffer (xxx) should also be locked prior to the CopyPixelFast call, so you'd be doing something like this...

Graphics 640,480,16
pic = LoadImage("Graphics/wall_2.png")

LockBuffer ; Current buffer...
LockBuffer ImageBuffer (pic)

CopyPixelFast 10,10,ImageBuffer(pic),10,10

UnlockBuffer ImageBuffer (pic)
UnlockBuffer

WaitKey
End



Ross C(Posted 2003) [#12]
well, the arrays would be stored in system memory, apposed to video memory. this would use alot of system memory up. thats the point of video card memory. and i'd imagine it would be slower when drawing the images??


injeevious(Posted 2003) [#13]
no as shown above its much faster to draw images from a normal array


Ross C(Posted 2003) [#14]
what, so writing lots of pixels to the screen is faster than using the draw image command? Or am i missing the point?

This example copys pixels across buffers and draws images to the screen. press 1 to get the images being drawn with DrawImage command and press 2 to get the images drawn by CopyPixelFast.

Graphics 800,600
SetBuffer BackBuffer()


img=CreateImage(50,50)

SetBuffer ImageBuffer(img)
Color 100,200,255
Rect 0,0,50,50

SetBuffer BackBuffer()

mode=0

Color 50,150,20

While Not KeyHit(1)

	Cls

	If KeyHit(2) Then mode=0
	If KeyHit(3) Then mode=1
	
	If mode=0 Then
				For loop=0 To 8
					For loop1=0 To 8
						DrawImage img,loop*52,loop1*52
					Next
				Next
	ElseIf mode=1 Then
				LockBuffer BackBuffer()
				LockBuffer ImageBuffer(img)
				For loop=0 To 8
					For loop1=0 To 8
						For loop2=0 To ImageWidth(img)-1
							For loop3=0 To ImageHeight(img)-1
								CopyPixelFast loop2,loop3,ImageBuffer(img),(loop*52)+loop2,(loop1*52)+loop3,BackBuffer()
							Next
						Next
					Next
				Next
				UnlockBuffer ImageBuffer(img)
				UnlockBuffer BackBuffer()
	End If
	
	If MilliSecs()<timer+1000 Then
								frame=frame+1
	Else
								fps=frame
								frame=0
								timer=MilliSecs()
	End If
	
	Text 0,0,"FPS="+fps
	Flip False
Wend
End


I do apoligise if i'm talking about something different from you ^_^


Foppy(Posted 2003) [#15]
Well it was not about drawing images in the normal way. The technique here is to copy them pixel by pixel in such a way
that the result is a scaled version of the original. And in that case reading the relevant pixel color from an array seems to
be faster than using ReadPixelFast on the original image.

So, the choice was not between DrawImage and Read/WritePixelFast but between look-up in an array and ReadPixelFast.

James, thanks for that example. I would never have guessed that ImageBuffer could be used in that way, this should make
some things easier!