/*
 *   Tiff Load/Save function 2    By N.Takahashi
 *
 *       ver1.1 1994/02/02	Tiff LZW圧縮/展開 サポート
 *       ver0.2 1994/01/30	Tiff 関数コール変更 + ファイル名変更
 *       -----------------------
 *       ver0.1 1993/11/15  初版
 */

/* これらは､TIFF形式のグラフィックデータを扱うための関数です｡ */

#include <stdio.h>
#include <stdlib.h>
#include "tiff2.h"


/* LZW圧縮/展開  構造体 */
typedef struct ntable {
	unsigned char ch;
	unsigned char cs;
	short dmy;
	struct ntable *next;
	int code;
	int hash;
	int len;
} TABLE;

typedef struct hchain {
	TABLE *tbl;
	struct hchain *next;
} CHAIN;


/* Tiff ヘッダ用 構造体 */
struct tiffid {
	char id[4];
	unsigned int tagstart;
};

struct tiffe {
	char tdata1[8];
	char tdata2[8];
};

struct tifftag {
	unsigned char tag[8];
	unsigned int data;
};


/* 関数の重複回避用 (ちょっと強引かな...) */
#define add_entry	Tiff__add_entry
#define tsearch		Tiff__tsearch
#define get_data	Tiff__get_data
#define put_code	Tiff__put_code

#define add_table	Tiff__add_table
#define get_code	Tiff__get_code
#define put_table	Tiff__put_table
#define init_table	Tiff__init_table
#define free_mem	Tiff__free_mem
#define alloc_mem	Tiff__alloc_mem

#define adjpal		Tiff__adjpal
#define cmpdata		Tiff__cmpdata


/* Prototype function */
int Tiff__comp( int size, char *pmem, char *cmem );
void add_entry( TABLE *s, int c );
TABLE *tsearch( TABLE *s, int c );
int get_data( void );
void put_code( int ch );

int Tiff__decomp( char *pmem, char *xmem );
void add_table( int s, int c );
int get_code( void );
void put_table( int code );
void init_table( void );
void free_mem( void );
int alloc_mem( void );

void adjpal( char *pal, int pasize );
int cmpdata( void *p1, void *p2, int n );


/* Global variable */

/* エラーメッセージ */
char *Tiff_err[]={
	"正常です｡",
	"ファイルがオープン出来ません｡",
	"リードエラーです｡",
	"Ｔｉｆｆ形式ではありません｡",
	"圧縮されていません｡",
	"メモリが足りません｡",
	"不正な色数です｡",
	"この圧縮法には対応していません｡",
	"不正な関数呼出しをしています｡"
};


/* LZW圧縮/展開  広域変数 */
#define CLEAR_CODE	256
#define EOF_CODE	257
#define MAXTABLE	4096	/* TiffLZWではこの値 */
#define MAXHASH		4096	/* これ位が適当か */


static CHAIN **Hash;		/* CHAIN *Hash[MAXHASH]  */
static CHAIN *Chain;		/* CHAIN Chain[MAXTABLE] */
static int Chain_ix=0;

static TABLE *Table;		/* TABLE Table[MAXTABLE] */
static int Cbl;
static int Table_ix;
static char *Pmem, *Xmem, *Cmem;
static int Psize;
static int Cc,Ccl;


/* Tiff ヘッダ用 広域変数 */
static struct tiffid Tiff_id={
	{0x49,0x49,0x2a,0x00},
	0x00000008
};

static struct tiffe Tiff_e1={
	{ 0x4b,0x00,0x00,0x00,0x01,0x00,0x00,0x00 },
	{ 0x4b,0x00,0x00,0x00,0x01,0x00,0x00,0x00 }
};

static struct tiffe Tiff_e2={
	{ 0x4b,0x00,0x00,0x00,0x02,0x00,0x00,0x00 },
	{ 0x4b,0x00,0x00,0x00,0x02,0x00,0x00,0x00 }
};

