/**********************************************************************
 
	Copyright (C) 2005- Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	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.

**********************************************************************/

#include	"machine/include.h"
#include	"memory_debug.h"
#include	"pri_level.h"
#include	"lock_level.h"
#include	"utils.h"
#include	"task.h"
#include	"matrix.h"
#include	"xl.h"
#include	"xlerror.h"
#include	"memory_routine.h"
#include	"jpeg.h"


XL_SEXP *
xl_mxUncompressJPEG(XLISP_ENV * env,XL_SEXP * s,XLISP_ENV * a,XL_SYM_FIELD * sf);
void * mx_glay_uncompress_1(unsigned char * d1);
void * mx_glay_uncompress_2(unsigned char * d1,int len);
void * mx_jpeg_uncompress_1(unsigned char * d1);
void * mx_jpeg_uncompress_2(unsigned char * d1,int len);

void
init_mxUncompressJPEG(XLISP_ENV * env)
{
	set_env(env,l_string(std_cm,"mxUncompressJPEG"),
		get_func_prim(xl_mxUncompressJPEG,FO_APPLICATIVE,0,2,2));
}

void *
mx_glay_uncompress_1(unsigned char * d1)
{
void * ret;
MATRIX_ALLOC_VECTOR_PARAM pp;
int ix_size[2];
MATRIX_DH_SET h;
unsigned char * p, * q;
	pp.dim = 2;
	pp.ix_size = &ix_size[0];
	pp.default_data = 0;
	ix_size[0] = d1[2];
	ix_size[1] = d1[3];
	ret = (*mx_type_uint8.alloc_data)
			(&mx_type_uint8,MD_MMALLOC,&pp,0,
			__FILE__,__LINE__);
	get_matrix_dh_set(&h,ret);
	p = &d1[4];
	q = (unsigned char*)h.offset;
	memcpy(q,p,h.total_element);
	return ret;
}

void *
mx_glay_uncompress_2(unsigned char * d1,int len)
{
unsigned char * tmp;
int ix_size[2];
MATRIX_DH_SET h;
int i;
void * ret;
int ww,hh;
unsigned char * p, * q;
MATRIX_ALLOC_VECTOR_PARAM pp;
	tmp = jpeg_uncompress(&ww,&hh,&d1[2],len-2);
	pp.dim = 2;
	pp.ix_size = &ix_size[0];
	pp.default_data = 0;
	ix_size[0] = ww;
	ix_size[1] = hh;
	ret = (*mx_type_uint8.alloc_data)
		(&mx_type_uint8,MD_MMALLOC,&pp,0,
		__FILE__,__LINE__);
	get_matrix_dh_set(&h,ret);
	p = tmp;
	q = (unsigned char*)h.offset;
	for ( i = 0 ; i < ww* hh ; i ++ ) {
		*q++ = *p;
		p += 4;
	}
	free(tmp);
	return ret;
}

void *
mx_jpeg_uncompress_1(unsigned char * d1)
{
void * ret;
MATRIX_ALLOC_VECTOR_PARAM pp;
int ix_size[2];
MATRIX_DH_SET h;
int i;
unsigned char * p;
int * q;
	pp.dim = 2;
	pp.ix_size = &ix_size[0];
	pp.default_data = 0;
	ix_size[0] = d1[2];
	ix_size[1] = d1[3];
	ret = (*mx_type_RGB.alloc_data)
			(&mx_type_RGB,MD_MMALLOC,&pp,0,
			__FILE__,__LINE__);
	get_matrix_dh_set(&h,ret);
	p = &d1[4];
	q = (int*)h.offset;
	for ( i = 0 ; i < h.total_element ; i ++ ) {
		*q++ = (p[0]<<24)
			+ (p[1]<<16)
			+ (p[2]<<8);
		p += 3;
	}
	return ret;
}


void *
mx_jpeg_uncompress_2(unsigned char * d1,int len)
{
unsigned char * tmp;
int ix_size[2];
MATRIX_DH_SET h;
int i;
void * ret;
int ww,hh;
unsigned char * p, * q;
MATRIX_ALLOC_VECTOR_PARAM pp;
	tmp = jpeg_uncompress(&ww,&hh,&d1[2],len-2);
	pp.dim = 2;
	pp.ix_size = &ix_size[0];
	pp.default_data = 0;
	ix_size[0] = ww;
	ix_size[1] = hh;
	ret = (*mx_type_RGB.alloc_data)
		(&mx_type_RGB,MD_MMALLOC,&pp,0,
		__FILE__,__LINE__);
	get_matrix_dh_set(&h,ret);
	p = tmp;
	q = (unsigned char*)h.offset;
	for ( i = 0 ; i < ww* hh ; i ++ ) {
		*q++ = (p[0]<<24)
			+ (p[1]<<16)
			+ (p[2]<<8);
		p += 4;
	}
	free(tmp);
	return ret;
}

XL_SEXP *
xl_mxUncompressJPEG(XLISP_ENV * env,XL_SEXP * s,XLISP_ENV * a,XL_SYM_FIELD * sf)
{
void * d1;
MATRIX_TOKEN * t;
XL_SEXP * ret;
MATRIX_ALLOC_BLOCK_PARAM * p;
unsigned char * hd;
void * ret_data;
	t = get_env_work(env);
	if ( t == 0 )
		return 0;
	d1 = get_vdata_from_sexp(get_el(s,1));
	if ( d1 == 0 )
		goto type_missmatch;
	p = (MATRIX_ALLOC_BLOCK_PARAM*)d1;
	hd = p->block;
	switch ( hd[0] ) {
	case 'g':
		switch ( hd[1] ) {
		case 'n':
			ret_data = mx_glay_uncompress_1(p->block);
			break;
		case 'j':
			ret_data = mx_glay_uncompress_2(p->block,p->size);
			break;
		default:
			er_panic("uncompress_JPEG");
		}
	case 'c':
		switch ( hd[1] ) {
		case 'n':
			ret_data = mx_jpeg_uncompress_1(p->block);
			break;
		case 'j':
			ret_data = mx_jpeg_uncompress_2(p->block,p->size);
			break;
		default:
			er_panic("uncompress_JPEG");
		}
	default:
		er_panic("uncompress_JPEG");
	}

	ret = List(
		n_get_symbol("data"),
		get_sexp_from_dim_code(t->process_node->matrix,t->process_node->dim_code),
		get_ptr(ret_data,gc_text),
		-1);
	goto end;

type_missmatch:
	ret = get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"mxUncompressJPEG"),
		0);
	goto end;
end:
	return ret;
}





