

//
// Modifications History
//
//$ LB (15/07/2002) : replaced MMset(m,0,NIL) by MMpush(NIL), to avoid the machine crash
//


#include	<malloc.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<io.h>
#include	<fcntl.h>
#include	<sys/stat.h>


#include <windows.h>

/*
#include "../kernel/mmemory.h"
#include "../kernel/listlab.h"
#include "../kernel/mbytec.h" 
#include "../kernel/scol.h"
#include "../kernel/fifo.h"

#include "../kernel/scolobj.h"

*/

#include "x/Version.h"
#include "x/scolplugin.h"


 
#include "jcomp.h"

typedef		int		BLKDCT8[64];

#define		IDCT_Precision_Shift	1
#define		IDCT_Precision_Base		(1 << IDCT_Precision_Shift)
#define		Decentrage_Bas			( -16*IDCT_Precision_Base*255 )
#define		Decentrage_Haut			(  16*IDCT_Precision_Base*255 )

#define FIX_SHIFT  16
#define FIX_BASE   ( 1 << FIX_SHIFT )
#define MULT(var,const) ( ((var) * (const))/FIX_BASE )

#define FIX_0_382683433  25080L
#define FIX_0_541196100  35468L
#define FIX_0_707106781  46341L
#define FIX_1_306562965  85627L
 
#define FIX_1_082392200  70936L
#define FIX_1_414213562  92682L
#define FIX_1_847759065  121095L
#define FIX_2_613125930  171254L

extern const char zigzag8[64];
extern const char zagzig8[64];
extern const int  AAN_Scale8[64];
extern const int Luminance_Standard8[64];
extern const int Chrominance_Standard8[64];
/*
  const char zigzag8[64]
           ={
               0, 1, 8,16, 9, 2, 3,10,
              17,24,32,25,18,11, 4, 5,
              12,19,26,33,40,48,41,34,
              27,20,13, 6, 7,14,21,28,
              35,42,49,56,57,50,43,36,
              29,22,15,23,30,37,44,51,
              58,59,52,45,38,31,39,46,
              53,60,61,54,47,55,62,63
            };

  const char zagzig8[64]
          ={
               0, 1, 5, 6,14,15,27,28,
               2, 4, 7,13,16,26,29,42,
               3, 8,12,17,25,30,41,43,
               9,11,18,24,31,40,44,53,
              10,19,23,32,39,45,52,54,
              20,22,33,38,46,51,55,60,
              21,34,37,47,50,56,59,61,
              35,36,48,49,57,58,62,63
           };

  const int  AAN_Scale8[64]
          ={
             16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
             22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
             21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
             19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
             16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
             12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
              8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
              4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
           };

  const int Luminance_Standard8[64]
         ={
            16, 11, 10, 16, 24, 40, 51, 61,
            12, 12, 14, 19, 26, 58, 60, 55,
            14, 13, 16, 24, 40, 57, 69, 56,
            14, 17, 22, 29, 51, 87, 80, 62,
            18, 22, 37, 56, 68,109,103, 77,
            24, 35, 55, 64, 81,104,113, 92,
            49, 64, 78, 87,103,121,120,101,
            72, 92, 95, 98,112,100,103, 99
          };

  const int Chrominance_Standard8[64]
         ={
            17, 18, 24, 47, 99, 99, 99, 99,
            18, 21, 26, 66, 99, 99, 99, 99,
            24, 26, 56, 99, 99, 99, 99, 99,
            47, 66, 99, 99, 99, 99, 99, 99,
            99, 99, 99, 99, 99, 99, 99, 99,
            99, 99, 99, 99, 99, 99, 99, 99,
            99, 99, 99, 99, 99, 99, 99, 99,
            99, 99, 99, 99, 99, 99, 99, 99
          };*/

  signed char *decentrage;
  signed char tab_decentrage[ Decentrage_Haut-Decentrage_Bas+1 ];


 #define		CODE_EOB		0
 #define		CODE_Z4			1
 #define		CODE_Z1_P1		2
 #define		CODE_Z1_M1		3
 #define		CODE_Z2_P1		4
 #define		CODE_Z2_M1		5
 #define		CODE_Z3_P1		6
 #define		CODE_Z3_M1		7
 #define		CODE_NZ_NV2		8
 #define		CODE_NZ_NV4		9
 #define		CODE_2V2		10
 #define		CODE_1V4		11
 #define		CODE_2V4		12
 #define		CODE_3V4		13
 #define		CODE_Z1			14
 #define		CODE_1V8		15
  
