/**********************************************************************
 
	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_mxCompressJPEG(XLISP_ENV * env,XL_SEXP * s,XLISP_ENV * a,XL_SYM_FIELD * sf);
void * mx_glay_compress_1(int * ,MATRIX_DH_SET * d1);
void * mx_glay_compress_2(int * ,MATRIX_DH_SET * d1);
void * mx_jpeg_compress_1(int * ,MATRIX_DH_SET * d1);
void * mx_jpeg_compress_2(int * ,MATRIX_DH_SET * d1);

void
init_mxCompressJPEG(XLISP_ENV * env)
{
	set_env(env,l_string(std_cm,"mxCompressJPEG"),
		get_func_prim(xl_mxCompressJPEG,FO_APPLICATIVE,0,2,2));
}

void *
mx_glay_compress_1(int * sp,MATRIX_DH_SET * d1)
{
char * ret;
int size;
	ret = mmalloc((size = d1->ix[0]*d1->ix[1]) + 4,gc_text);
	ret[0] = 'g';
	ret[1] = 'n';
	ret[2] = d1->ix[0];
	ret[3] = d1->ix[1];
	memcpy(&ret[4],d1->offset,size);
	*sp = size + 4;
	return ret;
}

void *
mx_glay_compress_2(int * sp,MATRIX_DH_SET * d1)
{
char * tmp;
int size;
char * ptr, * q;
char a;
unsigned char * _ret;
char * ret;
int i;
	tmp = d_alloc((size = d1->ix[0]*d1->ix[1])*sizeof(int));
	ptr = d1->offset;
	q = tmp;
	for ( i = 0 ; i < size ; i ++ ) {
		a = *ptr ++;
		*q++ = a;
		*q++ = a;
		*q++ = a;
		*q++ = a;
	}
	_ret = jpeg_compress(&size,tmp,d1->ix[0],d1->ix[1],8);
	ret = mmalloc(size+2,gc_text);
	memcpy(&ret[2],_ret,size);
	d_f_ree(tmp);
	free(_ret);
	ret[0] = 'g';
	ret[1] = 'j';
	*sp = size + 2;
	return ret;
}

void *
mx_jpeg_compress_1(int * sp,MATRIX_DH_SET * d1)
{
unsigned char * ret;
int size;
int i;
int * p;
unsigned char * q;
int c;
	ret = mmalloc((size = d1->ix[0]*d1->ix[1])*3 + 4,gc_text);
	ret[0] = 'c';
	ret[1] = 'n';
	ret[2] = d1->ix[0];
	ret[3] = d1->ix[1];
	q = &ret[2];
	p = (int*)d1->offset;
	for ( i = 0 ; i < size ; i ++ ) {
		c = *p ++;
		*q++ = (c >> 24)&0x0ff;
		*q++ = (c >> 16)&0x0ff;
		*q++ = (c >> 8)&0x0ff;
	}
	*sp = 3*size + 4;
	return ret;
}


void *
mx_jpeg_compress_2(int * sp,MATRIX_DH_SET * d1)
{
unsigned char * tmp;
int size;
int * ptr;
unsigned char * q;
int a;
unsigned char * _ret;
char * ret;
int i;
	tmp = d_alloc((size = d1->ix[0]*d1->ix[1])*4);
	ptr = d1->offset;
	q = tmp;
	for ( i = 0 ; i < size ; i ++ ) {
		a = *ptr ++;
		*q++ = (a >> 24)&0xff;
		*q++ = (a >> 16)&0xff;
		*q++ = (a >> 8)&0xff;
		*q++ = (a)&0xff;
	}
	_ret = jpeg_compress(&size,tmp,d1->ix[0],d1->ix[1],8);
	ret = mmalloc(size+2,gc_text);
	memcpy(&ret[2],_ret,size);
	d_f_ree(tmp);
	free(_ret);
	ret[0] = 'c';
	ret[1] = 'j';
	*sp = size + 2;
	return ret;
}

XL_SEXP *
xl_mxCompressJPEG(XLISP_ENV * env,XL_SEXP * s,XLISP_ENV * a,XL_SYM_FIELD * sf)
{
void * d1;
MATRIX_DH_SET dh1;
MATRIX_TOKEN * t;
XL_SEXP * ret;
void * d;
MATRIX_ALLOC_BLOCK_PARAM p;
	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;
	get_matrix_dh_set(&dh1,d1);
	if ( dh1.hd->dim != 2 )
		goto inv_param;
	switch ( dh1.hd->type ) {
	case MDT_UINT8|MDT_VECTOR:
		if ( dh1.ix[0] < 20 || dh1.ix[1] < 20 )
			p.block = mx_glay_compress_1(&p.size,&dh1);
		else	p.block = mx_glay_compress_2(&p.size,&dh1);
		break;
	case MDT_RGB8|MDT_VECTOR:
		if ( dh1.ix[0] < 20 || dh1.ix[1] < 20 )
			p.block = mx_jpeg_compress_1(&p.size,&dh1);
		else	p.block = mx_jpeg_compress_2(&p.size,&dh1);
		break;
	default:
		goto type_missmatch;
	}
	d = (*mx_type_block.alloc_data)(&mx_type_block,MD_MMALLOC,&p,0,
					__FILE__,__LINE__);
	d_f_ree(p.block);

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

type_missmatch:
	ret = get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"mxCompressJPEG"),
		0);
	goto end;
inv_param:
	ret = get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"mxCompressJPEG"),
		n_get_string("invalid parameter in mxCompressJPEG"));
	goto end;
end:
	return ret;
}





