Author Topic: need help with magnifier  (Read 5272 times)

0 Members and 1 Guest are viewing this topic.

Offline Merick

  • Atari ST
  • ***
  • Posts: 113
  • Karma: 7
    • View Profile
need help with magnifier
« on: March 23, 2008 »
I've been working on a "magnifier" effect. The magnified image it produces is based off of the upper left corner of the original image. I want it to be based off of the center section of the image instead but I can't figure out how to calculate the offsets

Code: [Select]
#include once "fbgfx.bi"
type tr
as integer wd,ht,npix
org as fb.image ptr
dest as fb.image ptr
tfm as uinteger ptr 'the transform matrix
f as integer

declare constructor (byval w as integer, byval h as integer, matrix as string, byval factor as single = 1)
declare destructor ()
declare sub transform(byval x as integer, byval y as integer)
end type

constructor tr (byval w as integer, byval h as integer, effect as string, byval factor as single = 1)
wd = w
ht =h
f = factor
npix = w*h ' number of pixels
org = imagecreate (w,h)
dest = imagecreate (w,h)
for i as integer = 0 to w-1
tfm = new uinteger[npix] ' transform array
next
var pitch = org->pitch / org->bpp
select case effect
case "flipxy"
for i as integer =0 to w*h-1   
tfm[i] = (w*h-1) -i
next 
case "mag"
for i as integer = 0 to h-1   
for j as integer = 0 to w-1
tfm[i*w+j] = cast(integer,(i / factor)) * pitch + cast(integer,(j / factor))
next
next
end select
end constructor

destructor tr()
imagedestroy org
imagedestroy dest
delete[] tfm
end destructor

sub tr.transform(byval x as integer, byval y as integer)
get (x,y) - step(wd-1,ht-1), org
var pitch = org->pitch / org->bpp
var o = cast(uinteger ptr, org+1)
var d = cast(uinteger ptr, dest+1)
dim as integer count = 0

for i as integer = 0 to ht-1
for j as integer = 0 to wd-1
d[i * pitch + j] = o[tfm[i*wd+j]]
next
next

put (x,y), dest', pset
end sub


dim as integer scw = 800, sch = 600
screenres scw,sch,32

dim as integer w = 100, h = 100
dim as tr effect = tr(w,h, "mag", 1.5)

dim as integer x = 200, y = 200


while not multikey(1)
if multikey(FB.SC_LEFT) and x > 0 then x -=1
if multikey(FB.SC_RIGHT) and x < scw-w-1 then x +=1
if multikey(FB.SC_UP) and y > 0 then y -=1
if multikey(FB.SC_DOWN) and y < sch-h-1 then y +=1
screenlock
cls

line (200+(w/4),200+(w/4))-STEP (w/2, h/2), rgb(0,0,255), BF

effect.transform(x,y)
line (x, y)-STEP (w, h), rgb(255,0,0), B
pset (x+(w/2),y+(h/2)), rgb(255,0,0)
screenunlock

wend

sleep

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: need help with magnifier
« Reply #1 on: March 24, 2008 »
Looks like in
tr.transform
you have
   var o = cast(uinteger ptr, org+1)
   var d = cast(uinteger ptr, dest+1)
these are the source and dest pointers for your fx, so you can control the source and dest by adding
x_pos+y_pos*wd
to each of them.

Jim
Challenge Trophies Won:

Offline Merick

  • Atari ST
  • ***
  • Posts: 113
  • Karma: 7
    • View Profile
Re: need help with magnifier
« Reply #2 on: March 24, 2008 »
in the constructor for tr I have this code:

Code: [Select]
case "mag"
for i as integer = 0 to h-1   
for j as integer = 0 to w-1
tfm[i*w+j] = cast(integer,(i / factor)) * pitch + cast(integer,(j / factor))
next
next