//------------------------------------------
  typedef	short int		BLKCRT8[64*3];

	int				quanti_jpeg[64*3];		// Table des quantifiants pour le JPEG
	BLKCRT8			blk;
  

 typedef struct pixel_tga {
	unsigned char	B;
	unsigned char	G;
	unsigned char	R;
 } PIXEL_TGA;							// 3 octets

 typedef struct pixel_rgb {
	unsigned char	B;
	unsigned char	G;
	unsigned char	R;
	unsigned char	flag;
 } PIXEL_RGB;							// 4 octets

 typedef struct pixel_yuv {
	signed char		nul;
	signed char		Y;
	signed char		U;
	signed char		V;
 } PIXEL_YUV;							// 4 octets

 typedef struct pixel_xyz {
	unsigned char		Z;
	unsigned char		Y;
	unsigned char		X;
	unsigned char		flag;
 } PIXEL_XYZ;							// 4 octets

int	nb_8x8_X;
int	nb_pxl_X;
int	nb_pxl_Y;
int	flip_jpg;
	int				nb_pxl_total;
	int				nb_8x8_total;
	PIXEL_RGB		*ref_rgb;
	PIXEL_YUV		*tmp_yuv;
	PIXEL_RGB		*ref_jpg;

 
	int				jpeg_qualite;
	unsigned char		*buf_jpg;
	unsigned char		*old_buf_jpg;
 	int					ptr_jpg;

	
#pragma pack (push ,1)

 typedef struct TGA_entete {
	char			comment_size;		// Taille du commentaire
	char			cmap_type;			// 1:LUT 0:Pas de LUT
	char			image_type;			// mode TGA:	2  = Couleur, non compr‚ss‚
										// 				10 = Couleur, compr‚ss‚
	unsigned short	cmap_offset;		// Position du premier index de LUT
	unsigned short	cmap_lenght;		// Taille de la LUT
	char			cmap_depth;			// Nbre bits constituant une entr‚e LUT
	unsigned short	image_X;			// Origine en X de l'image
	unsigned short	image_Y;			// Origine en Y de l'image
	unsigned short	image_width;		// Nbre pixels en largeur de l'image
	unsigned short	image_height;		// Nbre pixels en hauteur de l'image
	char			image_depth;		// Nbre bits pour codage d'un pixel
	char			image_descr;		// Descripteur format TGA
 } TGA_ENTETE;							// 18 octets

#pragma pack (pop)

TGA_ENTETE		tga_entete;
extern char			srce[64];
extern char			dest[64];
/*	char			srce[64]={"coco3.tga\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
	char			dest[64]={"cerf.jpg\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};*/


