/****************************************************************************
 *
 * "Distortion" (c) SID, May 6th, 1999
 *
 ***************************************************************************/
/* module data.h */

#ifndef TRUE
#define TRUE  1
#define FALSE 0
#endif

#define A 25                                /* 1st bifocal parameter */
#define B 50                                /* 2nd bifocal parameter */
#define X 2*XS+1+2*(B-A)             /*1st derived fisheye parameter */
#define Y 2*YS+1+2*(B-A)             /*2nd derived fisheye parameter */
#define XS 100                                           /* X window */
#define YS 100                                           /* Y window */

/* fnct */
void quit(Widget w, void *p);
void f0(Widget w, void *p);
void f1(Widget w, void *p);
void f2(Widget w, void *p);
void key(Widget w, char *input, int up_or_down, void *p);
void redisplay(Widget w, int x, int y, void *p);
 

 ****************************************************************************
/* module dot.c */

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include "libsx.h"
#include "grapx.h"

int xc, yc, flag, type;
unsigned char mag[4][X][Y];
int frq[4][X][Y];

extern unsigned char source[3][2*XS+1][2*YS+1];
extern Widget ww[9];

void quit(Widget w, void *p)
{
  exit(0);
}

int bifocal(int i, int x_source, int x_center)
{
  if (i<x_source+x_center-A) return i;
  if (i>x_source+x_center+A) return i+2*(B-A);
  return (i-x_source-x_center+A)*B/A+x_source+x_center-A;
}

int fish(int i)
{
  return (XS+B-A)*4*XS*i/((i+XS)*(i+XS));
}

int fisheye(int i, int x_source, int x_center)
{
  return fish(x_source) + ( i-x_source-x_center>0
        ?  fish((i-x_source-x_center)*x_source/(x_source-x_center))
        : -fish((x_source+x_center-i)*x_source/(x_source+x_center)));
}

void fill(int k)
{
  int i, j, i1, i2, j1, j2;

  for (i=0; i<X; i++)
  for (j=0; j<Y; j++)
  if (!frq[k][i][j])
  {
        for (i1=i; i1>-1 && !frq[k][i1][j]; i1--);
        for (i2=i; i2< X && !frq[k][i2][j]; i2++);
        for (j1=j; j1>-1 && !frq[k][i][j1]; j1--);
        for (j2=j; j2< Y && !frq[k][i][j2]; j2++);

        if (i1>-1 && i2< X && (frq[k][i][j]=1)) mag[k][i][j] =
                (mag[k][i1][j]*(i-i1)+mag[k][i2][j]*(i2-i))/(i2-i1);
        if (j1>-1 && j2< Y && (frq[k][i][j]=1)) mag[k][i][j] =
                (mag[k][i][j1]*(j-j1)+mag[k][i][j2]*(j2-j))/(j2-j1);
  }

  for (i=1; i<X-1; i++)
  for (j=1; j<Y-1; j++)
  if (!frq[k][i][j])
  {
        for (i1=i; i1>  0 && !frq[k][i1][j]; i1--);
        for (i2=i; i2<X-1 && !frq[k][i2][j]; i2++);
        for (j1=j; j1>  0 && !frq[k][i][j1]; j1--);
        for (j2=j; j2<Y-1 && !frq[k][i][j2]; j2++);

        mag[k][i][j] = (mag[k][i1][j1]+mag[k][i1][j2]+
                        mag[k][i2][j1]+mag[k][i2][j2])/4;
  }
}

void generate()
{
  int k, i, j, ii, jj;

  memset(frq, 0, sizeof(frq));
  memset(mag, 0, sizeof(mag));

  for (k=0; k<4; k++)
  if  (k!=1)
  {
        for (i=0; i<2*XS+1; i++)
        for (j=0; j<2*YS+1; j++)
        {
                ii = type ? (type==1 ? bifocal(i, XS, xc) :
                        fisheye(i, XS, xc)) : i+B-A;
                jj = type ? (type==1 ? bifocal(j, YS, yc) :
                        fisheye(j, YS, yc)) : j+B-A;

                mag[k][ii][jj] =
                        (mag[k][ii][jj]*frq[k][ii][jj] + source[k-(k>1)][i][j])
                        / ++frq[k][ii][jj];
        }
        if (type==3) fill(k);
  }
  else  if (type)
  {
        memset(mag[1], 255, sizeof(mag[1]));

        if (type==1)
        for (j=B-A-1; j<=B-A+1; j++)
        for (i=0; i<2*XS+1; i++)
                mag[1][X-bifocal(i, XS, -xc)][j+i] = 0;
        else
        for (j=B-A-1; j<=B-A+1; j++)
        for (i=0; i<2*XS+1; i++)
                mag[1][X-fisheye(i, XS, -xc)][i+j] = 0;
  }

  redisplay(NULL, 0, 0, 0);
}

