Author Topic: Fast Image Scaling [BB2D]  (Read 1653 times)

0 Members and 1 Guest are viewing this topic.

Offline mike_g

  • Amiga 1200
  • ****
  • Posts: 435
  • Karma: 34
    • View Profile
Fast Image Scaling [BB2D]
« on: August 20, 2007 »
Heres some code I made today for fast image scaling. Basically each image is a type with a number of frame handles dependant on SCALE_DETAIL. The CreateScaledImage() function then creates and draws an appropriately sized image for each frame.

Heres the code:
Code: [Select]
AppTitle "Fast Image Scaling"
Graphics 640, 480, 32, 2
SetBuffer BackBuffer()

;Each image has an array of handles for scaled versions
;The more handles the greater the scale detail
Const SCALE_DETAIL = 50 ;50 frames
Const SCALE_RANGE = 2   ;between 2 and 0.1

;Each image has a number of frames and a name as an identifier
Type image
Field name$
Field frames[SCALE_DETAIL]
End Type

pic = LoadImage("tree.png")
CreateScaledImage(pic, "tree")
FreeImage(image)



;---------------------------------------------------------------------------------------------------;
;******************************** DEMO PROGRAM *****************************************************;
;---------------------------------------------------------------------------------------------------;
SeedRnd MilliSecs()
;FRAME RATE VARIABLES
Global old_time = MilliSecs()
Global frame_count, fps

Type tree
Field image
Field scale
Field x, y
End Type
InitTrees()

inc=1: i=5
While Not KeyHit(1)
Cls

DrawTrees()

KeyInput()
FPS()
Flip
Wend
ClearScaled() ;free scaled images

;---------------------------------------------------------------------------------------------------;
;******************************** SCALE FUNCTIONS **************************************************;
;---------------------------------------------------------------------------------------------------;

Function CreateScaledImage(image, name$)
im.image = New image
im\name = "tree"


Local src_x, src_y ;co-ords to read from original image
Local src_w, src_h ;width and height of original
Local dst_x, dst_y ;co-ords to draw to scaled image
Local dst_w, dst_h ;width and height of scaled image
Local col, inc#    ;colour to draw , scale size increment

src_w = ImageWidth(image)
src_h = ImageHeight(image)
inc# = Float(SCALE_RANGE) / Float(SCALE_DETAIL)

SetBuffer ImageBuffer(image, mask)

For i = 1 To SCALE_DETAIL
image_size# = image_size# + inc#

dst_w = Floor(src_w * image_size#)
dst_h = Floor(src_h * image_size#)
 
im\frames[i] = CreateImage(dst_w, dst_h)

LockBuffer ImageBuffer(image)
LockBuffer ImageBuffer(im\frames[i])

For dst_y=0 To dst_h
src_y = Floor(dst_y / image_size#)
For dst_x=0 To dst_w
src_x = Floor(dst_x / image_size)
col = ReadPixelFast(src_x, src_y)
WritePixelFast(dst_x, dst_y, col, ImageBuffer(im\frames[i]))
Next
Next

UnlockBuffer ImageBuffer(image)
UnlockBuffer ImageBuffer(im\frames[i])

MaskImage im\frames[i], 255, 0, 255
Next

SetBuffer BackBuffer()
End Function


Function ClearScaled()
For im.image = Each image
For i = 1 To SCALE_DETAIL
FreeImage(im\frames[i])
Next
Next
End Function


;---------------------------------------------------------------------------------------------------;
;******************************** DEMO FUNCTIONS ***************************************************;
;---------------------------------------------------------------------------------------------------;

Function KeyInput()
If KeyDown(200)
ResizeTrees(1)
Else If KeyDown(208)
ResizeTrees(-1)
EndIf
End Function


Function ResizeTrees(inc)
im.image = First image
For t.tree = Each tree
go=0
If t\scale < SCALE_DETAIL And t\scale > 1 Then go =1

t\scale = t\scale +inc
If go = 1
t\image = im\frames[t\scale]
t\y = 240-(ImageHeight(t\image)/2)
EndIf
Next
End Function

Function DrawTrees()
For t.tree = Each tree
DrawImage t\image, t\x, t\y
Next
End Function

Function InitTrees()
;Make trees
im.image = First image
For i = 1 To 100
t.tree = New tree
t\scale = Rand(1, SCALE_DETAIL)
t\image = im\frames[t\scale]
t\x = Rand(0, 600)
t\y = 240-(ImageHeight(t\image)/2)
Next
;Sort trees by distance
a.tree = First tree
flag = True
While flag
flag = False
b.tree = Last tree
While a <> b
c.tree = Before b
If c = Null Then Exit
If b\scale < c\scale
Insert c After b
flag=True
Else
b=c
EndIf
Wend
a = After b
Wend
End Function

Function FPS()
If MilliSecs() > old_time+1000
old_time = MilliSecs()
fps=frame_count
frame_count=0
EndIf
Color 255, 255, 255
Text 0, 0, "FPS: "+fps
frame_count=frame_count+1
End Function
And heres an image for the test program:
« Last Edit: August 21, 2007 by mike_g »

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Fast Image Scaling [BB2D]
« Reply #1 on: August 21, 2007 »
Thanks for posting these routines mike! K+

In the case of scaling you can do a bit better than this routine.  Right now you have a divide per pixel which can be very slow.  What you can do instead is called interpolation.
You know that dst_x only increases by 1 each pixel, so the src_x is easy to calculate, it would go
dst = 0 src = 0/image_size
dst = 1 src = 1/image_size
dst = 2 src = 2/image_size
dst = 3 src = 3/image_size
etc.
You can see that src is increasing by 1/image_size for each pixel, and you can take advantage of that.
inc_x# = 1/image_size
dst = 0 src = 0
dst = 1 src = 0+inc_x
dst = 2 src = 0+inc_x+inc_x
dst = 2 src = 0+inc_x+inc_x_inc_x

etc.
So for each pixel you just need to add inc_x to src_x instead of performing a divide.
You can do the same with the y.  The only thing to remember is inc_x and src_x would need to be a float.

Cheers!

Jim
Challenge Trophies Won:

Offline mike_g

  • Amiga 1200
  • ****
  • Posts: 435
  • Karma: 34
    • View Profile
Re: Fast Image Scaling [BB2D]
« Reply #2 on: August 21, 2007 »
Thanks for the tips jim. TBH I wasn't really worried about the speed with the dividing as its all just pre-calc. But its good to know. Some sort of interpolation/pixel guessing/anti aliasing type thing would definitely be good though for cleaning up the images that are zoomed in on. I might work on that :) 

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17378
  • Karma: 497
  • evil/good
    • View Profile
    • My Homepage
Re: Fast Image Scaling [BB2D]
« Reply #3 on: August 21, 2007 »
It's definately worth working on and getting fast, you'll be surprised how useful a routine like that is.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline mike_g

  • Amiga 1200
  • ****
  • Posts: 435
  • Karma: 34
    • View Profile
Re: Fast Image Scaling [BB2D]
« Reply #4 on: August 22, 2007 »
I think the scaling is about as fast as you can get as its all pre-drawn, the prog just flicks through image handles. The bad part is it uses tons of RAM tho. As in: SCALE_DETAIL * the image size as a bitmap.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Fast Image Scaling [BB2D]
« Reply #5 on: September 04, 2007 »
Thats pretty smart mate, 50 fps here.
Welldone :)
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won: