/*--------------------------------------------------------------------
 *	$Id: psimage.c,v 1.13 2004/06/04 04:26:17 pwessel Exp $
 *
 *	Copyright (c) 1991-2004 by P. Wessel and W. H. F. Smith
 *	See COPYING file for copying and redistribution conditions.
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; version 2 of the License.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	Contact info: gmt.soest.hawaii.edu
 *--------------------------------------------------------------------*/
/*
 * psimage reads a 1, 8, 24, or 32 bit Sun rasterfile and plots it on the page
 *
 * Author:	Paul Wessel
 * Date:	28-JUN-2000
 * Version:	4
 *
 */

#include "gmt.h"

void place_image (unsigned char *buffer, double x0, double y0, double xlength, double ylength, int nx, int ny, int depth, int polarity, int rgb[]);

main (int argc, char **argv)
{
	int i, j, n, nn = -1, justify = 1, n_rep_x = 1, n_rep_y = 1, f_rgb[3], b_rgb[3], polarity = 0, *rgb, PS_interpolate = 1;
	
	BOOLEAN error = FALSE, invert = TRUE, monochrome = FALSE, replicate = FALSE, colorize = FALSE, frame = FALSE;
	
	double x0 = 0.0, y0 = 0.0, y, xlength = 0.0, ylength = 0.0, dpi = 0.0;
	
	char file[BUFSIZ], txt_a[32], txt_b[32], key[9];

	unsigned char *picture;
	
	struct rasterfile header;
	
	struct GMT_PEN pen;

	GMT_init_pen (&pen, GMT_PENWIDTH);
	for (i = 0; i < 3; i++) {
		f_rgb[i] = 0;
		b_rgb[i] = 255;
	}
	strcpy (key, "LB");
	
	argc = GMT_begin (argc, argv);
	
	/* Check and interpret the command line arguments */
	
	for (i = 1; i < argc; i++) {
		if (argv[i][0] == '-') {
			switch(argv[i][1]) {
		
				/* Common parameters */
			
				case 'K':
				case 'O':
				case 'P':
				case 'U':
				case 'V':
				case 'X':
				case 'x':
				case 'Y':
				case 'y':
				case 'c':
				case ':':
				case '\0':
					error += GMT_get_common_args (argv[i], 0, 0, 0, 0);
					break;
				
				/* Supplemental parameters */
			
				case 'C':
					n = sscanf (&argv[i][2], "%[^/]/%[^/]/%s", txt_a, txt_b, key);
					if (n < 2 || n > 3) {
						fprintf (stderr, "%s ERROR: Syntax is -C<xpos>/<ypos>[/<justify>]\n", GMT_program);
						error++;
					}
					x0 = GMT_convert_units (txt_a, GMT_INCH);
					y0 = GMT_convert_units (txt_b, GMT_INCH);
					if (n == 2) strcpy (key, "LB");	/* Default positioning */
					break;
				case 'E':	/* Specify image dpi */
					dpi = atof (&argv[i][2]);
					break;
				case 'F':	/* Specify frame pen */
					if (argv[i][2] && GMT_getpen (&argv[i][2], &pen)) {
						GMT_pen_syntax ('F');
						error++;
					}
					frame = TRUE;
					break;
				case 'G':
					colorize = TRUE;
					switch (argv[i][2]) {
						case 'F':
						case 'f':
							if (argv[i][3] == '-' && argv[i][4] == '\0')
	f_rgb[0] = f_rgb[1] = f_rgb[2] = -1;
							else if (GMT_getrgb (&argv[i][3], f_rgb)) {
								GMT_rgb_syntax ('G');
								error++;
							}
							break;
						case 'B':
						case 'b':
							if (argv[i][3] == '-' && argv[i][4] == '\0')
	b_rgb[0] = b_rgb[1] = b_rgb[2] = -1;
							else if (GMT_getrgb (&argv[i][3], b_rgb)) {
								GMT_rgb_syntax ('G');
								error++;
							}
							break;
						default:	/* Same as -Gf */
							if (argv[i][2] == '-' && argv[i][3] == '\0')
	f_rgb[0] = f_rgb[1] = f_rgb[2] = -1;
							else if (GMT_getrgb (&argv[i][2], f_rgb)) {
								GMT_rgb_syntax ('G');
								error++;
							}
							break;
					}
					break;
				case 'I':	/* Opposite sense than expected to match -Gfill behavior */
					invert = FALSE;
					break;
				case 'M':
					monochrome = TRUE;
					break;
				case 'N':
					replicate = TRUE;
					nn = sscanf (&argv[i][2], "%d/%d", &n_rep_x, &n_rep_y);
					break;
				case 'W':
					n = sscanf (&argv[i][2], "%[^/]/%s", txt_a, txt_b);
					xlength = GMT_convert_units (txt_a, GMT_INCH);
					if (n == 2) ylength = GMT_convert_units (txt_b, GMT_INCH);
					if (xlength < 0.0) {
						xlength = -xlength;
						PS_interpolate = -1;
					}
					break;
					
				/* Options not recognized */
						
				default:
					error = TRUE;
					fprintf (stderr, "GMT SYNTAX ERROR:  Unrecognized option -%c\n", argv[i][1]);
					break;
			}
		}
		else
			strcpy (file, argv[i]);
	}
	
	if (argc == 1 || GMT_quick) {
		fprintf (stderr,"psimage %s - To plot SUN rasterfiles on maps\n\n", GMT_VERSION);
		fprintf (stderr,"usage: psimage <rasterfile> [-E<dpi> or -W[-]<xlength>[/<ylength>]] [-C<xpos>/<ypos>[/<justify>]]\n");
		fprintf (stderr, "\t[-F<pen>] [-G[f|b]<rgb>] [-I] [-K] [-M] [-N<nx/ny>] [-O] [-P] [-U[label]]\n");
		fprintf (stderr, "\t[-V] [-X<x_shift>] [-Y<y_shift>] [-c<ncopies>]\n\n");
		
		if (GMT_quick) exit (EXIT_FAILURE);
		
		fprintf (stderr,"\t<rasterfile> is a 1, 8, 24, or 32-bit Sun rasterfile.\n");
		fprintf (stderr, "\t-E sets image dpi (dots per inch), OR\n");
		fprintf (stderr, "\t-W sets the size of the image.  If <ylength> = 0, it is\n");
		fprintf (stderr, "\t   assumed to be <xlength> * (ny / nx).  If <xlength> < 0\n");
		fprintf (stderr, "\t   then we use absolute value and interpolate image in PostScript.\n");
		fprintf (stderr,"\n\tOPTIONS:\n");
		fprintf (stderr,"\t-C sets the lower left position on the map for raster image [0/0].\n");
		fprintf (stderr,"\t   Optionally, append justification (see pstext for codes)\n");
		fprintf (stderr,"\t-F draws a frame around the image with the given pen.\n");
		fprintf (stderr,"\t-Gf and -Gb sets the foreground and background color, respectively,\n");
		fprintf (stderr,"\t   for 1-bit images to be colorized [Default is black and white]\n");
		fprintf (stderr,"\t   Set <rgb> = - for transparency\n");
		fprintf (stderr,"\t-I invert 1-bit images (does not affect 8 or 24-bit images).\n");
		GMT_explain_option ('K');
		fprintf (stderr,"\t-M Force color -> monochrome image using YIQ-transformation.\n");
		fprintf (stderr,"\t-N Replicate image nx by ny times [Default is no replication]\n");
		GMT_explain_option ('O');
		GMT_explain_option ('P');
		GMT_explain_option ('U');
		GMT_explain_option ('V');
		GMT_explain_option ('X');
		GMT_explain_option ('c');
		GMT_explain_option ('.');
		exit (EXIT_FAILURE);
	}

	/* Check that the options selected are mutually consistent */
	
	if (!file[0]) {
		fprintf (stderr, "%s: GMT SYNTAX ERROR:  Must specify input raster file\n", GMT_program);
		error++;
	}
	if (xlength <= 0.0 && dpi <= 0.0) {
		fprintf (stderr, "%s: Must specify image width (-W) or dpi (-E)\n", GMT_program);
		error++;
	}
	if ((replicate && nn < 0) || n_rep_x < 1 || n_rep_y < 1) {
		fprintf (stderr, "%s: GMT SYNTAX ERROR -N option:  Must specify positive values for replication\n", GMT_program);
		error++;
	}
	if (f_rgb[0] < 0 && b_rgb[0] < 0) {
		fprintf (stderr, "%s: GMT SYNTAX ERROR -G option:  Only one of fore/back-ground can be transparent for1-bit images\n", GMT_program);
		error++;
	}
	if (error) exit (EXIT_FAILURE);

	GMT_put_history (argc, argv);	/* Update .gmtcommands4 */
	
	if (access (file, R_OK)) {
		fprintf (stderr, "%s: Cannot find/open/read file %s\n", GMT_program, file);
		exit (EXIT_FAILURE);
	}

	if (f_rgb[0] < 0 || b_rgb[0] < 0) {	/* Determine if we want transparency of 1-bit image */
		colorize = FALSE;
		invert = !invert;
		if (f_rgb[0] < 0) {
			polarity = 1;	/* 0 + 1 */
			rgb = b_rgb;
		}
		else {
			polarity = 2;	/* 1 + 1 */
			rgb = f_rgb;
		}
	}

	picture = ps_loadraster (file, &header, invert, monochrome, colorize, f_rgb, b_rgb);

	if (!picture) {
		fprintf (stderr, "%s: Trouble loading/converting Sun rasterfile!\n", GMT_program);
		exit (EXIT_FAILURE);
	}
	
	if (!project_info.x_off_supplied && gmtdefs.overlay) gmtdefs.x_origin = 0.0;	/* Since map_setup is not called here */
	if (!project_info.y_off_supplied && gmtdefs.overlay) gmtdefs.y_origin = 0.0;

	ps_plotinit (NULL, gmtdefs.overlay, gmtdefs.page_orientation, gmtdefs.x_origin, gmtdefs.y_origin,
		gmtdefs.global_x_scale, gmtdefs.global_y_scale, gmtdefs.n_copies,
		gmtdefs.dpi, GMT_INCH, gmtdefs.paper_width, gmtdefs.page_rgb, gmtdefs.encoding.name, GMT_epsinfo (argv[0]));
		
	GMT_echo_command (argc, argv);
	if (gmtdefs.unix_time) GMT_timestamp (argc, argv);
	
	if (dpi > 0.0) xlength = (double) header.ras_width / dpi;
	if (ylength == 0.0) ylength = header.ras_height * xlength / header.ras_width;
	justify = GMT_just_decode (key, -1, -1);
	x0 -= 0.5 * ((justify-1)%4) * xlength;
	y0 -= 0.5 * (justify/4) * ylength;

	for (j = 0; j < n_rep_y; j++) {
		y = y0 + j * ylength;
		if (n_rep_y > 1 && gmtdefs.verbose) fprintf (stderr, "%s: Replicating image %d times for row %d\n", GMT_program, n_rep_x, j);
		for (i = 0; i < n_rep_x; i++) {
			place_image (picture, x0 + i * xlength, y, xlength, ylength, header.ras_width, header.ras_height, PS_interpolate * header.ras_depth, polarity, rgb);
		}
	}
 
 	if (frame) {
 		GMT_setpen (&pen);
 		ps_rect (x0, y0, x0 + (n_rep_x * xlength), y0 + (n_rep_y * ylength), GMT_no_rgb, TRUE);
 	}
 	
	ps_plotend (gmtdefs.last_page);
	
	ps_free ((void *)picture);

	GMT_end (argc, argv);
}

void place_image (unsigned char *buffer, double x0, double y0, double xlength, double ylength, int nx, int ny, int depth, int polarity, int rgb[])
{
	if (abs (depth) == 1 && polarity)
		ps_imagemask (x0, y0, xlength, ylength, buffer, nx, ny, polarity-1, rgb);
	else
		GMT_color_image (x0, y0, xlength, ylength, buffer, nx, ny, depth);
}
