Listing 1

/*
---------------
   main.c
   Time-stamp: <06 Dec 96 -- 14:20:16 siome>
   Dith - Special Dither of image pieces
   Siome Klein Goldenstein
  ---------------- */

 /* the following declare allows the program to
   compile and work with different version of TK
   (4.0 for Red Hat 3.0.3 and 4.1 for Red Hat 4.0
   for example) */
#define TK_IS_40 0

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

#if TK_IS_40
#include <tcl/tcl.h>
#include <tcl/tk.h>
#else
#include <tcl.h>
#include <tk.h>
#endif
#include "dither.h"

int    flx, frx, fuy, fdy;
int    ftx, fty;
double  *filter;
#if TK_IS_40
static Tk_Window mainWindow;a
#endif
int
main (int argc, char **argv)
{
  Tcl_Interp  *interp;
  char        s[100]; 

#if TK_IS_40
  static char *display = NULL;
#endif

  if (argc != 2)
  {
    fprintf(stderr,
     "%s: wrong number of arguments\n",
     argv[0]);
    exit (1);
  }
  /* Here begins the first step on C and TCL
     integration: The Tcl/Tk initialization.
     Notice that mainWindow is global variable */
  interp = Tcl_CreateInterp();
#if TK_IS_40
  mainWindow = Tk_CreateMainWindow(interp, 
     display, argv[0], "Tk");
  if (mainWindow == NULL)
  {
    fprintf(stderr, "%s\n", interp->result);
    exit(1);
  }
#endif
  if (Tcl_Init(interp) == TCL_ERROR)
  {
    fprintf(stderr, "Tcl_Init failed: %s\n",
      interp->result);
    exit (1);
  }
  if (Tk_Init(interp) == TCL_ERROR)
  {
    fprintf(stderr, "Tk_Init failed: %s\n",
      interp->result);
    exit (1);
  }
  /* The second step, creation of your Tcl 
     commands. The creation of a similar 
     initialization routine is just to keep
     the same style. */
  
  if (Dith_Init(interp) == TCL_ERROR)
  {
    fprintf(stderr,"Recon_Init failed: %s\n",
      interp->result);
    exit(1);
  }
  /* Now we create the original image and ask TCL
     to evaluate our "interface description"
     file. */
  
  sprintf(s,
    "image create photo original -file %s\n",
    argv[1]);
  Tcl_GlobalEval (interp,s);
  Tcl_EvalFile (interp,"./int-dither.tcl";<\n>)
  
  /* Finally, we let Tk take care of main loop */
  Tk_MainLoop();
  return (0);
}
/* The initalization Routine */
int
Dith_Init (Tcl_Interp *interp)
{
  Tcl_CreateCommand (interp, "CDith", 
     Dith_cdither, (ClientData *) NULL, 
    (Tcl_CmdDeleteProc *) NULL);
  return TCL_OK;
}
int
Dith_cdither (ClientData cd, Tcl_Interp *interp,
		  int argc, char **argv)
  Tk_PhotoHandle      todith;
  Tk_PhotoImageBlock  blorig, blnew;
  int   tx, ty;
  int   step;
  int   x, y, i;
  int   ct;
  double intens;

  /* get the image handle */
  todith = Tk_FindPhoto (argv[1]);

  /* get the vertical size of dithering cluster */
  step = atoi (argv[2]);

  /* Obtain the image itself from the handle */
  Tk_PhotoGetSize  (todith, &tx, &ty);
  Tk_PhotoGetImage (todith, &blorig);

  /* Create new "image" for placing the dither */
  blnew.width  = tx;
  blnew.height = ty;
  blnew.pitch  = tx;
  blnew.pixelSize = 1;
  blnew.offset[0] = 0;
  blnew.offset[1] = 0;
  blnew.offset[2] = 0;
  if ( (blnew.pixelPtr = (unsigned char*)
	calloc (tx * ty, sizeof (unsigned char)))==
	NULL)
  {
    fprintf (stderr,
     "Error in memory allocation\n");
    exit (1);
  }
  for (y=step-1; y<ty; y+=step)
  {
    for (x=0; x<tx; x++)
    {
      for (intens=0.0, ct = 0; ct< step; ct++)
	intens += ( RED(&blorig,x,y-ct) +  
		   GREEN(&blorig,x,y-ct) +
		   BLUE(&blorig,x,y-ct) ) / 3.0;
      intens /= (255.0 * step);
      i = rint(intens * (step-2)) + 1;
      for (ct=0; ct < (i/2); ct++)
      {
	/* for the sake of clarity, no optimization
   	    is done */
	RED(&blnew, x, y-step+1+ct) = 255;
	RED(&blnew, x, y-ct) = 255;
      }
      if (i%2)
	RED(&blnew, x, y-step+1+(i/2)) = 255;
      
    }
  }
  Tk_PhotoPutBlock (todith,&blnew,0,0,tx,ty);
  free (blnew.pixelPtr);
  
  return TCL_OK;
}