/*pixelop.c pixel operations for stscan.c*/
#include <exec/exec.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <graphics/rastport.h>
#include <libraries/reqbase.h>
#include <req_pragmas.h>
#include <stdio.h>
#include <string.h>
#include <functions.h>
#include "stscan.h"

static ULONG histo[16];

void floyd()
{ signed short lbuf[2][4000];
  UBYTE *grptr,*bwptr;
  USHORT i,j;
  signed short f,g;
  char wtitel[20];

  g=(signed short)(winpar.threshold/4);
  for (i=0;i<4000;i++) lbuf[0][i]=lbuf[1][i]=0;
  grptr=bwptr=memptr;
  for (i=0;i<memheight;i++)
  { for (j=0;j<memwidth;j++)
    { if (j&1) lbuf[0][j]=(signed short)(  (*(grptr+(j>>1)))     &15)+lbuf[1][j];
      else     lbuf[0][j]=(signed short)(( (*(grptr+(j>>1))) >>4)&15)+lbuf[1][j];
    }
    for (j=0;j<(memwidth>>3);j++) *(bwptr+j)=0;
    for (j=0;j<memwidth;j++)
    { if (lbuf[0][j]<g) 
      { f=lbuf[0][j];
        *(bwptr+(j>>3))|=bitval[j&7];
      }
      else f=lbuf[0][j]-15;
      lbuf[1][j]=(f+f+f)/8;
      lbuf[1][j+1]=f-2*lbuf[1][j];
      lbuf[0][j+1]+=((f+f+f)/8);
    }
    grptr+=(memwidth>>1);
    bwptr+=(memwidth>>3);
    if (!(i%100)) 
    { sprintf(&wtitel,"Dithering %03d %%",i*100/memheight);
      SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
    }
  }
  memneed=(memwidth*memheight)>>3;
  memgray=0;
  if (!(memptr=(UBYTE *)realloc(memptr,(memwidth*(memheight+ADDLIN))>>3)))
  { memneed=0;
    MessReq((UBYTE *)"Out Of Memory!");
  }
  SetWindowTitles(win," ",(UBYTE *)-1);
}

void ordered()
{ UBYTE *grptr,*bwptr;
  USHORT i,j;
  char wtitel[20];
  UBYTE refmat[4][4]={{0,7,2,9},{11,4,13,6},{3,10,1,8},{14,7,12,5}};
  UBYTE v;

  grptr=bwptr=memptr;
  for (i=0;i<memheight;i++)
  { for (j=0;j<memwidth;j++)
    { v=(j&1)?(  (*grptr)     &15)
             :(( (*grptr) >>4)&15);
      if (v>refmat[j&3][i&3]) *bwptr&=invbitval[j&7];
      else *bwptr|=bitval[j&7];
      if ((j&7)==7) bwptr++;
      if (j&1) grptr++;
    }
    if (!(i%100)) 
    { sprintf(&wtitel,"Dithering %03d %%",i*100/memheight);
      SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
    }
  }
  memneed=(memwidth*memheight)>>3;
  memgray=0;
  if (!(memptr=(UBYTE *)realloc(memptr,(memwidth*(memheight+ADDLIN))>>3)))
  { memneed=0;
    MessReq((UBYTE *)"Out Of Memory!");
  }
  SetWindowTitles(win," ",(UBYTE *)-1);
}

void thresh()
{ UBYTE *grptr,*bwptr;
  USHORT i,j;
  char wtitel[20];
  UBYTE v,g;

  grptr=bwptr=memptr;
  g=winpar.threshold/4;
  for (i=0;i<memheight;i++)
  { for (j=0;j<memwidth;j++)
    { v=(j&1)?(  (*grptr)     &15)
             :(( (*grptr) >>4)&15);
      if (v>g) *bwptr&=invbitval[j&7];
      else *bwptr|=bitval[j&7];
      if ((j&7)==7) bwptr++;
      if (j&1) grptr++;
    }
    if (!(i%100)) 
    { sprintf(&wtitel,"Thresholding %03d %%",i*100/memheight);
      SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
    }
  }
  memneed=(memwidth*memheight)>>3;
  memgray=0;
  if (!(memptr=(UBYTE *)realloc(memptr,(memwidth*(memheight+ADDLIN))>>3)))
  { memneed=0;
    MessReq((UBYTE *)"Out Of Memory!");
  }
  SetWindowTitles(win," ",(UBYTE *)-1);
}

