Allegro.cc - Online Community

Allegro.cc Forums » Off-Topic Ordeals » mathematics behind the zoom thing

This thread is locked; no one can reply to it. rss feed Print
mathematics behind the zoom thing
Johan Halmén
Member #1,550
September 2001

Remember this thread?

I started to develop something to recreate that. There appeared to be 46 individual frames in the sequence, but I started simply with four. I thought of making four images, each measuring 1024*768. Each image would contain the following image scaled to 128*96 (8th of the bigger one) in the centre. Each frame would show two images, the bigger one and the smaller one in the centre. I would blit them to the screen (or to a buffer, then to the screen, or flip buffers whatever) in say 256 turns, stretching both until in the last frame the smaller one would occupy the whole screen.

Since there should be a smooth zooming and there are two images involved, the stretching can't follow a linear path. It has to be exponential, logarithmic or whatever the right term is.

step    smaller img  ratio
====    ===========  =====
0       128          1
256     1024         8
512     8192         64   // this line is just for figuring
                          // out the right formula

So the function for computing the smaller image width would be
width = 128 * pow(8, step/256);

The width of the smaller image is one thing. Its coordinates is another thing. When the larger image grows, only a part of it is blitted and stretched to 1024*768. To compute the width and coordinates of the part is the third and fourth thing. All these four values probably follow a similar exponential thing, not a linear function.

I hope I'm on right track here. In this model the next image is always in the centre of the previous. But what if it could be anywhere, say in the upper right corner. And the next would be in lower right corner. Shifting the zooming centre from one corner to another might give a feel of a sharp turn in the camera path, like if the camera followed straight lines. The corners should be rounded, like if the camera followed a spline or something.

In the thread mentioned I suggested a game where a certain Mr. Potter is chasing someone flying on a broomstick. One could think of having not one but two or more smaller images, one of which the player chooses to zoom to.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Dennis
Member #1,090
July 2003
avatar

Making a game with this technique will require a truckload of highly skilled artists though, so I think it's impractical for a game. True 3D would be easier to create content for, imo.

Johan Halmén
Member #1,550
September 2001

You're right. But I had this idea of making the zoom thing work with hand painted images. These would be scanned and transfered to the program.

Another project would be to take images with a digital camera. I'd start with an image of our village. Next image would be my immediate neighbourhood. Next would be my living room window, where details from inside would be visible. Last image would be a picture frame on the living room wall showing our village.

Another project would simply be a chain project. I draw a fantasy image, 1024*768. I give it to someone, who scales it to 128*96, centres it on a 1024*768 image and draws the rest. He gives it further. Prefered tools are Gimp and a drawing pad.

I'd still need to fit the last image with my first image. I'd take the centre 128*96 from my image, magnify it to 1024*768, resize the last image and place it in the centre of the magnified centre of my original image. Then I'd do some refinements - correcting the blurness of the magnified parts of the image.

Anyone interested in participating in the chain? I draw my first image here, before next... um... monday.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Thomas Harte
Member #33
April 2000
avatar

Quote:

Since there should be a smooth zooming and there are two images involved, the stretching can't follow a linear path.

You mean the amount by which you zoom can't increase linearly? That isn't because two images are involved - it's just so that in a given time the same amount of growth happens. So, for example, a section of the image occupying 1x1 of the screen always grows to 2x2 in n seconds.

Anyway, the point is that you should have all your images scale so that they retain the same ratio of sizes. I guess that's obvious. But to zoom in you should just do something equivalent to zoom *= 1.2 or whatever. To zoom out, obviously zoom *= 1/1.2.

You've almost certainly already figured that all out, but nevertheless to prove the point:

