#include "_jpeglib.h"
#include "jpeg.h"

// OnMemory版は#define ONMEM

static int Jputc(unchar c,JDATA(p))
// 8bit出力:JPEGセグメントマーカー対応
// return : =0:OK , <>0:error（ファイルのみ）
{
	//printf("$%02x",c);
	#ifdef ONMEM
	*(*p)++=c;
	#else
	fputc(c,p); // fputc()は出力した文字またはEOSを返す
	#endif
	if (c==JPGMAKHED) { // バイト単位の出力でJPGMAKHEDを出力した時
		// その次の１バイトを0x00とし、JPEGセグメントマーカーとならないようにする
		// （データ単位のJPGMAKHEDではない）
		#ifdef ONMEM
		*(*p)++=0x00;
		#else
		fputc(0x00,p);
		#endif
		//printf("(00)");
	}
	return(
	#ifdef ONMEM
		0	// intにするためのダミー
	#else
		ferror(p)
	#endif
	);
}

static int Jputw(unshort w,JDATA(p))
// 16bit出力:JPEGセグメントマーカー対応
// return : =0:OK , <>0:error（ファイルのみ）
{
int ret;
	//printf("W:");
	ret=Jputc((unchar)(w>>8),p);
	#ifndef ONMEM
	if (!ret) {
	#endif
		//printf(",");
		ret=Jputc((unchar)(w),p);
	#ifndef ONMEM
	}
	#endif
	//printf("\n");
	return(ret);
}

static UR68 xdat={0,0};	// 保持中のデータ（ワークも含む）
static short xbits=0;	// xdatの上位何ビットが有効か；＝０なら無し
			// bitsとは数え始める起点が異なるので注意
#define	SZDAT	16	// xdatの内データ保持に使うビット数(.w[HW])

int m(BitOut(JDATA(p),unshort dat,int bits))
// fp   : 出力するファイル "wb"でオープンしておくこと（ファイルのみ）
// dat  : 出力するデータ
// bits : datの下位何ビットが有効か(1〜16)
// return : =0:OK , <>0:error（ファイルのみ）
{
int ret=0;
	// 処理の手順は、.w[LW]に入れて上に詰め、.lを<<して.w[HW]が詰まったら出力する。
	xdat.w[LW]=dat;
	xdat.w[LW]<<=(SZDAT-bits); // 上位へ詰める
	if (xbits+bits>SZDAT) { // あふれる時
		// ちょうどになるまでをまず出力させる
		xdat.l<<=(SZDAT-xbits);
		bits-=(SZDAT-xbits);
		ret=Jputw(xdat.w[HW],p);
		#ifndef ONMEM
		if (ret) return(ret);
		#endif
		xdat.w[HW]=0;
		xbits=0;
	} // 満たない／ちょうど
	xdat.l<<=bits;
	xbits+=bits;
	if (xbits==SZDAT) { // 切りの良い時は特別処理
		ret=Jputw(xdat.w[HW],p);
		xbits=0;
		xdat.w[HW]=0;
	}
	return(ret);
}

int m(BitOutFlush(JDATA(p)))
// 残りの掃き出し
{
int ret=0;
	//printf("掃き出し:");
	if (xbits>0) {
		xdat.w[LW]=0xffff; // 掃き出す時は残りビットを１にしておくため
		if (xbits>8) { // 9〜16:16bit出力
			xdat.l<<=(SZDAT-xbits); // 上位へ詰める
			ret=Jputw(xdat.w[HW],p);
		} else { // 1〜8:8bit出力
			xdat.l<<=(8-xbits); // 上位へ詰める
			ret=Jputc((unchar)xdat.w[HW],p);
			//printf("\n");
		}
		xbits=0;
		xdat.w[HW]=0;
	}
	//else {
		// xbits=0のときは残りはない
		//printf("なし\n");
	//}
	return(ret);
}

int m(PutMaker(JDATA(p),int RestartCount))
// リスタートマーカー出力
{
int ret;
	// まず現在残っているビットデータを掃き出す
	ret=m(BitOutFlush(p));
	if (!ret) {
		// マーカーを出力する
		//printf("[%02x,%02x]\n",JPGMAKHED,RestartCount+(RST0&0xff));
		#ifdef ONMEM
		*(*p)++=JPGMAKHED;
		*(*p)++=(RestartCount+(RST0&0xff));
		ret=0;
		#else
		fputc(JPGMAKHED,p);
		ret=(fputc((RestartCount+(RST0&0xff)),p)==EOF);
		#endif
	}
	return(ret);
}
