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]; } }
/* 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; }