static struct tifftag Tiff_tag[17]={
	{ {0xfe,0x00,0x04,0x00,0x01,0x00,0x00,0x00}, 0x00000000 },
	{ {0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x00000280 },
	{ {0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x000001e0 },
	{ {0x02,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x00000004 },
	{ {0x03,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x00000001 },
	{ {0x06,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x00000001 },
	{ {0x0a,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x00000002 },
	{ {0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00}, 0x00000200 },
	{ {0x15,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x00000001 },
	{ {0x16,0x01,0x04,0x00,0x01,0x00,0x00,0x00}, 0x000001e0 },
	{ {0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00}, 0x00025800 },
	{ {0x19,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x0000000f },
	{ {0x1a,0x01,0x05,0x00,0x01,0x00,0x00,0x00}, 0x000001f0 },
	{ {0x1b,0x01,0x05,0x00,0x01,0x00,0x00,0x00}, 0x000001f8 },
	{ {0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00}, 0x00000001 },
	{ {0x40,0x01,0x03,0x00,0x30,0x00,0x00,0x00}, 0x00000100 },
	{ {0x40,0x01,0x03,0x00,0x00,0x03,0x00,0x00}, 0x00000200 }
};


/* function */

/* 関数 Tiff_new : Tiff初期化
   戻り値 = Tiffアクセス構造体のポインタ
*/
Tiff *Tiff_new( void ) {
Tiff *tp;
	if( (tp=(Tiff *)malloc( sizeof( Tiff ) )) == NULL )
		return( NULL );
	tp->xsize = tp->ysize = tp->color = tp->comp = -1;
	tp->gmsize = tp->pmsize = 0;
	tp->gmem = tp->pmem = NULL;
	return( tp );
}


/* 関数 Tiff_delete : Tiff削除
   tp = Tiffアクセス構造体
*/
void Tiff_delete( Tiff *tp ) {
	if( tp!=NULL ) {
		if( tp->gmem!=NULL )
			free( tp->gmem );
		if( tp->pmem!=NULL )
			free( tp->pmem );
		free( tp );
		tp=NULL;
	}
}


/* 関数 Tiff_setgraph : (非圧縮)画像データ設定
   tp = Tiffアクセス構造体
   xsize , ysize = 画像サイズ
   color  = 色数
   gmem   = 画像データ
   pmem   = パレットデータ
*/
int Tiff_setgraph( Tiff *tp, int xsize, int ysize, int color, void *gmem, void *pmem ) {
	tp->xsize=xsize;
	tp->ysize=ysize;
	tp->color=color;
	tp->comp=1;
	tp->gmem=(char *)gmem;
	tp->pmem=(char *)pmem;
	tp->pmsize=0;
	switch( color ) {
		case 16:
			tp->gmsize=xsize*ysize*4/8;
			if( pmem!=NULL )
				tp->pmsize=16*3*2;
			break;
		case 256:
			tp->gmsize=xsize*ysize*8/8;
			if( pmem!=NULL )
				tp->pmsize=256*3*2;
			break;
		case 32768:
			tp->gmsize=xsize*ysize*16/8;
			break;
		default:
			return( Tiff__ILLCOL );
	}
	return( Tiff__OK );
}


/* 関数 Tiff_getgraph : (非圧縮)画像データ読みだし
   xsize , ysize = 画像サイズ
   color  = 色数
   gmem   = 画像データ
   pmem   = パレットデータ
   tp = Tiffアクセス構造体
*/
int Tiff_getgraph( int *xsize, int *ysize, int *color, char **gmem, char **pmem, Tiff *tp ) {
	if( tp->comp!=1 )
		return( Tiff__NOREAD );
	*xsize=tp->xsize;
	*ysize=tp->ysize;
	*color=tp->color;
	*gmem=tp->gmem;
	*pmem=tp->pmem;
	return( Tiff__OK );
}


/* 関数 Tiff_save : Tiff形式セーブ
   fn = ファイル名
   tp = Tiffアクセス構造体
*/
int Tiff_save( char *fn, Tiff *tp ) {
FILE *fp;
int pt=0,p,i;
char buf[16];

	if( tp->xsize<=0 || tp->ysize<=0
	 || tp->color<=0
	 || tp->gmem==NULL || tp->gmsize<=0
	 || ( tp->pmem!=NULL && tp->pmsize<=0 )
	  )
		return( Tiff__ILLCALL );


	p=( tp->pmem!=NULL )?3:1;
	switch( tp->color ) {
		case 2:
			Tiff_tag[3].data=1;
			Tiff_tag[5].data=0;
			Tiff_tag[6].data=1;
			Tiff_tag[7].data=0x200;
			Tiff_tag[11].data=1;
			break;
		case 256:
			Tiff_tag[3].data=8;
			Tiff_tag[5].data=p;
			Tiff_tag[6].data=1;
			Tiff_tag[11].data=255;
			if( tp->pmem!=NULL ) {
				Tiff_tag[7].data=0x800;
				pt=16;
			}
			else	
				Tiff_tag[7].data=0x200;
			break;
		case 32768:
			Tiff_tag[3].data=16;
			Tiff_tag[5].data=1;
			Tiff_tag[6].data=1;
			Tiff_tag[7].data=0x200;
			Tiff_tag[11].data=32767;
			break;
		case 16:
		default:
			Tiff_tag[3].data=4;
			Tiff_tag[5].data=p;
			Tiff_tag[6].data=2;
			Tiff_tag[7].data=0x200;
			Tiff_tag[11].data=15;
			if( tp->pmem!=NULL )
				pt=15;
	}
	Tiff_tag[1].data=tp->xsize;
	Tiff_tag[2].data=tp->ysize;
	Tiff_tag[9].data=tp->ysize;
	Tiff_tag[4].data=tp->comp;
	Tiff_tag[10].data=tp->gmsize;
	
	if( (fp=fopen( fn,"wb" ))==NULL )
		return( Tiff__NOOPEN );
	
	fseek( fp, 0L, SEEK_SET );
	for( i=0; i<16; i++ )
		buf[i]=0;
	for( i=0; i<32; i++ )
		fwrite( buf, sizeof(char), 16, fp );
	fseek( fp, 0L, SEEK_SET );
	
	fwrite( &Tiff_id, 1, sizeof(Tiff_id), fp );
	*(unsigned short *)buf=( tp->pmem!=NULL )?16:15;
	fwrite( buf, sizeof(char), 2, fp );
	
	for( i=0; i<15; i++ )
		fwrite( &Tiff_tag[i], 1, sizeof(Tiff_tag[0]), fp );
	
	if( tp->pmem!=NULL ) {
		fwrite( &Tiff_tag[pt], 1, sizeof(Tiff_tag[0]), fp );
		*(unsigned int *)buf=0;
		fwrite( buf, sizeof(char), 4, fp );
		adjpal( tp->pmem, tp->pmsize );
		fseek( fp, Tiff_tag[pt].data, SEEK_SET );
		fwrite( tp->pmem, 1, tp->pmsize, fp );
	}
	else {
		*(unsigned int *)buf=0;
		fwrite( buf, sizeof(char), 4, fp );
	}
	
	fseek( fp, 0x1f0L, SEEK_SET );
	if( tp->color==32768 && tp->xsize<=320 )
		fwrite( &Tiff_e2, 1, sizeof(Tiff_e2), fp );
	else
		fwrite( &Tiff_e1, 1, sizeof(Tiff_e1), fp );

	fseek( fp, Tiff_tag[7].data, SEEK_SET );
	fwrite( tp->gmem, 1, tp->gmsize, fp );

	fclose( fp );
	return( Tiff__OK );
}


/* 関数 Tiff_load : Tiff形式ロード
   fn = ファイル名
   tp = Tiffアクセス構造体
*/
int Tiff_load( char *fn, Tiff *tp ) {
FILE *fp;
int i,j,d,tag_n,ofs,palofs,cbit;
char buf[16];
	
	palofs=cbit=0;
	tp->xsize=tp->ysize=0;
	tp->comp=1;
	tp->gmsize=tp->pmsize=0;
	tp->color=0;
	
	if( (fp=fopen( fn,"rb" ))==NULL )
		return( Tiff__NOOPEN );
	
	if( fread( buf, 1, sizeof(Tiff_id), fp )<sizeof(Tiff_id) ) {
		fclose( fp );
		return( Tiff__NOREAD );
	}
	if( cmpdata( buf, &Tiff_id, sizeof(Tiff_id) ) ) {
		fclose( fp );
		return( Tiff__NOTIFF );
	}
	fread( buf, 1, sizeof(unsigned short), fp );
	tag_n=*(unsigned short *)buf;

	for( i=0; i<tag_n; i++ ) {
		fread( buf, 1, sizeof(Tiff_tag[0]), fp );
		for( j=0; j<17; j++ ) {
			if( cmpdata( buf, &Tiff_tag[j], sizeof(Tiff_tag[0].tag) )==0 ) {
				d=((struct tifftag *)buf)->data;
				switch( j ) {
					case 1:
						tp->xsize=d;
						break;
					case 2:
						tp->ysize=d;
						break;
					case 3:
						cbit=d;
						break;
					case 4:
						tp->comp=d;
						break;
					case 7:
						ofs=d;
						break;
					case 10:
						tp->gmsize=d;
						break;
					case 11:
						tp->color=d+1;
						break;
					case 15:
						palofs=d;
						tp->pmsize=0x60;
						break;
					case 16:
						palofs=d;
						tp->pmsize=0x600;
						break;
				}
			}
		}
	}
	
	if( tp->comp>1 && tp->comp!=5 ) {	/* 圧縮なし or LZW圧縮のみ */
		fclose( fp );
		return( Tiff__ILLCOMP );
	}
	
	if( tp->gmsize==0 ) {		/* gmsizeが設定されていない時の対策 */
		if( tp->comp>1 ) {
			fclose( fp );
			return( Tiff__NOTIFF );
		}
		tp->comp=1;
		tp->gmsize=(tp->xsize*tp->ysize*cbit)/8;
	}

	if( palofs>0 ) {
		if( (tp->pmem=(char *)malloc( tp->pmsize ))==NULL ) {
			fclose( fp );
			return( Tiff__NOMEM );
		}
		fseek( fp, palofs, SEEK_SET );
		fread( tp->pmem, sizeof(char), tp->pmsize, fp );
	}
	else {
		tp->pmem=NULL;
		tp->pmsize=0;
	}
	
	if( (tp->gmem=(char *)malloc( tp->gmsize ))==NULL ) {
		fclose( fp );
		return( Tiff__NOMEM );
	}
	fseek( fp, ofs, SEEK_SET );
	fread( tp->gmem, sizeof(char), tp->gmsize, fp );
	
	fclose( fp );
	return( Tiff__OK );
}


/* 関数 Tiff_decompress : Tiff LZW展開
   tp = Tiffアクセス構造体
*/
int Tiff_decompress( Tiff *tp ) {
int gxsize;
char *gxmem;

	if( tp->comp==1 )
		return( Tiff__OK );

	if( tp->comp!=5 )
		return( Tiff__ILLCOMP );
	
	gxsize=(tp->xsize)*(tp->ysize);
	switch( tp->color ) {
		case 16:
			gxsize/=2;
			break;
		case 256:
			break;
		case 32768:
			gxsize*=2;
			break;
		default:
			return( Tiff__ILLCOL );
	}
	if( (gxmem=(char *)malloc( gxsize ))==NULL )
		return( Tiff__NOMEM );

	if( Tiff__decomp( tp->gmem, gxmem )!=0 ) {
		free( gxmem );
		return( Tiff__NOMEM );
	}
	free( tp->gmem );
	tp->gmem=gxmem;
	tp->gmsize=gxsize;
	tp->comp=1;
	
	return( Tiff__OK );
}


/* 関数 Tiff_compress : Tiff LZW圧縮
   tp = Tiffアクセス構造体
*/
int Tiff_compress( Tiff *tp ) {
int gcsize;
char *gcmem;

	if( tp->comp!=1 )
		return( Tiff__NOCOMP );

	gcsize=(tp->gmsize*3)/2;	/* 圧縮後のサイズは圧縮前の1.5倍より
									小さい筈である｡ */
	if( (gcmem=(char *)malloc( gcsize )) == NULL )
		return( Tiff__NOMEM );

	gcsize=Tiff__comp( tp->gmsize, tp->gmem, gcmem );
	if( gcsize<0 ) {
		free( gcmem );
		return( Tiff__NOMEM );
	}
	free( tp->gmem );
	gcmem=realloc( gcmem, gcsize );
	tp->gmem=gcmem;
	tp->gmsize=gcsize;
	tp->comp=5;
	
	return( Tiff__OK );
}


/* 関数 Tiff_make_palette : Tiffパレット作成
   tp = Tiffアクセス構造体
*/
int Tiff_make_palette( Tiff *tp ) {
int i,br,rr,gg,bb;
unsigned short *pa;

	if( tp->pmem==NULL ) {
		switch( tp->color ) {
			case 16:
				tp->pmsize=0x60;
				break;
			case 256:
				tp->pmsize=0x600;
				break;
			default:
				return( Tiff__ILLCOL );
		}
		if( (tp->pmem=(char *)malloc( tp->pmsize ))==NULL ) {
			return( Tiff__NOMEM );
		}
		rr=gg=bb=0;
		pa=(unsigned short *)(tp->pmem);
		switch( tp->color ) {
			case 16:					/* パレットの値はFB386に合わせた */
				br=128;
				for( i=0; i<16; i++ ) {
					if( i>=8 )
						br=255;
					bb= (i&1)    *br;
					rr=((i&2)>>1)*br;
					gg=((i&4)>>2)*br;
					pa[i]=(rr<<8)|rr;
					pa[i+16]=(gg<<8)|gg;
					pa[i+32]=(bb<<8)|bb;
				}
				pa[8]=0x4040;
				pa[8+16]=0x4040;
				pa[8+32]=0x4040;
				break;
			case 256:
				for( i=0; i<256; i++ ) {
					bb=i & 3;
					if( bb>0 ) bb=bb*64+63;
					rr=(i>>2) & 7;
					if( rr>0 ) rr=rr*32+31;
					gg=(i>>5) & 7;
					if( gg>0 ) gg=gg*32+31;
					pa[i]=(rr<<8)|rr;
					pa[i+256]=(gg<<8)|gg;
					pa[i+512]=(bb<<8)|bb;
				}
				break;
		}
	}
	return( Tiff__OK );
}


/* 雑関数 */

/* Tiff用パレット調整 */
void adjpal( char *pal, int pasize ) {
int i;
unsigned short *pa;

	pa=(unsigned short *)pal;
	for( i=0; i<(pasize/2); i++ ) {
		if( (*pa & 0xff00)==0 )
			*pa=(*pa<<8)|(*pa&255);
		pa++;
	}
}


/* データ比較 */
int cmpdata( void *p1, void *p2, int n ) {
int i,e=0;
	for( i=0; i<n; i++ ) {
		if( *((char *)p1+i)!=*((char *)p2+i) ) {
			e=1;
			break;
		}
	}
	return( e );
}


/*  LZW 展開(decompress)  */

/* メモリ確保 */
int alloc_mem( void ) {
	if( (Table=(TABLE *)malloc( sizeof(TABLE)*MAXTABLE )) == NULL ) {
		free_mem();
		return( 1 );
	}
	if( (Chain=(CHAIN *)malloc( sizeof(CHAIN)*MAXTABLE )) == NULL ) {
		free_mem();
		return( 1 );
	}
	if( (Hash=(CHAIN **)malloc( sizeof(CHAIN *)*MAXHASH )) == NULL ) {
		free_mem();
		return( 1 );
	}
	return( 0 );
}


/* メモリ解放 */
void free_mem( void ) {
	if( Table!=NULL )
		free( Table );
	if( Chain!=NULL )
		free( Chain );
	if( Hash!=NULL )
		free( Hash );
}


/* テーブル初期化 */
void init_table( void ) {
int i;

	for( i=0; i<258; i++ ) {
		Table[i].ch=Table[i].cs=i;
		Table[i].next=NULL;
		Table[i].code=i;
		Table[i].hash=i*(MAXTABLE/256);
		Table[i].len=0;
	}
	for( i=0; i<MAXHASH; i++ ) {
		Hash[i]=NULL;
	}
}


/* 1バイトデータ出力 (マクロ) */
#define put_data( ch ) *(Xmem++)=(char)(ch)
/* void put_data( int ch ) {
	*(Xmem++)=(char)ch;
}*/


/* テーブルからデータ出力 */
void put_table( int code ) {
TABLE *tbp;
char *xmem;

	xmem=( Xmem+=Table[code].len+1 );
	*(--xmem)=Table[code].ch;
	tbp=Table[code].next;
	while( tbp!=NULL ) {
		*(--xmem)=tbp->ch;
		tbp=tbp->next;
	}
}


/* コードの入力 */
int get_code( void ) {
int d;

	while( Ccl<Cbl ) {
		Cc=(Cc<<8)|(*(Pmem++));
		Ccl+=8;
	}
	d=Cc;
	Ccl-=Cbl;
	Cc&=((1<<Ccl)-1);
	d=d>>Ccl;

	return( d );
}


/* テーブル追加 */
void add_table( int s, int c ) {
TABLE *tbp;

	tbp=&Table[Table_ix];
	tbp->ch=Table[c].cs;		/* 先頭CODE */
	tbp->cs=Table[s].cs;
	tbp->next=&Table[s];		/* 次のS    */
	tbp->code=Table_ix;
	tbp->len=Table[s].len+1;	/* CODEの長さ */
	Table_ix++;
}


/* LZW展開(下請け) */
int Tiff__decomp( char *pmem, char *xmem ) {
int code,next,ncbl;

	Pmem=pmem;		/* 元データアドレス   */
	Xmem=xmem;		/* 展開データアドレス */
	Cc=Ccl=0;

	if( alloc_mem() )
		return( -1 );		/* メモリ確保失敗 */
	init_table();
	Cbl=9;
	ncbl=512-1;
	while( ( next=get_code() )!=EOF_CODE ) {
		if( next==CLEAR_CODE ) {
			Cbl=9;
			ncbl=512-1;
			Table_ix=EOF_CODE+1;			/* 0x102 = 258 */
			if( ( code=get_code() )==EOF_CODE )
				break;
			put_table( code );
		}
		else if( next<Table_ix ) {
			put_table( next );
			add_table( code, next );		/* S:C */
			if( Table_ix==ncbl && Cbl<12 ) {
				Cbl++;
				ncbl=(1<<Cbl)-1;
			}
			code=next;
		}
		else {	/* next==Table_ix */
			put_table( code );				/* S */
			put_data( Table[code].cs );		/* C */
			add_table( code, code );		/* S:C */
			if( Table_ix==ncbl && Cbl<12 ) {
				Cbl++;
				ncbl=(1<<Cbl)-1;
			}
			code=next;
		}
	}
	free_mem();
	return( 0 );
}


/*  LZW 圧縮(compress)  */

/* コード出力 */
void put_code( int ch ) {
int d;

	Cc=(Cc<<Cbl)|ch;
	Ccl+=Cbl;
	while( Ccl>=8 ) {
		d=Cc;
		Ccl-=8;
		Cc&=((1<<Ccl)-1);
		d>>=Ccl;
		*(Cmem++)=d;
	}
}


/* データ入力 */
int get_data( void ) {
static int l=0;
	if( (l++)<Psize ) 
		return( *(Pmem++) );
	else {
		l=0;
		return( EOF );
	}
}


/* テーブル検索 */
TABLE *tsearch( TABLE *s, int c ) {
TABLE *n;
CHAIN *h;

	h=Hash[(s->hash+c)&(MAXHASH-1)];
	while( h!=NULL ) {
		n=h->tbl;
		if( n->ch==c && n->next==s )
			return( h->tbl );
		h=h->next;
	}
	return( NULL );
}


/* エントリ追加 */
void add_entry( TABLE *s, int c ) {
TABLE *tbp;
CHAIN *hc,**ha;

	tbp=&Table[Table_ix];
	tbp->ch=c;
	tbp->next=s;
	tbp->code=Table_ix;
	tbp->hash=(s->hash+c-Table_ix);		/* これが試した中で
											一番効率が良かった */
	
	ha=&Hash[(s->hash+c)&(MAXHASH-1)];
	hc=&Chain[Chain_ix++];
	hc->next=*ha;
	hc->tbl=tbp;
	*ha=hc;
	
	Table_ix++;
}


/* LZW圧縮(下請け) */
int Tiff__comp( int size, char *pmem, char *cmem ) {
TABLE *s,*p;
int ch,ncbl;

	Psize=size;		/* データサイズ       */
	Pmem=pmem;		/* 元データアドレス   */
	Cmem=cmem;		/* 圧縮データアドレス */
	Cc=Ccl=0;

	if( alloc_mem() )
		return( -1 );		/* メモリ確保失敗 */
	init_table();
	Cbl=9;
	ncbl=512;
	Table_ix=EOF_CODE+1;
	Chain_ix=0;
	put_code( CLEAR_CODE );
	
	if( (ch=get_data())==EOF )
		return( 0 );
	s=&Table[ch];
	while( (ch=get_data())!=EOF ) {
		if( (p=tsearch( s, ch ))!=NULL ) {
			s=p;
		}
		else {
			put_code( s->code );				/* S */
			if( Table_ix<(MAXTABLE-1) ) {
				add_entry( s, ch );				/* S:C */
				if( Table_ix==ncbl && Cbl<12 ) {
					Cbl++;
					ncbl=(1<<Cbl);
				}
			}
			else {
				put_code( CLEAR_CODE );
				init_table();
				Cbl=9;
				ncbl=512;
				Table_ix=EOF_CODE+1;
				Chain_ix=0;
			}
			s=&Table[ch];
		}
	}
	put_code( s->code );
	put_code( EOF_CODE );
	Cbl=7;
	put_code( 0 );		/* flush */

	free_mem();
	return( (int)(Cmem-cmem) );		/* 圧縮サイズ */
}

