Copying from one image to another

BlitzMax Forums/BlitzMax Beginners Area/Copying from one image to another

Mental Image(Posted 2006) [#1]
If I have created an image using CreatImage(xsize,ysize,0), how do I copy another image to a part of the image I have created.

I basically want the equivalent of DrawImage to draw the image to my image ratherthan the back buffer.

Hope that this makes sense......


tonyg(Posted 2006) [#2]
You can either
a) convert them both to pixmaps and use the pixmap paste method
b) draw them both to backbuffer and grabimage
c) Try this code...
Graphics 800,600,0
SeedRnd MilliSecs()
Global background:TImage=LoadImage("pic2.png")
Global image1:Timage=LoadImage("i1.png")  '512*512
Global image2:TImage=LoadImage("oval.png")
'Global image3:Timage=LoadImage("clogo1.png")
While Not KeyHit(key_escape)
        Cls
	Global start_func:Int
	Global end_func:Int
	Local red,green,blue:Int
'	GetMaskColor(red,green,blue)
	argb:Int=intcolor(255,0,255)
	start_func=MilliSecs()
	drawbuffer(image1,image2,Rand(0,700),Rand(0,500),argb)
	end_func=MilliSecs()
	DrawImage background,0,0
	DrawImage image1,0,0
	DrawText end_func-start_func,600,0
	Flip
Wend
WaitKey()
Function drawbuffer(imagea:TImage,imageb:TImage,x:Int,y:Int,argb:Int)
  If x + ImageWidth(imageb) > ImageWidth(imagea) Or y + ImageHeight(imageb) > ImageHeight(imagea) RuntimeError("Imagea to big to fit in imageb")
'  start_func=MilliSecs()
  mypixmap2:TPixmap=LockImage(imageb)
  UnlockImage(imageb)
  mypixmap1:TPixmap=LockImage(imagea)
  Local mypixelptr2:Int Ptr = Int Ptr(mypixmap2.pixelptr(0,0))
  Local mypixelptr2backup:Int Ptr = mypixelptr2
  Local mypixelptr1:Int Ptr = Int Ptr(mypixmap1.pixelptr(x,y))
  Local mypixelptr1backup:Int Ptr = mypixelptr1
  For my_x=0 To ((mypixmap2.width)*(mypixmap2.height))
     If mypixelptr2[0] <> argb   mypixelptr1[0]=mypixelptr2[0]
'        If Var mypixelptr2<>0 MemCopy (Byte Ptr(mypixelptr1),Byte Ptr(mypixelptr2),4)
'         If Var mypixelptr2 <> 0 mypixelptr1[0]=mypixelptr2[0]
'    EndIf
     mypixelptr1:+1
     mypixelptr2:+1
     If mypixelptr2 = mypixelptr2backup+(mypixmap2.pitch/4)
         mypixelptr1 = mypixelptr1backup+(mypixmap1.pitch/4)
         mypixelptr1backup=mypixelptr1
         mypixelptr2backup=mypixelptr2
     EndIf
  Next
  UnlockImage(imagea)
'  end_func=MilliSecs()
End Function
Function IntColor(R,G,B,A=255)
'returns argb value from red, green, blue.
     Return A Shl 24 | R Shl 16 | G Shl 8 | B Shl 0
End Function



Mental Image(Posted 2006) [#3]
Hi Tony, thanks for the reply.

I don't like option B, as I will be copying from my image to the back buffer on a regular basis (I basically want to build my image on a larger image and then copy sections of it to the back buffer to create a horizontal scroller), so option A seems like the one to go for.

Being a complete NEWB at BlitzMax, however, Pixmaps are a mystery to me, and your example is too complex for my poor brain to understand.

Is there any chance that you, or someone else, could give me a quick rundown on creating a new Pixmap using

CreatePixmap:TPixmap(width,height,format,align_bytes=4 )

- I can understand the width and height, guess at format, but down't understand the align_bytes - and then perform two operations:

1. Copy a rectangular image into an arbitrary position in my large Pixmap;

2. Copy a screen sized portion of the Pixmap to the back buffer.

I can't even find a Pixmap Paste method - is it just me or are the docs hard to follow?

Finally, are Pixmap operations fast?

Many thanks.


ImaginaryHuman(Posted 2006) [#4]
If you want to do it with your own OpenGL code, you can use:

glTexSubImage2D()

which will allow you to upload a rectangular portion of a pixmap at a given coordinate into an EXISTING image/texture. You probably can only do it if you make your own textures, but it doesn't require all the for-next loop malarky.


tonyg(Posted 2006) [#5]
Pixmaps are slow to draw compared to images (i.e. drawpixmap slow vs drawimage) but you can change pixmaps. To change an image you must convert it to a pixmap (using lock), change it and then convert it back.
Basically, that's what my code does.
Do you REALLY want to use a large pixmap rather than a TImage? I think the code should be quite straightforward using images rather than pixmaps.
The doc is difficult to use at first (and shouldn't be) and has had many comments. However, doubleclick any pixmapxxx command and scroll until you find the paste method.


Mental Image(Posted 2006) [#6]
Hi Tony,

because I did not really understand what your code was doing, I didn't see the subtelty of converting the image to a Pixmap, altering it, and then converting it back.

I agree the code to do what I want with images is easy - I just couldn't see how to keep modifying my scroll buffer (which is the image I will be copying to the back buffer).

Thanks.


ImaginaryHuman(Posted 2006) [#7]
I wonder if you could set up a triple-buffered system, whereby you actually only use the front two buffers for double-buffering, and use the third buffer as a backbuffer to store a backup of your background, which you never flip (so that it is not trashed) .. then copy from that third buffer to the 2nd one to draw stuff?