/*----------------------------------------------------------------------
    Line-preserving smoothing                   lpsmooth  ver 1.2
        Written by  H.Goto, Apr  2000
        Modified by H.Goto, July 2000
        Modified by H.Goto, Sep  2000
        Modified by H.Goto, Feb  2002
----------------------------------------------------------------------*/

/*--------------------------------------------------------------------
  Copyright (C) 2000-2002  Hideaki Goto

        All Rights Reserved

  Permission to use, copy, modify, and distribute this software and
  its documentation for any purpose is hereby granted without fee,
  provided that (i) the above copyright notice and this permission
  notice appear in all copies and in supporting documentation, (ii)
  the name of the author, Hideaki Goto, may not be used in any
  advertising or otherwise to promote the sale, use or other
  dealings in this software without prior written authorization
  from the author, (iii) this software may not be used for
  commercial products without prior written permission from the
  author, and (iv) the notice of the modification is specified in
  case of that the modified copies of this software are distributed.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
  THE AUTHOR WILL NOT BE RESPONSIBLE FOR ANY DAMAGE CAUSED BY THIS
  SOFTWARE.
--------------------------------------------------------------------*/

#define		DefaultProcessCount	1
#define		DefaultCenterWeight	1
#define		DefaultPixels		3

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

#include	"utypes.h"

#include	"ufilep.h"
#include	"siplib.h"
#include	"xiplib.h"

static int	sw_verbose = 0;




/*----------------------------------------------
    Load PGM image file
----------------------------------------------*/

static int load_image(char *fname,SIPImage **image,int *width,int *height){
	PBMFILE	PBMLD;
	int	retcode,depth,x,y;
	SIPImage	*imgbuf;
	int	bufwidth,bufheight,bufdepth;
	uchar	*lbuf,*src,*dst;
	*image = 0;	/* default value = NULL */
	PBMLD.setpal_fb(0,0xff);
	retcode = PBMLD.open(fname,"r");
	if ( retcode )  return(retcode);
	switch ( PBMLD.getfiletype() ){
	  case 0:	depth = 1;  bufdepth = 8;  break;
	  case 1:	depth = 8;  bufdepth = 8;  break;
	  case 2:	depth = 32;  bufdepth = 32;  break;	/* 24bit */
	  default:	return(-5);
	}
	*width  = PBMLD.getwidth();
	*height = PBMLD.getheight();

	bufwidth  = *width;
	bufheight = *height;

	if ( 0 == (lbuf = new uchar[3 * bufwidth]) )  return(-6);
	if ( 0 == (imgbuf = sip_CreateImage(bufwidth,bufheight,bufdepth)) ){
		delete []lbuf;
		return(-6);
	}
	sip_ClearImage(imgbuf,0xff);
	for ( y=0 ; y < *height ; y++ ){
		if ( 32 == depth ){
			if ( 0 != PBMLD.readline(-1,(void *)lbuf) ){
				delete []lbuf;
				return(-1);	/* read error */
			}
			src = lbuf;  dst = (uchar *)sip_getimgptr(imgbuf,y);
			for ( x=0 ; x < *width ; x++ ){
				dst[0] = src[0];
				dst[1] = src[1];
				dst[2] = src[2];
				dst[3] = 0;
				src += 3;  dst += 4;
			}
		}
		else if ( 8 == depth ){
			if ( 0 != PBMLD.readline(-1,\
				(void *)sip_getimgptr(imgbuf,y)) ){
				delete []lbuf;
				return(-1);	/* read error */
			}
		}
		else{	if ( 0 != PBMLD.readline_gray(-1,\
				(void *)sip_getimgptr(imgbuf,y)) ){
				delete []lbuf;
				return(-1);	/* read error */
			}
		}
	}
	*image = imgbuf;
	delete []lbuf;
	PBMLD.close();
	return(0);
}




/*----------------------------------------------
    Print usage
----------------------------------------------*/

static void usage(){
	fputs("lpsmooth v1.2, Copyright (C) 2000-2002 Hideaki Goto \n",stderr);
	fputs("Usage: lpsmooth [-options] in_file out_file \n",stderr);
	fputs("         -n N      :  smoothing counts (default N=1) \n",stderr);
	fputs("         -w N      :  weight factor for the central pixel (default N=1) \n",stderr);
	fputs("         -p N      :  number of the pixels used (1-9) (default N=3) \n",stderr);
	fputs("         -verbose  :  show processing information \n",stderr);
	fputs("Note:  lpsmooth -w 1 -p 9 ... is identical to calculating \n",stderr);
	fputs("       the moving average with a 3x3 mask. \n",stderr);
	fputs("       lpsmooth -w 0 -p N ... is identical to the k-nearest neighbor \n",stderr);
	fputs("       smoothing with k=N-1. \n",stderr);
}




/*----------------------------------------------
    Main routine
----------------------------------------------*/

int main(int ac,char *av[]){
	char	*infile  = NULL;
	char	*outfile = NULL;
	int	proc_counts = DefaultProcessCount;
	int	ctweight = DefaultCenterWeight;
	int	pixels = DefaultPixels;
	int	width,height;
	int	i,k;
	SIPImage	*image;

	for ( k=1, i=1 ; i<ac && k ; i++ ){
		if ( 0 == strcmp("-n",av[i]) ){
			if ( i++ >= ac ){  k=0; continue; }
			proc_counts = atoi(av[i]);
			if ( proc_counts < 1 ){  k=0; continue; }
			continue;
		}
		if ( 0 == strcmp("-w",av[i]) ){
			if ( i++ >= ac ){  k=0; continue; }
			ctweight = atoi(av[i]);
			if ( ctweight < 0 ){  k=0; continue; }
			continue;
		}
		if ( 0 == strcmp("-p",av[i]) ){
			if ( i++ >= ac ){  k=0; continue; }
			pixels = atoi(av[i]);
			if ( pixels < 1 || pixels > 9 ){  k=0; continue; }
			continue;
		}
		if ( 0 == strcmp("-verbose",av[i]) ){  sw_verbose = -1;  continue; }
		if ( 0 == strcmp("-v",av[i]) ){  sw_verbose = -1;  continue; }
		if ( av[i][0] == '-' && strlen(av[i]) > 1 ){  k=0;  continue; }
		if ( NULL == infile ){  infile = av[i];  continue; }
		if ( NULL == outfile ){  outfile = av[i];  continue; }
	}
	if ( k == 0 || outfile == NULL ){  usage();  return(0); }
	if ( k == 0 || infile == NULL ){  usage();  return(0); }
	if ( pixels == 1 && ctweight == 0 ){  usage();  return(0); }


/* ---- Read Image ---- */

	if ( 0 > load_image(infile,&image,&width,&height) ){
		fprintf(stderr,"Can't read \"%s\".\n",infile);
		return(2);
	}

	if ( sw_verbose ){
		fprintf(stderr,"Image size  = %d x %d\n",width,height);
		if ( image->depth == 32 ){
			fprintf(stderr,"Image depth = 24\n");
		}
		else{	fprintf(stderr,"Image depth = 8\n");
		}
	}


/* ---- Smoothing ---- */

	for ( i=0 ; i<proc_counts ; i++ ){
		sip_kNNsmooth(image,image,pixels,ctweight);
	}


/* ---- Save Image  ---- */

	if ( 0 > xip_SaveImage(outfile,image) ){
		fprintf(stderr,"Can't write \"%s\".\n",outfile);
	}

	sip_DestroyImage(image);
	return(0);
}


