Anyone got a nice little CopyRect type of function

BlitzMax Forums/BlitzMax Programming/Anyone got a nice little CopyRect type of function

? I searched the forum and found a couple of ideas. 1) Use CreateImage (smaller), GrabImage, then drawimage 2) set a view port 3) Indiepaths Render to Texture (or whatever it's called).

Anyone willing to say which is the best method, and has anyone got any code? I'm gonna try the viewport method first.

I would have sworn Tim posted a function for this some time ago that worked very well. I could be mistaken though. Its hard to remember who wrote what :c/

What are to wanting the function to do grey? is it to draw part of an image?

If you want to copy a rect FROM the backbuffer TO the backbuffer, in OpenGL at least you can use glCopyPixels()

You could also use glCopyTexSubImage2D() to copy into a texture then draw the texture.

Otherwise in non-OpenGL specific, use GrabPixmap, then create a second pixmap the size you want, then use Pixmap.paste, then DrawPixmap.

Can't you use SetUv or pixmapwindow?
Graphics 640,480
mypixmap:TPixmap=LoadPixmap("max.png")
mypixmaprect:TPixmap=PixmapWindow(mypixmap,20,20,100,100)
DrawPixmap mypixmap,0,0
DrawPixmap mypixmaprect,200,0

Flip
WaitKey()


If you just want to draw part of an image (Heavily based on Dreamora's code from another thread...it's a long story)...
Strict

Graphics 800,600

Global hImage:Timage = LoadImage ("griffe.png")
SetImageHandle hImage, 0,0

While Not KeyDown (KEY_ESCAPE)
  Cls
  
  SetColor  255, 255,255
  
  DrawRect 300,100,200,150
  DrawImage hImage, 250,100
  
  DrawRect 300,300,200,150
  DrawImageArea hImage, 300,300, 50, 0, 200, 150
  
  Flip
Wend

End


Function DrawImageArea(image:TImage, x#, y#, rx#, ry#, rw#, rh#, frame=0)
  Local origin_x#, origin_y# ; GetOrigin (origin_x, origin_y)
  Local tw = Pow2Size(image.width)
  Local th = Pow2Size(image.height)
  Local rw1#  = rx + rw
  Local rh1#  = ry + rh
  Local x0# = -image.handle_x, x1# = x0 + rw
  Local y0# = -image.handle_y, y1# = y0 + rh
  
  If rw1 > image.width
    x1 = x0 + rw + image.width - rw1
    rw1 = image.width
  EndIf
   
  If rh1 > image.height
    y1 = y0 + rh + image.height - rh1
    rh1 = image.height
  EndIf
?Win32
  If TD3D7ImageFrame(image.frame(frame))
    Local frame:TD3D7ImageFrame = TD3D7ImageFrame(image.frame(frame))
    
    frame.setUV(rx / tw, ry / th, rw1 / tw, rh1 / th)
    frame.Draw x0, y0, x1, y1, x + origin_x, y + origin_y
    frame.setUV(0, 0, image.width / Float(tw), image.height / Float(th))
  Else
?
    Local frame:TGLImageFrame = TGLImageFrame (image.frame(frame))
                
    frame.u0 = rx / tw
    frame.v0 = ry / th
    frame.u1 = rw1 / tw
    frame.v1 = rh1 / th
    
    frame.Draw x0, y0, x1, y1, x + origin_x, y + origin_y
    
    frame.u0 = 0
    frame.v0 = 0
    frame.u1 = image.width / Float(tw)
    frame.v1 = image.height / Float(th)
?Win32
  EndIf
?
  
  Function Pow2Size(n)
    Local ry = 1
    
    While ry < n
      ry :* 2
    Wend
    
    Return ry
  End Function
End Function


Blimey lots of responses, thanks a lot! In the end I did this, which works fine:

' -----------------------------------------------------------------------------
' ccCopyRect
' -----------------------------------------------------------------------------
Function ccCopyRect(image:TImage,x,y,w,h,frame=0)
	'Draws a part of an image by using a viewport.
	SetViewport x,y,w,h
	DrawImage(image,x,y,frame)
	SetViewport 0,0,screenwidth, screenheight
End Function


Anyway see anything wrong with this? It should be cross platform too right?

Yeah the problem with your code is that you are assuming that the starting co-ords for the image are always 0,0. What if I wanted to draw only the bottom-right of the image or a 32x32 square from the center of the image?

You might want to do a little more research Mr Alien .... I remember reading in the OpenGL manual, I think, that you cannot be gauranteed that a viewport will crop everything outside of the viewport area. A viewport is more for defining the characteristics of the area that you ARE looking at, which might be extended beyond the edges of that area. To be sure that an area definitely will be clipped you have to define a Scissor window and switch on the scissor test. At least for OpenGL. They say that otherwise, on some systems they will actually not clip at all and just draw over the edges, trashing everything outside of the `viewport area`.

Method SetViewport( x,y,w,h )
If x=0 And y=0 And w=GraphicsWidth() And h=GraphicsHeight()
glDisable GL_SCISSOR_TEST
Else
glEnable GL_SCISSOR_TEST
glScissor x,GraphicsHeight()-y-h,w,h
EndIf
End Method


Indiepath: Thanks I can fix that easy enough.

AngelDaniel: Yeah I read that when you posted it a few months back. Hmm..

Diable. Is that a *new* replacement method or the one in the modules, I'm not understanding this time of night ;-)

Diable. Is that a *new* replacement method or the one in the modules, I'm not understanding this time of night ;-)

Its taken out of glMax2D.bmx.

Is there something wrong with doing this...
Function tg_drawimagerect(image:TImage,x:Int,y:Int,xs:Int,ys:Int,width:Int,height:Int)
    DrawImage LoadImage(PixmapWindow(LockImage(image),xs,xy,width,height)),x,y
End Function

?
It seems quick enough, is native Bmax so OK for GL/DX and takes all rotates, blends etc