jbig2_mmr.c

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 994 行 · 第 1/2 页

C
994
字号
{ 3, 2 },
{ 3, 2 },
{ 3, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ 2, 2 },
{ -2, 4 },
{ -2, 4 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -1, 0 },
{ -3, 5 },
{ 1792, 4 },
{ 1792, 4 },
{ 1984, 5 },
{ 2048, 5 },
{ 2112, 5 },
{ 2176, 5 },
{ 2240, 5 },
{ 2304, 5 },
{ 1856, 4 },
{ 1856, 4 },
{ 1920, 4 },
{ 1920, 4 },
{ 2368, 5 },
{ 2432, 5 },
{ 2496, 5 },
{ 2560, 5 },
{ 18, 3 },
{ 18, 3 },
{ 18, 3 },
{ 18, 3 },
{ 18, 3 },
{ 18, 3 },
{ 18, 3 },
{ 18, 3 },
{ 52, 5 },
{ 52, 5 },
{ 640, 6 },
{ 704, 6 },
{ 768, 6 },
{ 832, 6 },
{ 55, 5 },
{ 55, 5 },
{ 56, 5 },
{ 56, 5 },
{ 1280, 6 },
{ 1344, 6 },
{ 1408, 6 },
{ 1472, 6 },
{ 59, 5 },
{ 59, 5 },
{ 60, 5 },
{ 60, 5 },
{ 1536, 6 },
{ 1600, 6 },
{ 24, 4 },
{ 24, 4 },
{ 24, 4 },
{ 24, 4 },
{ 25, 4 },
{ 25, 4 },
{ 25, 4 },
{ 25, 4 },
{ 1664, 6 },
{ 1728, 6 },
{ 320, 5 },
{ 320, 5 },
{ 384, 5 },
{ 384, 5 },
{ 448, 5 },
{ 448, 5 },
{ 512, 6 },
{ 576, 6 },
{ 53, 5 },
{ 53, 5 },
{ 54, 5 },
{ 54, 5 },
{ 896, 6 },
{ 960, 6 },
{ 1024, 6 },
{ 1088, 6 },
{ 1152, 6 },
{ 1216, 6 },
{ 64, 3 },
{ 64, 3 },
{ 64, 3 },
{ 64, 3 },
{ 64, 3 },
{ 64, 3 },
{ 64, 3 },
{ 64, 3 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 13, 1 },
{ 23, 4 },
{ 23, 4 },
{ 50, 5 },
{ 51, 5 },
{ 44, 5 },
{ 45, 5 },
{ 46, 5 },
{ 47, 5 },
{ 57, 5 },
{ 58, 5 },
{ 61, 5 },
{ 256, 5 },
{ 16, 3 },
{ 16, 3 },
{ 16, 3 },
{ 16, 3 },
{ 17, 3 },
{ 17, 3 },
{ 17, 3 },
{ 17, 3 },
{ 48, 5 },
{ 49, 5 },
{ 62, 5 },
{ 63, 5 },
{ 30, 5 },
{ 31, 5 },
{ 32, 5 },
{ 33, 5 },
{ 40, 5 },
{ 41, 5 },
{ 22, 4 },
{ 22, 4 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 14, 1 },
{ 15, 2 },
{ 15, 2 },
{ 15, 2 },
{ 15, 2 },
{ 15, 2 },
{ 15, 2 },
{ 15, 2 },
{ 15, 2 },
{ 128, 5 },
{ 192, 5 },
{ 26, 5 },
{ 27, 5 },
{ 28, 5 },
{ 29, 5 },
{ 19, 4 },
{ 19, 4 },
{ 20, 4 },
{ 20, 4 },
{ 34, 5 },
{ 35, 5 },
{ 36, 5 },
{ 37, 5 },
{ 38, 5 },
{ 39, 5 },
{ 21, 4 },
{ 21, 4 },
{ 42, 5 },
{ 43, 5 },
{ 0, 3 },
{ 0, 3 },
{ 0, 3 },
{ 0, 3 }
};

#define getbit(buf, x) ( ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 )

static int
jbig2_find_changing_element(const byte *line, int x, int w)
{
	int a, b;

	if (line == 0)
		return w;

	if (x == -1) {
		a = 0;
		x = 0;
	}
	else {
		a = getbit(line, x);
		x ++;
	}

	while (x < w) {
		b = getbit(line, x);
		if (a != b)
			break;
		x++;
	}

	return x;
}

static int
jbig2_find_changing_element_of_color(const byte *line, int x, int w, int color)
{
	if (line == 0)
		return w;
	x = jbig2_find_changing_element(line, x, w);
	if (x < w && getbit(line, x) != color)
		x = jbig2_find_changing_element(line, x, w);
	return x;
}

static const byte lm[8] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
static const byte rm[8] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };

static void
jbig2_set_bits(byte *line, int x0, int x1)
{
	int a0, a1, b0, b1, a;

	a0 = x0 >> 3;
	a1 = x1 >> 3;

	b0 = x0 & 7;
	b1 = x1 & 7;

	if (a0 == a1) {
		line[a0] |= lm[b0] & rm[b1];
	}
	else {
		line[a0] |= lm[b0];
		for (a = a0 + 1; a < a1; a++)
			line[a] = 0xFF;
		line[a1] |= rm[b1];
	}
}


static int
jbig2_decode_get_code(Jbig2MmrCtx *mmr, const mmr_table_node *table, int initial_bits)
{
	uint32_t word = mmr->word;
	int table_ix = word >> (32 - initial_bits);
	int val = table[table_ix].val;
	int n_bits = table[table_ix].n_bits;

	if (n_bits > initial_bits) {
		int mask = (1 << (32 - initial_bits)) - 1;
		table_ix = val + ((word & mask) >> (32 - n_bits));
		val = table[table_ix].val;
		n_bits = initial_bits + table[table_ix].n_bits;
	}

	jbig2_decode_mmr_consume(mmr, n_bits);

	return val;
}

static int
jbig2_decode_get_run(Jbig2MmrCtx *mmr, const mmr_table_node *table, int initial_bits)
{
	int result = 0;
	int val;

	do {
		val = jbig2_decode_get_code(mmr, table, initial_bits);
		result += val;
	} while (val >= 64);

	return result;
}

static void
jbig2_decode_mmr_line(Jbig2MmrCtx *mmr, const byte *ref, byte *dst)
{
	int a0, a1, a2, b1, b2;
	int c;

	a0 = -1;
	c = 0;		/* 0 is white, black is 1 */

	while (1)
	{
		uint32_t word = mmr->word;
		/* printf ("%08x\n", word); */

		if (a0 >= mmr->width)
			break;

		if ((word >> (32 - 3)) == 1)
		{
			int white_run, black_run;

			jbig2_decode_mmr_consume(mmr, 3);

			if (a0 == -1)
				a0 = 0;

			if (c == 0) {
				white_run = jbig2_decode_get_run(mmr, jbig2_mmr_white_decode, 8);
				black_run = jbig2_decode_get_run(mmr, jbig2_mmr_black_decode, 7);
				a1 = a0 + white_run;
				a2 = a1 + black_run;
				if (a1 > mmr->width) a1 = mmr->width;
				if (a2 > mmr->width) a2 = mmr->width;
				jbig2_set_bits(dst, a1, a2);
				a0 = a2;
				/* printf ("H %d %d\n", white_run, black_run); */
			}
			else
			{
				black_run = jbig2_decode_get_run(mmr, jbig2_mmr_black_decode, 7);
				white_run = jbig2_decode_get_run(mmr, jbig2_mmr_white_decode, 8);
				a1 = a0 + black_run;
				a2 = a1 + white_run;
				if (a1 > mmr->width) a1 = mmr->width;
				if (a2 > mmr->width) a2 = mmr->width;
				jbig2_set_bits(dst, a0, a1);
				a0 = a2;
				/* printf ("H %d %d\n", black_run, white_run); */
			}
		}

		else if ((word >> (32 - 4)) == 1)
		{
			/* printf ("P\n"); */
			jbig2_decode_mmr_consume(mmr, 4);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			b2 = jbig2_find_changing_element(ref, b1, mmr->width);
			if (c) jbig2_set_bits(dst, a0, b2);
			a0 = b2;
		}

		else if ((word >> (32 - 1)) == 1)
		{
			/* printf ("V(0)\n"); */
			jbig2_decode_mmr_consume(mmr, 1);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			if (c) jbig2_set_bits(dst, a0, b1);
			a0 = b1;
			c = !c;
		}

		else if ((word >> (32 - 3)) == 3)
		{
			/* printf ("VR(1)\n"); */
			jbig2_decode_mmr_consume(mmr, 3);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			if (b1 + 1 > mmr->width) break;
			if (c) jbig2_set_bits(dst, a0, b1 + 1);
			a0 = b1 + 1;
			c = !c;
		}

		else if ((word >> (32 - 6)) == 3)
		{
			/* printf ("VR(2)\n"); */
			jbig2_decode_mmr_consume(mmr, 6);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			if (b1 + 2 > mmr->width) break;
			if (c) jbig2_set_bits(dst, a0, b1 + 2);
			a0 = b1 + 2;
			c = !c;
		}

		else if ((word >> (32 - 7)) == 3)
		{
			/* printf ("VR(3)\n"); */
			jbig2_decode_mmr_consume(mmr, 7);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			if (b1 + 3 > mmr->width) break;
			if (c) jbig2_set_bits(dst, a0, b1 + 3);
			a0 = b1 + 3;
			c = !c;
		}

		else if ((word >> (32 - 3)) == 2)
		{
			/* printf ("VL(1)\n"); */
			jbig2_decode_mmr_consume(mmr, 3);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			if (b1 - 1 < 0) break;
			if (c) jbig2_set_bits(dst, a0, b1 - 1);
			a0 = b1 - 1;
			c = !c;
		}

		else if ((word >> (32 - 6)) == 2)
		{
			/* printf ("VL(2)\n"); */
			jbig2_decode_mmr_consume(mmr, 6);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			if (b1 - 2 < 0) break;
			if (c) jbig2_set_bits(dst, a0, b1 - 2);
			a0 = b1 - 2;
			c = !c;
		}

		else if ((word >> (32 - 7)) == 2)
		{
			/* printf ("VL(3)\n"); */
			jbig2_decode_mmr_consume(mmr, 7);
			b1 = jbig2_find_changing_element_of_color(ref, a0, mmr->width, !c);
			if (b1 - 3 < 0) break;
			if (c) jbig2_set_bits(dst, a0, b1 - 3);
			a0 = b1 - 3;
			c = !c;
		}

		else
			break;
	}
}

int
jbig2_decode_generic_mmr(Jbig2Ctx *ctx,
	Jbig2Segment *segment,
	const Jbig2GenericRegionParams *params,
	const byte *data, size_t size,
	Jbig2Image *image)
{
	Jbig2MmrCtx mmr;
	const int rowstride = image->stride;
	byte *dst = image->data;
	byte *ref = NULL;
	int y;

	jbig2_decode_mmr_init(&mmr, image->width, image->height, data, size);

	for (y = 0; y < image->height; y++) {
		memset(dst, 0, rowstride);
		jbig2_decode_mmr_line(&mmr, ref, dst);
		ref = dst;
		dst += rowstride;
	}

	return 0;
}

⌨️ 快捷键说明

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