/* Raw image loader (and saver) plugin 3.0
 *
 * by tim copperfield [timecop@japan.co.jp]
 * http://www.ne.jp/asahi/linux/timecop
 *
 * This plugin is not based on any other plugin.
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <sys/types.h>

#ifdef WIN32

#else
#include <sys/fcntl.h>
#endif

#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

#include <gtk/gtk.h>

#include "lib/plugin_main.h"
#include "lib/ui.h"

#include "fromrad.h"

#define GIMP_CHECK_SIZE 8
#define GIMP_CHECK_LIGHT 0
#define GIMP_CHECK_DARK 1

// radience data
COLR cbuf[MAXWIDTH];
unsigned short rbuf[MAXWIDTH];
unsigned short gbuf[MAXWIDTH];
unsigned short bbuf[MAXWIDTH];

typedef enum {
    RAW_RGB,			/* RGB Image */
    RAW_RGBA,			/* RGB Image with an Alpha channel */
    RAW_PLANAR,			/* Planar RGB */
    RAW_INDEXED			/* Indexed image */
} raw_type;

typedef enum {
    RAW_PALETTE_RGB,		/* standard RGB */
    RAW_PALETTE_BGR		/* Windows BGRX */
} raw_palette_type;

typedef struct {
    gint32 file_offset;		/* offset to beginning of image in raw data */
    gint32 image_width;		/* width of the raw image */
    gint32 image_height;	/* height of the raw image */
    raw_type image_type;	/* type of image (RGB, INDEXED, etc) */
    gint32 palette_offset;	/* offset inside the palette file, if any */
    raw_palette_type palette_type;	/* type of palette (RGB/BGR) */
} raw_config;

typedef struct {
    FILE *fp;			/* pointer to the already open file */
    TileDrawable *drawable;	/* gimp drawable */
    GPixelRgn region;	/* gimp pixel region */
    gint32 image_id;		/* gimp image id */
    guchar cmap[768];		/* color map for indexed images */
} raw_gimp_data;

raw_config *runtime;

/* support functions */
static gint32 load_image(gchar * filename);

/* gimp function prototypes */
static void query(void);
static void run(gchar * name,
		gint nparams,
		GParam * param,
		gint * nreturn_vals, GParam ** return_vals);

/* end prototypes */

GPlugInInfo PLUG_IN_INFO = {
    NULL,			/* init_proc  */
    NULL,			/* quit_proc  */
    query,			/* query_proc */
    run,			/* run_proc   */
};

MAIN()

static void query(void)
{
    static GParamDef load_args[] = {
	{PARAM_INT32, "run_mode", "Interactive"},
	{PARAM_STRING, "filename", "The name of the file to load"},
	{PARAM_STRING, "raw_filename", "The name entered"},
    };
    static gint nload_args = sizeof(load_args) / sizeof(load_args[0]);

    static GParamDef load_return_vals[] = {
	{PARAM_IMAGE, "image", "Output image"}
    };
    static gint nload_return_vals = (sizeof(load_return_vals) /
				     sizeof(load_return_vals[0]));

    gimp_install_procedure("file_hdr_load",
			   "Load hdr images",
			   "Load hdr images",
			   "timecop",
			   "timecop",
			   "Oct 2000",
			   "<Load>/HDR",
			   NULL,
			   PROC_PLUG_IN,
			   nload_args, nload_return_vals,
			   load_args, load_return_vals);

			   //"INDEXED,GRAY,RGB*,U16_RGB*,U16_GRAY*,FLOAT_RGB*,FLOAT16_RGB*,FLOAT16_GRAY*",

    gimp_register_magic_load_handler("file_hdr_load", "hdr", "", "");
/* rsr 5-11-03 TO-DO!
	gimp_register_save_handler ("file_hdr_save", "hdr", "");*/
}

GStatusType status = STATUS_SUCCESS;
GParam * params = NULL;
gint32 image_id;
gint32 drawable_id;
GtkWidget* load_dialog;
int bit_depth = 16;

