Draw only a part of an image?

BlitzMax Forums/BlitzMax Programming/Draw only a part of an image?

Hi there!

What would be a fast way to draw only a part of a larger image that is already loaded into memory (as Image Handle)?

No Blending / Alpha required!

Grisu

Use LoadAnimImage:TImage( url:Object,cell_width,cell_height,first_cell,cell_count,flags=-1 ) to create tiles from the image then use drawimage to draw the section you want with the frame parameter.

SetViewport looks like what you want.

SetViewport is unreliable on some hardware.

Try this (you'll have to use LockImage on myBigImage to use it as a pixmap).
mySmallImage:tImage = LoadImage(PixmapWindow(myBigImage,x,y,width,height))


Thanks guys!

This should be faster. I use it for my games

' -----------------------------------------------------------------------------
' ccDrawImageArea: Draws part of an image.
' (by Ian Duff)
' -----------------------------------------------------------------------------
Function ccDrawImageArea(image:TImage, x#, y#, rx#, ry#, rw#, rh#, theframe%=0)
 'Note that this code works fine in DirectX or OpenGL on PCs - it autodetects (Grey Alien).
 'Warning: make sure that none of your images have pixels right on the edge otherwise
 'when drawing clipped, they may leave smear in the clipped area! (Grey Alien).
  Local origin_x#, origin_y# ; GetOrigin (origin_x, origin_y)
  Local tw% = ccDrawImageAreaPow2Size(image.width)
  Local th% = ccDrawImageAreaPow2Size(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(theframe))
    Local frame:TD3D7ImageFrame = TD3D7ImageFrame(image.frame(theframe))
    
    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 frameA:TGLImageFrame = TGLImageFrame (image.frame(theframe))
    'Protect against frameA being null due to alt+tab. (Grey Alien)
	If frameA<>Null Then
	    frameA.u0 = rx / tw
	    frameA.v0 = ry / th
	    frameA.u1 = rw1 / tw
	    frameA.v1 = rh1 / th
	    
	    frameA.Draw x0, y0, x1, y1, x + origin_x, y + origin_y
	    
	    frameA.u0 = 0
	    frameA.v0 = 0
	    frameA.u1 = image.width / Float(tw)
	    frameA.v1 = image.height / Float(th)
	EndIf
?Win32
  EndIf
?
  
  Function ccDrawImageAreaPow2Size%(n%)
    Local ry% = 1
    
    While ry < n
      ry :* 2
    Wend
    
    Return ry
  End Function
End Function



"This should be faster." - Only on outdated gpu's. I didn't see a real "worth it" increase on newer gpu's.

I thought it was faster than this:

mySmallImage:tImage = LoadImage(PixmapWindow(myBigImage,x,y,width,height)) 
Because it worked directly in VRAM.

ahh.. I see... ok.

@ Grey Alien

This looks pretty cool. I've been searching the forums for a while for a single surface blitting example that also included the conditional compilation as to avoid the "TD3D7ImageFrame indentifier not found" error (yeah, i could've written it myself...but thanks!)

Would you say this workaround is on par with the TAnimImage class that Indiepath made?

-Jason