1#include "allegro.h"
2 
3int main(int argc, const char *argv[])
4{
5 BITMAP *img[2], *back;
6 fixed zoom = itofix(1);
7 
8 allegro_init();
9 install_keyboard();
10 
11 if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 512, 512, 0, 0)) {
12 return -1;
13 }
14 back = create_bitmap(SCREEN_W, SCREEN_H);
15 img[0] = create_bitmap(256, 256);
16 img[1] = create_bitmap(256, 256);
17 
18 clear_to_color(img[0], makecol(255, 0, 128));
19 clear_to_color(img[1], 0);
20 circlefill(img[1], 128, 128, 128, makecol(128, 128, 128));
21 int basec = 0;
22 
23 while(!key[KEY_ESC])
24 {
25 int TexW, TexH;
26 int c;
27
28 TexW = fmul(256, zoom);
29 TexH = fmul(256, zoom);
30 
31 c = 0;
32 clear(back);
33 while(c < 12)
34 {
35 stretch_sprite(back, img[(c+basec)&1], (SCREEN_W >> 1) - (TexW >> 1), (SCREEN_H >> 1) - (TexH >> 1), TexW, TexH);
36 TexW >>= 1; TexH >>= 1;
37 c++;
38 }
39 
40 zoom = fmul(zoom, ftofix(1.01));
41 if(zoom > itofix(6)) {zoom >>= 1; basec++;}
42 blit(back, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
43 }
44
45 destroy_bitmap(img[0]);
46 destroy_bitmap(img[1]);
47 destroy_bitmap(back);
48 return 0;
49}
50END_OF_MAIN()

Alas I can't draw to save my life, so can't really join in with your project...

Johan Halmén
Member #1,550
September 2001

I could stretch linearly if I only had one image. By linearly I mean that the size of the "virtual" original image would grow with a constant number of pixels per time. But it would look as if the flight into the centre of the picture would slow down. I said that the exponential function had to do with using two images. I only meant that when next frame is in turn, its stretch speed should look the same as the first frame's speed. Anyway...

Here's my working code (for 800*600*32 graphics):

1/*
2 * zoomy
3 *
4 * Created by Johan Halm&#381;n on 28.3.2006.
5 * Copyright (c) 2006 __MyCompanyName__. All rights reserved.
6 */
7 
8#include <Allegro/allegro.h>
9#include <math.h>
10 
11#define n_of_f 32
12 
13int main(int argc, const char *argv[])
14{
15 allegro_init();
16 install_keyboard();
17 install_mouse();
18 int small_widths[n_of_f], small_heights[n_of_f], small_x[n_of_f], small_y[n_of_f],
19 big_widths[n_of_f], big_heights[n_of_f], big_x[n_of_f], big_y[n_of_f];
20
21 for (int i = 0; i < n_of_f; i++)
22 {
23 double f = pow(8., double(i)/n_of_f);
24 double f2 = pow(8., double(n_of_f - i)/n_of_f);
25
26 small_widths<i> = 100 * f;
27 small_heights<i> = 75 * f;
28 small_x<i> = 400 - int(50 * f);
29 small_y<i> = 300 - int(37.5 * f);
30 big_widths<i> = 800. / f;
31 big_heights<i> = 600. / f;
32 big_x<i> = 400 - 50 * f2; // 0 - 350
33 big_y<i> = 300 - 37.5 * f2;
34 }
35
36 BITMAP *img[7], *buffer;
37
38 set_color_depth(32);
39 if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 800, 600, 0, 0)) {
40 allegro_message("Error setting 800x600x32 gfx mode:\n%s\n", allegro_error);
41 return -1;
42 }
43 img[0] = load_bitmap("../../27.bmp", NULL);
44 img[1] = load_bitmap("../../24.bmp", NULL);
45 img[2] = load_bitmap("../../21.bmp", NULL);
46 img[3] = load_bitmap("../../18.bmp", NULL);
47 img[4] = load_bitmap("../../15.bmp", NULL);
48 img[5] = load_bitmap("../../12.bmp", NULL);
49 img[6] = img[0];
50 buffer = create_bitmap(800, 600);
51 if (img[5] == NULL)
52 {
53 textout_ex(screen, font, "Bad thing!", 100, 100, 0xffffff, -1);
54 while (!keypressed());
55 }
56 do
57 {
58 for (int im = 0; im < 6 && !key[KEY_ESC]; im++)
59 for (int i = 0; i < n_of_f && !key[KEY_ESC]; i++)
60 {
61 stretch_blit(img[im], buffer, big_x<i>, big_y<i>, big_widths<i>, big_heights<i>,
62 0, 0, 800, 600);
63 stretch_blit(img[im+1], buffer, 0, 0, 800, 600,
64 small_x<i>, small_y<i>, small_widths<i>, small_heights<i>);
65 blit(buffer, screen, 0, 0, 0, 0, 800, 600);
66 while(mouse_b); // pause
67 }
68 }
69 while (!key[KEY_ESC]);
70 destroy_bitmap(img[0]);
71 destroy_bitmap(img[1]);
72 destroy_bitmap(img[2]);
73 destroy_bitmap(img[3]);
74 destroy_bitmap(img[4]);
75 destroy_bitmap(img[5]);
76 destroy_bitmap(buffer);
77 return 0;
78}
79END_OF_MAIN();

