/*
 * Texture.c - Does a simple Texture in Imagemaster
 */

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

struct jackinbuff
  {
    unsigned char *red;
    unsigned char *green;
    unsigned char *blue;
    unsigned char *mask;
    unsigned short x;
    unsigned short y;
  };

struct jackina
  {
    struct jackinbuff *primary;
    struct jackinbuff *secondary;
    struct jackinbuff *undo;
    struct jackinbuff *blend;
    struct jackinbuff *brush;
    unsigned char *mask;
    unsigned char jack[4]; 
    struct Screen *showscr;
    unsigned char pname[4];
    long   ver;
  };

static struct jackina *jackins;
static struct jackinbuff *primary_jack;
static struct jackinbuff *secondary_jack;
static struct jackinbuff *undo_jack;
static struct jackinbuff *blend_jack;
static struct jackinbuff *brush_jack;
static int arraycos[360];

/*
 * limit255()  limits colors to the valid range 0 to 255
 */
int limit255(int i)
  {
    if (i < 0) return(0);
    if (i > 255) return(255);
    return(i);
  }

/*
 * setupicos()  pre-calculates an inter based cos() array
 */
void setupicos()
  {
  int i;
  double rad;
    for (i=0; i<360; i++)
      {
        rad = (double)i / 57.29599951;
        rad = 512.0 * cos(rad);
        arraycos[i] = (int)rad;
      }
  }

/*
 * icos()  does an integer based cos() lookup
 *         input is degrees
 *         output is -512 to 512
 *   NOTE: setupicos() must be called once before this is called
 */
int icos(int i)
  {
    i = abs(i)%360;
    return(arraycos[i]);
  }

main(argc,argv)
int    argc;
char   *argv[];
  {
  unsigned int tpoint;
  int xw,yw,offset,yoffset,level,levelQ;
  int rrnew,ggnew,bbnew,p,rr,gg,bb,x,y;
  
  unsigned char *rbu;
  unsigned char *gbu;
  unsigned char *bbu;
  unsigned char *m;
  
  
    if (argc <= 2)
      {
        printf("TEXTURE : Not enough arguments supplied!\n");
        printf("TEXTURE <pointer to IM jackin structure> <level>\n");
        printf("A simple Imagemaster Public Interface operation.\n");
        return(1);
      }
    else
      {
        sscanf(argv[1],"%X",&tpoint);
        sscanf(argv[2],"%d",&level);
      }
    if (tpoint == 0)
      {
        printf("TEXTURE : Argument is ZERO!\n");
        return(1);
      }
      
    jackins = (struct jackina *)tpoint;
      
    if (jackins->jack[0] != 'J' ||
        jackins->jack[1] != 'A' ||
        jackins->jack[2] != 'C' ||
        jackins->jack[3] != 'K' )
      {
        printf("TEXTURE : Problem in information passed from Imagemaster!\n");
        return(1);
      }
    if (jackins->primary == NULL)
      {
        printf("TEXTURE : Primary buffer is NULL!\n");
        return(1);
      }
    if (openlibraries())
      {
        return(1);
      }
    xw = jackins->primary->x;
    yw = jackins->primary->y;
    if (xw == 0 || yw == 0)
      {
        printf("TEXTURE : Primary buffer is Empty!\n");
        return(1);
      }
    rbu = jackins->primary->red;
    gbu = jackins->primary->green;
    bbu = jackins->primary->blue;
    m   = jackins->mask;
    if (rbu == NULL || gbu == NULL || bbu == NULL)
      {
        printf("TEXTURE : Primary buffer is corrupted!\n");
        return(1);
      }
    /* Run through the image */
    levelQ = 100-level;
    progressbegin(jackins->showscr,yw,"Texture PI");
    
    setupicos();
    
    for (y=0; y<yw; y++)
      {
        progressupdate(y);
        yoffset = y * xw;
        for (x=0; x<=xw; x++)
          {
            offset = yoffset + x;
            if (m[offset] != '\0')
              {
                /* We get the old values */
                rr = *(rbu+offset);
                gg = *(gbu+offset);
                bb = *(bbu+offset);
                
                /* This is the position calculation */
                p = icos((x+y)*5) + icos(x-y);
                p = (p + 1024)%255 - 128;
                
                
                /* This is the texture added to the image colors */
                rrnew = limit255( rr + p); 
                ggnew = limit255( gg + p);
                bbnew = limit255( bb + p);
                
                /* This weights the change according to the user's prop */
                *(rbu+offset) = (rrnew*level + rr *levelQ)/100;
                *(gbu+offset) = (ggnew*level + gg *levelQ)/100;
                *(bbu+offset) = (bbnew*level + bb *levelQ)/100;
              }
          }
      }
    progressend();
    closelibraries();
    return(0);
  }

