//------------------------------------------------------------------------
// 圧縮
// OnMemory版は#define ONMEM
// 画面アドレスの計算とスーパーバイザーモードへの移行が機種依存

#include "_jpeglib.h"
#include "jpeg.h"
#include "astdio.h"
#include <iocslib.h>

#define	DEBUG	0
// デバッグモードはx68上でのみ有効
#if DEBUG >=1
#include <stdio.h>
#include <time.h>
#endif

//------------------------------------------------------------------------
// ハフマンテーブルは内部ハフマンテーブルに固定されている

int m(JpegPress(JDATA(p),int gsx,int gsy,int gwx,int gwy,long mode,short rstcnt
	,int mcux,int w
	,unchar *qY,unchar *qU,unchar *qV
	,short y[4][JWY*JWX] ,short u[JWY*JWX] ,short v[JWY*JWX],short suv[JWV*JWU]))
// 圧縮
{
#if DEBUG >=1
time_t ts;
#endif
int sp,gx,gy,i,mcuy,yw,mcu;
int fbw;
unshort *gram,*gram0;
static short dcy0=0,dcu0=0,dcv0=0;
void (*rgb2yuv)(unshort *,short *,short *,short *,int,int);
void (*dct)(short *,short *,unchar const *);
short RestartCount=0,RestartMaker=0;
	// モード別設定
	fbw=(mode&MD_BW); // 白黒モード
	if ((mode&MD_BMODE)==MD_BAI) { // 縦倍時
		dct=DCT2b;
		yw=JWY/2; // １回の処理y単位が半分になる
	} else { // 通常時
		dct=DCT2;
		yw=JWY;
	}
	/*	DCT	yw
	通常	DCT2	JWY
	縦倍	DCT2b	JWY/2
	
		mcu	mcuy	rgb2yuv
	1:1:1	1	yw	RGB2YUV1
	4:1:1	4	yw*2	RGB2YUV4
	2-:1:1	2	yw	RGB2YUV2_
	2I:1:1	2	yw*2	RGB2YUV2I
	*/
	switch (mode&MD_AMODE) {
		case MD_111: // 1:1:1
			mcu=1;	mcuy=yw;
			rgb2yuv =RGB2YUV1;
			#if DEBUG >=1
			printf("1:1:1 ");
			#endif
			break;
		case MD_411: // 4:1:1
			mcu=4;	mcuy=yw*2;
			rgb2yuv =RGB2YUV4;
			#if DEBUG >=1
			printf("4:1:1 ");
			#endif
			break;
		case MD_2_11: // 2-:1:1
			mcu=2;	mcuy=yw;
			rgb2yuv =RGB2YUV2_;
			#if DEBUG >=1
			printf("2-:1:1 ");
			#endif
			break;
		case MD_2I11: // 2I:1:1
			mcu=2;	mcuy=yw*2;
			rgb2yuv =RGB2YUV2I;
			#if DEBUG >=1
			printf("2I:1:1 ");
			#endif
			break;
	}
	mcuy*=w;
	
	// リスタートマーカー初期化
	if (rstcnt>0) RestartMaker=0;
	
	#if DEBUG >=1
	// モード表示
	{// MCU単位の画像幅を求める
	int gmx,gmy;
	gmx=(gwx/mcux)*mcux;
	gmy=(gwy/mcuy)*mcuy;
	printf("%d*%d=(%d+%d)*(%d+%d)画像:",gwx,gwy,gmx,gwx-gmx,gmy,gwy-gmy);
	}
	if (fbw) printf("白黒");
	if ((mode&MD_BMODE)==MD_BAI) { // 縦倍時
		printf("縦倍");
	}
	if (w>1) printf("縦横1/%d",w); // MD_BMODEに圧縮設定が有っても、画像幅の制約により実際には圧縮出来ない場合があるので
	printf("圧縮...");
	ts=clock();
	#endif
	
	gram=GramAdrs(gsx,gsy);
	sp=B_SUPER(0); // スーパーバイザーモードへ
	for (gy=0;gy<gwy;gy+=mcuy) {
		#if DEBUG >=2
		condrv_xoff(); printf("*"); condrv_xon();
		#endif
		gram0=gram;
		for (gx=0;gx<gwx;gx+=mcux) {
			int ret=0;
			// データ取得（ＭＣＵ毎）
			if (gx+mcux>gwx||gy+mcuy>gwy||w>1) { // 不完全MCU領域/倍率処理あり
				unshort vram[16*16]; // 4:1:1のMCU分
				GetRGB(gram,vram,mcux,mcuy,w,gwx-gx,gwy-gy);
				rgb2yuv(vram,&y[0][0],u,v,yw,mcux/w);
			} else { // 完全MCU領域/倍率処理なし
				rgb2yuv(gram,&y[0][0],u,v,yw,X68GWX);
			}
			gram+=mcux; // 次のブロックへ
			
			// ＤＣＴ→ハフマン符号化
			// Y
			for (i=0;i<mcu;i++) {
				dct(&y[i][0],suv,qY); // DCT->量子化
				ret+=m(HuffDC(p,suv[0],HuffDC_Y,&dcy0));
				ret+=m(HuffAC(p,suv   ,HuffAC_Y));
			}
			if (!fbw) { // 白黒でない時
				// U
				dct(u,suv,qU);
				ret+=m(HuffDC(p,suv[0],HuffDC_UV,&dcu0));
				ret+=m(HuffAC(p,suv   ,HuffAC_UV));
				// V
				dct(v,suv,qV);
				ret+=m(HuffDC(p,suv[0],HuffDC_UV,&dcv0));
				ret+=m(HuffAC(p,suv   ,HuffAC_UV));
			}
			#ifndef ONMEM
			if (ret) return(ret);
			#endif
			
			if (rstcnt>0) { // リスタートマーカーが有効な時
			    /* 一定ＭＣＵ毎にマーカーを出力する。
			       リスタートマーカーは以下の規則で入れるようであるが、
			       資料がないので本当の仕様は不明。
			　     １、各行末に必ず入るように間隔を設定する
				   PressParamで補正
			       ２、ただし、最終行の行末には入れない(EOIを入れるから）。
			　     ３、１行内のマーカー数には上限はない。
			       巷のファイルを見ると、１行に１６回出力しているものが多いが、
			　　　 それ以外もある。
			       （行末にマーカーが来なくても大丈夫なビューワーも多い。
			        全く駄目なのはJPEGEDくらいか。）
			    */
			    if (++RestartCount==rstcnt) {
				if (gx+mcux<gwx || gy+mcuy<gwy) {
					//printf("%d/",RestartCount);
					m(PutMaker(p,(int)RestartMaker));
				} // 最終行末に入れない
				if (++RestartMaker>=8) RestartMaker=0;
				RestartCount=0;
				dcy0=dcu0=dcv0=0; // DC値リセット
			    }
			}
		} // for gx
		// 次のMCUラインへ
		gram=gram0+X68GWX*mcuy;
	} //  for gy
	if (sp>=0) B_SUPER(sp);
	
	// ハフマンの最後書き出し
	m(BitOutFlush(p));
	
	#if DEBUG>=1
	printf("\n%d\n",clock()-ts);
	#endif
	
	return(0);
}

//------------------------------------------------------------------------