//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void	FDCT_8x8( BLKDCT8 *bloc )
{
 int	compteur;
 int	t0, t1, t2, t3, t4, t5, t6, t7, t10, t11, t12, t13;
 int	z1, z2, z3, z4, z5, z11, z13;
 int	*data;

	/* On commence par les lignes */
	data = (int *)bloc;
	for ( compteur = 0; compteur < 8; compteur++ )
	{
		t0 = data[0] + data[7];
		t7 = data[0] - data[7];
		t1 = data[1] + data[6];
		t6 = data[1] - data[6];
		t2 = data[2] + data[5];
		t5 = data[2] - data[5];
		t3 = data[3] + data[4];
		t4 = data[3] - data[4];

		/* Partie paire */
		t10 = t0 + t3;
		t13 = t0 - t3;
		t11 = t1 + t2;
		t12 = t1 - t2;
		data[0] = t10 + t11;
		data[4] = t10 - t11;
		z1 = MULT( t12 + t13, FIX_0_707106781 );
		data[2] = t13 + z1;
		data[6] = t13 - z1;

		/* Partie impaire */
		t10 = t4 + t5;
		t11 = t5 + t6;
		t12 = t6 + t7;
		z5 = MULT( t10-t12, FIX_0_382683433 );
		z2 = MULT( t10, FIX_0_541196100 ) + z5;
		z4 = MULT( t12, FIX_1_306562965 ) + z5;
		z3 = MULT( t11, FIX_0_707106781 );
		z11 = t7 + z3;
		z13 = t7 - z3;
		data[5] = z13 + z2;
		data[3] = z13 - z2;
		data[1] = z11 + z4;
		data[7] = z11 - z4;
		data += 8;
	}

	/* Passe 2 : Les colonnes */
	data = (int *)bloc;
	for ( compteur = 0; compteur < 8; compteur++ )
	{
		t0 = data[0*8] + data[7*8];
		t7 = data[0*8] - data[7*8];
		t1 = data[1*8] + data[6*8];
		t6 = data[1*8] - data[6*8];
		t2 = data[2*8] + data[5*8];
		t5 = data[2*8] - data[5*8];
		t3 = data[3*8] + data[4*8];
		t4 = data[3*8] - data[4*8];

		/* Partie paire */
		t10 = t0 + t3;
		t13 = t0 - t3;
		t11 = t1 + t2;
		t12 = t1 - t2;
		data[0*8] = t10 + t11;
		data[4*8] = t10 - t11;
		z1 = MULT( t12 + t13, FIX_0_707106781 );
		data[2*8] = t13 + z1;
		data[6*8] = t13 - z1;

		/* Partie impaire */
		t10 = t4 + t5;
		t11 = t5 + t6;
		t12 = t6 + t7;
		z5 = MULT( t10-t12, FIX_0_382683433 );
		z2 = MULT( t10, FIX_0_541196100 ) + z5;
		z4 = MULT( t12, FIX_1_306562965 ) + z5;
		z3 = MULT( t11, FIX_0_707106781 );
		z11 = t7 + z3;
		z13 = t7 - z3;
		data[5*8] = z13 + z2;
		data[3*8] = z13 - z2;
		data[1*8] = z11 + z4;
		data[7*8] = z11 - z4;
 		data++;
	}
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
int		Calcul_Echelle( int qualite );
/*
{
	if ( qualite < 0 ) qualite = 1;
	else
		if ( qualite > 100 ) qualite = 100;

	if ( qualite < 50 )  qualite = 5000 / qualite;
	else                 qualite = 200 - qualite*2;

	return( qualite );
}
*/
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void	Calcul_Luminance8( int qualite, int *tab_quanti );
/*
{
 int	i, tmp;

	qualite = Calcul_Echelle( qualite );
	for ( i = 0; i < 64; i++ )
	{
		tmp  = ( Luminance_Standard8[i]*qualite + 50L ) / 100;
		if ( tmp <= 0 ) tmp = 1;
		else
			if ( tmp > 255 ) tmp = 255;

		tab_quanti[i] = tmp;
	}
}
*/
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°

void	Calcul_Chrominance8( int qualite, int *tab_quanti );
/*
{
 int	i, tmp;

	qualite = Calcul_Echelle( qualite );
	for ( i = 0; i < 64; i++ )
	{
		tmp  = ( Chrominance_Standard8[i]*qualite + 50L ) / 100;
		if ( tmp <= 0 ) tmp = 1;
		else
			if ( tmp > 255 ) tmp = 255;

		tab_quanti[i] = tmp;
	}
}
*/
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//			Initialisation du decentrage

void	Init_Decentrage();
/*
{
 int	i, tmp;

	for ( i = 0; i <= Decentrage_Haut-Decentrage_Bas; i++ )
	{
		tmp = 128 + ( i+Decentrage_Bas ) / ( 8*IDCT_Precision_Base );

		if ( tmp < 0 ) tmp = 0;
		else
		if ( tmp > 255 ) tmp = 255;

		tab_decentrage[i] = (signed char)(tmp - 128);
	}

	decentrage = tab_decentrage - Decentrage_Bas;
}
*/
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//			Rourines de normalisation

void 	Normalise_Avant8( int *tab_quanti )
{
 int	i;

	for ( i = 0; i < 64; i++ )
		tab_quanti[i] = ( tab_quanti[i]*AAN_Scale8[i] + ( 1 << 10 ) ) >> ( 14-3 );
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void JPEG_Init_Quanti_Comp( int	facteur_qualite )
{
 int	i, j, k;
 int	quanti_lum[64];
 int	quanti_chr[64];

	Calcul_Luminance8( facteur_qualite, quanti_lum );
    Normalise_Avant8( quanti_lum );
    Calcul_Chrominance8( facteur_qualite, quanti_chr );
    Normalise_Avant8( quanti_chr );

	j = 0;
	for( i = 0; i < 64; i++ )
	{
		k = zigzag8[i];
		quanti_jpeg[j++] = quanti_lum[k];
		quanti_jpeg[j++] = quanti_chr[k];
		quanti_jpeg[j++] = quanti_chr[k];
	}
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void JPEG_Init_Ecriture()
{
	flip_jpg = 0;
	ptr_jpg = 0;
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void JPEG_End_Ecriture()
{
	if( flip_jpg == 1 )
	{
		ptr_jpg++;
		flip_jpg = 0;
	}
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void Ecrit_rle4( int code )
{
	if( flip_jpg == 0 )
	{
		buf_jpg[ptr_jpg] = (code & 0xF);
		flip_jpg = 1;
	}
	else
	{
		buf_jpg[ptr_jpg++] |= (code & 0xF)<<4;
		flip_jpg = 0;
	}
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
unsigned char Code2( short int i )
{
	if( i > 0 ) i--;
	return( i & 3 );
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
unsigned char Code4( short int i )
{
	if( i > 0 ) i--;
	return( i & 15 );
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void JPEG_Ecrit_Bloc( short int	*bloc )
{
 int i, j, k, n, end;
 int l, ll, j2, k2, j4, k4;

	k = 0;
	for( i = 0; i < 3; i++)
	{
 		for( j = i; j < 192; j += 3 )
		{
			if( bloc[j] > 127 ) bloc[j] = 127;
			if( bloc[j] < -128 ) bloc[j] = -128;
			blk[k++] = bloc[j];
		}
	}

	for( n = 0; n < 192; n += 64 )
	{
		end = n + 64;

		Ecrit_rle4( blk[n] >> 4 );
		Ecrit_rle4( blk[n] & 0xF );
		for( i = n+1; i < end; )
		{
			if( blk[i] == 0 )
			{
				j = i;
				while( ( blk[j] == 0 ) && ( j < end ) ) j++;

				k = j-i;

				if( j == end )
				{
					Ecrit_rle4( CODE_EOB );
					i = j;
				}
				else
				{
					l = k/5;
					for ( ll = 0; ll < l; ll++ ) Ecrit_rle4( CODE_Z4 );
					k = k%5;

					if( k == 0 )
					{
						i = j;
					}
					else
					{
						if( ( blk[j] < -8 ) || ( blk[j] > 8 ) )
						{
							for( l = 0; l < k; l++ ) Ecrit_rle4( CODE_Z1 );
							i = j;
						}
						else
						{
							if( ( blk[j] >= -1 ) && ( blk[j] <= 1 ) && ( k <= 3 ) )
							{
								if( k == 1 )
								{
									if( blk[j] ==  1 ) Ecrit_rle4( CODE_Z1_P1 );
									if( blk[j] == -1 ) Ecrit_rle4( CODE_Z1_M1 );
								}
								else
								{
									if( k == 2 )
									{
										if( blk[j] ==  1 ) Ecrit_rle4( CODE_Z2_P1 );
										if( blk[j] == -1 ) Ecrit_rle4( CODE_Z2_M1 );
									}
									else
									{
										if( blk[j] ==  1 ) Ecrit_rle4( CODE_Z3_P1 );
										if( blk[j] == -1 ) Ecrit_rle4( CODE_Z3_M1 );
									}
								}
								i = j + 1;
							}
							else
							{
								j2 = j;
								while( ( blk[j2] >= -2 ) && ( blk[j2] <= 2 )  && ( blk[j2] != 0 ) && ( j2 < end ) ) j2++;
								k2 = j2-j;
								j4 = j;
								while( ( blk[j4] >= -8 ) && ( blk[j4] <= 8 )  && ( blk[j4] != 0 ) && ( j4 < end ) ) j4++;
								k4 = j4-j;

								if( k2 > 1 )
								{
									if( k2 == 2 )
									{
										Ecrit_rle4( CODE_NZ_NV2 );
										Ecrit_rle4( ((k-1)<<2) + 0 );
										Ecrit_rle4( (Code2(blk[j]) << 2) | Code2(blk[j+1]) );
										i = j+2;
									}
									else
									{
										if( k2 == 3 )
										{
											Ecrit_rle4( CODE_NZ_NV2 );
											Ecrit_rle4( ((k-1)<<2) + 1 );
											Ecrit_rle4( (Code2(blk[j]) << 2) | Code2(blk[j+1]) );
											Ecrit_rle4( Code2(blk[j+2]) << 2 );
											i = j+3;
										}
										else
										{
											if( k2 == 4 )
											{
												Ecrit_rle4( CODE_NZ_NV2 );
												Ecrit_rle4( ((k-1)<<2) + 2 );
												Ecrit_rle4( (Code2(blk[j]) << 2) | Code2(blk[j+1]) );
												Ecrit_rle4( (Code2(blk[j+2]) << 2) | Code2(blk[j+3]) );
												i = j+4;
											}
											else
											{
												Ecrit_rle4( CODE_NZ_NV2 );
												Ecrit_rle4( ((k-1)<<2) + 3 );
												Ecrit_rle4( (Code2(blk[j]) << 2) | Code2(blk[j+1]) );
												Ecrit_rle4( (Code2(blk[j+2]) << 2) | Code2(blk[j+3]) );
												Ecrit_rle4( Code2(blk[j+4]) << 2 );
												i = j+5;
											}
										}
									}
								}
								else
								{
									if( k4 == 1 )
									{
										Ecrit_rle4( CODE_NZ_NV4 );
										Ecrit_rle4( ((k-1)<<2) + 0 );
										Ecrit_rle4( Code4(blk[j]) );
										i = j+1;
									}
									else
									{
										if( k4 == 2 )
										{
											Ecrit_rle4( CODE_NZ_NV4 );
											Ecrit_rle4( ((k-1)<<2) + 1 );
											Ecrit_rle4( Code4(blk[j]) );
											Ecrit_rle4( Code4(blk[j+1]) );
											i = j+2;
										}
										else
										{
											if( k4 == 3 )
											{
												Ecrit_rle4( CODE_NZ_NV4 );
												Ecrit_rle4( ((k-1)<<2) + 2 );
												Ecrit_rle4( Code4(blk[j]) );
												Ecrit_rle4( Code4(blk[j+1]) );
												Ecrit_rle4( Code4(blk[j+2]) );
												i = j+3;
											}
											else
											{
												Ecrit_rle4( CODE_NZ_NV4 );
												Ecrit_rle4( ((k-1)<<2) + 3 );
												Ecrit_rle4( Code4(blk[j]) );
												Ecrit_rle4( Code4(blk[j+1]) );
												Ecrit_rle4( Code4(blk[j+2]) );
												Ecrit_rle4( Code4(blk[j+3]) );
												i = j+4;
											}
										}
									}
								}
							}
						}
					}
				}
			}
			else
			{
				if( (blk[i] < -8) || (blk[i] > 8) )
				{
					Ecrit_rle4( CODE_1V8 );
					Ecrit_rle4( blk[i] >> 4 );
					Ecrit_rle4( blk[i] & 0xF );
					i++;
				}
				else
				{
					j2 = i;
					while( ( blk[j2] >= -2 ) && ( blk[j2] <= 2 )  && ( blk[j2] != 0 ) && ( j2 < end ) ) j2++;
					k2 = j2-i;
					j4 = i;
					while( ( blk[j4] >= -8 ) && ( blk[j4] <= 8 )  && ( blk[j4] != 0 ) && ( j4 < end ) ) j4++;
					k4 = j4-i;

					if( k2 >= 2 )
					{
						Ecrit_rle4( CODE_2V2 );
						Ecrit_rle4( (Code2(blk[i]) << 2) | Code2(blk[i+1]) );
						i += 2;
					}
					else
					{
						if( k4 >= 3 )
						{
							Ecrit_rle4( CODE_3V4 );
							Ecrit_rle4( Code4(blk[i++]) );
							Ecrit_rle4( Code4(blk[i++]) );
							Ecrit_rle4( Code4(blk[i++]) );
						}
						else
						{
							if( k4 >= 2 )
							{
								Ecrit_rle4( CODE_2V4 );
								Ecrit_rle4( Code4(blk[i++]) );
								Ecrit_rle4( Code4(blk[i++]) );
							}
							else
							{
								Ecrit_rle4( CODE_1V4 );
								Ecrit_rle4( Code4(blk[i++]) );
							}
						}
					}
				}
			}
		}
	}
}


//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°

void	JPG_InitCompression( int	jpg_qualite ) 
{
	jpeg_qualite = jpg_qualite;
	Init_Decentrage();
	JPEG_Init_Ecriture();
	JPEG_Init_Quanti_Comp( jpeg_qualite );
}


//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
int JPG_Comprime_Bloc( PIXEL_RGB *image_rgb, int index, char* buf  )
{
 int	a, d, j, k, l;
 int	red, green, blue;
 int	lum, cb, cr;
 int	b, c;
 BLKDCT8    conv_Y, conv_U, conv_V;
 BLKCRT8	bloc;

	buf_jpg = buf;
	ptr_jpg = 0;
	flip_jpg = 0;

	a = (index % nb_8x8_X)*8 + (index / nb_8x8_X)*8*nb_pxl_X;
	d = 0;
	for( k = 0; k < 8; k++ )
	{
		for( l = 0; l < 8; l++ )
		{
			blue  = image_rgb[a].B;
			green = image_rgb[a].G;
			red   = image_rgb[a].R;
			
			lum = ( 3*red +6*green +blue )/10;
			cb  = ( blue-lum )/2;
			cr  = (( red-lum )*10)/16;

			conv_Y[d] = lum-128;
			conv_U[d] = cb;
			conv_V[d] = cr;

			d++;
			a++;
		}
		a += nb_pxl_X-8;
	}

	// FDCT des trois blocs
	FDCT_8x8( &conv_Y );
    FDCT_8x8( &conv_U );
    FDCT_8x8( &conv_V );

	// Zig-Zag et stockage du bloc de critere
	for( d = 0, k = 0; k < 64; k++ )
	{
		c = zigzag8[k];
		bloc[d++] = conv_Y[c];
		bloc[d++] = conv_U[c];
		bloc[d++] = conv_V[c];
	}

	// quantification
	for( j = 0; j < 192; j++ )
	{
		a = bloc[j];
		b = quanti_jpeg[j];
		if( a >= 0 )
			c =  ( b/2 + a ) /b;
		else
			c = -( b/2 - a ) /b;
		bloc[j] = c;
	}

	// Compression
	JPEG_Ecrit_Bloc( bloc );

	if( flip_jpg == 1 )
	{
		ptr_jpg++;
	}

	return( ptr_jpg );
}


void Erreur( char* message );
/*
{
  printf( "ERREUR:\n     %s\n", message );
	exit(0);
}
*/
/*
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void Definition_Taille_Image()
{
 int	handle;

	handle = sizeof( TGA_ENTETE );
 
	if( ( handle = open( srce, O_RDONLY | O_BINARY) ) < 0 )
	{
		Erreur("Impossible d'ouvrir le fichier source\n");
	}
	if( read( handle, &tga_entete, sizeof(TGA_ENTETE) ) != sizeof(TGA_ENTETE) )
	{
		Erreur("Probléme lors de la lecture entete fichier source\n");
	}
	close( handle );

	nb_pxl_X = tga_entete.image_width;
	nb_pxl_Y = tga_entete.image_height;

	if( (nb_pxl_X == 0) || (nb_pxl_Y == 0) )
	{
		Erreur("Image nulle\n");
	}
	if( (nb_pxl_X % 8) != 0 )
	{
		Erreur("La largeur des images n'est pas un multiple de 8\n");
	}
	if( (nb_pxl_Y % 8) != 0 )
	{
		Erreur("La hauteur des images n'est pas un multiple de 8\n");
	}

	nb_pxl_total = nb_pxl_X*nb_pxl_Y;
	nb_8x8_X = nb_pxl_X/8;
	nb_8x8_total = nb_pxl_total/64;
}

//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
void Charge_TGA( PIXEL_RGB *image, char *fichier )
{
 int		handle;
 int		i, j;
 int		idx_srce, idx_dest;
 PIXEL_TGA	*image_tmp;

	// -------- allocation d'un buffer temporaire de chargement
	image_tmp = (PIXEL_TGA *)malloc( nb_pxl_total*sizeof(PIXEL_TGA) );

	// -------- lecture TGA
	if( ( handle = open( fichier, O_RDONLY | O_BINARY) ) < 0 )
	{
		Erreur("Impossible d'ouvrir le fichier source\n");
	}
	if( read( handle, &tga_entete, sizeof(TGA_ENTETE) ) != sizeof(TGA_ENTETE) )
	{
		Erreur("ProblŠme lors de la lecture entete fichier source\n");
	}
	if( read( handle, image_tmp, nb_pxl_total*sizeof(PIXEL_TGA) ) != nb_pxl_total*sizeof(PIXEL_TGA) )
	{
		Erreur("ProblŠme lors de la lecture corp fichier source\n");
	}

	// -------- conversion 24 bit -> 32 bits et flip vertical de l'image
	idx_dest = (nb_pxl_Y-1)*nb_pxl_X;
	idx_srce = 0;
	for( i = 0; i < nb_pxl_Y; i++ )
	{
		for( j = 0; j < nb_pxl_X; j++ )
		{
			image[idx_dest].B   = image_tmp[idx_srce].B;
			image[idx_dest].G   = image_tmp[idx_srce].G;
			image[idx_dest++].R = image_tmp[idx_srce++].R;
		}
		idx_dest -= 2*nb_pxl_X;
	}

	// -------- lib‚ration du buffer temporaire de chargement
	free( image_tmp );

	close( handle );
}

void Sauve_Compression( char *fichier, char* src, int nb_car )
{
 int		handle;
 int		toto;

	toto = nb_car;

	// -------- ecriture JPG
	
	if( ( handle = open( fichier, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE ) ) < 0 )
	{
		Erreur("Impossible d'ouvrir le fichier destination\n");
	}
	if( write( handle, &tga_entete, sizeof( TGA_ENTETE ) ) != sizeof( TGA_ENTETE ) )
	{
		Erreur("ProblŠme lors de l'‚criture de l'entete du fichier destination\n");
	}
	if( write( handle, &jpeg_qualite, sizeof( int ) ) != sizeof( int ) )
	{
		Erreur("ProblŠme lors de l'‚criture de l'entete du fichier destination\n");
	}
	if( write( handle, &nb_pxl_X, sizeof( int ) ) != sizeof( int ) )
	{
		Erreur("ProblŠme lors de l'‚criture de l'entete du fichier destination\n");
	}
	if( write( handle, &nb_pxl_Y, sizeof( int ) ) != sizeof( int ) )
	{
		Erreur("ProblŠme lors de l'‚criture de l'entete du fichier destination\n");
	}
	if( write( handle, &toto, sizeof( int ) ) != sizeof( int ) )
	{
		Erreur("ProblŠme lors de l'‚criture de l'entete du fichier destination\n");
	}
	if( write( handle, src, nb_car ) != nb_car )
	{
		Erreur("ProblŠme lors de l'‚criture du corp du fichier destination\n");
	}

	close( handle );
}
*/	
int Jlastlevel=-1;

int JCompInit(mmachine m)
{
  int level;

  level=MMget(m,0)>>1;
//  if (level==Jlastlevel) return 0;
  Jlastlevel=level;

  if (level<1) level=1;
  if (level>99) level=99;
	JPG_InitCompression( level );  

  return 0;
}

//int Mpushstrblocn(mmachine m,char *buf,int l);
//$ LB (15/07/2002) : replaced MMset(m,0,NIL) by MMpush(NIL), to avoid the machine crash
int JComp(mmachine m)
{
  int i,image,taille;
  char * Image;
  char * buf_new,*buf_current;

  nb_pxl_Y=MMpull(m)>>1;
  nb_pxl_X=MMpull(m)>>1;
  image = MMpull(m)>>1;

  if (image==NIL) 
  {
	  MMechostr(MSKDEBUG, "\n_JComp : image is nil\n");
	  MMpush (m, NIL);
    return 0;
  }

  Image=MMstartstr(m,image);
  buf_new=malloc(MMsizestr(m,image));

  if(buf_new==NULL) 
  {
	  MMechostr(MSKDEBUG, "\n_JComp : creation of the destination buffer failed!\n");
	MMpush(m,NIL);
    return 0;
  }

     buf_current=buf_new;

	if( (nb_pxl_X == 0) || (nb_pxl_Y == 0) )
	{
		MMechostr(MSKDEBUG,"_JComp : Image nulle\n");
    MMpush(m,NIL);
    return 0;
	}

	if( (nb_pxl_X % 8) != 0 )
	{
	MMechostr(MSKDEBUG,"_JComp : La largeur des images n'est pas un multiple de 8\n");
    MMpush(m,NIL);
    return 0;
	}


	if( (nb_pxl_Y % 8) != 0 )
	{
		MMechostr(MSKDEBUG,"_JComp : La hauteur des images n'est pas un multiple de 8\n");
    MMpush(m,NIL);
    return 0;
	}

	nb_pxl_total = nb_pxl_X*nb_pxl_Y;
	nb_8x8_X = nb_pxl_X/8;
	nb_8x8_total = nb_pxl_total/64;


	for( i = 0; i < nb_8x8_total; i++ )
	{
    // important
		taille = JPG_Comprime_Bloc((struct pixel_rgb *)Image, i, buf_current );
		// paramètres: pointeur sur image en PIXEL_RGB, indice, pointeur où ecrire
	
		buf_current += taille;
	}

  i=Mpushstrblocn(m,buf_new,buf_current-buf_new);

  free(buf_new);

  return i;
}


/* 
void main()
{
	char* buf_current;
	int i;
	int taille;

	Definition_Taille_Image();

	
// important
	JPG_InitCompression( 60 );  
	// qualite de 1 à 99


	
	
	old_buf_jpg		= (unsigned char *)			malloc( 65536*2 );
	buf_current		= old_buf_jpg;
	ref_rgb			= (PIXEL_RGB *)				malloc( nb_pxl_total*sizeof(PIXEL_RGB) );

	Charge_TGA( ref_rgb, srce );
	
	for( i = 0; i < nb_8x8_total; i++ )
	{

		
// important
		taille = JPG_Comprime_Bloc(ref_rgb, i, buf_current );
		// paramètres: pointeur sur image en PIXEL_RGB, indice, pointeur où ecrire
	
		
		buf_current += taille;
		printf( "taille = %d\n", taille );
	}

	printf( "---------taille = %d\n", (int)buf_current - (int)old_buf_jpg );
	getch();

	Sauve_Compression( dest, old_buf_jpg, (int)buf_current - (int)old_buf_jpg );
		
	free( ref_rgb );
	free( old_buf_jpg );
}*/