In this part, tfm is a ptr array containing the pre-calculated coordinates for the transformation. When applied to the o and d buffers it basically makes it so that point (x,y) in d is the same as point( (x/factor), (y/factor) in the o buffer. (o and d are just so I can have direct access to the org and dest images without using point/pset)

 In order to do what I want, I need to add offsets to the coords in the tfm[i*w+j] = cast(integer,(i / factor)) * pitch + cast(integer,(j / factor)) statement. The problem is that I haven't been able to figure out the right way to calculate the offsets to keep the area that gets enlarged to the center of the box. For a factor of two, I could just use (wd/4) and (ht/4), but that doesn't work if I set the factor to something like 1.5 or 5
« Last Edit: March 24, 2008 by Merick »

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: need help with magnifier
« Reply #3 on: March 24, 2008 »
I don't think you do need to change tfm.  Because that is the same thing as adding to where you take the points from later on.  ie.  Either you can add 10along and 3down to every offset in tfm, or you can START 10along and 3down in your source.  It's the same thing, I think.  tfm can be constant.

Jim
Challenge Trophies Won:

Offline Merick

  • Atari ST
  • ***
  • Posts: 113
  • Karma: 7
    • View Profile
Re: need help with magnifier
« Reply #4 on: March 24, 2008 »
tfm is constant - the values are calculated only once by the constructor

Well, if I were to add the offsets to the source instead of tfm, then easiest would be to the x,y coords in this statment:

get (x,y) - step(wd-1,ht-1), org

However, that still leaves me with with the problem of figuring out the correct offsets to use, an none of the formulas I've tried have worked

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: need help with magnifier
« Reply #5 on: March 24, 2008 »
Is this what you're looking for?
Code: [Select]
get (x+(wd/2)/1.41,y+(ht/2)/1.41) - step((wd-1),(ht-1)), org

Jim
Challenge Trophies Won:

Offline Merick

  • Atari ST
  • ***
  • Posts: 113
  • Karma: 7
    • View Profile
Re: need help with magnifier
« Reply #6 on: March 24, 2008 »
erm, no... hardcoding the numbers like that will make it work for only one size, I need it to be based off of the "f" typemember (the magnification factor sent to the constructor) so that it will always be centered on the target area. I've tried things like x+(wd/f), x+(wd/(2+f)), x+(wd/(2*f)), etc...

And I just remembered why I was using the offsets with tfm instead of the image buffers - it's because "get" will fail if any of the coords you give it are outside the screen area itself, so if your target is 100x100 pixels and you have offsets in the get statement in the transform sub, then the magnifier will stop working even before you get to screenwidth-100 or screenheight-100. However, if you use the offsets when calculating tfm then you will be able to set the bottom or right sides of the magnifier right on the edge of the screen and still have it work


*edit*

Here's a win32 compiled version of this using an actual image, use the arrow keys to move the target around:
http://freefile.kristopherw.us/uploads/merick/mag.zip

transform.exe was compiled without using any offsets at all, it works anywhere on the screen, but it only enlarges the upper left corner of the target area

transform2 was compiled with offsets on the get statement, if you move along the bottom or right edges of the screen the image in the target freezes because the offsets are making get fail

transform3 uses the same offsets as 2, but it uses them when calculating the tfm look-up array instead of in the get statement (in this, it does stretch the center of the target to fill the box, but only because I hardcoded it for a mag factor of 2)
« Last Edit: March 24, 2008 by Merick »

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: need help with magnifier
« Reply #7 on: March 24, 2008 »
1.41 is sqrt(2), which has nothing to do with the scale factor.  The coordinates of the left hand corner of your square are

cornerx = centrex + width /2 * 1.41
cornery = centry + height /2 * 1.41

Maybe all that's left is to scale that by f or 1/f.

cornerx = centrex + f * width /2 * 1.41
cornery = centrey + f * height /2 * 1.41

I suppose I'm still confused as to what the problem is.  Can you put a 'sleep 50' in your main loop.  Right now it runs/renders so fast that if I just tap an arrow key the cursor zooms to the edge of the page.

Jim
Challenge Trophies Won:

Offline Merick

  • Atari ST
  • ***
  • Posts: 113
  • Karma: 7
    • View Profile
Re: need help with magnifier
« Reply #8 on: March 24, 2008 »
Here's a (crude) image to try to display what I'm having trouble with. The big box represents the target area. The smaller box inside it represents the area that will get stretched to fill the main box, the higher the number that you pass to the "factor" argument, the smaller that box will become. #1 shows how it works if I don't use any offsets, #2 shows where I want it to be, the other 3 are examples of how it ended up with some of the various calculation methods I've tried, based off of f

*edit*

Well, I finally figured out the equation:

tfm[y*w+x] = cast(integer,(y / factor)+ ((h-(h/factor))/2))* pitch + cast(integer,(x / factor)+((w-(w/factor))/2))
« Last Edit: March 26, 2008 by Merick »

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: need help with magnifier
« Reply #9 on: March 30, 2008 »
Good news!
Jim
Challenge Trophies Won: