⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 coder_zf.c

📁 基于小波的图像压缩
💻 C
字号:

/*****

ZeroFlag coder:

codes bytewise but only using binary arithcoders.

	sends "is byte == 0"	(conditioned on activity of N and W)
	then sign				(conditioned on signs of N and W)
	then (abs(byte)-1)	using a unary adaptive binary code

fast AND excellent compression

*****/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crblib/inc.h>
#include <crblib/arithc.h>
#include "coder.h"

extern int tune_param;

#define	VAL_CONTEXTS		16
#define	VAL_CONTEXT_MAX		(VAL_CONTEXTS -1)
#define NUM_CONTEXTS		VAL_CONTEXTS
#define TAIL_CONTEXTS		VAL_CONTEXTS

#define SIGN_CONTEXTS		4

#define TOTMAX			4000
#define INC				30

#define P0_INIT			8
#define P1_INIT			0

#define bitModel(bit,P0,PT)		do { PT += INC; if (!(bit)) P0 += INC;  if ( PT > TOTMAX ) { PT >>= 1; P0 >>= 1; P0++; PT += 2; } } while(0)
#define bitEnc(bit,ari,P0,PT)	do { arithEncBit(ari,P0,PT,bit);	bitModel(bit,P0,PT); } while(0)
#define bitDec(bit,ari,P0,PT)	do { bit = arithDecBit(ari,P0,PT);	bitModel(bit,P0,PT); } while(0)

void coderZF_encodeBand(coder *me,int *band,int w,int h,int fullw,int *parent);
void coderZF_decodeBand(coder *me,int *band,int w,int h,int fullw,int *parent);

typedef struct {
	int signs_p0[SIGN_CONTEXTS];
	int signs_pt[SIGN_CONTEXTS];
	int stats_p0[NUM_CONTEXTS];
	int stats_pt[NUM_CONTEXTS];
	int tails_p0[TAIL_CONTEXTS];
	int tails_pt[TAIL_CONTEXTS];
} myInfo;

void coderZF_init(coder *c)
{
myInfo *d;
int i;

	if ( (d = new(myInfo)) == NULL )
		errexit("ozero init failed");

	c->data = d;

	for(i=0;i<NUM_CONTEXTS;i++) {
		d->stats_p0[i] = P0_INIT+1; d->stats_pt[i] = 2+P0_INIT+P1_INIT;
	}

	for(i=0;i<SIGN_CONTEXTS;i++) {
		d->signs_p0[i] = 100;
		d->signs_pt[i] = 200;
	}

	for(i=0;i<TAIL_CONTEXTS;i++) {
		d->tails_p0[i] = 100;
		d->tails_pt[i] = 2000;
	}

}

void coderZF_free(coder *c)
{
	if ( c->data ) {
		myInfo *d;
		d = c->data;
		free(d);
		c->data = NULL;
	}
}

coder coderZF = {
		"ZeroFlag",
		coderZF_init,
		coderZF_free,
		coderZF_encodeBand,
		coderZF_decodeBand
	};

static int sign_context;	/** cheesy way to return two values **/

static int mcontext(int *dp,int x,int y,int fullw)
{
	if ( y == 0 ) {
		if ( x > 0 ) {
			int W;

			W = dp[-1];

			if ( isneg(W) ) { sign_context = 2; W = - W; }
			else sign_context =0;

			return min(VAL_CONTEXT_MAX, (W>>1));
		} else {
			 sign_context = 0 ;
			return 0;
		}
	} else if ( x == 0 ) {
		int N;

		N = dp[-fullw];

		if ( isneg(N) ) { sign_context = 1; N = - N; }
		else sign_context = 0;

		return min(VAL_CONTEXT_MAX, (N>>1));
	} else {
		int N,W;

		N = dp[-fullw];
		W = dp[-1];

		if ( isneg(N) ) { sign_context = 1; N = - N; }
		else sign_context = 0;
		if ( isneg(W) ) { sign_context += 2; W = - W; }

		return min(VAL_CONTEXT_MAX, ((N + W)>>2));
	}
}

