/* Riemersma dither * * This program reads in an uncompressed gray-scale image with one byte per * pixel and a size of 256*256 pixels (no image header). It dithers the image * and writes an output image in the same format. * * This program was tested with Borland C++ 3.1 16-bit (DOS), compiled in * large memory model. For other compilers, you may have to replace the * calls to _fmalloc() and _ffree() with straight malloc() and free() calls. */ #include /* for _fmalloc() and _ffree() */ #include #include #include #include #define WIDTH 256 #define HEIGHT 256 #define BLOCKSIZE 16384 // read in chunks of 16 kBytes enum { NONE, UP, LEFT, DOWN, RIGHT, }; /* variables needed for the Riemersma dither algorithm */ static int cur_x=0, cur_y=0; static int img_width=0, img_height=0; static unsigned char *img_ptr; #define SIZE 16 /* queue size: number of pixels remembered */ #define MAX 16 /* relative weight of youngest pixel in the * queue, versus the oldest pixel */ static int weights[SIZE]; /* weights for the errors of recent pixels */ static void init_weights(int a[],int size,int max) { double m = exp(log(max)/(size-1)); double v; int i; for (i=0, v=1.0; i=128) ? 255 : 0; memmove(error,error+1,(SIZE-1)*sizeof error[0]); /* shift queue */ error[SIZE-1] = *pixel - pvalue; *pixel=(unsigned char)pvalue; } static void move(int direction) { /* dither the current pixel */ if (cur_x>=0 && cur_x=0 && cur_y1) { value >>= 1; result++; } /*while */ return result; } void Riemersma(void *image,int width,int height) { int level,size; /* determine the required order of the Hilbert curve */ size=max(width,height); level=log2(size); if ((1L << level) < size) level++; init_weights(weights,SIZE,MAX); img_ptr=image; img_width=width; img_height=height; cur_x=0; cur_y=0; if (level>0) hilbert_level(level,UP); move(NONE); } void main(int argc,char *argv[]) { unsigned char *ptr; unsigned char *image; FILE *fp; long filesize; char filename[128]; /* check arguments */ if (argc<2 || argc>3) { printf("Usage: riemer [output]\n\n" "Input and output files must be raw gray-scale " "files with a size of 256*256\n" "pixels; one byte per pixel.\n"); return; } /* if */ if ((fp=fopen(argv[1],"rb"))==NULL) { printf("File not found (%s)\n",argv[1]); return; } /* if */ if ((image=_fmalloc((long)WIDTH*HEIGHT))==NULL) { printf("Insufficient memory\n"); return; } /* if */ /* read in the file */ filesize=(long)WIDTH*HEIGHT; ptr=image; while (filesize>BLOCKSIZE) { fread(ptr,1,BLOCKSIZE,fp); filesize-=BLOCKSIZE; ptr+=BLOCKSIZE; } /* while */ if (filesize>0) fread(ptr,1,(int)filesize,fp); fclose(fp); /* dither (replacing the original */ Riemersma(image,WIDTH,HEIGHT); /* save the dithered file */ if (argc==3) strcpy(filename,argv[2]); else strcpy(filename,"riemer.raw"); fp=fopen(filename,"wb"); if (fp==NULL) { printf("Cannot create file \"%s\"\n",filename); return; } /* if */ filesize=(long)WIDTH*HEIGHT; ptr=image; while (filesize>BLOCKSIZE) { fwrite(ptr,1,BLOCKSIZE,fp); filesize-=BLOCKSIZE; ptr+=BLOCKSIZE; } /* while */ if (filesize>0) fwrite(ptr,1,(int)filesize,fp); fclose(fp); _ffree(image); }