コード例 #1
0
void encode_picture(block_struct *imageBlocks, ImageProperties *imgProp, FILE *outFile)
{	
	//repeat for Y,U,V :
	BlockRow current_blocks = imageBlocks->U_blocks;

	coeficient_frequencies *coef = gather_dct_symbol_statiscits(current_blocks, imageBlocks->numberOfBlocks);
	huffman_specification *ac_spec = generate_huffman_specification_table(coef->ac_freq);
	huffman_specification *dc_spec = generate_huffman_specification_table(coef->ac_freq);
	huffman_code *ac_huff_code = generate_huffman_table(ac_spec, false);
	huffman_code *dc_huff_code = generate_huffman_table(dc_spec, false);

	print_huffman_tables(coef, ac_spec, dc_spec, ac_huff_code, dc_huff_code);

	working_state state;
	initialaze_state(&state, outFile);
	//ENCODE
	int last_dc_value = 0;
	for (int blkn = 0; blkn < imageBlocks->numberOfBlocks; blkn++) {
		encode_one_block(&state, current_blocks[blkn], last_dc_value, dc_huff_code, ac_huff_code);
		last_dc_value = current_blocks[blkn][0];
	}
}
コード例 #2
0
ファイル: encoder.cpp プロジェクト: XYDXYD/jpeg_DEW-RDO
/* main function */
int main(int *argc, char **argv)
{
	register int i, j, k, u, v, temp2;
	int ac_counts[257], dc_counts[257];
	int inblock[8][8], inblock1[8][8], *zz_coef, *zz_ind, adct_1b[8][8];
	int last_dc_value = 0, tempdc;
	int begin, end, fix_part, ite_num;
	int *stack, point, total = 0;
	int *a, num_blk, wm_len, *wm_bit;
	int tr_nod_no = 0, base = 0;
	int tr,th,td,tb;
	int *zz;
	int aa[64][64], bb[64][64], x1, y1, x2, y2, tempint;
	double ad[8][8];
	int cc[64], x, y,n/*,cc1[64][64]存小块的cut*/;
	double Sc;

	unsigned char input[ROWS][COLS];
	double lamda2, scale, time, temp, temp1, scale2;
	double epslon = 0.1, previouscost, distortion, rate_tle, minimumcost;
	double c[8] = { 0.707,1.0,1.0,1.0,1.0,1.0,1.0,1.0 };

	int block_types[4096];
	int block_type = 1;//表示当前块是否为置零块,0表示当前块置零,-1表示不嵌入信息的块
	int cut = 63;//表示截止频率

	statenode *state;
	FILE *infd;
	myjpeg_compress_struct Lena_jpeg_struct;

	//initilize for writing JPEG
	Lena_jpeg_struct.image_width = 512;
	Lena_jpeg_struct.image_height = 512;
	Lena_jpeg_struct.num_components = 1;
	Lena_jpeg_struct.max_h_samp_factor = 4;
	Lena_jpeg_struct.max_v_samp_factor = 4;
	Lena_jpeg_struct.adobe_tag = 0;
	Lena_jpeg_struct.quant_tbl_0 = (unsigned char *)malloc(64 * sizeof(unsigned char));
	Lena_jpeg_struct.comp_info[0].component_id = 1;
	Lena_jpeg_struct.comp_info[0].h_samp_factor = 1;
	Lena_jpeg_struct.comp_info[0].v_samp_factor = 1;
	Lena_jpeg_struct.comp_info[0].quant_tbl_no = 0;
	Lena_jpeg_struct.comp_info[0].width_in_blocks = 512 / 8;
	Lena_jpeg_struct.comp_info[0].height_in_blocks = 512 / 8;
	Lena_jpeg_struct.comp_info[0].MCU_width = 8;
	Lena_jpeg_struct.comp_info[0].MCU_height = 8;
	Lena_jpeg_struct.comp_info[0].last_col_width = 8;
	Lena_jpeg_struct.comp_info[0].last_row_height = 8;
	//end of initialize
	zz = (int *)malloc(64 * sizeof(int));
	for (k = 0; k < 64; k++)
	{
		cc[k] = 63;
	}
	/*random shuffle of block position*/
	for (i = 0;i < 64;i++)
	{
		for (j = 0;j < 64;j++)
		{
			aa[i][j] = i;
			bb[i][j] = j;
		}
	}
	// for(int oc=0; oc<17392;oc++)
	//  for(k=0;k<500;k++)
	srand(513619669);
	for (int oc = 0; oc < 36813; oc++)   //277588; 936813
	{
		for (k = 0;k < 100;k++)
		{
			
			x1 = (int)(63 * rand()) / 32767;  	 y1 = (int)(63 * rand()) / 32767;

			x2 = (int)(63 * rand()) / 32767;      y2 = (int)(63 * rand()) / 32767;

			tempint = aa[x1][y1];
			aa[x1][y1] = aa[x2][y2];

			/* if(aa[x1][y1]<0)
			{		 k=k;
			}
			*/
			aa[x2][y2] = tempint;

			tempint = bb[x1][y1];
			bb[x1][y1] = bb[x2][y2];
			bb[x2][y2] = tempint;
		}//aa和bb矩阵中任意交换元素
	}
	/*random shuffle of block position*/

	begin = clock();
	// number of 8x8 blocks
	num_blk = (int)ROWS*COLS / 64;
	// get lamda, iteration number and scaling factor from the command line argument
	wm_len = atoi(argv[1]);//水印的长度
	lamda2 = atof(argv[2]);
	scale = atof(argv[3]);
	scale2 = atof(argv[4]);
	wm_bit = new (int[wm_len]);

	//a is used to represent wm bit
	a = (int *)malloc(num_blk*wm_len*sizeof(int));

	a[0] = 0; a[1] = 1;	a[2] = 0;	a[3] = 0;	a[4] = 0;	a[5] = 1;	a[6] = 1;
	for (i = 7;i < num_blk*wm_len;i++)
		a[i] = (a[i - 7] + a[i - 6]) % 2;

	//
	for (i = 0;i < 64;i++)
		qtbl_1d_thrld[i] = 1;

	//initilize original quantization table for JWC and the quantization for attack
	for (i = 0; i < 8; i++)
	{
		for (j = 0; j < 8; j++)
		{
			temp1 = scale2*qtbl_d[i][j] + 0.5;
			if (temp1 < 1) Q[zigzag[i][j]] = 1;
			else if (temp1>255) Q[zigzag[i][j]] = 255;
			else Q[zigzag[i][j]] = (int)temp1;
			//Q[zigzag[i][j]]=qtbl_d[i][j];//1; //int(0.1*qtbl_d[i][j]+0.5);
			//int(0.5*qtbl_d[i][j]+0.5);////2*qtbl_d[i][j];//0;
			//int(0.1*qtbl_d[i][j]+0.5);//qtbl_d[i][j]/2; 
			temp1 = scale*qtbl_d[i][j];
			if (temp1 < 1) ori_qtbl[i][j] = 1;
			else if (temp1>255) ori_qtbl[i][j] = 255;
			else ori_qtbl[i][j] = (int)temp1;
			//ori_qtbl[i][j]=(temp1<256)?((int)temp1):255;
		}
	}
	//generate the one-dimension quantization table from ori_qtbl [] zigzag[]
	for (u = 0; u < 8; u++)
		for (v = 0; v < 8; v++)
			qtbl_1d[zigzag[u][v]] = ori_qtbl[u][v];



	// intilialization for optimization
	// output_buffer=(char *)calloc(ROWS*COLS, sizeof(char));
	zz_coef = (int *)malloc(64 * sizeof(int)); /* store the coefficent of one block */

	zz_ind = (int *)malloc(64 * sizeof(int));
	state = (statenode *)malloc(64 * sizeof(statenode));
	stack = (int *)malloc(64 * sizeof(int));

	// initial the first state (state 0) once which corresponds to the DC coefficient
	state[0].r = 0;
	state[0].dist_cum = 0;
	state[0].rate_cum = 0;
	state[0].min_cost = 0;


	/* input the original pgm image to input[][] */
	// infd=fopen("lena512.raw","rb");
	infd = fopen(argv[5], "rb");
	fread(input, sizeof(unsigned char), ROWS*COLS, infd);
	fclose(infd);
	
	//precompress the image
	// count the time
	// begin=clock();
	for (i = 0; i < 256; i++)
	{
		ac_counts[i] = 0;
		dc_counts[i] = 0;
	}

	/* the ROWSxCOLS image is processed by ROWS/8xCOLS/8 block lines and columns */
	for (i = 0; i < ROWS / 8; i++)
	{
		for (j = 0; j < COLS / 8; j++)
		{
			// change the format of unsigned char to integer before computation 
			int sum = 0;
			for (u = 0; u < 8; u++)
			{
				for (v = 0; v < 8; v++)
				{

					inblock[u][v] = (int)input[i * 8 + u][j * 8 + v];
					sum += inblock[u][v];
				}
			}
			double blk_mean = (double)sum / 64;
			//sigmasquare[i][j] = 0;

			//for (u = 0; u < 8; u++)
			//{
			//	for (v = 0; v < 8; v++)
			//	{

			//		sigmasquare[i][j] += (inblock[u][v] - blk_mean)*(inblock[u][v] - blk_mean);

			//	}
			//}
			//sigmasquare[i][j] = 2 * sigmasquare[i][j] / 64 + 58.5225;//每一个块的方差*2 + c2

			// remove the mean of pixels in the image block
			for (u = 0; u < 8; u++)
				for (v = 0; v < 8; v++)
					inblock[u][v] = inblock[u][v] - 128;

			// call fast integer forward DCT function	
			/* Forward DCT of one block */
			int x, y;
			temp = 0.0;
			for (u = 0; u < 8; u++)
			{
				for (v = 0; v < 8; v++)
				{
					temp = 0.0;
					for (x = 0; x < 8; x++)
						for (y = 0; y < 8; y++)
							temp += (double)inblock[x][y] * cos((2 * x + 1)*u*pi / 16)*cos((2 * y + 1)*v*pi / 16);
					adct_1b[u][v] = (int)temp*c[u] * c[v] / 4;
				}
			}
			//GX_DCT_Weight_dct_8x8(inblock,adct_1b);  fast algorithm
			///////////////////////////////////////////////////////////////////////////////////////////
			double coe_mean = 0;
			double abs_adct[8][8];
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					abs_adct[i][j] = adct_1b[i][j];
					coe_mean += abs_adct[i][j] / 64;
				}
			}
			sigmasquare[i][j] = 0;
			for (u = 0; u < 8; u++)
			{
				for (v = 0; v < 8; v++)
				{
					sigmasquare[i][j] += sqterm(abs_adct[u][v], coe_mean);
				}
			}
			sigmasquare[i][j] = 2 * sigmasquare[i][j] / 64 + 58.5225;//每一个块的方差*2 + c2
			///////////////////////////////////////////////////////////////////////////////////////////
			//sigmasquare[i][j] = 4000;
			// Quanntization of one block 
			for (u = 0; u < 8; u++)
			{
				for (v = 0; v < 8; v++)
				{
					adct[i * 8 + u][j * 8 + v] = adct_1b[u][v];
					temp1 = adct_1b[u][v];
					if (temp1 < 0)
					{
						temp1 = -temp1;
						temp1 += ori_qtbl[u][v] / 2;
						temp2 = (int)temp1 / ori_qtbl[u][v];
						recon_index[i * 8 + u][j * 8 + v] = -temp2;
					}
					else
					{
						temp1 += ori_qtbl[u][v] / 2;
						temp2 = (int)temp1 / ori_qtbl[u][v];
						recon_index[i * 8 + u][j * 8 + v] = temp2;
					}
				}
			}
			// change the 8x8 block to zigzag sequence form 
			for (u = 0; u < 8; u++)
				for (v = 0; v < 8; v++)
					zz_ind[zigzag[u][v]] = recon_index[i * 8 + u][j * 8 + v];

			// replace DC value of each block as the difference (DPCM)
			tempdc = zz_ind[0];
			zz_ind[0] = zz_ind[0] - last_dc_value;
			last_dc_value = tempdc;

			// Fake Huffman encode to get the statistices of the (run, pair) of this image
			fake_blockencode(zz_ind, ac_counts, &total, dc_counts);

		} /* end of the loop for one block */
	}
	// optimizing AC
	ite_num = 1; // at least one iteration
	previouscost = 0;
	//////////////////////////////////////////////////确定截止频率/////////////////////////////////////////////////////////////////
	int count = 0; //DCT块计数器
	for (i = 0; i < ROWS / 8; i++)
	{
		for (j = 0; j < COLS / 8; j++)
		{
			if (count % 32 == 0)
			{
				double total_sc = 0;
				for (k = 63; k >= 0; k--)
				{
					int tmp_count = -1;
					Sc = 0;
					for (int p = i; p < ROWS / 8; p++)//到了一个区域的开头,往后遍历32个块
					{
						for (int q = j; q < COLS / 8; q++)
						{
							tmp_count++;
							//Sc += (zz[k] * zz[k]);
							//cout << endl;
							for (u = 0; u < 8; u++)
							{
								for (v = 0; v < 8; v++)
								{
									zz_coef[zigzag[u][v]] = adct[aa[p][q] * 8 + u][bb[p][q] * 8 + v];//实现块置换的地方
									//cout << zz_coef[zigzag[u][v]] << endl;h
								}
							}
							Sc += zz_coef[k]*zz_coef[k];
							if (tmp_count == 31) break;
						}
						if (tmp_count == 31) break;
					}
					total_sc += Sc;

					if (total_sc >= 70000)
					{
						if (count / 32 % 2 == 1) //B区域
							cc[count / 64] = min(cc[count / 64], k);
						else
							cc[count / 64] = k;
						break;
					}
					if (k < 7)
					{
						cc[count / 64] = k;	
						break;
					}
				}
			}
			count++;
		}
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////    。
	////////////////////////////////////////////////存储默认量化矩阵下的,反量化后的系数。即c/Q25 * Q25////////////////////////////////////
	int iq_index[ROWS][COLS];
	for (i = 0; i < ROWS / 8; i++)
	{
		for (j = 0; j < COLS / 8; j++)
		{
			for (u = 0; u < 8; u++)
			{
				for (v = 0; v < 8; v++)
				{
					iq_index[i * 8 + u][j * 8 + v] = recon_index[i * 8 + u][j * 8 + v] * ori_qtbl[u][v];
				}
			}
		}
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	for (;;)
	{
		// generate the entropy vector
		temp1 = log10((float)total) / log10((float)2);
		for (i = 0; i < 256; i++)
		{
			fix_part = (int)i & 0x0F;
			if (ac_counts[i] == 0)
				ac_r[i] = lamda2*(fix_part + temp1);
			else
				ac_r[i] = lamda2*(fix_part + temp1 - log10((float)ac_counts[i]) / log10((float)2));
		}

		total = 0;
		distortion = 0;
		rate_tle = 0;
		minimumcost = 0;
		for (i = 0; i < 256; i++)
			ac_counts[i] = 0;

		count = 0; //DCT块计数器置零
		for (i = 0; i < ROWS / 8; i++)
		{
			for (j = 0; j < COLS / 8; j++)
			{
				for (int k = 0;k < 256; k++)
					ent_ac[k] = sigmasquare[aa[i][j]][bb[i][j]] * ac_r[k];


				for (u = 0; u < 8; u++)
					for (v = 0; v < 8; v++)
						zz_coef[zigzag[u][v]] = adct[aa[i][j] * 8 + u][bb[i][j] * 8 + v];//实现块置换的地方
 //hide--------------------------------------------

				td = count / 64;
				//th = (tr % 2 + td % 2) % 2;
				tb = (td < num_blk*wm_len) ? a[td] : -1; //如果该块没有水印要嵌入,置tb为-1
				//cout << tb << endl;
				//			printf("a=%d\n", a[td]);
				if ((tb == 0 && count / 32 % 2 == 0)/*A区域*/ || (tb == 1 && count / 32 % 2 == 1)/*B区域*/)
				{
					for (k = cc[td]; k <= 63; k++)
					{
						zz_coef[k] = 0;
					}
					block_type = 0;
					block_types[count] = 0;
				}
				else if ((tb == 0 && count / 32 % 2 == 1)/*A区域*/ || (tb == 1 && count / 32 % 2 == 0)/*B区域*/)
				{
					block_type = 1; //该块是非置零块
					block_types[count] = 1;
				}
				else
				{
					block_type = -1; //该块不嵌入信息
					block_types[count] = -1;
				}
				/*for (u = 0; u < 8; u++)
				{
					for (v = 0; v < 8; v++)
						cout << zz_coef[zigzag[u][v]] << " ";
					cout << endl;
				}*/
				cut = cc[td];

				opti_block(aa[i][j], bb[i][j], zz_coef, state, stack/*64个int*/, &point/*空*/, ac_counts/*全零*/, &total/*totalpair*/, &distortion, &rate_tle, &minimumcost, block_type, cut);
				count++;
			}
		}

		distortion = distortion / (ROWS*COLS);
		rate_tle = rate_tle / (ROWS*COLS*lamda2);
		minimumcost = minimumcost / (ROWS*COLS);
		printf("Current normalized distortion is %f\n", distortion);
		printf("Current normalized bit rate is %f\n", rate_tle);
		printf("Current normalized minimumcost is %f\n", minimumcost);

		// check whether the iteration converges
		if (fabs(previouscost - minimumcost) < epslon)
			break;
		ite_num++;
		if (ite_num > 300)
			break;
		previouscost = minimumcost;
		//update the quantization table 
		update_qtbl(cc, block_types, aa, bb);
		
	}

	///////////////////////////////////////////每一个块新的反量化值要不小于默认量化矩阵下的反量化值/////////////////////////////////////////////////////
	int tmp_zz_coef1[64], tmp_zz_coef2[64];
	count = 0; //DCT块计数器
	int error_count = 0;
	for (i = 0; i < ROWS / 8; i++)
	{
		for (j = 0; j < COLS / 8; j++)
		{
			td = count / 64;
			tb = (td < num_blk*wm_len) ? a[td] : -1; //如果该块没有水印要嵌入,置tb为-1
			for (u = 0; u < 8; u++)
				for (v = 0; v < 8; v++)
				{
					tmp_zz_coef1[zigzag[u][v]] = recon_index[aa[i][j] * 8 + u][bb[i][j] * 8 + v];
					tmp_zz_coef2[zigzag[u][v]] = iq_index[aa[i][j] * 8 + u][bb[i][j] * 8 + v];
				}
			if ((tb == 0 && count / 32 % 2 == 0)/*A区域*/ || (tb == 1 && count / 32 % 2 == 1)/*B区域*/)
			{//置零块
				for (int ii = cc[count / 64]; ii < 64; ii++)
				{
					if (tmp_zz_coef1[ii] != 0)
						cout << "置零块中的零变成非零了" << endl;  //置零块不能变成非零
				}
			}
			else if ((tb == 0 && count / 32 % 2 == 1)/*A区域*/ || (tb == 1 && count / 32 % 2 == 0)/*B区域*/)
			{//该块是非置零块
				int accu_before = 0, accu_after = 0;
				for (int ii = cc[count / 64]; ii < 64; ii++)
				{
					accu_before += sqr(tmp_zz_coef2[ii]);
					accu_after += sqr(tmp_zz_coef1[ii] * qtbl_1d[ii]);
				}
				if (accu_before > accu_after || accu_before == 0)
				{
					cout << "非置零块中的截止频率以上的能量变小了" << endl;
					error_count++;
					cout << error_count << "差值为" << accu_before - accu_after << endl; //
				}
			}
			count++;
		}
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	// end=clock();
	pairnum_0 = customized_table(dc_counts, dc_bits_0, dc_val_0);
	pairnum = customized_table(ac_counts, ac_bits_0, ac_val_0);

	for (i = 0;i < 8;i++)
		for (j = 0;j < 8;j++)
			Lena_jpeg_struct.quant_tbl_0[i * 8 + j] = (unsigned char)qtbl_1d[zigzag[i][j]];

	//write to JPEG file
	//stream=fopen("stream.jpg", "wb");
	stream = fopen(argv[6], "wb");
	outputheader(&Lena_jpeg_struct);

	last_dc_value = 0;

	for (i = 0; i < ROWS / 8; i++)
	{
		for (j = 0; j < COLS / 8; j++)
		{
			for (u = 0; u < 8; u++)
				for (v = 0; v < 8; v++)
					zz_ind[zigzag[u][v]] = recon_index[i * 8 + u][j * 8 + v];
			// replace DC value of each block as the difference (DPCM)  
			tempdc = zz_ind[0];
			zz_ind[0] = zz_ind[0] - last_dc_value;
			last_dc_value = tempdc;
			//block_encode(zz_ind, dctbl, actbl);


			encode_one_block(0, zz_ind);
		}
	}

	finishjpegstream();
	fclose(stream);

	end = clock();
	time = (double)(end - begin) / CLOCKS_PER_SEC;
	printf("%d iterations of optimization!\n", (ite_num - 1));
	printf("%8.6f seconds has been used\n", time);
	printf("pairnum=%d\n", pairnum);

	free(zz_coef);     free(zz_ind);
	free(state);

	free(stack);
	free(a);

	free(Lena_jpeg_struct.quant_tbl_0);


	delete wm_bit;

	system("pause");
	return 0;

}