图像可变游程之混乱代码

图像可变游程之混乱代码

图像可变游程之混乱编码

这里,对我的自画像代码作一个简要解释。自画像代码实际上是一个解码器。包括两个部分:

  1. 图像的可变游程编码(varied length coding)
  2. 混乱编码(obfuscated coding)
    最关键部分就是那个码表了。这里介绍如何生成一个可变游程之混乱编码后码表。

可变游程编码(VLC)

实际上,我的自画像采用了一个简单的游程编码。其基本原理如下:

  1. 采用最简单的二值图像游程编码,只需要交替数0,1的个数
  2. 偶数字节表示0的长度,奇数字节表示1的长度
  3. 采用ASCII码的字符表示长度,那么实际字节非原始长度编码,而是可显示字符加上0或1的长度所对应的字符

混乱编码

上一节介绍了VLC编码方法,但是有一个问题,每个字节表示的长度是有限的(由于可选用的可显示字符有限)。我们假设其为M。以一个0长度为L(L〉M)的编码为例,由于VLC奇偶分别编码的原因,由于L超过M,所以要先编一个长度为M的偶数字符,然后编一个长度为0的奇数字符,然后再编一个长度为(L-M)的偶数字符。
值得注意的是,表示长度为0的字符,可以从多个字符中随机选择,这就是混乱编码的由来。

参考代码

可以简单用如下编码器生成一个二值bmp图像的可变游程之混乱编码后的字符表了。

int gen_bmp_2bit_vlc_tbl(char *img, FILE *fp) {
	int  i, j, k;
	int  idx;
	int  cnt_bit_flag; // 0: count bit 0 run-length; 1: count bit 1 run-length
	int  force_cnt_bit_flag;
	int  bits_1, bits_0;
	int  max_run_length;
	unsigned char c[16];
	
	// at first, count bit 0
	cnt_bit_flag = 0;
	bits_0 = 0;
	bits_1 = 0;
	max_run_length = 0;
	force_cnt_bit_flag = FORCE_DONE;
	idx = 0;
	for (i=0; i<H; i++) {
		fseek(fp, -(i+1)*W/8, SEEK_END);
		fread(&c, sizeof(unsigned char), W/8, fp);
		for (j=0; j<W/8; j++) {
			for (k = 0; k < 8; k++) {
				if (force_cnt_bit_flag == FORCE_0) {
					cnt_bit_flag = 0;
					assert(bits_1 > 0);
					printf("%c", img[idx++] = bits_1 + MIN_ASCII);
					if (bits_1 > max_run_length)
						max_run_length = bits_1;
					bits_1 = 0;
					force_cnt_bit_flag = FORCE_DONE;
					bits_0 = 0;
				}
				else if (force_cnt_bit_flag == FORCE_1) {
					cnt_bit_flag = 1;
					assert(bits_0 > 0);
					printf("%c", img[idx++] = bits_0 + MIN_ASCII);
					if (bits_0 > max_run_length)
						max_run_length = bits_0;
					bits_0 = 0;
					force_cnt_bit_flag = FORCE_DONE;
					bits_1 = 0;
				}

				if (c[j] & 0x80) {
					if (cnt_bit_flag == 0) {
						cnt_bit_flag = 1;
						if (bits_0 <= 0)
							printf("%c", img[idx++] = (rand() % (MIN_ASCII - OBF_ASCII + 1) + OBF_ASCII));
						else
							printf("%c", img[idx++] = bits_0 + MIN_ASCII);
						if (bits_0 > max_run_length)
							max_run_length = bits_0;
						bits_0 = 0;
					}
					bits_1++;
					if (bits_1 >= MAX_RUN_LENGTH) {
						// force change
						force_cnt_bit_flag = FORCE_0;
					}
				}
				else {
					if (cnt_bit_flag == 1) {
						cnt_bit_flag = 0;
						if (bits_1 <= 0)
							printf("%c", img[idx++] = (rand() % (MIN_ASCII - OBF_ASCII + 1) + OBF_ASCII));
						else
							printf("%c", img[idx++] = bits_1+MIN_ASCII);
						if (bits_1 > max_run_length)
							max_run_length = bits_1;
						bits_1 = 0;
					}
					bits_0++;
					if (bits_0 >= MAX_RUN_LENGTH) {
						// force change
						force_cnt_bit_flag = 1;
					}
				}
				c[j] = c[j] << 1;
			}
		}		
	}
	// force the last out
	if (bits_0 != 0) {
		printf("%c\n", img[idx++] = bits_0 + MIN_ASCII);
		if (bits_0 > max_run_length)
			max_run_length = bits_0;
		bits_0 = 0;
	}
	else if (bits_1 != 0) {
		printf("%c\n", img[idx++] = bits_1 + MIN_ASCII);
		if (bits_1 > max_run_length)
			max_run_length = bits_1;
		bits_1 = 0;
	}	
	return idx;
}
    原文作者:游程编码问题
    原文地址: https://blog.csdn.net/exxnxx/article/details/84957404
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