• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 241
  • Last Modified:

Manipulating 2D Images

Alright, What I'm looking to learn how to do is make effect like the "Geiss" screensaver.  In other words, I need to know how to take a 2D image, and then warp it.  The 2 main effects that I want to know how to do are...
1) Where the screen zooms towards you (I think it's called Blitter feedback)
2) Where a spiral moves over the image. (I like the entire range of these effects)

The closest I've come to understanding these effects is that they use tables, and then I'm assuming they modify the tables using an equation, then render the table.  Also, the table equations seem to be polar ones..

I found one equation set that seems to do d=d*d;and r=r*r
(where d=distance and r=angle) to the table, and it produces a "hill" effect.

Any help would be greatly apprecatied!
0
Firefunk
Asked:
Firefunk
  • 2
1 Solution
 
nils pipenbrinckCommented:
the geiss effect is pretty simple.. it's a feedback effect which generates a new image from the last rendered one.

to render the new image you need a table. The table has one entry for each pixel of the image. in this entry you can look up from where to copy the pixel of the previous frame.


some pseudo code to render a frame: (for a 320*240 resolution)

int table_x [320*240];
int table_y [320*240];

int i=0;
for (int y=0; y<240; y++)
for (int x=0; x<320; x++)
{
  newimage[i] =  oldimage[table_y[i] * 320 + table_x[i]);
  i++;
}

show (newimage);
memcpy (oldimage, newimage, ...)


the trick of the geiss screensaver is, that it doesn't only read out one pixel, but 4 and do a bilinear interpolation between them. That's where the cool smoothing comes from.

to do so you have to store the coordinates in your arrays with more precision than simple integer. I use fixedpoint arithmetics and render the stuff with a hand full of mmx instructions.

(If you need help ask me.. I can give you working code if you want..)



now you need to calculate the tables.

this little code generates a zooming effect..


i=0;
for (int y=0; y<240; y++)
for (int x=0; x<320; x++)
{
  table_x[i] = (x-160)*1.1;
  table_y[i] = (y-120)*1.1;
  i++;
}

and this is something like your twirl effect:

i=0;
for (int y=0; y<240; y++)
for (int x=0; x<320; x++)
{
  float xx = x-160;
  float yy = y-120;

  // distance from center of screen;
  float dist = sqrt(xx*xx+yy*yy)*0.01;

  // rotate based on distance and
  // zoom a little bit:

  float s = sin(dist)*1.1;
  float c = cos(dist)*1.1;
  table_x[i] = 160+c*xx-s*yy;
  table_y[i] = 120+c*yy+s*xx;
  i++;
}

I hope you got the idea..

again, if you have any further questions ask me..

  Nils




0
 
FirefunkAuthor Commented:
Thank you SO much!  We need more people like you in this world!

I'd love to see some working code if you wouldn't mind! If you want to get in contact with me, please just use my E-mail : Firefunk@bigfoot.com
(If you want to)

Thank you so much again....You've just helped me more today than I've been able to find for the last month!

Thank you!!

0
 
nils pipenbrinckCommented:
hehe

that's funny.. I've worked the whole day on some eyecandies here...


and since I was in the mood to code here is the example code I talked about (it's ugly dos-code... but you should get it up and running)...



#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <math.h>


int  table_x[320*200];
int  table_y[320*200];
char buf1[320*200];
char buf2[320*200];

int lerp (const int a, const int b, const int x)
{
  // linear interpolation
  return a + (((b-a)*x)>>16);
}

void render (char * dest, char * source)
{
  int i;
  int * tabx;
  int * taby;
  tabx = table_x;
  taby = table_y;
  for ( i=0; i<320*200; i++)
      {
    int x,y,offset,c,d;
    x=*tabx++;
    y=*taby++;
    offset = (x>>16)+320*(y>>16);
    c = lerp(source[offset],     source[offset+1],       x&0xffff);
    d = lerp(source[offset+320], source[offset+1+320], x&0xffff);
    *dest++ = lerp (c,d, y&0xffff);
  }
}

void make_table (void)
{
  // zoom effect..
  int x,y,i;
  i=0;
  for (y=0; y<200; y++)
  for (x=0; x<320; x++)
  {
    table_x[i] = (160<<16)+(x-160)*65000;
    table_y[i] = (100<<16)+(y-100)*65000;
    if(table_x[i]<0) table_x[i]=0;
    if(table_x[i]>(319<<16)) table_x[i]=(319<<16);
    if(table_y[i]<0) table_y[i]=0;
    if(table_y[i]>(199<<16)) table_y[i]=(199<<16);
    i++;
  }
}

void make_table_2 (void)
{
  int x,y,i;
  i=0;
  for (y=0; y<200; y++)
  for (x=0; x<320; x++)
  {
    float xx = (x-160);
    float yy = (y-100);
    float dist = sqrt (xx*xx+yy*yy)*0.0002;
    float s = sin(dist)*0.99;
    float c = cos(dist)*0.99;

    table_x[i] = (160.0+ xx * c - yy * s)*65536.0;
    table_y[i] = (100.0+ yy * c + xx * s)*65536.0;
    if(table_x[i]<0) table_x[i]=0;
    if(table_x[i]>(319<<16)) table_x[i]=(319<<16);
    if(table_y[i]<0) table_y[i]=0;
    if(table_y[i]>(199<<16)) table_y[i]=(199<<16);
    i++;
  }
}

void graphic (int on)
{
  // system dependent.. this turns on 320x200x8bit under dos
  int n;
  if ( on )
  {
    _asm {
      mov eax, 13h
      int 10h
    }
    outp (0x3c8, 0);
    for ( n=0; n<256; n++ )
    {
      outp (0x3c9, n>>2);
      outp (0x3c9, n>>2);
      outp (0x3c9, n>>2);
    }
  } else {
    _asm {
      mov eax, 3h
      int 10h
    }
  }
}

void blit (char * source)
{
  // system dependent.. this shows the picture.
  memcpy ((char *) 0xa0000, source, 320*200);
}



void main (void)
{
  char ch;
  int n;
  float t=0;
  memset (buf1, 0, 320*240);

//  make_table ();   // zoom effect
  make_table_2 (); // rotation effect..
  graphic (1);

  ch=0;
  do
  {
    // draw some lisajous dots
    // makes sure there is something to feedback..
    for ( n=0; n<100; n++ )
    {
      int x,y;
      float tt = t + 3.14*(float)n/100.0;
      x=160+80.0*sin(tt*3.0);
      y=100+50.0*cos(tt*2.3);
      buf1[320*y+x]=255;
    }
    t+=0.05;
    render (buf2, buf1);
    blit (buf2);
    memcpy (buf1, buf2, 320*200);
  } while ( !kbhit() );

  graphic (0);
}
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now