static void
run(gchar * name,
    gint nparams,
    GParam * param, gint * nreturn_vals, GParam ** return_vals)
{

    static GParam values[2];
    GRunModeType run_mode;

    run_mode = (GRunModeType)param[0].data.d_int32;
	params = param;
	status = STATUS_SUCCESS;
    *nreturn_vals = 1;
    *return_vals = values;
    values[0].type = PARAM_STATUS;
    values[0].data.d_status = STATUS_EXECUTION_ERROR;

    /* allocate config structure and fill with defaults */
    runtime = (raw_config *)g_malloc0(sizeof(raw_config));
    runtime->file_offset = 0;
    runtime->image_width = 128;
    runtime->image_height = 128;
    runtime->image_type = RAW_RGB;
    runtime->palette_offset = 0;
    runtime->palette_type = RAW_PALETTE_RGB;

    /* load image */
    if (strcmp(name, "file_hdr_load") == 0 ) 
    {
        if (run_mode == RUN_INTERACTIVE) {
			gimp_get_data(name, runtime);
            status = STATUS_SUCCESS;
        } else {
            status = STATUS_CALLING_ERROR;
        }
        /* we are okay, and the user clicked OK in the load dialog */
        if (status == STATUS_SUCCESS) {
            image_id = load_image(param[1].data.d_string);
            if (image_id != -1) {
                gimp_set_data(name, runtime, sizeof(raw_config));
                *nreturn_vals = 2;
                values[1].type = PARAM_IMAGE;
                values[1].data.d_image = image_id;
            } else {
                status = STATUS_CALLING_ERROR;
            }
        }
    } 
    values[0].data.d_status = status;
    g_free(runtime);
}

gint32 load_image(gchar * filename)
{
	int i,j,k;
    /* main struct with the image info in it */
    raw_gimp_data *data;

    /* stuff for the gimp image, local to this function */
    gint32 layer_id = -1;
    GImageType itype = RGB;
    GDrawableType ltype = RGBA_IMAGE;
    unsigned char* bufPtr = 0;
    float Gamma = 2.2;
    float Stop = 0.;
 
    gint bpp = 0;
    // radience handling 
    FILE *inf;
    int xsize, ysize;
    int  dogamma = 0;
    float f;
    float r,g,b;
    gfloat *rowptr=NULL, *rowc=NULL, *buf =NULL;;

    /* allocate the raw_gimp_data structure */
    data = (raw_gimp_data *)g_malloc0(sizeof(raw_gimp_data));

    inf = fopen(filename,"rb");
    if(!inf) {
        fprintf(stderr,"fromrad: can't open %s\n",filename);
        exit(1);
    }
    if (checkheader(inf,COLRFMT,(FILE *)NULL) < 0 ||
		fgetresolu(&xsize, &ysize, inf) < 0) {
        fprintf(stderr,"fromrad: input not in Radiance format\n");
        exit(1);
    }

	switch (32) /* radience format */
	{
		case 32: /* floating point data */
		default:
			bpp = 8;
			bpp = 32;
            itype = FLOAT_RGB;
            //ltype = (alpha) ? FLOAT_RGBA_IMAGE : FLOAT_RGB_IMAGE;
            ltype = FLOAT_RGB_IMAGE;
			break;
    }

    /* create new gimp image */
    data->image_id =
		gimp_image_new(xsize, ysize, itype);

    /* set image filename */
    gimp_image_set_filename(data->image_id, filename);

    /* create new layer - local variable */
    layer_id =
		gimp_layer_new(data->image_id, "Background",
		      xsize, ysize, ltype,
		      100, NORMAL_MODE);
    gimp_image_add_layer(data->image_id, layer_id, 0);

    /* create gimp drawable for the image */
    data->drawable = gimp_drawable_get(layer_id);

    /* initialize pixel region */
    gimp_pixel_rgn_init(&data->region, data->drawable, 0, 0,
			xsize, ysize,
			TRUE, FALSE);

    /* load image */
    buf = (gfloat *)g_malloc(xsize * ysize *bpp);

    gimp_progress_init (g_strconcat("Loading ",filename,NULL));


    //Stop = pow(2.0, expadj);

	for(i=0;i<ysize;i++) {

        freadcolrs(cbuf,xsize,inf);

        // Pointer to gimp framebuffer
        // unpack data for gimp
        rowc = buf+(i*xsize*3);
        bufPtr = ((unsigned char*)cbuf);
        k = 0;
        for (j = 0; j < xsize; j++)
        {

            if(bufPtr[3]) {
                f = ldexp(1.0, bufPtr[3]-(int)(128+8));

                r = bufPtr[0] * f;
                g = bufPtr[1] * f;
                b = bufPtr[2] * f;

                rowc[k++] = r;
                rowc[k++] = g;
                rowc[k++] = b;
            } else {     
                rowc[k++] = 0.0f;
                rowc[k++] = 0.0f;
                rowc[k++] = 0.0f;
            }

            bufPtr += 4;
        }
		gimp_progress_update((gfloat) i / (gfloat) ysize);
	}
    gimp_pixel_rgn_set_rect(&data->region, (guchar *)buf, 0, 0, xsize, ysize);

    g_free(buf);
    gimp_drawable_flush(data->drawable);
    gimp_drawable_detach(data->drawable);

    return data->image_id;
}