void f0(Widget w, void *p)
{
  type = 0;
  generate();
}

void f1(Widget w, void *p)
{
  type = 1;
  generate();
}

void f2(Widget w, void *p)
{
  type = 2;
  generate();
}

void  key(Widget w, char *input, int up_or_down, void *p)
{
  if (!strstr(input, "Up") && !strstr(input, "Down") &&
      !strstr(input, "Left") && !strstr(input, "Right")) return;

  if (flag=1-flag) return;

  if (strstr(input, "Up" ) && xc-10 > A-XS) xc -= 10;
  else if (strstr(input, "Down") && xc+10 < XS-A) xc += 10;
  else if (strstr(input, "Left" ) && yc-10 > A-YS) yc -= 10;
  else if (strstr(input, "Right") && yc+10 < YS-A) yc += 10;
  else return;

  generate();
}

void redisplay(Widget w, int x, int y, void *p)
{
  int i;

  for (i=0; i<4; i++)
  {
        SetDrawArea(ww[i+5]);
        DrawImage(mag[i], 0, 0, X, Y);
  }
}
 

 ****************************************************************************
/* module main.c */

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

#include "libsx.h"
#include "grapx.h"

Widget ww[9];
unsigned char source[3][2*XS+1][2*YS+1], c;

void display(int argc, char **argv)
{
  int i, j;
  FILE *photo, *text;

  for (i=0; i<2*XS+1; i++)
  for (j=0; j<2*YS+1; j++)
        if (i%10&&j%10) source[0][i][j]=255;

  photo = fopen("photo", "r");
  for (i=0; i<2*XS+1; i++)
  for (j=0; j<2*YS+1; j++)
  {
        fscanf(photo, "%u", &c);
        source[1][i][j] = c;
  }
  fclose(photo);

  text = fopen("text", "r");
  for (i=0; i<2*XS+1; i++)
  for (j=0; j<2*YS+1; j++)
  {
        fscanf(text, "%u", &c);
        source[2][i][j] = c;
  }
  fclose(text);

  if (OpenDisplay(argc, argv) == FALSE) return;

  ww[0] = MakeMenu("Type");
  ww[1] = MakeMenuItem(ww[0], "initial view ", (ButtonCB) f0, NULL);
  ww[2] = MakeMenuItem(ww[0], "bifocal view ", (ButtonCB) f1, NULL);
  ww[3] = MakeMenuItem(ww[0], "fisheye view ", (ButtonCB) f2, NULL);
  ww[4] = MakeButton("Quit", (ButtonCB) quit, NULL);
  ww[5] = MakeDrawArea(X, Y, (RedisplayCB) redisplay, NULL);
  ww[6] = MakeDrawArea(X, Y, (RedisplayCB) redisplay, NULL);
  ww[7] = MakeDrawArea(X, Y, (RedisplayCB) redisplay, NULL);
  ww[8] = MakeDrawArea(X, Y, (RedisplayCB) redisplay, NULL);

  SetWidgetPos(ww[1], PLACE_UNDER, ww[0], NO_CARE, NULL);
  SetWidgetPos(ww[4], PLACE_RIGHT, ww[0], NO_CARE, NULL);
  SetWidgetPos(ww[5], PLACE_UNDER, ww[0], NO_CARE, NULL);
  SetWidgetPos(ww[6], PLACE_RIGHT, ww[5], NO_CARE, NULL);
  SetWidgetPos(ww[6], PLACE_UNDER, ww[0], NO_CARE, NULL);
  SetWidgetPos(ww[7], PLACE_UNDER, ww[5], NO_CARE, NULL);
  SetWidgetPos(ww[8], PLACE_RIGHT, ww[7], NO_CARE, NULL);
  SetWidgetPos(ww[8], PLACE_UNDER, ww[5], NO_CARE, NULL);

  SetKeypressCB(ww[5], (KeyCB) key);
  SetKeypressCB(ww[6], (KeyCB) key);
  SetKeypressCB(ww[7], (KeyCB) key);
  SetKeypressCB(ww[8], (KeyCB) key);

  ShowDisplay();
  SetColorMap(GREY_SCALE_2);
  for(i=0; i<9; i++)
  {
        SetFgColor(ww[i], 255);
        SetBorderColor(ww[i], 255);
  }
}

main(int argc, char **argv)
{
  display(argc, argv);
  MainLoop();
}