void togray()
{ UBYTE *bwptr,*grptr;
  USHORT i,j;
  char wtitel[20];
  UBYTE v;
  ULONG g;

  memneed=(memwidth*memheight)>>1;
  if (!(memptr=(UBYTE *)realloc(memptr,(memwidth*(memheight+ADDLIN))>>1)))
  { memneed=0;
    MessReq((UBYTE *)"Out Of Memory!");
  }
  else 
  { memgray=1;
    bwptr=memptr+((memwidth*memheight)>>3);
    grptr=memptr+((memwidth*memheight)>>1);
    for (i=0;i<memheight;i++)
    { for (j=0;j<memwidth;j+=8)
      { v= ~(*(--bwptr)); g=0;
        if (v&128) g|=0xf0000000;
        if (v& 64) g|=0x0f000000;
        if (v& 32) g|=0x00f00000;
        if (v& 16) g|=0x000f0000;
        if (v&  8) g|=0x0000f000;
        if (v&  4) g|=0x00000f00;
        if (v&  2) g|=0x000000f0;
        if (v&  1) g|=0x0000000f;
        *(--grptr)=(UBYTE)(g&0xff);
        *(--grptr)=(UBYTE)((g>>8)&0xff);
        *(--grptr)=(UBYTE)((g>>16)&0xff);
        *(--grptr)=(UBYTE)((g>>24)&0xff);
      }
      if (!(i%128)) 
      { sprintf(&wtitel,"Converting %03d %%",i*100/memheight);
        SetWindowTitles(win,&wtitel[0],(UBYTE *)-1);
      }
    }
    SetWindowTitles(win," ",(UBYTE *)-1);
  }
}


void invert()
{ UBYTE *picptr;
  ULONG i;

  picptr=memptr;
  for (i=0;i<memneed;i++) *(picptr++)=~(*picptr);
}

void mirrorh()
{ UBYTE *picptr;
  ULONG i,j;
  UBYTE temp[4000];
  ULONG bpl;

  bpl=(memgray)?(memwidth>>1):(memwidth>>3);
  picptr=memptr;
  if (memgray)
    for (i=0;i<memheight;i++)
    { memcpy(&temp[1],picptr,bpl);
      for (j=bpl;j>0;j--)
        *(picptr++)=(((temp[j]&0x0f)<<4)|((temp[j]&0xf0)>>4));
    }
  else 
    for (i=0;i<memheight;i++)
    { memcpy(&temp[1],picptr,bpl);
      for (j=bpl;j>0;j--)
        *(picptr++)=revbit[temp[j]];
    }
}

void mirrorv()
{ UBYTE *l1ptr,*l2ptr;
  USHORT i;
  UBYTE temp[4000];
  ULONG bpl;

  bpl=(memgray)?(memwidth>>1):(memwidth>>3);
  l1ptr=memptr;
  l2ptr=memptr+(memheight-1)*bpl;
  for (i=0;i<(memheight>>1);i++)
  { memcpy(&temp[0],l1ptr,bpl);
    memcpy(l1ptr,l2ptr,bpl);
    memcpy(l2ptr,&temp[0],bpl);
    l1ptr+=bpl;
    l2ptr-=bpl;
  }
}

static void counthisto()
{ ULONG cnt;
  UBYTE *picptr;
  UBYTE i,b;

  for (i=0;i<16;i++) histo[i]=0;
  picptr=memptr;
  for (cnt=0;cnt<memneed;cnt++)
  { b=*(picptr++);
    histo[b&0x0f]++;
    histo[(b>>4)&0x0f]++;
  }
}

void viewhisto(struct RastPort *wrp)
{ ULONG max=0;
  UBYTE i;
  UWORD ampl;
  UBYTE *plptr[4];
  
  counthisto();
  for (i=0;i<16;i++) if (histo[i]>max) max=histo[i];
  for (i=0;i<4;i++) plptr[i]=(UBYTE *)(rp->BitMap->Planes[i]+1680);
  clrscr(plptr[0],plptr[1],plptr[2],plptr[3]);
  SetWrMsk(wrp,15);
  SetDrMd(wrp,JAM1);
  SetDrPt(wrp,0xffff);
  SetAPen(wrp,1);
  Move(wrp,50,390); Draw(wrp,529,390);
  for(i=0;i<16;i++)
  { SetAPen(wrp,1);
    ampl=histo[i]*350/max;
    Move(wrp,50+i*30,390);
    Draw(wrp,50+i*30,390-ampl);
    Draw(wrp,79+i*30,390-ampl);
    Draw(wrp,79+i*30,390);
    if (ampl>1)
    { SetAPen(wrp,(i+1)&0x0f);
      RectFill(wrp,51+i*30,391-ampl,78+i*30,389);
    }
  }
}
        
void stretchhisto()
{ ULONG integ[16];
  UBYTE lut[16];
  UBYTE largelut[256];
  UWORD i;
  ULONG cnt;
  UBYTE *picptr;
 
  counthisto();
  integ[0]=histo[0];
  for(i=1;i<16;i++) integ[i]=histo[i]+integ[i-1];
  for(i=0;i<16;i++) lut[i]=(UBYTE)((integ[i]*15)/integ[15])&0x0f;
  for(i=0;i<256;i++) largelut[i]=(((lut[(i>>4)&0x0f])<<4)|(lut[i&0x0f]));
  picptr=memptr;
  for(cnt=0;cnt<memneed;cnt++) {*picptr=largelut[*picptr]; picptr++; }
}