void coderZF_encodeBand(coder *me,int *band,int width,int height,int fullw,int *parent)
{
int x,y,context,V;
int *dp;
arithInfo *ari;
int *signs_p0,*signs_pt;
int *tails_p0,*tails_pt;
int *stats_p0,*stats_pt;

	ari = me->arith;
	stats_p0 = ((myInfo *)me->data)->stats_p0;
	stats_pt = ((myInfo *)me->data)->stats_pt;
	signs_p0 = ((myInfo *)me->data)->signs_p0;
	signs_pt = ((myInfo *)me->data)->signs_pt;
	tails_p0 = ((myInfo *)me->data)->tails_p0;
	tails_pt = ((myInfo *)me->data)->tails_pt;

	dp = band;
	for(y=0;y<height;y++) {
		if ( coder_timetostop(me) ) { coder_didstop(me,y); return; }
		for(x=0;x<width;x++) {

			context = mcontext(dp+x,x,y,fullw);

			if ( (V=dp[x]) == 0 ) {
				bitEnc(0,ari,stats_p0[context],stats_pt[context]);
			} else {
				bitEnc(1,ari,stats_p0[context],stats_pt[context]);

				switch(V) {
					case 4:
						bitEnc(0,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;
					case 3:
						bitEnc(0,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;
					case 2:
						bitEnc(0,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;
					case 1:
						bitEnc(0,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;
					case 0:
						break;
					case -1:
						bitEnc(1,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;
					case -2:
						bitEnc(1,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;
					case -3:
						bitEnc(1,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;
					case -4:
						bitEnc(1,ari,signs_p0[sign_context],signs_pt[sign_context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);
						break;

					default:
						if ( V > 0 ) {
							bitEnc(0,ari,signs_p0[sign_context],signs_pt[sign_context]);
							V--;
						} else {
							bitEnc(1,ari,signs_p0[sign_context],signs_pt[sign_context]);
							V = - V -1;
						}

						/* send remainder */
						while(V--) bitEnc(1,ari,tails_p0[context],tails_pt[context]);
						bitEnc(0,ari,tails_p0[context],tails_pt[context]);

						break;
				}

			}
		}
		dp += fullw;
	}
}

void coderZF_decodeBand(coder *me,int *band,int width,int height,int fullw,int *parent)
{
int x,y,bit,sign,context,V;
int *dp;
arithInfo *ari;
int *signs_p0,*signs_pt;
int *stats_p0,*stats_pt;
int *tails_p0,*tails_pt;

	ari = me->arith;
	stats_p0 = ((myInfo *)me->data)->stats_p0;
	stats_pt = ((myInfo *)me->data)->stats_pt;
	signs_p0 = ((myInfo *)me->data)->signs_p0;
	signs_pt = ((myInfo *)me->data)->signs_pt;
	tails_p0 = ((myInfo *)me->data)->tails_p0;
	tails_pt = ((myInfo *)me->data)->tails_pt;

	dp = band;
	for(y=0;y<height;y++) {
		if ( coder_timetostopd(me,y) ) return;
		for(x=0;x<width;x++) {

			context = mcontext(dp+x,x,y,fullw);

			bitDec(bit,ari,stats_p0[context],stats_pt[context]);

			if ( bit == 0 ) {
				dp[x] = 0;
			} else {
				bitDec(sign,ari,signs_p0[sign_context],signs_pt[sign_context]);

				bitDec(bit,ari,tails_p0[context],tails_pt[context]);
				if ( !bit ) {
					dp[x] = (1 - sign - sign);
				} else {
					bitDec(bit,ari,tails_p0[context],tails_pt[context]);
					if ( !bit ) {
						if ( sign ) dp[x] = -2; else dp[x] = 2;
					} else {
						bitDec(bit,ari,tails_p0[context],tails_pt[context]);
						if ( !bit ) {
							if ( sign ) dp[x] = -3; else dp[x] = 3;
						} else {
							bitDec(bit,ari,tails_p0[context],tails_pt[context]);
							if ( !bit ) {
								if ( sign ) dp[x] = -4; else dp[x] = 4;
							} else {
								V = 4;
								do {
									V++;
									bitDec(bit,ari,tails_p0[context],tails_pt[context]);
								} while( bit == 1 );

								if ( sign ) dp[x] = -V; else dp[x] = V;
							}
						}
					}
				}
			}
		}
		dp += fullw;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -