Code archives/Graphics/ScaleImageFast
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This function scales an image an arbitrary amount on each axis, and is 80x faster than the default ScaleImage function in Blitz! Actually, I should say, it is 80x faster than the ScaleImage function in BlitzPlus. I have not tested it against the ScaleImage function in Blitz3D. It will probably be faster than the one in Blitz3D as well, but the major speed boost here may be due to CopyRect being hardware accelerated in BlitzPlus. | |||||
; ------------------------------------------------------------------------------------------------------------------------------------- ; This function scales an image an arbitrary amount on the X and Y axis, and returns a pointer to the new image. ; The original image is not modified. ; ; This function is 80x faster than the ScaleImage function that comes with Blitz! ; ------------------------------------------------------------------------------------------------------------------------------------- Function ScaleImageFast(SrcImage, ScaleX#, ScaleY#) Local SrcWidth, SrcHeight Local DestWidth, DestHeight Local ScratchImage, DestImage Local SrcBuffer, ScratchBuffer, DestBuffer Local X1, Y1, X2, Y2 ; Get the width and height of the source image. SrcWidth = ImageWidth(SrcImage) SrcHeight = ImageHeight(SrcImage) ; Calculate the width and height of the dest image. DestWidth = Floor(SrcWidth * ScaleX#) DestHeight = Floor(SrcHeight * ScaleY#) ; If the image does not need to be scaled, just copy the image and exit the function. If (SrcWidth = DestWidth) And (SrcHeight = DestHeight) Then Return CopyImage(SrcImage) ; Create a scratch image that is as tall as the source image, and as wide as the destination image. ScratchImage = CreateImage(DestWidth, SrcHeight) ; Create the destination image. DestImage = CreateImage(DestWidth, DestHeight) ; Get pointers to the image buffers. SrcBuffer = ImageBuffer(SrcImage) ScratchBuffer = ImageBuffer(ScratchImage) DestBuffer = ImageBuffer(DestImage) ; Duplicate columns from source image to scratch image. For X2 = 0 To DestWidth-1 X1 = Floor(X2 / ScaleX#) CopyRect X1, 0, 1, SrcHeight, X2, 0, SrcBuffer, ScratchBuffer Next ; Duplicate rows from scratch image to destination image. For Y2 = 0 To DestHeight-1 Y1 = Floor(Y2 / ScaleY#) CopyRect 0, Y1, DestWidth, 1, 0, Y2, ScratchBuffer, DestBuffer Next ; Free the scratch image. FreeImage ScratchImage ; Return the new image. Return DestImage End Function |
Comments
| ||
this is cool. and since we are talking about it, how about to use a sprite to scale an image? simply move the original onto a texture, then move the sprite away from a camera until it reaches a certain size, den take it by Renderworld. Could be pretty fast. Sorry for hijacking the thread :P |
| ||
Swift.... Although very fast it is a massive memory consumer. It brought up the 'Virtual Memory Low' alert when I ran it. You are better off creating your scratch images outside your function and setting them as Global and not using the free image command at all. Here is an example by Nullmind (blitzcoder) that I have modified that uses a scratch image the same size as the screen. Time tests on my XP2400+ & Ati 9000 Pro... ScaleImage = 1840 millisecs to scale to full screen DrawSizeImage = 13 millisecs to scale to full screen Conclusion... DrawSizeImage Function is 141 times faster than the Blitz ScaleImage command. ; Fast Bitmap Scale. Original by Nullmind. ; ; Use I & O keys to zoom in and out ; SeedRnd(MilliSecs()) SW=800:SH=600 Graphics SW,SH,32,2 SetBuffer BackBuffer() Global scratch%=CreateImage(SW,SH) ; create a scratch image For r=1 To 500 ; draw random stuff x=Rand(0,SW):y=Rand(0,SH) s=Rand(20,100):Color Rand(0,255),Rand(0,255),Rand(0,255) Rect x,y,s,s Next Image=CreateImage(200,200) ; grab an image from it GrabImage image,350,350 ;Image=LoadImage("MapTile.bmp") ; Or load an image here w=ImageWidth(Image):h=ImageHeight(Image) x=250:y=175 Color 255,255,255 SI=6 ; Size increase in pixels Repeat If KeyDown(23) w=w+SI:h=h+SI:x=x-(SI/2):y=y-(SI/2) EndIf If KeyDown(24) w=w-SI:h=h-SI:x=x+(SI/2):y=y+(SI/2) EndIf DrawSizeImage(Image,x,y,w,h) Text 0,0,"Use I & O keys to Zoom" Flip False:Cls Until KeyDown(1) End ; ********************************************************** Function DrawSizeImage(image,x%,y%,w%,h%) Local ih%=ImageHeight(image) Local iw%=ImageWidth(image) Local sw%=Abs(w) Local sh%=Abs(h) Local xr#=(Float(iw)/Float(sw)) Local yr#=(Float(ih)/Float(sh)) fromimg=ImageBuffer(image) toimg=ImageBuffer(scratch) Local vf=-1+((h>0)*2) Local fw=(w<0)*w Local fh=(h<0)*h If w>=0 For ix=0 To sw CopyRect ix*xr,0,1,ih,ix,0,fromimg,toimg Next Else For ix=0 To sw CopyRect ix*xr,0,1,ih,sw-ix,0,fromimg,toimg Next EndIf For iy=0 To sh CopyRect 0,iy*yr,sw,1,x+fw,y+(iy*vf),toimg Next End Function |
| ||
very nice |
Code Archives Forum