I got six images. Actually I used six images from the Zoomquilt. In Zoomquilt the ratio between successive images was 1:2 so I picked every third. Or actually only six of them and did some editing to fit the last with the first. Anyway, to run my code, you have to do the same or draw your own six images. The paths for the images are OSX style.

n_of_f defines in how many steps the stretch blitting happens in each turn. It kind of controls the speed, since everything happens as fast as possible. A value of 256 was too slow, the two images didn't mix very well, partly due to stretch_blit() ugliness. But the higher speed, the better it looks. My (wife's) iBook G3 runs at 700 MHz.

I do some pow() calculating to create lookup tables for the coordinates and sizes for the blittings.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Neil Walker
Member #210
April 2000
avatar

Ooh that's bonny. If you add a bit of cursor movement to Thomas's it's rather splendid.

I've made both versions for windows viewing if anyone is interested:
http://retrospec.sgn.net/quilty.rar

In the thomas one you can use the cursor keys, and in bonny one you can use the right-mouse button as coded to stop it by the frame.

you'll need the 42 dll.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Johan Halmén
Member #1,550
September 2001

Ok, here's my Monday post. I guess it's Monday in Australia already.

Below are four images, zoomy01.jpg - zoomy04.jpg. The last one could be completed with a background that would link to the next image.

Take the last image, resize it to 128*96 and enlarge the canvas to 1024*768. Complete the image around the shrunk original. Rename the new image following the naming pattern. Put your image here, either as a url link, an img link or an attached file. My images probably are too high quality.

Write a post here where you reserve the next images. Complete them as soon as possible so the next one can continue the chain. Any style is allowed, as long as the transition from the middle 128*96 part to the surrounding image is smooth.

http://edu.loviisa.fi/~jhalmen/bilder/zoomy/zoomy01.jpg
zoomy01.jpg
http://edu.loviisa.fi/~jhalmen/bilder/zoomy/zoomy02.jpg
zoomy02.jpg
http://edu.loviisa.fi/~jhalmen/bilder/zoomy/zoomy03.jpg
zoomy03.jpg
http://edu.loviisa.fi/~jhalmen/bilder/zoomy/zoomy04.jpg
zoomy04.jpg
Please feel free to edit the pink background if you want. My idea was that this is a green glass bowl with sugar cubes, standing on a table.

[edit]
oops, guess I have to change server, this one is stuck.
[edit2]
changed.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

FMC
Member #4,431
March 2004
avatar

Fast&Furious cliché hack :P

http://img309.imageshack.us/img309/7061/zoomy050qk.jpg

[FMC Studios] - [Caries Field] - [Ctris] - [Pman] - [Chess for allegroites]
Written laws are like spiders' webs, and will, like them, only entangle and hold the poor and weak, while the rich and powerful will easily break through them. -Anacharsis
Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails. Explore. Dream. Discover. -Mark Twain

Johan Halmén
Member #1,550
September 2001

Great! Only the white background could be filled with something that merges to the next image. Next one that carries on could do that. Or the white space could be good as it is. Next image could contain lots of stuff flowing in the white space.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

FMC
Member #4,431
March 2004
avatar

I was thinking of putting the shrinked image inside a marble, ala MIB ending... i'm struggling a little to find a good image, though

[FMC Studios] - [Caries Field] - [Ctris] - [Pman] - [Chess for allegroites]
Written laws are like spiders' webs, and will, like them, only entangle and hold the poor and weak, while the rich and powerful will easily break through them. -Anacharsis
Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails. Explore. Dream. Discover. -Mark Twain

Go to: