├── Hou ├── IDCT.m ├── Ori_photo.jpg ├── Redeme.txt ├── SSIM.m ├── appraise.m ├── costFun.m ├── countDCT.m ├── debug_main.m ├── generate_stego.m ├── get63bin.m ├── getpayload.m ├── getuintcost63bin.m ├── jpegread │ ├── jpeg_read.c │ ├── jpeg_read.mexa64 │ ├── jpeg_read.mexglx │ ├── jpeg_read.mexw32 │ ├── jpeg_read.mexw64 │ ├── jpeg_write.c │ ├── jpeg_write.mexa64 │ ├── jpeg_write.mexglx │ ├── jpeg_write.mexw32 │ └── jpeg_write.mexw64 ├── mark.m ├── matrix_index.m ├── recoverstego.m ├── select_block2.m ├── simulate.m ├── stego.jpg ├── synthesize.m ├── testimgs │ ├── Airplane.tiff │ ├── Baboon.tiff │ ├── Lena.tiff │ └── Peppers.tiff └── utils │ ├── AnyDistortion.m │ ├── arith_decode.c │ ├── arith_decode.m │ ├── arith_decode.mexw64 │ ├── arith_encode.c │ ├── arith_encode.m │ ├── arith_encode.mexw64 │ ├── bi2de.m │ ├── compressFun.m │ ├── compressOhead.m │ ├── de2bi.m │ ├── entropyEmbed.m │ ├── minDistortionEmr.m │ ├── minDistortionMsk.m │ ├── min_distortion_br.m │ ├── nonCrossEdge.m │ └── recursiveConstruct.m ├── Hou_Improved ├── IDCT.m ├── Ori_photo.jpg ├── SSIM.m ├── Stego │ └── QF30 │ │ └── 1.pgm_2000.jpg ├── appraise.m ├── costFun.m ├── countDCT.m ├── debug_main.m ├── generate_stego.m ├── get63bin.m ├── get_psnring.m ├── getcodelength.m ├── getpayload.m ├── getuintcost63bin.m ├── jpeg_emdding.m ├── jpegread │ ├── jpeg_read.c │ ├── jpeg_read.mexa64 │ ├── jpeg_read.mexglx │ ├── jpeg_read.mexw32 │ ├── jpeg_read.mexw64 │ ├── jpeg_write.c │ ├── jpeg_write.mexa64 │ ├── jpeg_write.mexglx │ ├── jpeg_write.mexw32 │ └── jpeg_write.mexw64 ├── mark.m ├── matrix_index.m ├── recoverstego.m ├── select_block2.m ├── simulate.m ├── stego.m ├── sum_payload.m ├── synthesize.m └── utils │ ├── AnyDistortion.m │ ├── arith_decode.c │ ├── arith_decode.m │ ├── arith_decode.mexw64 │ ├── arith_encode.c │ ├── arith_encode.m │ ├── arith_encode.mexw64 │ ├── bi2de.m │ ├── compressFun.m │ ├── compressOhead.m │ ├── de2bi.m │ ├── entropyEmbed.m │ ├── minDistortionEmr.m │ ├── minDistortionMsk.m │ ├── min_distortion_br.m │ ├── nonCrossEdge.m │ └── recursiveConstruct.m ├── Huang ├── Getzeronum.m ├── JPEG_Toolbox │ ├── jpeg_read.mexa64 │ ├── jpeg_read.mexw64 │ ├── jpeg_write.mexa64 │ └── jpeg_write.mexw64 ├── SSIM.m ├── Stego │ └── QF30 │ │ └── 1.pgm_2000.jpg ├── debug_main.m ├── jpeg_emdding.m ├── jpeg_extract.m ├── jpeg_hist.m ├── name30.jpg ├── process.m ├── psnr.m ├── re.jpg ├── stego.jpg ├── sum_payload.m └── testimgs │ ├── Airplane.tiff │ ├── Baboon.tiff │ ├── Lena.tiff │ └── Peppers.tiff ├── Huang_Improved ├── IDCT.m ├── JPEG_Toolbox │ ├── jpeg_read.mexa64 │ ├── jpeg_read.mexw64 │ ├── jpeg_write.mexa64 │ └── jpeg_write.mexw64 ├── SSIM.m ├── Stego │ └── QF30 │ │ └── 1.pgm_2000.jpg ├── debug_main.m ├── getadd_psnr_HS.m ├── getcodelength.m ├── getpayload_HS.m ├── getsignal.m ├── jpeg_emdding_HS.m ├── jpeg_extract.m ├── jpeg_re.jpg ├── name30.jpg ├── psnr.m └── testimgs │ ├── Airplane.tiff │ ├── Baboon.tiff │ ├── Lena.tiff │ └── Peppers.tiff └── README.md /Hou/IDCT.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/IDCT.m -------------------------------------------------------------------------------- /Hou/Ori_photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/Ori_photo.jpg -------------------------------------------------------------------------------- /Hou/Redeme.txt: -------------------------------------------------------------------------------- 1 | Begin with debug_main.m -------------------------------------------------------------------------------- /Hou/SSIM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/SSIM.m -------------------------------------------------------------------------------- /Hou/appraise.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/appraise.m -------------------------------------------------------------------------------- /Hou/costFun.m: -------------------------------------------------------------------------------- 1 | function Q_cost=costFun(Q) 2 | [m,n]=size(Q); 3 | Q_cost=zeros(m,n,63); 4 | id=0; 5 | for i=1:8 6 | for j=1:8 7 | if (i+j)~=2 8 | Diff=zeros(8,8); 9 | Diff(i,j)=1; 10 | temp=IDCT(Q.*Diff); 11 | id=id+1; 12 | Q_cost(:,:,id)=temp;%sqrt(temp/64); 13 | end 14 | end 15 | end 16 | 17 | end -------------------------------------------------------------------------------- /Hou/countDCT.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/countDCT.m -------------------------------------------------------------------------------- /Hou/debug_main.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/debug_main.m -------------------------------------------------------------------------------- /Hou/generate_stego.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/generate_stego.m -------------------------------------------------------------------------------- /Hou/get63bin.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/get63bin.m -------------------------------------------------------------------------------- /Hou/getpayload.m: -------------------------------------------------------------------------------- 1 | function payload = getpayload(S) 2 | [m,n] = size(S); 3 | payload=0; 4 | for i=1:m 5 | for j=1:n 6 | if mod(i,8) == 1 && mod(j,8) == 1 7 | elseif S(i,j) == 1 || S(i,j) == -1 8 | payload = payload + 1; 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Hou/getuintcost63bin.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/getuintcost63bin.m -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_read.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jpeg_read.c 3 | * 4 | * JPEGOBJ = JPEG_READ(FILENAME) 5 | * 6 | * Returns JPEGOBJ, a Matlab struct containing the JPEG header information, 7 | * quantization tables, and the DCT coefficients. 8 | * 9 | * This software is based in part on the work of the Independent JPEG Group. 10 | * In order to compile, you must first build IJG's JPEG Tools code library, 11 | * available at ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. 12 | * 13 | * Phil Sallee 6/2003 14 | * 15 | * Copyright (c) 2003 The Regents of the University of California. 16 | * All Rights Reserved. 17 | * 18 | * Permission to use, copy, modify, and distribute this software and its 19 | * documentation for educational, research and non-profit purposes, 20 | * without fee, and without a written agreement is hereby granted, 21 | * provided that the above copyright notice, this paragraph and the 22 | * following three paragraphs appear in all copies. 23 | * 24 | * Permission to incorporate this software into commercial products may 25 | * be obtained by contacting the University of California. Contact Jo Clare 26 | * Peterman, University of California, 428 Mrak Hall, Davis, CA, 95616. 27 | * 28 | * This software program and documentation are copyrighted by The Regents 29 | * of the University of California. The software program and 30 | * documentation are supplied "as is", without any accompanying services 31 | * from The Regents. The Regents does not warrant that the operation of 32 | * the program will be uninterrupted or error-free. The end-user 33 | * understands that the program was developed for research purposes and 34 | * is advised not to rely exclusively on the program for any reason. 35 | * 36 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 37 | * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, 38 | * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND 39 | * ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN 40 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF 41 | * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 42 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 | * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 44 | * BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE 45 | * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 46 | * 47 | */ 48 | 49 | 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include "mex.h" 56 | 57 | 58 | /* We need to create our own error handler so that we can override the 59 | * default handler in case a fatal error occurs. The standard error_exit 60 | * method calls exit() which doesn't clean things up properly and also 61 | * exits Matlab. This is described in the example.c routine provided in 62 | * the IJG's code library. 63 | */ 64 | struct my_error_mgr { 65 | struct jpeg_error_mgr pub; /* "public" fields */ 66 | jmp_buf setjmp_buffer; /* for return to caller */ 67 | }; 68 | 69 | 70 | /* The default output_message routine causes a seg fault in Matlab, 71 | * at least on Windows. Its generally used to emit warnings, since 72 | * fatal errors call the error_exit routine, so we emit a Matlab 73 | * warning instead. If desired, warnings can be turned off by the 74 | * user with "warnings off". -- PAS 10/03 75 | */ 76 | METHODDEF(void) 77 | my_output_message (j_common_ptr cinfo) 78 | { 79 | char buffer[JMSG_LENGTH_MAX]; 80 | 81 | /* Create the message */ 82 | (*cinfo->err->format_message) (cinfo, buffer); 83 | 84 | mexWarnMsgTxt(buffer); 85 | } 86 | 87 | typedef struct my_error_mgr * my_error_ptr; 88 | 89 | METHODDEF(void) 90 | my_error_exit (j_common_ptr cinfo) 91 | { 92 | char buffer[JMSG_LENGTH_MAX]; 93 | 94 | /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ 95 | my_error_ptr myerr = (my_error_ptr) cinfo->err; 96 | 97 | /* create the message */ 98 | (*cinfo->err->format_message) (cinfo, buffer); 99 | printf("Error: %s\n",buffer); 100 | 101 | /* return control to the setjmp point */ 102 | longjmp(myerr->setjmp_buffer, 1); 103 | } 104 | 105 | 106 | /* Substitute for mxCreateDoubleScalar, which is not available 107 | * on earlier versions of Matlab */ 108 | mxArray *mxCDS(double val) { 109 | mxArray *mxtemp; 110 | double *p; 111 | 112 | mxtemp = mxCreateDoubleMatrix(1, 1, mxREAL); 113 | p = mxGetPr(mxtemp); 114 | *p = val; 115 | 116 | return mxtemp; 117 | } 118 | 119 | 120 | /* mex function */ 121 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 122 | { 123 | struct jpeg_decompress_struct cinfo; 124 | struct my_error_mgr jerr; 125 | jpeg_component_info *compptr; 126 | jvirt_barray_ptr *coef_arrays; 127 | jpeg_saved_marker_ptr marker_ptr; 128 | FILE *infile; 129 | JDIMENSION blk_x,blk_y; 130 | JBLOCKARRAY buffer; 131 | JCOEFPTR bufptr; 132 | JQUANT_TBL *quant_ptr; 133 | JHUFF_TBL *huff_ptr; 134 | int strlen, c_width, c_height, ci, i, j, n, dims[2]; 135 | char *filename; 136 | double *mp, *mptop; 137 | mxChar *mcp; 138 | mxArray *mxtemp, *mxjpeg_obj, *mxcoef_arrays, *mxcomments; 139 | mxArray *mxquant_tables, *mxhuff_tables, *mxcomp_info; 140 | 141 | /* field names jpeg_obj Matlab struct */ 142 | const char *jobj_field_names[] = { 143 | "image_width", /* image width in pixels */ 144 | "image_height", /* image height in pixels */ 145 | "image_components", /* number of image color components */ 146 | "image_color_space", /* in/out_color_space */ 147 | "jpeg_components", /* number of JPEG color components */ 148 | "jpeg_color_space", /* color space of DCT coefficients */ 149 | "comments", /* COM markers, if any */ 150 | "coef_arrays", /* DCT arrays for each component */ 151 | "quant_tables", /* quantization tables */ 152 | "ac_huff_tables", /* AC huffman encoding tables */ 153 | "dc_huff_tables", /* DC huffman encoding tables */ 154 | "optimize_coding", /* flag to optimize huffman tables */ 155 | "comp_info", /* component info struct array */ 156 | "progressive_mode", /* is progressive mode */ 157 | }; 158 | const int num_jobj_fields = 14; 159 | 160 | /* field names comp_info struct */ 161 | const char *comp_field_names[] = { 162 | "component_id", /* JPEG one byte identifier code */ 163 | "h_samp_factor", /* horizontal sampling factor */ 164 | "v_samp_factor", /* vertical sampling factor */ 165 | "quant_tbl_no", /* quantization table number for component */ 166 | "dc_tbl_no", /* DC entropy coding table number */ 167 | "ac_tbl_no" /* AC entropy encoding table number */ 168 | }; 169 | const int num_comp_fields = 6; 170 | 171 | const char *huff_field_names[] = {"counts","symbols"}; 172 | 173 | /* check input value */ 174 | if (nrhs != 1) mexErrMsgTxt("One input argument required."); 175 | if (mxIsChar(prhs[0]) != 1) 176 | mexErrMsgTxt("Filename must be a string"); 177 | 178 | /* check output return jpegobj struct */ 179 | if (nlhs > 1) mexErrMsgTxt("Too many output arguments"); 180 | 181 | /* get filename */ 182 | strlen = mxGetM(prhs[0])*mxGetN(prhs[0]) + 1; 183 | filename = mxCalloc(strlen, sizeof(char)); 184 | mxGetString(prhs[0],filename,strlen); 185 | 186 | /* open file */ 187 | if ((infile = fopen(filename, "rb")) == NULL) 188 | mexErrMsgTxt("Can't open file"); 189 | 190 | /* set up the normal JPEG error routines, then override error_exit. */ 191 | cinfo.err = jpeg_std_error(&jerr.pub); 192 | jerr.pub.error_exit = my_error_exit; 193 | jerr.pub.output_message = my_output_message; 194 | 195 | /* establish the setjmp return context for my_error_exit to use. */ 196 | if (setjmp(jerr.setjmp_buffer)) { 197 | jpeg_destroy_decompress(&cinfo); 198 | fclose(infile); 199 | mexErrMsgTxt("Error reading file"); 200 | } 201 | 202 | /* initialize JPEG decompression object */ 203 | jpeg_create_decompress(&cinfo); 204 | jpeg_stdio_src(&cinfo, infile); 205 | 206 | /* save contents of markers */ 207 | jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF); 208 | 209 | /* read header and coefficients */ 210 | jpeg_read_header(&cinfo, TRUE); 211 | 212 | /* create Matlab jpegobj struct */ 213 | mxjpeg_obj = mxCreateStructMatrix(1,1,num_jobj_fields,jobj_field_names); 214 | 215 | /* for some reason out_color_components isn't being set by 216 | jpeg_read_header, so we will infer it from out_color_space: */ 217 | switch (cinfo.out_color_space) { 218 | case JCS_GRAYSCALE: 219 | cinfo.out_color_components = 1; 220 | break; 221 | case JCS_RGB: 222 | cinfo.out_color_components = 3; 223 | break; 224 | case JCS_YCbCr: 225 | cinfo.out_color_components = 3; 226 | break; 227 | case JCS_CMYK: 228 | cinfo.out_color_components = 4; 229 | break; 230 | case JCS_YCCK: 231 | cinfo.out_color_components = 4; 232 | break; 233 | } 234 | 235 | /* copy header information */ 236 | mxSetField(mxjpeg_obj,0,"image_width", 237 | mxCDS(cinfo.image_width)); 238 | mxSetField(mxjpeg_obj,0,"image_height", 239 | mxCDS(cinfo.image_height)); 240 | mxSetField(mxjpeg_obj,0,"image_color_space", 241 | mxCDS(cinfo.out_color_space)); 242 | mxSetField(mxjpeg_obj,0,"image_components", 243 | mxCDS(cinfo.out_color_components)); 244 | mxSetField(mxjpeg_obj,0,"jpeg_color_space", 245 | mxCDS(cinfo.jpeg_color_space)); 246 | mxSetField(mxjpeg_obj,0,"jpeg_components", 247 | mxCDS(cinfo.num_components)); 248 | mxSetField(mxjpeg_obj,0,"progressive_mode", 249 | mxCDS(cinfo.progressive_mode)); 250 | 251 | /* set optimize_coding flag for jpeg_write() */ 252 | mxSetField(mxjpeg_obj,0,"optimize_coding",mxCDS(FALSE)); 253 | 254 | /* copy component information */ 255 | mxcomp_info = mxCreateStructMatrix(1,cinfo.num_components, 256 | num_comp_fields,comp_field_names); 257 | mxSetField(mxjpeg_obj,0,"comp_info",mxcomp_info); 258 | for (ci = 0; ci < cinfo.num_components; ci++) { 259 | mxSetField(mxcomp_info,ci,"component_id", 260 | mxCDS(cinfo.comp_info[ci].component_id)); 261 | mxSetField(mxcomp_info,ci,"h_samp_factor", 262 | mxCDS(cinfo.comp_info[ci].h_samp_factor)); 263 | mxSetField(mxcomp_info,ci,"v_samp_factor", 264 | mxCDS(cinfo.comp_info[ci].v_samp_factor)); 265 | mxSetField(mxcomp_info,ci,"quant_tbl_no", 266 | mxCDS(cinfo.comp_info[ci].quant_tbl_no+1)); 267 | mxSetField(mxcomp_info,ci,"ac_tbl_no", 268 | mxCDS(cinfo.comp_info[ci].ac_tbl_no+1)); 269 | mxSetField(mxcomp_info,ci,"dc_tbl_no", 270 | mxCDS(cinfo.comp_info[ci].dc_tbl_no+1)); 271 | } 272 | 273 | /* copy markers */ 274 | mxcomments = mxCreateCellMatrix(0,0); 275 | mxSetField(mxjpeg_obj,0,"comments",mxcomments); 276 | marker_ptr = cinfo.marker_list; 277 | while (marker_ptr != NULL) { 278 | switch (marker_ptr->marker) { 279 | case JPEG_COM: 280 | /* this comment index */ 281 | n = mxGetN(mxcomments); 282 | 283 | /* allocate space in cell array for a new comment */ 284 | mxSetPr(mxcomments,mxRealloc(mxGetPr(mxcomments), 285 | (n+1)*mxGetElementSize(mxcomments))); 286 | mxSetM(mxcomments,1); 287 | mxSetN(mxcomments,n+1); 288 | 289 | /* create new char array to store comment string */ 290 | dims[0] = 1; 291 | dims[1] = marker_ptr->data_length; 292 | mxtemp = mxCreateCharArray(2,dims); 293 | mxSetCell(mxcomments,n,mxtemp); 294 | mcp = (mxChar *) mxGetPr(mxtemp); 295 | 296 | /* copy comment string to char array */ 297 | for (i = 0; i < (int) marker_ptr->data_length; i++) 298 | *mcp++ = (mxChar) marker_ptr->data[i]; 299 | 300 | break; 301 | default: 302 | break; 303 | } 304 | marker_ptr = marker_ptr->next; 305 | } 306 | 307 | /* copy the quantization tables */ 308 | mxquant_tables = mxCreateCellMatrix(1,NUM_QUANT_TBLS); 309 | mxSetField(mxjpeg_obj,0,"quant_tables",mxquant_tables); 310 | mxSetN(mxquant_tables, 0); 311 | for (n = 0; n < NUM_QUANT_TBLS; n++) { 312 | if (cinfo.quant_tbl_ptrs[n] != NULL) { 313 | mxSetN(mxquant_tables, n+1); 314 | mxtemp = mxCreateDoubleMatrix(DCTSIZE, DCTSIZE, mxREAL); 315 | mxSetCell(mxquant_tables,n,mxtemp); 316 | mp = mxGetPr(mxtemp); 317 | quant_ptr = cinfo.quant_tbl_ptrs[n]; 318 | for (i = 0; i < DCTSIZE; i++) 319 | for (j = 0; j < DCTSIZE; j++) 320 | mp[j*DCTSIZE+i] = (double) quant_ptr->quantval[i*DCTSIZE+j]; 321 | } 322 | } 323 | 324 | /* copy the AC huffman tables */ 325 | mxhuff_tables = mxCreateStructMatrix(1,NUM_HUFF_TBLS,2,huff_field_names); 326 | mxSetField(mxjpeg_obj,0,"ac_huff_tables",mxhuff_tables); 327 | mxSetN(mxhuff_tables, 0); 328 | for (n = 0; n < NUM_HUFF_TBLS; n++) { 329 | if (cinfo.ac_huff_tbl_ptrs[n] != NULL) { 330 | huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; 331 | mxSetN(mxhuff_tables, n+1); 332 | 333 | mxtemp = mxCreateDoubleMatrix(1, 16, mxREAL); 334 | mxSetField(mxhuff_tables,n,"counts",mxtemp); 335 | mp = mxGetPr(mxtemp); 336 | for (i = 1; i <= 16; i++) *mp++ = huff_ptr->bits[i]; 337 | 338 | mxtemp = mxCreateDoubleMatrix(1, 256, mxREAL); 339 | mxSetField(mxhuff_tables,n,"symbols",mxtemp); 340 | mp = mxGetPr(mxtemp); 341 | for (i = 0; i < 256; i++) *mp++ = huff_ptr->huffval[i]; 342 | } 343 | } 344 | 345 | /* copy the DC huffman tables */ 346 | mxhuff_tables = mxCreateStructMatrix(1,NUM_HUFF_TBLS,2,huff_field_names); 347 | mxSetField(mxjpeg_obj,0,"dc_huff_tables",mxhuff_tables); 348 | mxSetN(mxhuff_tables, 0); 349 | for (n = 0; n < NUM_HUFF_TBLS; n++) { 350 | if (cinfo.dc_huff_tbl_ptrs[n] != NULL) { 351 | huff_ptr = cinfo.dc_huff_tbl_ptrs[n]; 352 | mxSetN(mxhuff_tables, n+1); 353 | 354 | mxtemp = mxCreateDoubleMatrix(1, 16, mxREAL); 355 | mxSetField(mxhuff_tables,n,"counts",mxtemp); 356 | mp = mxGetPr(mxtemp); 357 | for (i = 1; i <= 16; i++) *mp++ = huff_ptr->bits[i]; 358 | 359 | mxtemp = mxCreateDoubleMatrix(1, 256, mxREAL); 360 | mxSetField(mxhuff_tables,n,"symbols",mxtemp); 361 | mp = mxGetPr(mxtemp); 362 | for (i = 0; i < 256; i++) *mp++ = huff_ptr->huffval[i]; 363 | } 364 | } 365 | 366 | /* creation and population of the DCT coefficient arrays */ 367 | coef_arrays = jpeg_read_coefficients(&cinfo); 368 | mxcoef_arrays = mxCreateCellMatrix(1,cinfo.num_components); 369 | mxSetField(mxjpeg_obj,0,"coef_arrays",mxcoef_arrays); 370 | for (ci = 0; ci < cinfo.num_components; ci++) { 371 | compptr = cinfo.comp_info + ci; 372 | c_height = compptr->height_in_blocks * DCTSIZE; 373 | c_width = compptr->width_in_blocks * DCTSIZE; 374 | 375 | /* create Matlab dct block array for this component */ 376 | mxtemp = mxCreateDoubleMatrix(c_height, c_width, mxREAL); 377 | mxSetCell(mxcoef_arrays,ci,mxtemp); 378 | mp = mxGetPr(mxtemp); 379 | mptop = mp; 380 | 381 | /* copy coefficients from virtual block arrays */ 382 | for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y++) { 383 | buffer = (cinfo.mem->access_virt_barray) 384 | ((j_common_ptr) &cinfo, coef_arrays[ci], blk_y, 1, FALSE); 385 | for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 386 | bufptr = buffer[0][blk_x]; 387 | for (i = 0; i < DCTSIZE; i++) /* for each row in block */ 388 | for (j = 0; j < DCTSIZE; j++) /* for each column in block */ 389 | mp[j*c_height+i] = (double) bufptr[i*DCTSIZE+j]; 390 | mp+=DCTSIZE*c_height; 391 | } 392 | mp=(mptop+=DCTSIZE); 393 | } 394 | } 395 | 396 | /* done with cinfo */ 397 | jpeg_finish_decompress(&cinfo); 398 | jpeg_destroy_decompress(&cinfo); 399 | 400 | /* close input file */ 401 | fclose(infile); 402 | 403 | /* set output */ 404 | if (nlhs == 1) plhs[0] = mxjpeg_obj; 405 | 406 | } 407 | -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_read.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_read.mexa64 -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_read.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_read.mexglx -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_read.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_read.mexw32 -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_read.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_read.mexw64 -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_write.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jpeg_write.c 3 | * 4 | * JPEG_WRITE(JPEGOBJ,FILENAME) 5 | * 6 | * Reads JPEGOBJ, a Matlab struct containing the JPEG header, 7 | * quantization tables and the DCT coefficients (as returned by JPEG_READ), 8 | * and writes the information into a JPEG file with the name FILENAME. 9 | * 10 | * This software is based in part on the work of the Independent JPEG Group. 11 | * In order to compile, you must first build IJG's JPEG Tools code library, 12 | * available at ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. 13 | * 14 | * Phil Sallee, Surya De 6/2003 15 | * 16 | * Copyright (c) 2003 The Regents of the University of California. 17 | * All Rights Reserved. 18 | * 19 | * Permission to use, copy, modify, and distribute this software and its 20 | * documentation for educational, research and non-profit purposes, 21 | * without fee, and without a written agreement is hereby granted, 22 | * provided that the above copyright notice, this paragraph and the 23 | * following three paragraphs appear in all copies. 24 | * 25 | * Permission to incorporate this software into commercial products may 26 | * be obtained by contacting the University of California. Contact Jo Clare 27 | * Peterman, University of California, 428 Mrak Hall, Davis, CA, 95616. 28 | * 29 | * This software program and documentation are copyrighted by The Regents 30 | * of the University of California. The software program and 31 | * documentation are supplied "as is", without any accompanying services 32 | * from The Regents. The Regents does not warrant that the operation of 33 | * the program will be uninterrupted or error-free. The end-user 34 | * understands that the program was developed for research purposes and 35 | * is advised not to rely exclusively on the program for any reason. 36 | * 37 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 38 | * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, 39 | * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND 40 | * ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN 41 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF 42 | * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 43 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 44 | * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 45 | * BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE 46 | * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 47 | * 48 | */ 49 | 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include "mex.h" 58 | 59 | 60 | /* We need to create our own error handler so that we can override the 61 | * default handler in case a fatal error occurs. The standard error_exit 62 | * method calls exit() which doesn't clean things up properly and also 63 | * exits Matlab. This is described in the example.c routine provided in 64 | * the IJG's code library. 65 | */ 66 | struct my_error_mgr { 67 | struct jpeg_error_mgr pub; /* "public" fields */ 68 | jmp_buf setjmp_buffer; /* for return to caller */ 69 | }; 70 | 71 | /* The default output_message routine causes a seg fault in Matlab, 72 | * at least on Windows. Its generally used to emit warnings, since 73 | * fatal errors call the error_exit routine, so we emit a Matlab 74 | * warning instead. If desired, warnings can be turned off by the 75 | * user with "warnings off". -- PAS 10/03 76 | */ 77 | METHODDEF(void) 78 | my_output_message (j_common_ptr cinfo) 79 | { 80 | char buffer[JMSG_LENGTH_MAX]; 81 | 82 | /* Create the message */ 83 | (*cinfo->err->format_message) (cinfo, buffer); 84 | 85 | mexWarnMsgTxt(buffer); 86 | } 87 | 88 | typedef struct my_error_mgr * my_error_ptr; 89 | 90 | METHODDEF(void) 91 | my_error_exit (j_common_ptr cinfo) 92 | { 93 | char buffer[JMSG_LENGTH_MAX]; 94 | 95 | /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ 96 | my_error_ptr myerr = (my_error_ptr) cinfo->err; 97 | 98 | /* create the message */ 99 | (*cinfo->err->format_message) (cinfo, buffer); 100 | printf("Error: %s\n",buffer); 101 | 102 | /* return control to the setjmp point */ 103 | longjmp(myerr->setjmp_buffer, 1); 104 | } 105 | 106 | 107 | /* mex function */ 108 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 109 | { 110 | struct jpeg_compress_struct cinfo; 111 | struct my_error_mgr jerr; 112 | const mxArray *mxjpeg_obj; 113 | mxArray *mxcoef_arrays,*mxhuff_tables,*mxcomp_info,*mxtemp, 114 | *mxquant_tables,*mxcomments; 115 | char *filename,*comment; 116 | int strlen,c_height,c_width,ci,i,j,n,t; 117 | FILE *outfile; 118 | jvirt_barray_ptr *coef_arrays = NULL; 119 | jpeg_component_info *compptr; 120 | JDIMENSION blk_x,blk_y; 121 | JBLOCKARRAY buffer; 122 | JCOEFPTR bufptr; 123 | double *mp, *mptop; 124 | 125 | /* check the input values */ 126 | if (nrhs != 2) mexErrMsgTxt("Two input arguments required."); 127 | 128 | /* check the output values */ 129 | if (nlhs != 0) mexErrMsgTxt("Too many output arguments."); 130 | if (mxIsChar(prhs[1]) != 1) mexErrMsgTxt("Filename must be a string."); 131 | 132 | /* get filename */ 133 | strlen = mxGetM(prhs[1])*mxGetN(prhs[1]) + 1; 134 | filename = mxCalloc(strlen, sizeof(char)); 135 | mxGetString(prhs[1],filename,strlen); 136 | 137 | /* open the output file*/ 138 | if ((outfile = fopen(filename, "wb")) == NULL) 139 | mexErrMsgTxt("Can't open file."); 140 | 141 | /* set up the normal JPEG error routines, then override error_exit. */ 142 | cinfo.err = jpeg_std_error(&jerr.pub); 143 | jerr.pub.error_exit = my_error_exit; 144 | jerr.pub.output_message = my_output_message; 145 | 146 | /* establish the setjmp return context for my_error_exit to use. */ 147 | if (setjmp(jerr.setjmp_buffer)) 148 | { 149 | jpeg_destroy_compress(&cinfo); 150 | fclose(outfile); 151 | mexErrMsgTxt("Error writing to file."); 152 | } 153 | 154 | /* set the input */ 155 | mxjpeg_obj = prhs[0]; 156 | 157 | /* initialize JPEG decompression object */ 158 | jpeg_create_compress(&cinfo); 159 | 160 | /* write the output file */ 161 | jpeg_stdio_dest(&cinfo, outfile); 162 | 163 | /* Set the compression object with our parameters */ 164 | cinfo.image_width = 165 | (unsigned int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_width")); 166 | cinfo.image_height = 167 | (unsigned int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_height")); 168 | cinfo.input_components = 169 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_components")); 170 | cinfo.in_color_space = 171 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_color_space")); 172 | 173 | /* set the compression object with default parameters */ 174 | jpeg_set_defaults(&cinfo); 175 | 176 | cinfo.optimize_coding = 177 | (unsigned char) mxGetScalar(mxGetField(mxjpeg_obj,0,"optimize_coding")); 178 | cinfo.num_components = 179 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"jpeg_components")); 180 | cinfo.jpeg_color_space = 181 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"jpeg_color_space")); 182 | 183 | /* basic support for writing progressive mode JPEG */ 184 | if (mxGetField(mxjpeg_obj,0,"progressive_mode")) { 185 | if ((int) mxGetScalar(mxGetField(mxjpeg_obj,0,"progressive_mode"))) 186 | jpeg_simple_progression(&cinfo); 187 | } 188 | 189 | /* obtain the component array from the jpeg object */ 190 | mxcomp_info = mxGetField(mxjpeg_obj,0,"comp_info"); 191 | 192 | /* copy component information into cinfo from jpeg_obj*/ 193 | for (ci = 0; ci < cinfo.num_components; ci++) 194 | { 195 | cinfo.comp_info[ci].component_id = 196 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"component_id")); 197 | cinfo.comp_info[ci].h_samp_factor = 198 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"h_samp_factor")); 199 | cinfo.comp_info[ci].v_samp_factor = 200 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"v_samp_factor")); 201 | cinfo.comp_info[ci].quant_tbl_no = 202 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"quant_tbl_no"))-1; 203 | cinfo.comp_info[ci].ac_tbl_no = 204 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"ac_tbl_no"))-1; 205 | cinfo.comp_info[ci].dc_tbl_no = 206 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"dc_tbl_no"))-1; 207 | } 208 | 209 | 210 | /* request virtual block arrays */ 211 | mxcoef_arrays = mxGetField(mxjpeg_obj, 0, "coef_arrays"); 212 | coef_arrays = (jvirt_barray_ptr *) 213 | (cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_IMAGE, 214 | sizeof(jvirt_barray_ptr) * cinfo.num_components); 215 | for (ci = 0; ci < cinfo.num_components; ci++) 216 | { 217 | compptr = cinfo.comp_info + ci; 218 | 219 | c_height = mxGetM(mxGetCell(mxcoef_arrays,ci)); 220 | c_width = mxGetN(mxGetCell(mxcoef_arrays,ci)); 221 | compptr->height_in_blocks = c_height / DCTSIZE; 222 | compptr->width_in_blocks = c_width / DCTSIZE; 223 | 224 | coef_arrays[ci] = (cinfo.mem->request_virt_barray) 225 | ((j_common_ptr) &cinfo, JPOOL_IMAGE, TRUE, 226 | (JDIMENSION) jround_up((long) compptr->width_in_blocks, 227 | (long) compptr->h_samp_factor), 228 | (JDIMENSION) jround_up((long) compptr->height_in_blocks, 229 | (long) compptr->v_samp_factor), 230 | (JDIMENSION) compptr->v_samp_factor); 231 | } 232 | 233 | 234 | /* realize virtual block arrays */ 235 | jpeg_write_coefficients(&cinfo,coef_arrays); 236 | 237 | /* populate the array with the DCT coefficients */ 238 | for (ci = 0; ci < cinfo.num_components; ci++) 239 | { 240 | compptr = cinfo.comp_info + ci; 241 | 242 | /* Get a pointer to the mx coefficient array */ 243 | mxtemp = mxGetCell(mxcoef_arrays,ci); 244 | mp = mxGetPr(mxtemp); 245 | mptop = mp; 246 | 247 | c_height = mxGetM(mxtemp); 248 | c_width = mxGetN(mxtemp); 249 | 250 | /* Copy coefficients to virtual block arrays */ 251 | for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y++) 252 | { 253 | buffer = (cinfo.mem->access_virt_barray) 254 | ((j_common_ptr) &cinfo, coef_arrays[ci], blk_y, 1, TRUE); 255 | 256 | for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) 257 | { 258 | bufptr = buffer[0][blk_x]; 259 | for (i = 0; i < DCTSIZE; i++) /* for each row in block */ 260 | for (j = 0; j < DCTSIZE; j++) /* for each column in block */ 261 | bufptr[i*DCTSIZE+j] = (JCOEF) mp[j*c_height+i]; 262 | mp+=DCTSIZE*c_height; 263 | } 264 | mp=(mptop+=DCTSIZE); 265 | } 266 | } 267 | 268 | /* get the quantization tables */ 269 | mxquant_tables = mxGetField(mxjpeg_obj,0,"quant_tables"); 270 | for (n = 0; n < mxGetN(mxquant_tables); n++) 271 | { 272 | if (cinfo.quant_tbl_ptrs[n] == NULL) 273 | cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo); 274 | 275 | /* Fill the table */ 276 | mxtemp = mxGetCell(mxquant_tables,n); 277 | mp = mxGetPr(mxtemp); 278 | for (i = 0; i < DCTSIZE; i++) 279 | for (j = 0; j < DCTSIZE; j++) { 280 | t = mp[j*DCTSIZE+i]; 281 | 282 | if (t<1 || t>65535) 283 | mexErrMsgTxt("Quantization table entries not in range 1..65535"); 284 | 285 | cinfo.quant_tbl_ptrs[n]->quantval[i*DCTSIZE+j] = 286 | (UINT16) t; 287 | } 288 | } 289 | 290 | /* set remaining quantization table slots to null */ 291 | for (; n < NUM_QUANT_TBLS; n++) 292 | cinfo.quant_tbl_ptrs[n] = NULL; 293 | 294 | /* Get the AC and DC huffman tables but check for optimized coding first*/ 295 | if (cinfo.optimize_coding == FALSE) 296 | { 297 | if (mxGetField(mxjpeg_obj,0,"ac_huff_tables") != NULL) 298 | { 299 | mxhuff_tables = mxGetField(mxjpeg_obj,0,"ac_huff_tables"); 300 | if( mxGetN(mxhuff_tables) > 0) 301 | { 302 | for (n = 0; n < mxGetN(mxhuff_tables); n++) 303 | { 304 | if (cinfo.ac_huff_tbl_ptrs[n] == NULL) 305 | cinfo.ac_huff_tbl_ptrs[n] = 306 | jpeg_alloc_huff_table((j_common_ptr) &cinfo); 307 | 308 | mxtemp = mxGetField(mxhuff_tables,n,"counts"); 309 | mp = mxGetPr(mxtemp); 310 | for (i = 1; i <= 16; i++) 311 | cinfo.ac_huff_tbl_ptrs[n]->bits[i] = (UINT8) *mp++; 312 | mxtemp = mxGetField(mxhuff_tables,n,"symbols"); 313 | mp = mxGetPr(mxtemp); 314 | for (i = 0; i < 256; i++) 315 | cinfo.ac_huff_tbl_ptrs[n]->huffval[i] = (UINT8) *mp++; 316 | } 317 | for (; n < NUM_HUFF_TBLS; n++) cinfo.ac_huff_tbl_ptrs[n] = NULL; 318 | } 319 | } 320 | 321 | if (mxGetField(mxjpeg_obj,0, "dc_huff_tables") != NULL) 322 | { 323 | mxhuff_tables = mxGetField(mxjpeg_obj,0,"dc_huff_tables"); 324 | if( mxGetN(mxhuff_tables) > 0) 325 | { 326 | for (n = 0; n < mxGetN(mxhuff_tables); n++) 327 | { 328 | if (cinfo.dc_huff_tbl_ptrs[n] == NULL) 329 | cinfo.dc_huff_tbl_ptrs[n] = 330 | jpeg_alloc_huff_table((j_common_ptr) &cinfo); 331 | 332 | mxtemp = mxGetField(mxhuff_tables,n,"counts"); 333 | mp = mxGetPr(mxtemp); 334 | for (i = 1; i <= 16; i++) 335 | cinfo.dc_huff_tbl_ptrs[n]->bits[i] = (unsigned char) *mp++; 336 | mxtemp = mxGetField(mxhuff_tables,n,"symbols"); 337 | mp = mxGetPr(mxtemp); 338 | for (i = 0; i < 256; i++) 339 | cinfo.dc_huff_tbl_ptrs[n]->huffval[i] = (unsigned char) *mp++; 340 | } 341 | for (; n < NUM_HUFF_TBLS; n++) cinfo.dc_huff_tbl_ptrs[n] = NULL; 342 | } 343 | } 344 | } 345 | 346 | /* copy markers */ 347 | mxcomments = mxGetField(mxjpeg_obj,0,"comments"); 348 | n = mxGetN(mxcomments); 349 | for (i = 0; i < n; i++) 350 | { 351 | mxtemp = mxGetCell(mxcomments,i); 352 | strlen = mxGetN(mxtemp) + 1; 353 | comment = mxCalloc(strlen, sizeof(char)); 354 | mxGetString(mxtemp,comment,strlen); 355 | jpeg_write_marker(&cinfo, JPEG_COM, comment, strlen-1); 356 | mxFree(comment); 357 | } 358 | 359 | /* done with cinfo */ 360 | jpeg_finish_compress(&cinfo); 361 | jpeg_destroy_compress(&cinfo); 362 | 363 | /* close the file */ 364 | fclose(outfile); 365 | } 366 | -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_write.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_write.mexa64 -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_write.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_write.mexglx -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_write.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_write.mexw32 -------------------------------------------------------------------------------- /Hou/jpegread/jpeg_write.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/jpegread/jpeg_write.mexw64 -------------------------------------------------------------------------------- /Hou/mark.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/mark.m -------------------------------------------------------------------------------- /Hou/matrix_index.m: -------------------------------------------------------------------------------- 1 | function [ matrix ] = matrix_index(sel_index) 2 | matrix=zeros(8); 3 | for p=1:length(sel_index) 4 | row=ceil((sel_index(p)+1)/8); 5 | col=mod(sel_index(p),8)+1; 6 | matrix(row,col)=1; 7 | end 8 | 9 | end 10 | 11 | -------------------------------------------------------------------------------- /Hou/recoverstego.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/recoverstego.m -------------------------------------------------------------------------------- /Hou/select_block2.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/select_block2.m -------------------------------------------------------------------------------- /Hou/simulate.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/simulate.m -------------------------------------------------------------------------------- /Hou/stego.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/stego.jpg -------------------------------------------------------------------------------- /Hou/synthesize.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/synthesize.m -------------------------------------------------------------------------------- /Hou/testimgs/Airplane.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/testimgs/Airplane.tiff -------------------------------------------------------------------------------- /Hou/testimgs/Baboon.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/testimgs/Baboon.tiff -------------------------------------------------------------------------------- /Hou/testimgs/Lena.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/testimgs/Lena.tiff -------------------------------------------------------------------------------- /Hou/testimgs/Peppers.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/testimgs/Peppers.tiff -------------------------------------------------------------------------------- /Hou/utils/AnyDistortion.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/utils/AnyDistortion.m -------------------------------------------------------------------------------- /Hou/utils/arith_decode.c: -------------------------------------------------------------------------------- 1 | /* MEX ROUTINE FOR ARITHMETIC DECODING */ 2 | 3 | /* 4 | Matlab MEX routine for arithmetic coding, modified from the adaptive 5 | arithmetic coding software by R. M. Neal contained in the following 6 | reference: 7 | 8 | Witten, I. H., Neal, R. M., and Cleary, J. G. (1987) 9 | "Arithmetic coding for data compression", Communications 10 | of the ACM, vol. 30, no. 6 (June). 11 | 12 | This modified version of the arithmetic coding software allows 13 | frequencies to be passed for each symbol, rather than estimating them 14 | adaptively. 15 | 16 | Accepts a Nx1 array of bits, and an NxS array of symbol frequencies. 17 | Returns an Nx1 output array of symbols ranging from 1..S. 18 | 19 | Adapted to MEX format by Phil Sallee 6/19/00 20 | Modified for steganography embedding by Phil Sallee 6/03 21 | */ 22 | 23 | 24 | #include 25 | #include "math.h" 26 | 27 | 28 | /* SIZE OF ARITHMETIC CODE VALUES. */ 29 | #define code_value_bits 16 /* Number of bits in a code value */ 30 | #define max_freq 16383 31 | typedef long code_value; /* Type of an arithmetic code value */ 32 | #define top_value (((long)1< 3) 65 | mexErrMsgTxt("Too many output arguments"); 66 | 67 | maxip = mxGetM(prhs[0])*mxGetN(prhs[0]); 68 | if (mxGetM(prhs[0]) != 1 & mxGetN(prhs[0]) != 1) 69 | mexErrMsgTxt("Input bit array must be a vector"); 70 | 71 | numsymval = mxGetN(prhs[1]); 72 | numsym = mxGetM(prhs[1]); 73 | 74 | /* create output array */ 75 | plhs[0] = mxCreateDoubleMatrix(numsym,1,mxREAL); 76 | 77 | /* get pointers to arrays */ 78 | symarr = mxGetPr(plhs[0]); 79 | inarr = mxGetPr(prhs[0]); 80 | farr = mxGetPr(prhs[1]); 81 | 82 | /* input bits to fill the code value */ 83 | value = 0; 84 | for (i = 0; i1)) mexErrMsgTxt("bad input bit!\n"); 88 | value += (long) inarr[ip++]; 89 | } 90 | } 91 | 92 | /* initialize code range and bits_to_follow */ 93 | low = 0; 94 | high = top_value; 95 | 96 | /* allocate cumulative frequency array */ 97 | cf = mxMalloc((numsymval+1) * sizeof(long)); 98 | if (cf==NULL) mexErrMsgTxt("Couldn't allocate cumulative freq array"); 99 | 100 | /* decode symbols */ 101 | for (i=0; i numsymval) { 121 | printf("cf[0]=%d, cf[1]=%d, cf[2]=%d, cum=%d\n",cf[0],cf[1],cf[2],cum); 122 | mexErrMsgTxt("Internal error: bad symbol!\n"); 123 | } 124 | 125 | /* Narrow code range for this symbol */ 126 | high = low + (range*cf[symbol])/cfsum - 1; 127 | low = low + (range*cf[symbol-1])/cfsum; 128 | 129 | if (high < low) 130 | mexErrMsgTxt("Internal error: bad range!\n"); 131 | 132 | /* Loop to input bits */ 133 | for (;;) { 134 | if (high=half) { 138 | value -= half; 139 | low -= half; 140 | high -= half; 141 | br+=btf; btf=1; 142 | } 143 | else if (low>=first_qtr && high1) mexErrMsgTxt("bad input bit!\n"); 157 | value += inarr[ip++]; 158 | } 159 | else { 160 | lastbit = !lastbit; 161 | value += lastbit; 162 | } 163 | } 164 | 165 | symarr[i] = symbol; 166 | sd++; 167 | 168 | /* check for too many garbage bits */ 169 | if (br >= maxip) break; 170 | } 171 | 172 | /* return number of bits read that can be uniquely obtained 173 | from the symbols that were decoded regardless of any other 174 | symbols that may follow (necessary for steganographic use) */ 175 | if (nlhs > 1) { 176 | plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL); 177 | p = mxGetPr(plhs[1]); 178 | *p = br; 179 | } 180 | 181 | /* return number of symbols decoded */ 182 | if (nlhs > 2) { 183 | plhs[2] = mxCreateDoubleMatrix(1,1,mxREAL); 184 | p = mxGetPr(plhs[2]); 185 | *p = sd; 186 | } 187 | 188 | mxFree(cf); 189 | } 190 | -------------------------------------------------------------------------------- /Hou/utils/arith_decode.m: -------------------------------------------------------------------------------- 1 | % [SYMBOLS, BITSREAD, NUMSYM] = ARITH_DECODE(BITS, FREQS) 2 | % 3 | % Matlab MEX routine for arithmetic coding, modified from the adaptive 4 | % arithmetic coding software by R. M. Neal contained in the following 5 | % reference: 6 | % 7 | % Witten, I. H., Neal, R. M., and Cleary, J. G. (1987) 8 | % "Arithmetic coding for data compression", Communications 9 | % of the ACM, vol. 30, no. 6 (June). 10 | % 11 | % This modified version of the arithmetic coding software allows 12 | % frequencies to be passed for each symbol, rather than estimating them 13 | % adaptively. 14 | % 15 | % Accepts a Nx1 array of bits, and an NxS array of symbol frequencies. 16 | % Returns an Nx1 output array of symbols ranging from 1..S. 17 | % 18 | % This routine has been modified to return the number of bits read 19 | % that can be uniquely determined from the decoded symbols (BITSREAD) as 20 | % well as the number of symbols used (NUMSYM). This is necessary for 21 | % steganography purposes in which the symbols are used as a transmission 22 | % channel to send a message which may have arbitrary length. 23 | 24 | % Adapted to MEX format by Phil Sallee 6/19/00 25 | % Modified for steganography embedding by Phil Sallee 6/03 26 | 27 | error('Need to compile MEX routine ARITH_DECODE.C Type "mex arith_decode.c".'); 28 | -------------------------------------------------------------------------------- /Hou/utils/arith_decode.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/utils/arith_decode.mexw64 -------------------------------------------------------------------------------- /Hou/utils/arith_encode.c: -------------------------------------------------------------------------------- 1 | /* MEX ROUTINE FOR ARITHMETIC ENCODING */ 2 | 3 | /* 4 | Matlab MEX routine for arithmetic coding, modified from the adaptive 5 | arithmetic coding software by R. M. Neal contained in the following 6 | reference: 7 | 8 | Witten, I. H., Neal, R. M., and Cleary, J. G. (1987) 9 | "Arithmetic coding for data compression", Communications 10 | of the ACM, vol. 30, no. 6 (June). 11 | 12 | This modified version of the arithmetic coding software allows 13 | frequencies to be passed for each symbol, rather than estimating them 14 | adaptively. 15 | 16 | Accepts a Nx1 array of symbols 1..S, and an NxS array of 17 | symbol frequencies. Returns an Nx1 output array of bits. 18 | 19 | Adapted to MEX format by Phil Sallee 6/19/00 20 | Modified for steganography decoding by Phil Sallee 6/03 21 | */ 22 | 23 | 24 | #include 25 | #include "math.h" 26 | 27 | 28 | /* SIZE OF ARITHMETIC CODE VALUES. */ 29 | #define code_value_bits 16 /* Number of bits in a code value */ 30 | #define max_freq 16383 31 | typedef long code_value; /* Type of an arithmetic code value */ 32 | #define top_value (((long)1< 1) 60 | mexErrMsgTxt("Too many output arguments"); 61 | 62 | if (mxGetN(prhs[0]) != 1) 63 | mexErrMsgTxt("Input symbol array must be a column vector"); 64 | 65 | numsymval = mxGetN(prhs[1]); 66 | numsym = mxGetM(prhs[0]); 67 | 68 | if (mxGetM(prhs[1]) != numsym) 69 | mexErrMsgTxt("Frequency array must have same num of rows as symbol array"); 70 | 71 | /* allocate extra large buffer to hold output */ 72 | maxop = numsym * numsymval + 100; 73 | outbuf = mxCalloc(maxop, sizeof(int)); 74 | 75 | /* get pointers to arrays */ 76 | symarr = mxGetPr(prhs[0]); 77 | farr = mxGetPr(prhs[1]); 78 | 79 | /* allocate cumulative frequency array */ 80 | cf = mxMalloc((numsymval+1) * sizeof(long)); 81 | if (cf==NULL) mexErrMsgTxt("Couldn't allocate cumulative freq array"); 82 | 83 | /* start encoding, initialize code range and bits_to_follow */ 84 | low = 0; 85 | high = top_value; 86 | bits_to_follow = 0; 87 | 88 | /* encode symbols */ 89 | for (i=0; i numsymval)) 108 | mexErrMsgTxt("Symbol out of range\n"); 109 | 110 | if (cf[symbol-1] == cf[symbol]) 111 | mexErrMsgTxt("Can't encode symbol with zero frequency\n"); 112 | 113 | /* Narrow code range for this symbol */ 114 | range = (long)(high-low)+1; 115 | high = low + (range*cf[symbol])/cfsum - 1; 116 | low = low + (range*cf[symbol-1])/cfsum; 117 | 118 | /* Loop to output bits */ 119 | for (;;) { 120 | 121 | if (op + bits_to_follow > maxop - 4) { 122 | maxop = maxop * 2; 123 | printf("reallocating memory for %d ints\n",maxop); 124 | tmpptr = mxRealloc(outbuf, maxop * sizeof(int)); 125 | if (tmpptr == NULL) mexErrMsgTxt("Can't reallocate memory"); 126 | else outbuf = tmpptr; 127 | } 128 | 129 | if (high 0) { 132 | outbuf[op++] = 1; 133 | bits_to_follow -= 1; 134 | } 135 | } 136 | else if (low>=half) { /* Output 1 if in high half.*/ 137 | outbuf[op++] = 1; 138 | while (bits_to_follow > 0) { 139 | outbuf[op++] = 0; 140 | bits_to_follow -= 1; 141 | } 142 | low -= half; 143 | high -= half; /* Subtract offset to top. */ 144 | } 145 | else if (low>=first_qtr /* Output an opposite bit */ 146 | && high 0) { 168 | outbuf[op++] = 1; 169 | bits_to_follow -= 1; 170 | } 171 | } 172 | else { 173 | outbuf[op++] = 1; 174 | while (bits_to_follow > 0) { 175 | outbuf[op++] = 0; 176 | bits_to_follow -= 1; 177 | } 178 | } 179 | */ 180 | 181 | /* create new output array of correct size and fill it */ 182 | plhs[0] = mxCreateDoubleMatrix(op,1,mxREAL); 183 | outarr = mxGetPr(plhs[0]); 184 | for (i=0; i1) 52 | sigStr(size(sigStr,2)+1) = '/'; 53 | end 54 | % --- Assign the string and numeric flags 55 | if(ischar(varargin{i})) 56 | sigStr(size(sigStr,2)+1) = 's'; 57 | elseif(isnumeric(varargin{i})) 58 | sigStr(size(sigStr,2)+1) = 'n'; 59 | else 60 | error('comm:bi2de:InvalidInputArg','Optional parameters must be string or numeric.'); 61 | end 62 | end 63 | 64 | % --- Identify parameter signitures and assign values to variables 65 | switch sigStr 66 | 67 | % --- bi2de(d) 68 | case '' 69 | 70 | % --- bi2de(d, p) 71 | case 'n' 72 | p = varargin{1}; 73 | 74 | % --- bi2de(d, flag) 75 | case 's' 76 | flag = varargin{1}; 77 | 78 | % --- bi2de(d, p, flag) 79 | case 'n/s' 80 | p = varargin{1}; 81 | flag = varargin{2}; 82 | 83 | % --- bi2de(d, flag, p) 84 | case 's/n' 85 | flag = varargin{1}; 86 | p = varargin{2}; 87 | 88 | % --- If the parameter list does not match one of these signatures. 89 | otherwise 90 | error('comm:bi2de:InvalidSeqArg','Syntax error.'); 91 | end 92 | 93 | if isempty(b) 94 | error('comm:bi2de:InputEmpty','Required parameter empty.'); 95 | end 96 | 97 | if max(max(b < 0)) || max(max(~isfinite(b))) || (~isreal(b)) || ... 98 | (max(max(floor(b) ~= b))) 99 | error('comm:bi2de:InvalidInput','Input must contain only finite real positive integers.'); 100 | end 101 | 102 | % Set up the base to convert from. 103 | if isempty(p) 104 | p = 2; 105 | elseif max(size(p)) > 1 106 | error('comm:bi2de:NonScalarBase','Source base must be a scalar.'); 107 | elseif (floor(p) ~= p) || (~isfinite(p)) || (~isreal(p)) 108 | error('comm:bi2de:InvalidBase','Source base must be a finite real integer.'); 109 | elseif p < 2 110 | error('comm:bi2de:BaseLessThan2','Source base must be greater than or equal to two.'); 111 | end 112 | 113 | if max(max(b)) > (p-1) 114 | error('comm:bi2de:InvalidInputElement','The elements of the matrix are larger than the base can represent.'); 115 | end 116 | 117 | n = size(b,2); 118 | 119 | % If a flag is specified to flip the input such that the MSB is to the left. 120 | if isempty(flag) 121 | flag = 'right-msb'; 122 | elseif ~(strcmp(flag, 'right-msb') || strcmp(flag, 'left-msb')) 123 | error('comm:bi2de:InvalidFlag','Invalid string flag.'); 124 | end 125 | 126 | if strcmp(flag, 'left-msb') 127 | 128 | b2 = b; 129 | b = b2(:,n:-1:1); 130 | 131 | end 132 | 133 | %%% The conversion 134 | max_length = 1024; 135 | pow2vector = p.^(0:1:(size(b,2)-1)); 136 | size_B = min(max_length,size(b,2)); 137 | d = b(:,1:size_B)*pow2vector(:,1:size_B).'; 138 | 139 | % handle the infs... 140 | idx = find(max(b(:,max_length+1:size(b,2)).') == 1); 141 | d(idx) = inf; 142 | 143 | % data type conversion 144 | if ~strcmp(inType, 'logical') 145 | d = feval(inType, d); 146 | end 147 | 148 | % [EOF] 149 | -------------------------------------------------------------------------------- /Hou/utils/compressFun.m: -------------------------------------------------------------------------------- 1 | function [ y ] = compressFun( x ) 2 | %COMPRESS Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | B=length(x); 6 | Max_Val=max(x); 7 | j=find(x==Max_Val); 8 | Diff = zeros(B,1); 9 | Diff(1)=x(1); 10 | for i=2:j 11 | Diff(i)=x(i)-x(i-1); 12 | end 13 | for i=j+1:B 14 | Diff(i)=x(i-1)-x(i); 15 | end 16 | 17 | % compress positions 18 | Pos=(Diff<0); 19 | Pos=double(Pos); 20 | p1=sum(Pos)/B; 21 | Frequency=ones(B,2); 22 | Frequency(:,1)=(1-p1)*Frequency(:,1); 23 | Frequency(:,2)=p1*Frequency(:,2); 24 | Pos=Pos+1; 25 | Pos=reshape(Pos,B,1); 26 | [Comp1]=arith_encode(Pos,Frequency); 27 | oh1=size(Comp1,1); 28 | 29 | % compress diffs 30 | Diff=abs(Diff); 31 | temp=max(Diff); 32 | temp=log2(temp); 33 | Digit=ceil(temp)+1; 34 | BiSeq=de2bi(Diff,Digit); 35 | BiSeq=reshape(BiSeq,B*Digit,1); 36 | q1=sum(BiSeq)/(B*Digit); 37 | Frequency=ones(B*Digit,2); 38 | Frequency(:,1)=(1-q1)*Frequency(:,1); 39 | Frequency(:,2)=q1*Frequency(:,2); 40 | BiSeq=BiSeq+1; 41 | [Comp2]=arith_encode(BiSeq,Frequency); 42 | oh2=size(Comp2,1); 43 | y=oh1+oh2+ceil(log2(B)); 44 | 45 | end 46 | 47 | -------------------------------------------------------------------------------- /Hou/utils/compressOhead.m: -------------------------------------------------------------------------------- 1 | function [ compSeq ] = compressOhead( stego,cover,Qyx,xRange,yRange) 2 | %COMPRESSOHEAD Summary of this function goes here 3 | % Detailed explanation goes here 4 | eps=0.0001; 5 | [nB,mB]=size(Qyx); 6 | 7 | coverLen = length(cover); 8 | coverind = zeros(coverLen,1); 9 | for xi=1:mB 10 | coverind(cover==xRange(xi)) = xi; 11 | end 12 | cover = coverind; 13 | 14 | compSeq = zeros(coverLen,1); 15 | compLen = 0; 16 | for yi=1:nB 17 | pos = find(stego==yRange(yi)); 18 | if ~isempty(pos) && ~any(abs(Qyx(yi,:)-1.0)1) 47 | sigStr(size(sigStr,2)+1) = '/'; 48 | end; 49 | % --- Assign the string and numeric flags 50 | if(ischar(varargin{i})) 51 | sigStr(size(sigStr,2)+1) = 's'; 52 | elseif(isnumeric(varargin{i})) 53 | sigStr(size(sigStr,2)+1) = 'n'; 54 | else 55 | error('comm:de2bi:InvalidArg','Only string and numeric arguments are accepted.'); 56 | end; 57 | end; 58 | 59 | % --- Identify parameter signitures and assign values to variables 60 | switch sigStr 61 | % --- de2bi(d) 62 | case 'n' 63 | d = varargin{1}; 64 | 65 | % --- de2bi(d, n) 66 | case 'n/n' 67 | d = varargin{1}; 68 | n = varargin{2}; 69 | 70 | % --- de2bi(d, msbFlag) 71 | case 'n/s' 72 | d = varargin{1}; 73 | msbFlag = varargin{2}; 74 | 75 | % --- de2bi(d, n, msbFlag) 76 | case 'n/n/s' 77 | d = varargin{1}; 78 | n = varargin{2}; 79 | msbFlag = varargin{3}; 80 | 81 | % --- de2bi(d, msbFlag, n) 82 | case 'n/s/n' 83 | d = varargin{1}; 84 | msbFlag = varargin{2}; 85 | n = varargin{3}; 86 | 87 | % --- de2bi(d, n, p) 88 | case 'n/n/n' 89 | d = varargin{1}; 90 | n = varargin{2}; 91 | p = varargin{3}; 92 | 93 | % --- de2bi(d, n, p, msbFlag) 94 | case 'n/n/n/s' 95 | d = varargin{1}; 96 | n = varargin{2}; 97 | p = varargin{3}; 98 | msbFlag = varargin{4}; 99 | 100 | % --- de2bi(d, n, msbFlag, p) 101 | case 'n/n/s/n' 102 | d = varargin{1}; 103 | n = varargin{2}; 104 | msbFlag = varargin{3}; 105 | p = varargin{4}; 106 | 107 | % --- de2bi(d, msbFlag, n, p) 108 | case 'n/s/n/n' 109 | d = varargin{1}; 110 | msbFlag = varargin{2}; 111 | n = varargin{3}; 112 | p = varargin{4}; 113 | 114 | % --- If the parameter list does not match one of these signatures. 115 | otherwise 116 | error('comm:de2bi:InvalidArgSeq','Syntax error.'); 117 | end; 118 | 119 | if isempty(d) 120 | error('comm:de2bi:NoInput','Required parameter empty.'); 121 | end 122 | 123 | inType = class(d); 124 | d = double(d(:)); 125 | len_d = length(d); 126 | 127 | if max(max(d < 0)) || max(max(~isfinite(d))) || (~isreal(d)) || (max(max(floor(d) ~= d))) 128 | error('comm:de2bi:InvalidInput','Input must contain only finite real positive integers.'); 129 | end 130 | 131 | % Assign the base to convert to. 132 | if isempty(p) 133 | p = 2; 134 | elseif max(size(p) ~= 1) 135 | error('comm:de2bi:NonScalarBase','Destination base must be scalar.'); 136 | elseif (~isfinite(p)) || (~isreal(p)) || (floor(p) ~= p) 137 | error('comm:de2bi:InvalidBase','Destination base must be a finite real integer.'); 138 | elseif p < 2 139 | error('comm:de2bi:BaseLessThan2','Cannot convert to a base of less than two.'); 140 | end; 141 | 142 | % Determine minimum length required. 143 | tmp = max(d); 144 | if tmp ~= 0 % Want base-p log of tmp. 145 | ntmp = floor( log(tmp) / log(p) ) + 1; 146 | else % Since you can't take log(0). 147 | ntmp = 1; 148 | end 149 | 150 | % This takes care of any round off error that occurs for really big inputs. 151 | if ~( (p^ntmp) > tmp ) 152 | ntmp = ntmp + 1; 153 | end 154 | 155 | % Assign number of columns in output matrix. 156 | if isempty(n) 157 | n = ntmp; 158 | elseif max(size(n) ~= 1) 159 | error('comm:de2bi:NonScalarN','Specified number of columns must be scalar.'); 160 | elseif (~isfinite(n)) || (~isreal(n)) || (floor(n) ~= n) 161 | error('comm:de2bi:IvalidN','Specified number of columns must be a finite real integer.'); 162 | elseif n < ntmp 163 | error('comm:de2bi:SmallN','Specified number of columns in output matrix is too small.'); 164 | end 165 | 166 | % Check if the string msbFlag is valid. 167 | if isempty(msbFlag) 168 | msbFlag = 'right-msb'; 169 | elseif ~(strcmp(msbFlag, 'right-msb') || strcmp(msbFlag, 'left-msb')) 170 | error('comm:de2bi:InvalidMsbFlag','Invalid string msbFlag.'); 171 | end 172 | 173 | % Initial value. 174 | b = zeros(len_d, n); 175 | 176 | % Perform conversion. 177 | %Vectorized conversion for P=2 case 178 | if(p==2) 179 | [f,e]=log2(max(d)); % How many digits do we need to represent the numbers? 180 | b=rem(floor(d*pow2(1-max(n,e):0)),p); 181 | if strcmp(msbFlag, 'right-msb') 182 | b = fliplr(b); 183 | end; 184 | else 185 | for i = 1 : len_d % Cycle through each element of the input vector/matrix. 186 | j = 1; 187 | tmp = d(i); 188 | while (j <= n) && (tmp > 0) % Cycle through each digit. 189 | b(i, j) = rem(tmp, p); % Determine current digit. 190 | tmp = floor(tmp/p); 191 | j = j + 1; 192 | end; 193 | end; 194 | % If a msbFlag is specified to flip the output such that the MSB is to the left. 195 | if strcmp(msbFlag, 'left-msb') 196 | b2 = b; 197 | b = b2(:,n:-1:1); 198 | end; 199 | end; 200 | 201 | b = feval(inType, b); % data type conversion 202 | 203 | % [EOF] 204 | -------------------------------------------------------------------------------- /Hou/utils/entropyEmbed.m: -------------------------------------------------------------------------------- 1 | function [ stego,mesLen ] = entropyEmbed( cover,mess,Qxy,xRange,yRange) 2 | %ENTROPYEMBED Summary of this function goes here 3 | % Detailed explanation goes here 4 | % cover: the cover signal 5 | % mess: the message to embed 6 | % Qxy: the conditional probability Py|x 7 | eps=0.0001; 8 | stego = cover; 9 | mesLen = 0; 10 | [mB,nB] = size(Qxy); 11 | for xi=1:mB 12 | pos = find(cover==xRange(xi)); 13 | xN = length(pos); 14 | if xN>0 15 | yi = find(abs(Qxy(xi,:)-1.0) < eps); 16 | if yi 17 | stego(pos) = yRange(yi)*ones(xN,1); 18 | else%if abs(sum(Qxy(xi,:))-1.0)<1e-8 19 | fq = repmat(Qxy(xi,:),xN,1); 20 | [symbols,mLen] = arith_decode(mess(mesLen+1:end),fq); 21 | stego(pos) = yRange(symbols); 22 | mesLen = mesLen+mLen; 23 | end 24 | end 25 | end 26 | 27 | 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /Hou/utils/minDistortionEmr.m: -------------------------------------------------------------------------------- 1 | function [ Py,Dav,exitfg,iters] = minDistortionEmr(Px,Dxy,Hy) 2 | % Miniminze average distortion between stego-signal and cover-signal 3 | % 4 | % Input: 5 | % Px : cover-signal probability distribution 6 | % Dxy : square error distortion matrix 7 | % Hy : expected stego-signal entropy 8 | % 9 | % Output: 10 | % Py : stego-signal probability distribution 11 | % Dav : corresponding minimized distortion value 12 | % exitfg : exit flag: 0-->success -1-->invalid input 1-->failed 13 | % iters : number of iterations 14 | %%******************************************************************** 15 | % 16 | % author: Xiaocheng Hu 17 | % college: University of Science and Technology of China 18 | % date: 9/2/2012 19 | % 20 | %%********************************************************************* 21 | 22 | [m,n] = size(Dxy); 23 | 24 | % input validation 25 | % 26 | if ( abs(sum(Px)-1.0) > 1e-8 ) || (Hy > log(n)) || (Hy < -sum(Px.*log(Px))) 27 | Pxy=zeros(m,n);Dav=0;exitfg=-1; 28 | disp('minDistortionEmr invalid input!'); 29 | return; 30 | end 31 | %} 32 | 33 | % 34 | MPx = Px(:,ones(n,1));%repmat(Px,1,n); 35 | Dxy = MPx.*Dxy; 36 | 37 | %parameters 38 | MAXITERS = 300; 39 | Tol = 1e-8; 40 | NTTol = 1e-8; 41 | MU = 20; 42 | Alpha = 0.01; 43 | Beta = 0.6; 44 | 45 | % initialize x0 46 | x = zeros(n+m+1,1);%+1.0; 47 | x(1:n) = log(1/n)+1.0; 48 | x(n+1:n+m) = abs(x(1))+0.01; 49 | x(n+m+1) = 1.0; 50 | 51 | % initialize t0 with least square 52 | Mfx = Dxy+repmat(x(n+1:n+m),1,n)+Px*(x(1:n)'); 53 | fx = [Mfx(:);x(n+m+1)]; 54 | lA = [exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy]; 55 | lb = [(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 56 | t = (lA'*lb)/(lA'*lA); 57 | t = ceil(t); 58 | %t=1; 59 | 60 | % 61 | for iters=1:MAXITERS 62 | % calculate function value and it's gratitude 63 | val=t*(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1))-sum(log(fx)); 64 | grad=t*([exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy])-[(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 65 | 66 | 67 | %{ 68 | Hf0=[diag(exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)),zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2); ... 69 | zeros(m,m+n+1); ... 70 | -(exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2))',zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]; 71 | Hfx=[-diag(sum((MPx./Mfx).^2)) , -(MPx./(Mfx.^2))', zeros(n,1); ... 72 | -(MPx./(Mfx.^2)) , -diag(sum(1./(Mfx.^2),2)), zeros(m,1); ... 73 | zeros(1,n) , zeros(1,m) , -1/(x(n+m+1)^2)]; 74 | hess=t*Hf0-Hfx; 75 | Dx=-hess\grad; 76 | %} 77 | % Calculate Newton step, fast 78 | Dx=fast_linear_solver(t*exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)+(sum((MPx./Mfx).^2))', ... 79 | t*[zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2)]+[(MPx./(Mfx.^2))',zeros(n,1)], ... 80 | t*[zeros(m,m),zeros(m,1);zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]+[diag(sum(1./(Mfx.^2),2)),zeros(m,1);zeros(1,m),1/(x(n+m+1)^2)], ... 81 | -grad); 82 | fprime=grad'*Dx; 83 | 84 | % Solved Centering step and update t 85 | if( (-fprime < NTTol)) 86 | gap=(m*n+1)/t; 87 | 88 | % stopping criterion 89 | if( gap < Tol ),break;end; 90 | 91 | % update t and continue the next Centering step 92 | t=MU*t; 93 | continue; 94 | end 95 | 96 | % Backtracking step 1, ensure the domain of fx 97 | step=1; 98 | DMf=repmat(Dx(n+1:n+m),1,n)+Px*(Dx(1:n)');Dff=[DMf(:);Dx(n+m+1)]; 99 | while any((fx+step*Dff)<=0) 100 | step=Beta*step; 101 | end 102 | 103 | newx = x+step*Dx; 104 | newfx = fx+step*Dff; 105 | % Backtracking step 2, decrease fx sufficiently 106 | % 107 | while ( (t*(newx(n+m+1)*sum(exp(newx(1:n)/newx(n+m+1)-1))+sum(newx(n+1:n+m))-Hy*newx(n+m+1))-sum(log(newfx))) > (val+Alpha*step*fprime) ) 108 | step=Beta*step; 109 | newx=x+step*Dx; 110 | newfx=fx+step*Dff; 111 | end 112 | %} 113 | 114 | % update variables 115 | x = newx; 116 | fx = newfx; 117 | Mfx = Mfx+step*DMf; 118 | 119 | 120 | end 121 | 122 | % Output 123 | Py = exp(x(1:n)/x(n+m+1)-1); 124 | Dav = -(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1)); 125 | 126 | % check if success 127 | if( abs(sum(Py)-1.0) < 1e-8 ) 128 | exitfg=0; 129 | else 130 | exitfg=1; 131 | end 132 | fprintf('minDistortionEmr Iters: %d\t Distortion: %f\t Sum of Py: %f\n',iters,Dav,sum(Py)); 133 | 134 | %% Block elimination method to solve linear equations 135 | function [sx]=fast_linear_solver(A11,A12,A22,b) 136 | [sn,sm]=size(A12); 137 | b1=b(1:sn); 138 | b2=b(sn+1:sn+sm); 139 | 140 | invA11=1./A11; 141 | Tm=repmat(invA11',sm,1).*(A12'); 142 | S=A22-Tm*A12; 143 | bs=b2-Tm*b1; 144 | % check if S is positive definite 145 | % 146 | [L,p]=chol(S,'lower'); 147 | if (p > 0) 148 | sx=zeros(sn+sm,1); 149 | return; 150 | end 151 | 152 | zz=L\bs; 153 | x2=L'\zz; 154 | %} 155 | %topts.SYM=true;topts.POSDEF=true; 156 | %[x2,Rf]=linsolve(S,bs,topts); 157 | %x2=S\bs; 158 | x1=invA11.*(b1-A12*x2); 159 | sx=[x1;x2]; 160 | end 161 | 162 | end 163 | 164 | -------------------------------------------------------------------------------- /Hou/utils/minDistortionMsk.m: -------------------------------------------------------------------------------- 1 | function [ Pxy,Dav,exitfg,iters] = minDistortionMsk(Px,Dxy,Hy) 2 | % Miniminze average distortion between stego-signal and cover-signal 3 | % 4 | % Input: 5 | % Px : cover-signal probability distribution 6 | % Dxy : distortion matrix 7 | % Hy : expected stego-signal entropy 8 | % 9 | % Output: 10 | % Pxy : conditional probability distribution Py|x 11 | % Dav : corresponding minimized distortion value 12 | % exitfg : exit flag: 0-->success -1-->invalid input 1-->failed 13 | % iters : number of iterations 14 | %%******************************************************************** 15 | % 16 | % author: Xiaocheng Hu 17 | % college: University of Science and Technology of China 18 | % date: 9/2/2012 19 | % 20 | %%********************************************************************* 21 | 22 | [m,n] = size(Dxy); 23 | % input validation 24 | % 25 | if ( abs(sum(Px)-1.0) > 1e-8 ) || (Hy > log(n)) || (Hy < -sum(Px.*log(Px))) 26 | Pxy=zeros(m,n);Dav=0;exitfg=-1; 27 | disp('minDistortionEmr invalid input!'); 28 | return; 29 | end 30 | %} 31 | 32 | % 33 | MPx = Px(:,ones(n,1));%repmat(Px,1,n); 34 | Dxy = MPx.*Dxy; 35 | 36 | %parameters 37 | MAXITERS = 300; 38 | Tol = 1e-8; 39 | NTTol = 1e-8; 40 | MU = 20; 41 | Alpha = 0.01; 42 | Beta = 0.6; 43 | 44 | % initialize x0 45 | x = zeros(n+m+1,1);%+1.0; 46 | x(1:n) = log(1/n)+1.0; 47 | x(n+1:n+m) = abs(x(1))+0.01; 48 | x(n+m+1) = 1.0; 49 | 50 | % initialize t0 with least square 51 | Mfx = Dxy+repmat(x(n+1:n+m),1,n)+Px*(x(1:n)'); 52 | fx = [Mfx(:);x(n+m+1)]; 53 | lA = [exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy]; 54 | lb = [(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 55 | t = (lA'*lb)/(lA'*lA); 56 | t = ceil(t); 57 | %t=1; 58 | 59 | % 60 | for iters=1:MAXITERS 61 | % calculate function value and it's gratitude 62 | val=t*(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1))-sum(log(fx)); 63 | grad=t*([exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy])-[(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 64 | 65 | 66 | %{ 67 | Hf0=[diag(exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)),zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2); ... 68 | zeros(m,m+n+1); ... 69 | -(exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2))',zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]; 70 | Hfx=[-diag(sum((MPx./Mfx).^2)) , -(MPx./(Mfx.^2))', zeros(n,1); ... 71 | -(MPx./(Mfx.^2)) , -diag(sum(1./(Mfx.^2),2)), zeros(m,1); ... 72 | zeros(1,n) , zeros(1,m) , -1/(x(n+m+1)^2)]; 73 | hess=t*Hf0-Hfx; 74 | Dx=-hess\grad; 75 | %} 76 | % Calculate Newton step, fast 77 | Dx=fast_linear_solver(t*exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)+(sum((MPx./Mfx).^2))', ... 78 | t*[zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2)]+[(MPx./(Mfx.^2))',zeros(n,1)], ... 79 | t*[zeros(m,m),zeros(m,1);zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]+[diag(sum(1./(Mfx.^2),2)),zeros(m,1);zeros(1,m),1/(x(n+m+1)^2)], ... 80 | -grad); 81 | fprime=grad'*Dx; 82 | 83 | % Solved Centering step and update t 84 | if( (-fprime < NTTol)) 85 | gap=(m*n+1)/t; 86 | 87 | % stopping criterion 88 | if( gap < Tol ),break;end; 89 | 90 | % update t and continue the next Centering step 91 | t=MU*t; 92 | continue; 93 | end 94 | 95 | % Backtracking step 1, ensure the domain of fx 96 | step=1; 97 | DMf=repmat(Dx(n+1:n+m),1,n)+Px*(Dx(1:n)');Dff=[DMf(:);Dx(n+m+1)]; 98 | while any((fx+step*Dff)<=0) 99 | step=Beta*step; 100 | end 101 | 102 | newx = x+step*Dx; 103 | newfx = fx+step*Dff; 104 | % Backtracking step 2, decrease fx sufficiently 105 | % 106 | while ( (t*(newx(n+m+1)*sum(exp(newx(1:n)/newx(n+m+1)-1))+sum(newx(n+1:n+m))-Hy*newx(n+m+1))-sum(log(newfx))) > (val+Alpha*step*fprime) ) 107 | step=Beta*step; 108 | newx=x+step*Dx; 109 | newfx=fx+step*Dff; 110 | end 111 | %} 112 | 113 | % update variables 114 | x = newx; 115 | fx = newfx; 116 | Mfx = Mfx+step*DMf; 117 | 118 | 119 | end 120 | 121 | % Output 122 | Py = exp(x(1:n)/x(n+m+1)-1); 123 | %Dav = -(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1)); 124 | Pxy = nonCrossEdge(Px,Py); 125 | %% linear optimization to get Pxy 126 | % A1 = zeros(n,m*n); 127 | % for ii=1:n 128 | % A1(ii,(ii-1)*m+1:ii*m) = Px'; 129 | % end 130 | % blc1 = Py; 131 | % buc1 = Py; 132 | % 133 | % A2 = zeros(m,m*n); 134 | % for ii=1:m 135 | % A2(ii,ii:m:m*n) = 1; 136 | % end 137 | % blc2 = ones(m,1); 138 | % buc2 = ones(m,1); 139 | % 140 | % c = Dxy(:); 141 | % A = [A1;A2]; 142 | % blc = [blc1;blc2]; 143 | % buc = [buc1;buc2]; 144 | % blx = zeros(m*n,1); 145 | % bux = ones(m*n,1); 146 | % 147 | % param = []; 148 | % param.MSK_IPAR_INTPNT_BASIS = 'MSK_BI_NO_ERROR'; 149 | % param.MSK_IPAR_BI_IGNORE_MAX_ITER = 'MSK_ON'; 150 | % param.MSK_IPAR_LOG = 0; 151 | % param.MSK_DPAR_INTPNT_NL_TOL_PFEAS = 1.0e-12; 152 | % param.MSK_DPAR_INTPNT_NL_TOL_DFEAS = 1.0e-12; 153 | % param.MSK_DPAR_INTPNT_NL_TOL_REL_GAP = 1.0e-12; 154 | % 155 | % [res] = msklpopt(c,A,blc,buc,blx,bux,param); 156 | % yy = res.sol.itr.xx; 157 | % yy(abs(yy)<=1e-6)=0;%-4 158 | % Pxy = reshape(yy,m,n); 159 | Dav = trace(Dxy*Pxy'); 160 | 161 | % check if success 162 | if( abs(sum(Py)-1.0) < 1e-8 ) 163 | exitfg=0; 164 | else 165 | exitfg=1; 166 | end 167 | fprintf('minDistortionEmr Iteration: %d\t Distortion: %f\t Sum of Py: %f\n',iters,Dav,sum(Py)); 168 | 169 | %% Block elimination method to solve linear equations 170 | function [sx]=fast_linear_solver(A11,A12,A22,b) 171 | [sn,sm]=size(A12); 172 | b1=b(1:sn); 173 | b2=b(sn+1:sn+sm); 174 | 175 | invA11=1./A11; 176 | Tm=repmat(invA11',sm,1).*(A12'); 177 | S=A22-Tm*A12; 178 | bs=b2-Tm*b1; 179 | % check if S is positive definite 180 | % 181 | [L,p]=chol(S,'lower'); 182 | if (p > 0) 183 | sx=zeros(sn+sm,1); 184 | return; 185 | end 186 | 187 | zz=L\bs; 188 | x2=L'\zz; 189 | %} 190 | %topts.SYM=true;topts.POSDEF=true; 191 | %[x2,Rf]=linsolve(S,bs,topts); 192 | %x2=S\bs; 193 | x1=invA11.*(b1-A12*x2); 194 | sx=[x1;x2]; 195 | end 196 | 197 | end 198 | 199 | -------------------------------------------------------------------------------- /Hou/utils/min_distortion_br.m: -------------------------------------------------------------------------------- 1 | function [ Py,ef,Dav] = min_distortion_br( Ps,Dsy,Hy ) 2 | % Miniminze average distortion between stego-signal and cover-signal 3 | % 4 | % Input: 5 | % Ps : cover-signal probability distribution 6 | % Dsy : distortion matrix 7 | % Hy : expected stego-signal entropy 8 | % 9 | % Output: 10 | % Py : stego-signal probability distribution 11 | % ef : exit flag: 0-->success -1-->invalid input 1-->failed 12 | % Dav : corresponding minimal distortion value 13 | 14 | % 15 | tic; 16 | 17 | % validation of Hy 18 | [m,n]=size(Dsy); 19 | if (Hy > log(n)) || (Hy < -sum(Ps.*log(Ps))) 20 | disp('invalid entropy input!'); 21 | Py=[]; 22 | Dav=0; 23 | ef=-1; 24 | return; 25 | end 26 | %} 27 | 28 | % 29 | MPs=repmat(Ps,1,n); 30 | Dsy=MPs.*Dsy; 31 | 32 | %parameters 33 | MAXITERS=200; 34 | Tol=1e-4; 35 | NTTol=1e-6; 36 | XTol=1e-4; 37 | MU=20; 38 | Alpha=0.01; 39 | Beta=0.6; 40 | 41 | % initialize x0 42 | x=zeros(n+m+1,1)+1.0; 43 | %x(1:n)=-1.0; 44 | x(1:n)=log(1/n)+1.0; 45 | x(n+1:n+m)=abs(x(1))+0.01; 46 | x(n+m+1)=1.0; 47 | 48 | % initialize t0 with least square 49 | Mfx=Dsy+repmat(x(n+1:n+m),1,n)+Ps*(x(1:n)'); 50 | fx=[Mfx(:);x(n+m+1)]; 51 | lA=[exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy]; 52 | lb=[(sum(MPs./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 53 | t=lA'*lb/(lA'*lA); 54 | t=ceil(t); 55 | %t=1; 56 | 57 | % initialize gap 58 | gap=1; 59 | step=1; 60 | % 61 | for iters=1:MAXITERS 62 | %assert(min(fx)>=0); 63 | iters; 64 | % calculate function value and it's gratitude 65 | val=t*(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1))-sum(log(fx)); 66 | grad=t*([exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy])-[(sum(MPs./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 67 | 68 | 69 | %{ 70 | Hf0=[diag(exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)),zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2); ... 71 | zeros(m,m+n+1); ... 72 | -(exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2))',zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]; 73 | Hfx=[-diag(sum((MPs./Mfx).^2)) , -(MPs./(Mfx.^2))', zeros(n,1); ... 74 | -(MPs./(Mfx.^2)) , -diag(sum(1./(Mfx.^2),2)), zeros(m,1); ... 75 | zeros(1,n) , zeros(1,m) , -1/(x(n+m+1)^2)]; 76 | hess=t*Hf0-Hfx; 77 | %Dx=-hess\grad; 78 | %} 79 | % Calculate Newton step 80 | Dx=fast_linear_solver(t*exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)+(sum((MPs./Mfx).^2))', ... 81 | t*[zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2)]+[(MPs./(Mfx.^2))',zeros(n,1)], ... 82 | t*[zeros(m,m),zeros(m,1);zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]+[diag(sum(1./(Mfx.^2),2)),zeros(m,1);zeros(1,m),1/(x(n+m+1)^2)], ... 83 | -grad); 84 | fprime=grad'*Dx; 85 | %if(~fprime),break;end; 86 | %assert(fprime<=0); 87 | 88 | % Solved Centering step and update t 89 | if( (-fprime < NTTol) || (step) < XTol) 90 | step=1; 91 | gap=(m*n+1)/t; 92 | 93 | % stopping criterion 94 | if( gap < Tol ),break;end; 95 | 96 | % update t and continue the next Centering step 97 | t=MU*t; 98 | continue; 99 | end 100 | 101 | % Backtracking step 1, ensure the domain of fx 102 | step=1; 103 | DMf=repmat(Dx(n+1:n+m),1,n)+Ps*(Dx(1:n)');Dff=[DMf(:);Dx(n+m+1)]; 104 | while (min(fx+step*Dff)<=0) 105 | step=Beta*step; 106 | end 107 | 108 | % Backtracking step 2, decrease fx sufficiently 109 | newx=x+step*Dx; 110 | newfx=fx+step*Dff; 111 | %newfx=Dsy+repmat(newx(n+1:n+m),1,n)+Ps*(newx(1:n)');newfx=[newfx(:);newx(n+m+1)]; 112 | while ( (t*(newx(n+m+1)*sum(exp(newx(1:n)/newx(n+m+1)-1))+sum(newx(n+1:n+m))-Hy*newx(n+m+1))-sum(log(newfx))) > (val+Alpha*step*fprime) ) 113 | step=Beta*step; 114 | newx=x+step*Dx; 115 | newfx=fx+step*Dff; 116 | %newfx=Dsy+repmat(newx(n+1:n+m),1,n)+Ps*(newx(1:n)');newfx=[newfx(:);newx(n+m+1)]; 117 | end 118 | %} 119 | step; 120 | 121 | % update variables 122 | x=newx; 123 | fx=newfx; 124 | Mfx=Mfx+step*DMf; 125 | 126 | 127 | end 128 | 129 | % 130 | Py=exp(x(1:n)/x(n+m+1)-1); 131 | if( abs(sum(Py)-1.0) < 1e-8 ) 132 | ef=0; 133 | else 134 | ef=1; 135 | end 136 | Dav=-(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1)); 137 | fprintf('min_distortion_br: #iter %d #gap %f #time(s) %f\n',iters,gap,toc); 138 | 139 | 140 | % Block elimination method to solve linear equations 141 | function [sx]=fast_linear_solver(A11,A12,A22,b) 142 | [sn,sm]=size(A12); 143 | b1=b(1:sn); 144 | b2=b(sn+1:sn+sm); 145 | 146 | invA11=1./A11; 147 | Tm=repmat(invA11',sm,1).*(A12'); 148 | S=A22-Tm*A12; 149 | % check if S is positive definite 150 | % 151 | [L,p]=chol(S,'lower'); 152 | if (p > 0) 153 | sx=zeros(sn+sm,1); 154 | return; 155 | end 156 | %} 157 | 158 | bs=b2-Tm*b1; 159 | zz=L\bs; 160 | x2=L'\zz; 161 | %topts.SYM=true;topts.POSDEF=true; 162 | %[x2,Rf]=linsolve(S,bs,topts); 163 | %x2=S\bs; 164 | %x2=pinv(S)*bs; 165 | x1=invA11.*(b1-A12*x2); 166 | sx=[x1;x2]; 167 | end 168 | 169 | end 170 | 171 | -------------------------------------------------------------------------------- /Hou/utils/nonCrossEdge.m: -------------------------------------------------------------------------------- 1 | function [Qxy,Qyx]=nonCrossEdge(Px,Py) 2 | 3 | m = length(Px); 4 | CPx = zeros(m+1,1); 5 | for i=1:m 6 | CPx(i+1)=CPx(i)+Px(i); 7 | end 8 | 9 | n = length(Py); 10 | CPy = zeros(n+1,1); 11 | for i=1:n 12 | CPy(i+1)=CPy(i)+Py(i); 13 | end 14 | 15 | Qxy = zeros(m,n); 16 | Qyx = zeros(m,n); 17 | for x=0:(m-1) 18 | for y=0:(n-1) 19 | jval = max(0,min(CPx(x+2),CPy(y+2))-max(CPx(x+1),CPy(y+1))); 20 | 21 | Qxy(x+1,y+1)= jval/(Px(x+1)+eps); 22 | Qyx(x+1,y+1)= jval/(Py(y+1)+eps); 23 | end 24 | end 25 | Qyx=Qyx'; 26 | 27 | end -------------------------------------------------------------------------------- /Hou/utils/recursiveConstruct.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou/utils/recursiveConstruct.m -------------------------------------------------------------------------------- /Hou_Improved/IDCT.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/IDCT.m -------------------------------------------------------------------------------- /Hou_Improved/Ori_photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/Ori_photo.jpg -------------------------------------------------------------------------------- /Hou_Improved/SSIM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/SSIM.m -------------------------------------------------------------------------------- /Hou_Improved/Stego/QF30/1.pgm_2000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/Stego/QF30/1.pgm_2000.jpg -------------------------------------------------------------------------------- /Hou_Improved/appraise.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/appraise.m -------------------------------------------------------------------------------- /Hou_Improved/costFun.m: -------------------------------------------------------------------------------- 1 | function Q_cost=costFun(Q) 2 | [m,n]=size(Q); 3 | Q_cost=zeros(m,n,63); 4 | id=0; 5 | for i=1:8 6 | for j=1:8 7 | if (i+j)~=2 8 | Diff=zeros(8,8); 9 | Diff(i,j)=1; 10 | temp=IDCT(Q.*Diff); 11 | id=id+1; 12 | Q_cost(:,:,id)=temp;%sqrt(temp/64); 13 | end 14 | end 15 | end 16 | 17 | end -------------------------------------------------------------------------------- /Hou_Improved/countDCT.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/countDCT.m -------------------------------------------------------------------------------- /Hou_Improved/debug_main.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/debug_main.m -------------------------------------------------------------------------------- /Hou_Improved/generate_stego.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/generate_stego.m -------------------------------------------------------------------------------- /Hou_Improved/get63bin.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/get63bin.m -------------------------------------------------------------------------------- /Hou_Improved/get_psnring.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/get_psnring.m -------------------------------------------------------------------------------- /Hou_Improved/getcodelength.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/getcodelength.m -------------------------------------------------------------------------------- /Hou_Improved/getpayload.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/getpayload.m -------------------------------------------------------------------------------- /Hou_Improved/getuintcost63bin.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/getuintcost63bin.m -------------------------------------------------------------------------------- /Hou_Improved/jpeg_emdding.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpeg_emdding.m -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_read.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jpeg_read.c 3 | * 4 | * JPEGOBJ = JPEG_READ(FILENAME) 5 | * 6 | * Returns JPEGOBJ, a Matlab struct containing the JPEG header information, 7 | * quantization tables, and the DCT coefficients. 8 | * 9 | * This software is based in part on the work of the Independent JPEG Group. 10 | * In order to compile, you must first build IJG's JPEG Tools code library, 11 | * available at ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. 12 | * 13 | * Phil Sallee 6/2003 14 | * 15 | * Copyright (c) 2003 The Regents of the University of California. 16 | * All Rights Reserved. 17 | * 18 | * Permission to use, copy, modify, and distribute this software and its 19 | * documentation for educational, research and non-profit purposes, 20 | * without fee, and without a written agreement is hereby granted, 21 | * provided that the above copyright notice, this paragraph and the 22 | * following three paragraphs appear in all copies. 23 | * 24 | * Permission to incorporate this software into commercial products may 25 | * be obtained by contacting the University of California. Contact Jo Clare 26 | * Peterman, University of California, 428 Mrak Hall, Davis, CA, 95616. 27 | * 28 | * This software program and documentation are copyrighted by The Regents 29 | * of the University of California. The software program and 30 | * documentation are supplied "as is", without any accompanying services 31 | * from The Regents. The Regents does not warrant that the operation of 32 | * the program will be uninterrupted or error-free. The end-user 33 | * understands that the program was developed for research purposes and 34 | * is advised not to rely exclusively on the program for any reason. 35 | * 36 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 37 | * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, 38 | * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND 39 | * ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN 40 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF 41 | * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 42 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 | * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 44 | * BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE 45 | * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 46 | * 47 | */ 48 | 49 | 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include "mex.h" 56 | 57 | 58 | /* We need to create our own error handler so that we can override the 59 | * default handler in case a fatal error occurs. The standard error_exit 60 | * method calls exit() which doesn't clean things up properly and also 61 | * exits Matlab. This is described in the example.c routine provided in 62 | * the IJG's code library. 63 | */ 64 | struct my_error_mgr { 65 | struct jpeg_error_mgr pub; /* "public" fields */ 66 | jmp_buf setjmp_buffer; /* for return to caller */ 67 | }; 68 | 69 | 70 | /* The default output_message routine causes a seg fault in Matlab, 71 | * at least on Windows. Its generally used to emit warnings, since 72 | * fatal errors call the error_exit routine, so we emit a Matlab 73 | * warning instead. If desired, warnings can be turned off by the 74 | * user with "warnings off". -- PAS 10/03 75 | */ 76 | METHODDEF(void) 77 | my_output_message (j_common_ptr cinfo) 78 | { 79 | char buffer[JMSG_LENGTH_MAX]; 80 | 81 | /* Create the message */ 82 | (*cinfo->err->format_message) (cinfo, buffer); 83 | 84 | mexWarnMsgTxt(buffer); 85 | } 86 | 87 | typedef struct my_error_mgr * my_error_ptr; 88 | 89 | METHODDEF(void) 90 | my_error_exit (j_common_ptr cinfo) 91 | { 92 | char buffer[JMSG_LENGTH_MAX]; 93 | 94 | /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ 95 | my_error_ptr myerr = (my_error_ptr) cinfo->err; 96 | 97 | /* create the message */ 98 | (*cinfo->err->format_message) (cinfo, buffer); 99 | printf("Error: %s\n",buffer); 100 | 101 | /* return control to the setjmp point */ 102 | longjmp(myerr->setjmp_buffer, 1); 103 | } 104 | 105 | 106 | /* Substitute for mxCreateDoubleScalar, which is not available 107 | * on earlier versions of Matlab */ 108 | mxArray *mxCDS(double val) { 109 | mxArray *mxtemp; 110 | double *p; 111 | 112 | mxtemp = mxCreateDoubleMatrix(1, 1, mxREAL); 113 | p = mxGetPr(mxtemp); 114 | *p = val; 115 | 116 | return mxtemp; 117 | } 118 | 119 | 120 | /* mex function */ 121 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 122 | { 123 | struct jpeg_decompress_struct cinfo; 124 | struct my_error_mgr jerr; 125 | jpeg_component_info *compptr; 126 | jvirt_barray_ptr *coef_arrays; 127 | jpeg_saved_marker_ptr marker_ptr; 128 | FILE *infile; 129 | JDIMENSION blk_x,blk_y; 130 | JBLOCKARRAY buffer; 131 | JCOEFPTR bufptr; 132 | JQUANT_TBL *quant_ptr; 133 | JHUFF_TBL *huff_ptr; 134 | int strlen, c_width, c_height, ci, i, j, n, dims[2]; 135 | char *filename; 136 | double *mp, *mptop; 137 | mxChar *mcp; 138 | mxArray *mxtemp, *mxjpeg_obj, *mxcoef_arrays, *mxcomments; 139 | mxArray *mxquant_tables, *mxhuff_tables, *mxcomp_info; 140 | 141 | /* field names jpeg_obj Matlab struct */ 142 | const char *jobj_field_names[] = { 143 | "image_width", /* image width in pixels */ 144 | "image_height", /* image height in pixels */ 145 | "image_components", /* number of image color components */ 146 | "image_color_space", /* in/out_color_space */ 147 | "jpeg_components", /* number of JPEG color components */ 148 | "jpeg_color_space", /* color space of DCT coefficients */ 149 | "comments", /* COM markers, if any */ 150 | "coef_arrays", /* DCT arrays for each component */ 151 | "quant_tables", /* quantization tables */ 152 | "ac_huff_tables", /* AC huffman encoding tables */ 153 | "dc_huff_tables", /* DC huffman encoding tables */ 154 | "optimize_coding", /* flag to optimize huffman tables */ 155 | "comp_info", /* component info struct array */ 156 | "progressive_mode", /* is progressive mode */ 157 | }; 158 | const int num_jobj_fields = 14; 159 | 160 | /* field names comp_info struct */ 161 | const char *comp_field_names[] = { 162 | "component_id", /* JPEG one byte identifier code */ 163 | "h_samp_factor", /* horizontal sampling factor */ 164 | "v_samp_factor", /* vertical sampling factor */ 165 | "quant_tbl_no", /* quantization table number for component */ 166 | "dc_tbl_no", /* DC entropy coding table number */ 167 | "ac_tbl_no" /* AC entropy encoding table number */ 168 | }; 169 | const int num_comp_fields = 6; 170 | 171 | const char *huff_field_names[] = {"counts","symbols"}; 172 | 173 | /* check input value */ 174 | if (nrhs != 1) mexErrMsgTxt("One input argument required."); 175 | if (mxIsChar(prhs[0]) != 1) 176 | mexErrMsgTxt("Filename must be a string"); 177 | 178 | /* check output return jpegobj struct */ 179 | if (nlhs > 1) mexErrMsgTxt("Too many output arguments"); 180 | 181 | /* get filename */ 182 | strlen = mxGetM(prhs[0])*mxGetN(prhs[0]) + 1; 183 | filename = mxCalloc(strlen, sizeof(char)); 184 | mxGetString(prhs[0],filename,strlen); 185 | 186 | /* open file */ 187 | if ((infile = fopen(filename, "rb")) == NULL) 188 | mexErrMsgTxt("Can't open file"); 189 | 190 | /* set up the normal JPEG error routines, then override error_exit. */ 191 | cinfo.err = jpeg_std_error(&jerr.pub); 192 | jerr.pub.error_exit = my_error_exit; 193 | jerr.pub.output_message = my_output_message; 194 | 195 | /* establish the setjmp return context for my_error_exit to use. */ 196 | if (setjmp(jerr.setjmp_buffer)) { 197 | jpeg_destroy_decompress(&cinfo); 198 | fclose(infile); 199 | mexErrMsgTxt("Error reading file"); 200 | } 201 | 202 | /* initialize JPEG decompression object */ 203 | jpeg_create_decompress(&cinfo); 204 | jpeg_stdio_src(&cinfo, infile); 205 | 206 | /* save contents of markers */ 207 | jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF); 208 | 209 | /* read header and coefficients */ 210 | jpeg_read_header(&cinfo, TRUE); 211 | 212 | /* create Matlab jpegobj struct */ 213 | mxjpeg_obj = mxCreateStructMatrix(1,1,num_jobj_fields,jobj_field_names); 214 | 215 | /* for some reason out_color_components isn't being set by 216 | jpeg_read_header, so we will infer it from out_color_space: */ 217 | switch (cinfo.out_color_space) { 218 | case JCS_GRAYSCALE: 219 | cinfo.out_color_components = 1; 220 | break; 221 | case JCS_RGB: 222 | cinfo.out_color_components = 3; 223 | break; 224 | case JCS_YCbCr: 225 | cinfo.out_color_components = 3; 226 | break; 227 | case JCS_CMYK: 228 | cinfo.out_color_components = 4; 229 | break; 230 | case JCS_YCCK: 231 | cinfo.out_color_components = 4; 232 | break; 233 | } 234 | 235 | /* copy header information */ 236 | mxSetField(mxjpeg_obj,0,"image_width", 237 | mxCDS(cinfo.image_width)); 238 | mxSetField(mxjpeg_obj,0,"image_height", 239 | mxCDS(cinfo.image_height)); 240 | mxSetField(mxjpeg_obj,0,"image_color_space", 241 | mxCDS(cinfo.out_color_space)); 242 | mxSetField(mxjpeg_obj,0,"image_components", 243 | mxCDS(cinfo.out_color_components)); 244 | mxSetField(mxjpeg_obj,0,"jpeg_color_space", 245 | mxCDS(cinfo.jpeg_color_space)); 246 | mxSetField(mxjpeg_obj,0,"jpeg_components", 247 | mxCDS(cinfo.num_components)); 248 | mxSetField(mxjpeg_obj,0,"progressive_mode", 249 | mxCDS(cinfo.progressive_mode)); 250 | 251 | /* set optimize_coding flag for jpeg_write() */ 252 | mxSetField(mxjpeg_obj,0,"optimize_coding",mxCDS(FALSE)); 253 | 254 | /* copy component information */ 255 | mxcomp_info = mxCreateStructMatrix(1,cinfo.num_components, 256 | num_comp_fields,comp_field_names); 257 | mxSetField(mxjpeg_obj,0,"comp_info",mxcomp_info); 258 | for (ci = 0; ci < cinfo.num_components; ci++) { 259 | mxSetField(mxcomp_info,ci,"component_id", 260 | mxCDS(cinfo.comp_info[ci].component_id)); 261 | mxSetField(mxcomp_info,ci,"h_samp_factor", 262 | mxCDS(cinfo.comp_info[ci].h_samp_factor)); 263 | mxSetField(mxcomp_info,ci,"v_samp_factor", 264 | mxCDS(cinfo.comp_info[ci].v_samp_factor)); 265 | mxSetField(mxcomp_info,ci,"quant_tbl_no", 266 | mxCDS(cinfo.comp_info[ci].quant_tbl_no+1)); 267 | mxSetField(mxcomp_info,ci,"ac_tbl_no", 268 | mxCDS(cinfo.comp_info[ci].ac_tbl_no+1)); 269 | mxSetField(mxcomp_info,ci,"dc_tbl_no", 270 | mxCDS(cinfo.comp_info[ci].dc_tbl_no+1)); 271 | } 272 | 273 | /* copy markers */ 274 | mxcomments = mxCreateCellMatrix(0,0); 275 | mxSetField(mxjpeg_obj,0,"comments",mxcomments); 276 | marker_ptr = cinfo.marker_list; 277 | while (marker_ptr != NULL) { 278 | switch (marker_ptr->marker) { 279 | case JPEG_COM: 280 | /* this comment index */ 281 | n = mxGetN(mxcomments); 282 | 283 | /* allocate space in cell array for a new comment */ 284 | mxSetPr(mxcomments,mxRealloc(mxGetPr(mxcomments), 285 | (n+1)*mxGetElementSize(mxcomments))); 286 | mxSetM(mxcomments,1); 287 | mxSetN(mxcomments,n+1); 288 | 289 | /* create new char array to store comment string */ 290 | dims[0] = 1; 291 | dims[1] = marker_ptr->data_length; 292 | mxtemp = mxCreateCharArray(2,dims); 293 | mxSetCell(mxcomments,n,mxtemp); 294 | mcp = (mxChar *) mxGetPr(mxtemp); 295 | 296 | /* copy comment string to char array */ 297 | for (i = 0; i < (int) marker_ptr->data_length; i++) 298 | *mcp++ = (mxChar) marker_ptr->data[i]; 299 | 300 | break; 301 | default: 302 | break; 303 | } 304 | marker_ptr = marker_ptr->next; 305 | } 306 | 307 | /* copy the quantization tables */ 308 | mxquant_tables = mxCreateCellMatrix(1,NUM_QUANT_TBLS); 309 | mxSetField(mxjpeg_obj,0,"quant_tables",mxquant_tables); 310 | mxSetN(mxquant_tables, 0); 311 | for (n = 0; n < NUM_QUANT_TBLS; n++) { 312 | if (cinfo.quant_tbl_ptrs[n] != NULL) { 313 | mxSetN(mxquant_tables, n+1); 314 | mxtemp = mxCreateDoubleMatrix(DCTSIZE, DCTSIZE, mxREAL); 315 | mxSetCell(mxquant_tables,n,mxtemp); 316 | mp = mxGetPr(mxtemp); 317 | quant_ptr = cinfo.quant_tbl_ptrs[n]; 318 | for (i = 0; i < DCTSIZE; i++) 319 | for (j = 0; j < DCTSIZE; j++) 320 | mp[j*DCTSIZE+i] = (double) quant_ptr->quantval[i*DCTSIZE+j]; 321 | } 322 | } 323 | 324 | /* copy the AC huffman tables */ 325 | mxhuff_tables = mxCreateStructMatrix(1,NUM_HUFF_TBLS,2,huff_field_names); 326 | mxSetField(mxjpeg_obj,0,"ac_huff_tables",mxhuff_tables); 327 | mxSetN(mxhuff_tables, 0); 328 | for (n = 0; n < NUM_HUFF_TBLS; n++) { 329 | if (cinfo.ac_huff_tbl_ptrs[n] != NULL) { 330 | huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; 331 | mxSetN(mxhuff_tables, n+1); 332 | 333 | mxtemp = mxCreateDoubleMatrix(1, 16, mxREAL); 334 | mxSetField(mxhuff_tables,n,"counts",mxtemp); 335 | mp = mxGetPr(mxtemp); 336 | for (i = 1; i <= 16; i++) *mp++ = huff_ptr->bits[i]; 337 | 338 | mxtemp = mxCreateDoubleMatrix(1, 256, mxREAL); 339 | mxSetField(mxhuff_tables,n,"symbols",mxtemp); 340 | mp = mxGetPr(mxtemp); 341 | for (i = 0; i < 256; i++) *mp++ = huff_ptr->huffval[i]; 342 | } 343 | } 344 | 345 | /* copy the DC huffman tables */ 346 | mxhuff_tables = mxCreateStructMatrix(1,NUM_HUFF_TBLS,2,huff_field_names); 347 | mxSetField(mxjpeg_obj,0,"dc_huff_tables",mxhuff_tables); 348 | mxSetN(mxhuff_tables, 0); 349 | for (n = 0; n < NUM_HUFF_TBLS; n++) { 350 | if (cinfo.dc_huff_tbl_ptrs[n] != NULL) { 351 | huff_ptr = cinfo.dc_huff_tbl_ptrs[n]; 352 | mxSetN(mxhuff_tables, n+1); 353 | 354 | mxtemp = mxCreateDoubleMatrix(1, 16, mxREAL); 355 | mxSetField(mxhuff_tables,n,"counts",mxtemp); 356 | mp = mxGetPr(mxtemp); 357 | for (i = 1; i <= 16; i++) *mp++ = huff_ptr->bits[i]; 358 | 359 | mxtemp = mxCreateDoubleMatrix(1, 256, mxREAL); 360 | mxSetField(mxhuff_tables,n,"symbols",mxtemp); 361 | mp = mxGetPr(mxtemp); 362 | for (i = 0; i < 256; i++) *mp++ = huff_ptr->huffval[i]; 363 | } 364 | } 365 | 366 | /* creation and population of the DCT coefficient arrays */ 367 | coef_arrays = jpeg_read_coefficients(&cinfo); 368 | mxcoef_arrays = mxCreateCellMatrix(1,cinfo.num_components); 369 | mxSetField(mxjpeg_obj,0,"coef_arrays",mxcoef_arrays); 370 | for (ci = 0; ci < cinfo.num_components; ci++) { 371 | compptr = cinfo.comp_info + ci; 372 | c_height = compptr->height_in_blocks * DCTSIZE; 373 | c_width = compptr->width_in_blocks * DCTSIZE; 374 | 375 | /* create Matlab dct block array for this component */ 376 | mxtemp = mxCreateDoubleMatrix(c_height, c_width, mxREAL); 377 | mxSetCell(mxcoef_arrays,ci,mxtemp); 378 | mp = mxGetPr(mxtemp); 379 | mptop = mp; 380 | 381 | /* copy coefficients from virtual block arrays */ 382 | for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y++) { 383 | buffer = (cinfo.mem->access_virt_barray) 384 | ((j_common_ptr) &cinfo, coef_arrays[ci], blk_y, 1, FALSE); 385 | for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { 386 | bufptr = buffer[0][blk_x]; 387 | for (i = 0; i < DCTSIZE; i++) /* for each row in block */ 388 | for (j = 0; j < DCTSIZE; j++) /* for each column in block */ 389 | mp[j*c_height+i] = (double) bufptr[i*DCTSIZE+j]; 390 | mp+=DCTSIZE*c_height; 391 | } 392 | mp=(mptop+=DCTSIZE); 393 | } 394 | } 395 | 396 | /* done with cinfo */ 397 | jpeg_finish_decompress(&cinfo); 398 | jpeg_destroy_decompress(&cinfo); 399 | 400 | /* close input file */ 401 | fclose(infile); 402 | 403 | /* set output */ 404 | if (nlhs == 1) plhs[0] = mxjpeg_obj; 405 | 406 | } 407 | -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_read.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_read.mexa64 -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_read.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_read.mexglx -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_read.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_read.mexw32 -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_read.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_read.mexw64 -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_write.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jpeg_write.c 3 | * 4 | * JPEG_WRITE(JPEGOBJ,FILENAME) 5 | * 6 | * Reads JPEGOBJ, a Matlab struct containing the JPEG header, 7 | * quantization tables and the DCT coefficients (as returned by JPEG_READ), 8 | * and writes the information into a JPEG file with the name FILENAME. 9 | * 10 | * This software is based in part on the work of the Independent JPEG Group. 11 | * In order to compile, you must first build IJG's JPEG Tools code library, 12 | * available at ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. 13 | * 14 | * Phil Sallee, Surya De 6/2003 15 | * 16 | * Copyright (c) 2003 The Regents of the University of California. 17 | * All Rights Reserved. 18 | * 19 | * Permission to use, copy, modify, and distribute this software and its 20 | * documentation for educational, research and non-profit purposes, 21 | * without fee, and without a written agreement is hereby granted, 22 | * provided that the above copyright notice, this paragraph and the 23 | * following three paragraphs appear in all copies. 24 | * 25 | * Permission to incorporate this software into commercial products may 26 | * be obtained by contacting the University of California. Contact Jo Clare 27 | * Peterman, University of California, 428 Mrak Hall, Davis, CA, 95616. 28 | * 29 | * This software program and documentation are copyrighted by The Regents 30 | * of the University of California. The software program and 31 | * documentation are supplied "as is", without any accompanying services 32 | * from The Regents. The Regents does not warrant that the operation of 33 | * the program will be uninterrupted or error-free. The end-user 34 | * understands that the program was developed for research purposes and 35 | * is advised not to rely exclusively on the program for any reason. 36 | * 37 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 38 | * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, 39 | * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND 40 | * ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN 41 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF 42 | * CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 43 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 44 | * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 45 | * BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE 46 | * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 47 | * 48 | */ 49 | 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include "mex.h" 58 | 59 | 60 | /* We need to create our own error handler so that we can override the 61 | * default handler in case a fatal error occurs. The standard error_exit 62 | * method calls exit() which doesn't clean things up properly and also 63 | * exits Matlab. This is described in the example.c routine provided in 64 | * the IJG's code library. 65 | */ 66 | struct my_error_mgr { 67 | struct jpeg_error_mgr pub; /* "public" fields */ 68 | jmp_buf setjmp_buffer; /* for return to caller */ 69 | }; 70 | 71 | /* The default output_message routine causes a seg fault in Matlab, 72 | * at least on Windows. Its generally used to emit warnings, since 73 | * fatal errors call the error_exit routine, so we emit a Matlab 74 | * warning instead. If desired, warnings can be turned off by the 75 | * user with "warnings off". -- PAS 10/03 76 | */ 77 | METHODDEF(void) 78 | my_output_message (j_common_ptr cinfo) 79 | { 80 | char buffer[JMSG_LENGTH_MAX]; 81 | 82 | /* Create the message */ 83 | (*cinfo->err->format_message) (cinfo, buffer); 84 | 85 | mexWarnMsgTxt(buffer); 86 | } 87 | 88 | typedef struct my_error_mgr * my_error_ptr; 89 | 90 | METHODDEF(void) 91 | my_error_exit (j_common_ptr cinfo) 92 | { 93 | char buffer[JMSG_LENGTH_MAX]; 94 | 95 | /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ 96 | my_error_ptr myerr = (my_error_ptr) cinfo->err; 97 | 98 | /* create the message */ 99 | (*cinfo->err->format_message) (cinfo, buffer); 100 | printf("Error: %s\n",buffer); 101 | 102 | /* return control to the setjmp point */ 103 | longjmp(myerr->setjmp_buffer, 1); 104 | } 105 | 106 | 107 | /* mex function */ 108 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 109 | { 110 | struct jpeg_compress_struct cinfo; 111 | struct my_error_mgr jerr; 112 | const mxArray *mxjpeg_obj; 113 | mxArray *mxcoef_arrays,*mxhuff_tables,*mxcomp_info,*mxtemp, 114 | *mxquant_tables,*mxcomments; 115 | char *filename,*comment; 116 | int strlen,c_height,c_width,ci,i,j,n,t; 117 | FILE *outfile; 118 | jvirt_barray_ptr *coef_arrays = NULL; 119 | jpeg_component_info *compptr; 120 | JDIMENSION blk_x,blk_y; 121 | JBLOCKARRAY buffer; 122 | JCOEFPTR bufptr; 123 | double *mp, *mptop; 124 | 125 | /* check the input values */ 126 | if (nrhs != 2) mexErrMsgTxt("Two input arguments required."); 127 | 128 | /* check the output values */ 129 | if (nlhs != 0) mexErrMsgTxt("Too many output arguments."); 130 | if (mxIsChar(prhs[1]) != 1) mexErrMsgTxt("Filename must be a string."); 131 | 132 | /* get filename */ 133 | strlen = mxGetM(prhs[1])*mxGetN(prhs[1]) + 1; 134 | filename = mxCalloc(strlen, sizeof(char)); 135 | mxGetString(prhs[1],filename,strlen); 136 | 137 | /* open the output file*/ 138 | if ((outfile = fopen(filename, "wb")) == NULL) 139 | mexErrMsgTxt("Can't open file."); 140 | 141 | /* set up the normal JPEG error routines, then override error_exit. */ 142 | cinfo.err = jpeg_std_error(&jerr.pub); 143 | jerr.pub.error_exit = my_error_exit; 144 | jerr.pub.output_message = my_output_message; 145 | 146 | /* establish the setjmp return context for my_error_exit to use. */ 147 | if (setjmp(jerr.setjmp_buffer)) 148 | { 149 | jpeg_destroy_compress(&cinfo); 150 | fclose(outfile); 151 | mexErrMsgTxt("Error writing to file."); 152 | } 153 | 154 | /* set the input */ 155 | mxjpeg_obj = prhs[0]; 156 | 157 | /* initialize JPEG decompression object */ 158 | jpeg_create_compress(&cinfo); 159 | 160 | /* write the output file */ 161 | jpeg_stdio_dest(&cinfo, outfile); 162 | 163 | /* Set the compression object with our parameters */ 164 | cinfo.image_width = 165 | (unsigned int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_width")); 166 | cinfo.image_height = 167 | (unsigned int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_height")); 168 | cinfo.input_components = 169 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_components")); 170 | cinfo.in_color_space = 171 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"image_color_space")); 172 | 173 | /* set the compression object with default parameters */ 174 | jpeg_set_defaults(&cinfo); 175 | 176 | cinfo.optimize_coding = 177 | (unsigned char) mxGetScalar(mxGetField(mxjpeg_obj,0,"optimize_coding")); 178 | cinfo.num_components = 179 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"jpeg_components")); 180 | cinfo.jpeg_color_space = 181 | (int) mxGetScalar(mxGetField(mxjpeg_obj,0,"jpeg_color_space")); 182 | 183 | /* basic support for writing progressive mode JPEG */ 184 | if (mxGetField(mxjpeg_obj,0,"progressive_mode")) { 185 | if ((int) mxGetScalar(mxGetField(mxjpeg_obj,0,"progressive_mode"))) 186 | jpeg_simple_progression(&cinfo); 187 | } 188 | 189 | /* obtain the component array from the jpeg object */ 190 | mxcomp_info = mxGetField(mxjpeg_obj,0,"comp_info"); 191 | 192 | /* copy component information into cinfo from jpeg_obj*/ 193 | for (ci = 0; ci < cinfo.num_components; ci++) 194 | { 195 | cinfo.comp_info[ci].component_id = 196 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"component_id")); 197 | cinfo.comp_info[ci].h_samp_factor = 198 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"h_samp_factor")); 199 | cinfo.comp_info[ci].v_samp_factor = 200 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"v_samp_factor")); 201 | cinfo.comp_info[ci].quant_tbl_no = 202 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"quant_tbl_no"))-1; 203 | cinfo.comp_info[ci].ac_tbl_no = 204 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"ac_tbl_no"))-1; 205 | cinfo.comp_info[ci].dc_tbl_no = 206 | (int) mxGetScalar(mxGetField(mxcomp_info,ci,"dc_tbl_no"))-1; 207 | } 208 | 209 | 210 | /* request virtual block arrays */ 211 | mxcoef_arrays = mxGetField(mxjpeg_obj, 0, "coef_arrays"); 212 | coef_arrays = (jvirt_barray_ptr *) 213 | (cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_IMAGE, 214 | sizeof(jvirt_barray_ptr) * cinfo.num_components); 215 | for (ci = 0; ci < cinfo.num_components; ci++) 216 | { 217 | compptr = cinfo.comp_info + ci; 218 | 219 | c_height = mxGetM(mxGetCell(mxcoef_arrays,ci)); 220 | c_width = mxGetN(mxGetCell(mxcoef_arrays,ci)); 221 | compptr->height_in_blocks = c_height / DCTSIZE; 222 | compptr->width_in_blocks = c_width / DCTSIZE; 223 | 224 | coef_arrays[ci] = (cinfo.mem->request_virt_barray) 225 | ((j_common_ptr) &cinfo, JPOOL_IMAGE, TRUE, 226 | (JDIMENSION) jround_up((long) compptr->width_in_blocks, 227 | (long) compptr->h_samp_factor), 228 | (JDIMENSION) jround_up((long) compptr->height_in_blocks, 229 | (long) compptr->v_samp_factor), 230 | (JDIMENSION) compptr->v_samp_factor); 231 | } 232 | 233 | 234 | /* realize virtual block arrays */ 235 | jpeg_write_coefficients(&cinfo,coef_arrays); 236 | 237 | /* populate the array with the DCT coefficients */ 238 | for (ci = 0; ci < cinfo.num_components; ci++) 239 | { 240 | compptr = cinfo.comp_info + ci; 241 | 242 | /* Get a pointer to the mx coefficient array */ 243 | mxtemp = mxGetCell(mxcoef_arrays,ci); 244 | mp = mxGetPr(mxtemp); 245 | mptop = mp; 246 | 247 | c_height = mxGetM(mxtemp); 248 | c_width = mxGetN(mxtemp); 249 | 250 | /* Copy coefficients to virtual block arrays */ 251 | for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y++) 252 | { 253 | buffer = (cinfo.mem->access_virt_barray) 254 | ((j_common_ptr) &cinfo, coef_arrays[ci], blk_y, 1, TRUE); 255 | 256 | for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) 257 | { 258 | bufptr = buffer[0][blk_x]; 259 | for (i = 0; i < DCTSIZE; i++) /* for each row in block */ 260 | for (j = 0; j < DCTSIZE; j++) /* for each column in block */ 261 | bufptr[i*DCTSIZE+j] = (JCOEF) mp[j*c_height+i]; 262 | mp+=DCTSIZE*c_height; 263 | } 264 | mp=(mptop+=DCTSIZE); 265 | } 266 | } 267 | 268 | /* get the quantization tables */ 269 | mxquant_tables = mxGetField(mxjpeg_obj,0,"quant_tables"); 270 | for (n = 0; n < mxGetN(mxquant_tables); n++) 271 | { 272 | if (cinfo.quant_tbl_ptrs[n] == NULL) 273 | cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo); 274 | 275 | /* Fill the table */ 276 | mxtemp = mxGetCell(mxquant_tables,n); 277 | mp = mxGetPr(mxtemp); 278 | for (i = 0; i < DCTSIZE; i++) 279 | for (j = 0; j < DCTSIZE; j++) { 280 | t = mp[j*DCTSIZE+i]; 281 | 282 | if (t<1 || t>65535) 283 | mexErrMsgTxt("Quantization table entries not in range 1..65535"); 284 | 285 | cinfo.quant_tbl_ptrs[n]->quantval[i*DCTSIZE+j] = 286 | (UINT16) t; 287 | } 288 | } 289 | 290 | /* set remaining quantization table slots to null */ 291 | for (; n < NUM_QUANT_TBLS; n++) 292 | cinfo.quant_tbl_ptrs[n] = NULL; 293 | 294 | /* Get the AC and DC huffman tables but check for optimized coding first*/ 295 | if (cinfo.optimize_coding == FALSE) 296 | { 297 | if (mxGetField(mxjpeg_obj,0,"ac_huff_tables") != NULL) 298 | { 299 | mxhuff_tables = mxGetField(mxjpeg_obj,0,"ac_huff_tables"); 300 | if( mxGetN(mxhuff_tables) > 0) 301 | { 302 | for (n = 0; n < mxGetN(mxhuff_tables); n++) 303 | { 304 | if (cinfo.ac_huff_tbl_ptrs[n] == NULL) 305 | cinfo.ac_huff_tbl_ptrs[n] = 306 | jpeg_alloc_huff_table((j_common_ptr) &cinfo); 307 | 308 | mxtemp = mxGetField(mxhuff_tables,n,"counts"); 309 | mp = mxGetPr(mxtemp); 310 | for (i = 1; i <= 16; i++) 311 | cinfo.ac_huff_tbl_ptrs[n]->bits[i] = (UINT8) *mp++; 312 | mxtemp = mxGetField(mxhuff_tables,n,"symbols"); 313 | mp = mxGetPr(mxtemp); 314 | for (i = 0; i < 256; i++) 315 | cinfo.ac_huff_tbl_ptrs[n]->huffval[i] = (UINT8) *mp++; 316 | } 317 | for (; n < NUM_HUFF_TBLS; n++) cinfo.ac_huff_tbl_ptrs[n] = NULL; 318 | } 319 | } 320 | 321 | if (mxGetField(mxjpeg_obj,0, "dc_huff_tables") != NULL) 322 | { 323 | mxhuff_tables = mxGetField(mxjpeg_obj,0,"dc_huff_tables"); 324 | if( mxGetN(mxhuff_tables) > 0) 325 | { 326 | for (n = 0; n < mxGetN(mxhuff_tables); n++) 327 | { 328 | if (cinfo.dc_huff_tbl_ptrs[n] == NULL) 329 | cinfo.dc_huff_tbl_ptrs[n] = 330 | jpeg_alloc_huff_table((j_common_ptr) &cinfo); 331 | 332 | mxtemp = mxGetField(mxhuff_tables,n,"counts"); 333 | mp = mxGetPr(mxtemp); 334 | for (i = 1; i <= 16; i++) 335 | cinfo.dc_huff_tbl_ptrs[n]->bits[i] = (unsigned char) *mp++; 336 | mxtemp = mxGetField(mxhuff_tables,n,"symbols"); 337 | mp = mxGetPr(mxtemp); 338 | for (i = 0; i < 256; i++) 339 | cinfo.dc_huff_tbl_ptrs[n]->huffval[i] = (unsigned char) *mp++; 340 | } 341 | for (; n < NUM_HUFF_TBLS; n++) cinfo.dc_huff_tbl_ptrs[n] = NULL; 342 | } 343 | } 344 | } 345 | 346 | /* copy markers */ 347 | mxcomments = mxGetField(mxjpeg_obj,0,"comments"); 348 | n = mxGetN(mxcomments); 349 | for (i = 0; i < n; i++) 350 | { 351 | mxtemp = mxGetCell(mxcomments,i); 352 | strlen = mxGetN(mxtemp) + 1; 353 | comment = mxCalloc(strlen, sizeof(char)); 354 | mxGetString(mxtemp,comment,strlen); 355 | jpeg_write_marker(&cinfo, JPEG_COM, comment, strlen-1); 356 | mxFree(comment); 357 | } 358 | 359 | /* done with cinfo */ 360 | jpeg_finish_compress(&cinfo); 361 | jpeg_destroy_compress(&cinfo); 362 | 363 | /* close the file */ 364 | fclose(outfile); 365 | } 366 | -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_write.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_write.mexa64 -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_write.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_write.mexglx -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_write.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_write.mexw32 -------------------------------------------------------------------------------- /Hou_Improved/jpegread/jpeg_write.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/jpegread/jpeg_write.mexw64 -------------------------------------------------------------------------------- /Hou_Improved/mark.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/mark.m -------------------------------------------------------------------------------- /Hou_Improved/matrix_index.m: -------------------------------------------------------------------------------- 1 | function [ matrix ] = matrix_index(sel_index) 2 | matrix=zeros(8); 3 | for p=1:length(sel_index) 4 | row=ceil((sel_index(p)+1)/8); 5 | col=mod(sel_index(p),8)+1; 6 | matrix(row,col)=1; 7 | end 8 | 9 | end 10 | 11 | -------------------------------------------------------------------------------- /Hou_Improved/recoverstego.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/recoverstego.m -------------------------------------------------------------------------------- /Hou_Improved/select_block2.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/select_block2.m -------------------------------------------------------------------------------- /Hou_Improved/simulate.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/simulate.m -------------------------------------------------------------------------------- /Hou_Improved/stego.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/stego.m -------------------------------------------------------------------------------- /Hou_Improved/sum_payload.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/sum_payload.m -------------------------------------------------------------------------------- /Hou_Improved/synthesize.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/synthesize.m -------------------------------------------------------------------------------- /Hou_Improved/utils/AnyDistortion.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/utils/AnyDistortion.m -------------------------------------------------------------------------------- /Hou_Improved/utils/arith_decode.c: -------------------------------------------------------------------------------- 1 | /* MEX ROUTINE FOR ARITHMETIC DECODING */ 2 | 3 | /* 4 | Matlab MEX routine for arithmetic coding, modified from the adaptive 5 | arithmetic coding software by R. M. Neal contained in the following 6 | reference: 7 | 8 | Witten, I. H., Neal, R. M., and Cleary, J. G. (1987) 9 | "Arithmetic coding for data compression", Communications 10 | of the ACM, vol. 30, no. 6 (June). 11 | 12 | This modified version of the arithmetic coding software allows 13 | frequencies to be passed for each symbol, rather than estimating them 14 | adaptively. 15 | 16 | Accepts a Nx1 array of bits, and an NxS array of symbol frequencies. 17 | Returns an Nx1 output array of symbols ranging from 1..S. 18 | 19 | Adapted to MEX format by Phil Sallee 6/19/00 20 | Modified for steganography embedding by Phil Sallee 6/03 21 | */ 22 | 23 | 24 | #include 25 | #include "math.h" 26 | 27 | 28 | /* SIZE OF ARITHMETIC CODE VALUES. */ 29 | #define code_value_bits 16 /* Number of bits in a code value */ 30 | #define max_freq 16383 31 | typedef long code_value; /* Type of an arithmetic code value */ 32 | #define top_value (((long)1< 3) 65 | mexErrMsgTxt("Too many output arguments"); 66 | 67 | maxip = mxGetM(prhs[0])*mxGetN(prhs[0]); 68 | if (mxGetM(prhs[0]) != 1 & mxGetN(prhs[0]) != 1) 69 | mexErrMsgTxt("Input bit array must be a vector"); 70 | 71 | numsymval = mxGetN(prhs[1]); 72 | numsym = mxGetM(prhs[1]); 73 | 74 | /* create output array */ 75 | plhs[0] = mxCreateDoubleMatrix(numsym,1,mxREAL); 76 | 77 | /* get pointers to arrays */ 78 | symarr = mxGetPr(plhs[0]); 79 | inarr = mxGetPr(prhs[0]); 80 | farr = mxGetPr(prhs[1]); 81 | 82 | /* input bits to fill the code value */ 83 | value = 0; 84 | for (i = 0; i1)) mexErrMsgTxt("bad input bit!\n"); 88 | value += (long) inarr[ip++]; 89 | } 90 | } 91 | 92 | /* initialize code range and bits_to_follow */ 93 | low = 0; 94 | high = top_value; 95 | 96 | /* allocate cumulative frequency array */ 97 | cf = mxMalloc((numsymval+1) * sizeof(long)); 98 | if (cf==NULL) mexErrMsgTxt("Couldn't allocate cumulative freq array"); 99 | 100 | /* decode symbols */ 101 | for (i=0; i numsymval) { 121 | printf("cf[0]=%d, cf[1]=%d, cf[2]=%d, cum=%d\n",cf[0],cf[1],cf[2],cum); 122 | mexErrMsgTxt("Internal error: bad symbol!\n"); 123 | } 124 | 125 | /* Narrow code range for this symbol */ 126 | high = low + (range*cf[symbol])/cfsum - 1; 127 | low = low + (range*cf[symbol-1])/cfsum; 128 | 129 | if (high < low) 130 | mexErrMsgTxt("Internal error: bad range!\n"); 131 | 132 | /* Loop to input bits */ 133 | for (;;) { 134 | if (high=half) { 138 | value -= half; 139 | low -= half; 140 | high -= half; 141 | br+=btf; btf=1; 142 | } 143 | else if (low>=first_qtr && high1) mexErrMsgTxt("bad input bit!\n"); 157 | value += inarr[ip++]; 158 | } 159 | else { 160 | lastbit = !lastbit; 161 | value += lastbit; 162 | } 163 | } 164 | 165 | symarr[i] = symbol; 166 | sd++; 167 | 168 | /* check for too many garbage bits */ 169 | if (br >= maxip) break; 170 | } 171 | 172 | /* return number of bits read that can be uniquely obtained 173 | from the symbols that were decoded regardless of any other 174 | symbols that may follow (necessary for steganographic use) */ 175 | if (nlhs > 1) { 176 | plhs[1] = mxCreateDoubleMatrix(1,1,mxREAL); 177 | p = mxGetPr(plhs[1]); 178 | *p = br; 179 | } 180 | 181 | /* return number of symbols decoded */ 182 | if (nlhs > 2) { 183 | plhs[2] = mxCreateDoubleMatrix(1,1,mxREAL); 184 | p = mxGetPr(plhs[2]); 185 | *p = sd; 186 | } 187 | 188 | mxFree(cf); 189 | } 190 | -------------------------------------------------------------------------------- /Hou_Improved/utils/arith_decode.m: -------------------------------------------------------------------------------- 1 | % [SYMBOLS, BITSREAD, NUMSYM] = ARITH_DECODE(BITS, FREQS) 2 | % 3 | % Matlab MEX routine for arithmetic coding, modified from the adaptive 4 | % arithmetic coding software by R. M. Neal contained in the following 5 | % reference: 6 | % 7 | % Witten, I. H., Neal, R. M., and Cleary, J. G. (1987) 8 | % "Arithmetic coding for data compression", Communications 9 | % of the ACM, vol. 30, no. 6 (June). 10 | % 11 | % This modified version of the arithmetic coding software allows 12 | % frequencies to be passed for each symbol, rather than estimating them 13 | % adaptively. 14 | % 15 | % Accepts a Nx1 array of bits, and an NxS array of symbol frequencies. 16 | % Returns an Nx1 output array of symbols ranging from 1..S. 17 | % 18 | % This routine has been modified to return the number of bits read 19 | % that can be uniquely determined from the decoded symbols (BITSREAD) as 20 | % well as the number of symbols used (NUMSYM). This is necessary for 21 | % steganography purposes in which the symbols are used as a transmission 22 | % channel to send a message which may have arbitrary length. 23 | 24 | % Adapted to MEX format by Phil Sallee 6/19/00 25 | % Modified for steganography embedding by Phil Sallee 6/03 26 | 27 | error('Need to compile MEX routine ARITH_DECODE.C Type "mex arith_decode.c".'); 28 | -------------------------------------------------------------------------------- /Hou_Improved/utils/arith_decode.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/utils/arith_decode.mexw64 -------------------------------------------------------------------------------- /Hou_Improved/utils/arith_encode.c: -------------------------------------------------------------------------------- 1 | /* MEX ROUTINE FOR ARITHMETIC ENCODING */ 2 | 3 | /* 4 | Matlab MEX routine for arithmetic coding, modified from the adaptive 5 | arithmetic coding software by R. M. Neal contained in the following 6 | reference: 7 | 8 | Witten, I. H., Neal, R. M., and Cleary, J. G. (1987) 9 | "Arithmetic coding for data compression", Communications 10 | of the ACM, vol. 30, no. 6 (June). 11 | 12 | This modified version of the arithmetic coding software allows 13 | frequencies to be passed for each symbol, rather than estimating them 14 | adaptively. 15 | 16 | Accepts a Nx1 array of symbols 1..S, and an NxS array of 17 | symbol frequencies. Returns an Nx1 output array of bits. 18 | 19 | Adapted to MEX format by Phil Sallee 6/19/00 20 | Modified for steganography decoding by Phil Sallee 6/03 21 | */ 22 | 23 | 24 | #include 25 | #include "math.h" 26 | 27 | 28 | /* SIZE OF ARITHMETIC CODE VALUES. */ 29 | #define code_value_bits 16 /* Number of bits in a code value */ 30 | #define max_freq 16383 31 | typedef long code_value; /* Type of an arithmetic code value */ 32 | #define top_value (((long)1< 1) 60 | mexErrMsgTxt("Too many output arguments"); 61 | 62 | if (mxGetN(prhs[0]) != 1) 63 | mexErrMsgTxt("Input symbol array must be a column vector"); 64 | 65 | numsymval = mxGetN(prhs[1]); 66 | numsym = mxGetM(prhs[0]); 67 | 68 | if (mxGetM(prhs[1]) != numsym) 69 | mexErrMsgTxt("Frequency array must have same num of rows as symbol array"); 70 | 71 | /* allocate extra large buffer to hold output */ 72 | maxop = numsym * numsymval + 100; 73 | outbuf = mxCalloc(maxop, sizeof(int)); 74 | 75 | /* get pointers to arrays */ 76 | symarr = mxGetPr(prhs[0]); 77 | farr = mxGetPr(prhs[1]); 78 | 79 | /* allocate cumulative frequency array */ 80 | cf = mxMalloc((numsymval+1) * sizeof(long)); 81 | if (cf==NULL) mexErrMsgTxt("Couldn't allocate cumulative freq array"); 82 | 83 | /* start encoding, initialize code range and bits_to_follow */ 84 | low = 0; 85 | high = top_value; 86 | bits_to_follow = 0; 87 | 88 | /* encode symbols */ 89 | for (i=0; i numsymval)) 108 | mexErrMsgTxt("Symbol out of range\n"); 109 | 110 | if (cf[symbol-1] == cf[symbol]) 111 | mexErrMsgTxt("Can't encode symbol with zero frequency\n"); 112 | 113 | /* Narrow code range for this symbol */ 114 | range = (long)(high-low)+1; 115 | high = low + (range*cf[symbol])/cfsum - 1; 116 | low = low + (range*cf[symbol-1])/cfsum; 117 | 118 | /* Loop to output bits */ 119 | for (;;) { 120 | 121 | if (op + bits_to_follow > maxop - 4) { 122 | maxop = maxop * 2; 123 | printf("reallocating memory for %d ints\n",maxop); 124 | tmpptr = mxRealloc(outbuf, maxop * sizeof(int)); 125 | if (tmpptr == NULL) mexErrMsgTxt("Can't reallocate memory"); 126 | else outbuf = tmpptr; 127 | } 128 | 129 | if (high 0) { 132 | outbuf[op++] = 1; 133 | bits_to_follow -= 1; 134 | } 135 | } 136 | else if (low>=half) { /* Output 1 if in high half.*/ 137 | outbuf[op++] = 1; 138 | while (bits_to_follow > 0) { 139 | outbuf[op++] = 0; 140 | bits_to_follow -= 1; 141 | } 142 | low -= half; 143 | high -= half; /* Subtract offset to top. */ 144 | } 145 | else if (low>=first_qtr /* Output an opposite bit */ 146 | && high 0) { 168 | outbuf[op++] = 1; 169 | bits_to_follow -= 1; 170 | } 171 | } 172 | else { 173 | outbuf[op++] = 1; 174 | while (bits_to_follow > 0) { 175 | outbuf[op++] = 0; 176 | bits_to_follow -= 1; 177 | } 178 | } 179 | */ 180 | 181 | /* create new output array of correct size and fill it */ 182 | plhs[0] = mxCreateDoubleMatrix(op,1,mxREAL); 183 | outarr = mxGetPr(plhs[0]); 184 | for (i=0; i1) 52 | sigStr(size(sigStr,2)+1) = '/'; 53 | end 54 | % --- Assign the string and numeric flags 55 | if(ischar(varargin{i})) 56 | sigStr(size(sigStr,2)+1) = 's'; 57 | elseif(isnumeric(varargin{i})) 58 | sigStr(size(sigStr,2)+1) = 'n'; 59 | else 60 | error('comm:bi2de:InvalidInputArg','Optional parameters must be string or numeric.'); 61 | end 62 | end 63 | 64 | % --- Identify parameter signitures and assign values to variables 65 | switch sigStr 66 | 67 | % --- bi2de(d) 68 | case '' 69 | 70 | % --- bi2de(d, p) 71 | case 'n' 72 | p = varargin{1}; 73 | 74 | % --- bi2de(d, flag) 75 | case 's' 76 | flag = varargin{1}; 77 | 78 | % --- bi2de(d, p, flag) 79 | case 'n/s' 80 | p = varargin{1}; 81 | flag = varargin{2}; 82 | 83 | % --- bi2de(d, flag, p) 84 | case 's/n' 85 | flag = varargin{1}; 86 | p = varargin{2}; 87 | 88 | % --- If the parameter list does not match one of these signatures. 89 | otherwise 90 | error('comm:bi2de:InvalidSeqArg','Syntax error.'); 91 | end 92 | 93 | if isempty(b) 94 | error('comm:bi2de:InputEmpty','Required parameter empty.'); 95 | end 96 | 97 | if max(max(b < 0)) || max(max(~isfinite(b))) || (~isreal(b)) || ... 98 | (max(max(floor(b) ~= b))) 99 | error('comm:bi2de:InvalidInput','Input must contain only finite real positive integers.'); 100 | end 101 | 102 | % Set up the base to convert from. 103 | if isempty(p) 104 | p = 2; 105 | elseif max(size(p)) > 1 106 | error('comm:bi2de:NonScalarBase','Source base must be a scalar.'); 107 | elseif (floor(p) ~= p) || (~isfinite(p)) || (~isreal(p)) 108 | error('comm:bi2de:InvalidBase','Source base must be a finite real integer.'); 109 | elseif p < 2 110 | error('comm:bi2de:BaseLessThan2','Source base must be greater than or equal to two.'); 111 | end 112 | 113 | if max(max(b)) > (p-1) 114 | error('comm:bi2de:InvalidInputElement','The elements of the matrix are larger than the base can represent.'); 115 | end 116 | 117 | n = size(b,2); 118 | 119 | % If a flag is specified to flip the input such that the MSB is to the left. 120 | if isempty(flag) 121 | flag = 'right-msb'; 122 | elseif ~(strcmp(flag, 'right-msb') || strcmp(flag, 'left-msb')) 123 | error('comm:bi2de:InvalidFlag','Invalid string flag.'); 124 | end 125 | 126 | if strcmp(flag, 'left-msb') 127 | 128 | b2 = b; 129 | b = b2(:,n:-1:1); 130 | 131 | end 132 | 133 | %%% The conversion 134 | max_length = 1024; 135 | pow2vector = p.^(0:1:(size(b,2)-1)); 136 | size_B = min(max_length,size(b,2)); 137 | d = b(:,1:size_B)*pow2vector(:,1:size_B).'; 138 | 139 | % handle the infs... 140 | idx = find(max(b(:,max_length+1:size(b,2)).') == 1); 141 | d(idx) = inf; 142 | 143 | % data type conversion 144 | if ~strcmp(inType, 'logical') 145 | d = feval(inType, d); 146 | end 147 | 148 | % [EOF] 149 | -------------------------------------------------------------------------------- /Hou_Improved/utils/compressFun.m: -------------------------------------------------------------------------------- 1 | function [ y ] = compressFun( x ) 2 | %COMPRESS Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | B=length(x); 6 | Max_Val=max(x); 7 | j=find(x==Max_Val); 8 | Diff = zeros(B,1); 9 | Diff(1)=x(1); 10 | for i=2:j 11 | Diff(i)=x(i)-x(i-1); 12 | end 13 | for i=j+1:B 14 | Diff(i)=x(i-1)-x(i); 15 | end 16 | 17 | % compress positions 18 | Pos=(Diff<0); 19 | Pos=double(Pos); 20 | p1=sum(Pos)/B; 21 | Frequency=ones(B,2); 22 | Frequency(:,1)=(1-p1)*Frequency(:,1); 23 | Frequency(:,2)=p1*Frequency(:,2); 24 | Pos=Pos+1; 25 | Pos=reshape(Pos,B,1); 26 | [Comp1]=arith_encode(Pos,Frequency); 27 | oh1=size(Comp1,1); 28 | 29 | % compress diffs 30 | Diff=abs(Diff); 31 | temp=max(Diff); 32 | temp=log2(temp); 33 | Digit=ceil(temp)+1; 34 | BiSeq=de2bi(Diff,Digit); 35 | BiSeq=reshape(BiSeq,B*Digit,1); 36 | q1=sum(BiSeq)/(B*Digit); 37 | Frequency=ones(B*Digit,2); 38 | Frequency(:,1)=(1-q1)*Frequency(:,1); 39 | Frequency(:,2)=q1*Frequency(:,2); 40 | BiSeq=BiSeq+1; 41 | [Comp2]=arith_encode(BiSeq,Frequency); 42 | oh2=size(Comp2,1); 43 | y=oh1+oh2+ceil(log2(B)); 44 | 45 | end 46 | 47 | -------------------------------------------------------------------------------- /Hou_Improved/utils/compressOhead.m: -------------------------------------------------------------------------------- 1 | function [ compSeq ] = compressOhead( stego,cover,Qyx,xRange,yRange) 2 | %COMPRESSOHEAD Summary of this function goes here 3 | % Detailed explanation goes here 4 | eps=0.0001; 5 | [nB,mB]=size(Qyx); 6 | 7 | coverLen = length(cover); 8 | coverind = zeros(coverLen,1); 9 | for xi=1:mB 10 | coverind(cover==xRange(xi)) = xi; 11 | end 12 | cover = coverind; 13 | 14 | compSeq = zeros(coverLen,1); 15 | compLen = 0; 16 | for yi=1:nB 17 | pos = find(stego==yRange(yi)); 18 | if ~isempty(pos) && ~any(abs(Qyx(yi,:)-1.0)1) 47 | sigStr(size(sigStr,2)+1) = '/'; 48 | end; 49 | % --- Assign the string and numeric flags 50 | if(ischar(varargin{i})) 51 | sigStr(size(sigStr,2)+1) = 's'; 52 | elseif(isnumeric(varargin{i})) 53 | sigStr(size(sigStr,2)+1) = 'n'; 54 | else 55 | error('comm:de2bi:InvalidArg','Only string and numeric arguments are accepted.'); 56 | end; 57 | end; 58 | 59 | % --- Identify parameter signitures and assign values to variables 60 | switch sigStr 61 | % --- de2bi(d) 62 | case 'n' 63 | d = varargin{1}; 64 | 65 | % --- de2bi(d, n) 66 | case 'n/n' 67 | d = varargin{1}; 68 | n = varargin{2}; 69 | 70 | % --- de2bi(d, msbFlag) 71 | case 'n/s' 72 | d = varargin{1}; 73 | msbFlag = varargin{2}; 74 | 75 | % --- de2bi(d, n, msbFlag) 76 | case 'n/n/s' 77 | d = varargin{1}; 78 | n = varargin{2}; 79 | msbFlag = varargin{3}; 80 | 81 | % --- de2bi(d, msbFlag, n) 82 | case 'n/s/n' 83 | d = varargin{1}; 84 | msbFlag = varargin{2}; 85 | n = varargin{3}; 86 | 87 | % --- de2bi(d, n, p) 88 | case 'n/n/n' 89 | d = varargin{1}; 90 | n = varargin{2}; 91 | p = varargin{3}; 92 | 93 | % --- de2bi(d, n, p, msbFlag) 94 | case 'n/n/n/s' 95 | d = varargin{1}; 96 | n = varargin{2}; 97 | p = varargin{3}; 98 | msbFlag = varargin{4}; 99 | 100 | % --- de2bi(d, n, msbFlag, p) 101 | case 'n/n/s/n' 102 | d = varargin{1}; 103 | n = varargin{2}; 104 | msbFlag = varargin{3}; 105 | p = varargin{4}; 106 | 107 | % --- de2bi(d, msbFlag, n, p) 108 | case 'n/s/n/n' 109 | d = varargin{1}; 110 | msbFlag = varargin{2}; 111 | n = varargin{3}; 112 | p = varargin{4}; 113 | 114 | % --- If the parameter list does not match one of these signatures. 115 | otherwise 116 | error('comm:de2bi:InvalidArgSeq','Syntax error.'); 117 | end; 118 | 119 | if isempty(d) 120 | error('comm:de2bi:NoInput','Required parameter empty.'); 121 | end 122 | 123 | inType = class(d); 124 | d = double(d(:)); 125 | len_d = length(d); 126 | 127 | if max(max(d < 0)) || max(max(~isfinite(d))) || (~isreal(d)) || (max(max(floor(d) ~= d))) 128 | error('comm:de2bi:InvalidInput','Input must contain only finite real positive integers.'); 129 | end 130 | 131 | % Assign the base to convert to. 132 | if isempty(p) 133 | p = 2; 134 | elseif max(size(p) ~= 1) 135 | error('comm:de2bi:NonScalarBase','Destination base must be scalar.'); 136 | elseif (~isfinite(p)) || (~isreal(p)) || (floor(p) ~= p) 137 | error('comm:de2bi:InvalidBase','Destination base must be a finite real integer.'); 138 | elseif p < 2 139 | error('comm:de2bi:BaseLessThan2','Cannot convert to a base of less than two.'); 140 | end; 141 | 142 | % Determine minimum length required. 143 | tmp = max(d); 144 | if tmp ~= 0 % Want base-p log of tmp. 145 | ntmp = floor( log(tmp) / log(p) ) + 1; 146 | else % Since you can't take log(0). 147 | ntmp = 1; 148 | end 149 | 150 | % This takes care of any round off error that occurs for really big inputs. 151 | if ~( (p^ntmp) > tmp ) 152 | ntmp = ntmp + 1; 153 | end 154 | 155 | % Assign number of columns in output matrix. 156 | if isempty(n) 157 | n = ntmp; 158 | elseif max(size(n) ~= 1) 159 | error('comm:de2bi:NonScalarN','Specified number of columns must be scalar.'); 160 | elseif (~isfinite(n)) || (~isreal(n)) || (floor(n) ~= n) 161 | error('comm:de2bi:IvalidN','Specified number of columns must be a finite real integer.'); 162 | elseif n < ntmp 163 | error('comm:de2bi:SmallN','Specified number of columns in output matrix is too small.'); 164 | end 165 | 166 | % Check if the string msbFlag is valid. 167 | if isempty(msbFlag) 168 | msbFlag = 'right-msb'; 169 | elseif ~(strcmp(msbFlag, 'right-msb') || strcmp(msbFlag, 'left-msb')) 170 | error('comm:de2bi:InvalidMsbFlag','Invalid string msbFlag.'); 171 | end 172 | 173 | % Initial value. 174 | b = zeros(len_d, n); 175 | 176 | % Perform conversion. 177 | %Vectorized conversion for P=2 case 178 | if(p==2) 179 | [f,e]=log2(max(d)); % How many digits do we need to represent the numbers? 180 | b=rem(floor(d*pow2(1-max(n,e):0)),p); 181 | if strcmp(msbFlag, 'right-msb') 182 | b = fliplr(b); 183 | end; 184 | else 185 | for i = 1 : len_d % Cycle through each element of the input vector/matrix. 186 | j = 1; 187 | tmp = d(i); 188 | while (j <= n) && (tmp > 0) % Cycle through each digit. 189 | b(i, j) = rem(tmp, p); % Determine current digit. 190 | tmp = floor(tmp/p); 191 | j = j + 1; 192 | end; 193 | end; 194 | % If a msbFlag is specified to flip the output such that the MSB is to the left. 195 | if strcmp(msbFlag, 'left-msb') 196 | b2 = b; 197 | b = b2(:,n:-1:1); 198 | end; 199 | end; 200 | 201 | b = feval(inType, b); % data type conversion 202 | 203 | % [EOF] 204 | -------------------------------------------------------------------------------- /Hou_Improved/utils/entropyEmbed.m: -------------------------------------------------------------------------------- 1 | function [ stego,mesLen ] = entropyEmbed( cover,mess,Qxy,xRange,yRange) 2 | %ENTROPYEMBED Summary of this function goes here 3 | % Detailed explanation goes here 4 | % cover: the cover signal 5 | % mess: the message to embed 6 | % Qxy: the conditional probability Py|x 7 | eps=0.0001; 8 | stego = cover; 9 | mesLen = 0; 10 | [mB,nB] = size(Qxy); 11 | for xi=1:mB 12 | pos = find(cover==xRange(xi)); 13 | xN = length(pos); 14 | if xN>0 15 | yi = find(abs(Qxy(xi,:)-1.0) < eps); 16 | if yi 17 | stego(pos) = yRange(yi)*ones(xN,1); 18 | else%if abs(sum(Qxy(xi,:))-1.0)<1e-8 19 | fq = repmat(Qxy(xi,:),xN,1); 20 | [symbols,mLen] = arith_decode(mess(mesLen+1:end),fq); 21 | stego(pos) = yRange(symbols); 22 | mesLen = mesLen+mLen; 23 | end 24 | end 25 | end 26 | 27 | 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /Hou_Improved/utils/minDistortionEmr.m: -------------------------------------------------------------------------------- 1 | function [ Py,Dav,exitfg,iters] = minDistortionEmr(Px,Dxy,Hy) 2 | % Miniminze average distortion between stego-signal and cover-signal 3 | % 4 | % Input: 5 | % Px : cover-signal probability distribution 6 | % Dxy : square error distortion matrix 7 | % Hy : expected stego-signal entropy 8 | % 9 | % Output: 10 | % Py : stego-signal probability distribution 11 | % Dav : corresponding minimized distortion value 12 | % exitfg : exit flag: 0-->success -1-->invalid input 1-->failed 13 | % iters : number of iterations 14 | %%******************************************************************** 15 | % 16 | % author: Xiaocheng Hu 17 | % college: University of Science and Technology of China 18 | % date: 9/2/2012 19 | % 20 | %%********************************************************************* 21 | 22 | [m,n] = size(Dxy); 23 | 24 | % input validation 25 | % 26 | if ( abs(sum(Px)-1.0) > 1e-8 ) || (Hy > log(n)) || (Hy < -sum(Px.*log(Px))) 27 | Pxy=zeros(m,n);Dav=0;exitfg=-1; 28 | disp('minDistortionEmr invalid input!'); 29 | return; 30 | end 31 | %} 32 | 33 | % 34 | MPx = Px(:,ones(n,1));%repmat(Px,1,n); 35 | Dxy = MPx.*Dxy; 36 | 37 | %parameters 38 | MAXITERS = 300; 39 | Tol = 1e-8; 40 | NTTol = 1e-8; 41 | MU = 20; 42 | Alpha = 0.01; 43 | Beta = 0.6; 44 | 45 | % initialize x0 46 | x = zeros(n+m+1,1);%+1.0; 47 | x(1:n) = log(1/n)+1.0; 48 | x(n+1:n+m) = abs(x(1))+0.01; 49 | x(n+m+1) = 1.0; 50 | 51 | % initialize t0 with least square 52 | Mfx = Dxy+repmat(x(n+1:n+m),1,n)+Px*(x(1:n)'); 53 | fx = [Mfx(:);x(n+m+1)]; 54 | lA = [exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy]; 55 | lb = [(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 56 | t = (lA'*lb)/(lA'*lA); 57 | t = ceil(t); 58 | %t=1; 59 | 60 | % 61 | for iters=1:MAXITERS 62 | % calculate function value and it's gratitude 63 | val=t*(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1))-sum(log(fx)); 64 | grad=t*([exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy])-[(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 65 | 66 | 67 | %{ 68 | Hf0=[diag(exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)),zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2); ... 69 | zeros(m,m+n+1); ... 70 | -(exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2))',zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]; 71 | Hfx=[-diag(sum((MPx./Mfx).^2)) , -(MPx./(Mfx.^2))', zeros(n,1); ... 72 | -(MPx./(Mfx.^2)) , -diag(sum(1./(Mfx.^2),2)), zeros(m,1); ... 73 | zeros(1,n) , zeros(1,m) , -1/(x(n+m+1)^2)]; 74 | hess=t*Hf0-Hfx; 75 | Dx=-hess\grad; 76 | %} 77 | % Calculate Newton step, fast 78 | Dx=fast_linear_solver(t*exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)+(sum((MPx./Mfx).^2))', ... 79 | t*[zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2)]+[(MPx./(Mfx.^2))',zeros(n,1)], ... 80 | t*[zeros(m,m),zeros(m,1);zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]+[diag(sum(1./(Mfx.^2),2)),zeros(m,1);zeros(1,m),1/(x(n+m+1)^2)], ... 81 | -grad); 82 | fprime=grad'*Dx; 83 | 84 | % Solved Centering step and update t 85 | if( (-fprime < NTTol)) 86 | gap=(m*n+1)/t; 87 | 88 | % stopping criterion 89 | if( gap < Tol ),break;end; 90 | 91 | % update t and continue the next Centering step 92 | t=MU*t; 93 | continue; 94 | end 95 | 96 | % Backtracking step 1, ensure the domain of fx 97 | step=1; 98 | DMf=repmat(Dx(n+1:n+m),1,n)+Px*(Dx(1:n)');Dff=[DMf(:);Dx(n+m+1)]; 99 | while any((fx+step*Dff)<=0) 100 | step=Beta*step; 101 | end 102 | 103 | newx = x+step*Dx; 104 | newfx = fx+step*Dff; 105 | % Backtracking step 2, decrease fx sufficiently 106 | % 107 | while ( (t*(newx(n+m+1)*sum(exp(newx(1:n)/newx(n+m+1)-1))+sum(newx(n+1:n+m))-Hy*newx(n+m+1))-sum(log(newfx))) > (val+Alpha*step*fprime) ) 108 | step=Beta*step; 109 | newx=x+step*Dx; 110 | newfx=fx+step*Dff; 111 | end 112 | %} 113 | 114 | % update variables 115 | x = newx; 116 | fx = newfx; 117 | Mfx = Mfx+step*DMf; 118 | 119 | 120 | end 121 | 122 | % Output 123 | Py = exp(x(1:n)/x(n+m+1)-1); 124 | Dav = -(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1)); 125 | 126 | % check if success 127 | if( abs(sum(Py)-1.0) < 1e-8 ) 128 | exitfg=0; 129 | else 130 | exitfg=1; 131 | end 132 | fprintf('minDistortionEmr Iters: %d\t Distortion: %f\t Sum of Py: %f\n',iters,Dav,sum(Py)); 133 | 134 | %% Block elimination method to solve linear equations 135 | function [sx]=fast_linear_solver(A11,A12,A22,b) 136 | [sn,sm]=size(A12); 137 | b1=b(1:sn); 138 | b2=b(sn+1:sn+sm); 139 | 140 | invA11=1./A11; 141 | Tm=repmat(invA11',sm,1).*(A12'); 142 | S=A22-Tm*A12; 143 | bs=b2-Tm*b1; 144 | % check if S is positive definite 145 | % 146 | [L,p]=chol(S,'lower'); 147 | if (p > 0) 148 | sx=zeros(sn+sm,1); 149 | return; 150 | end 151 | 152 | zz=L\bs; 153 | x2=L'\zz; 154 | %} 155 | %topts.SYM=true;topts.POSDEF=true; 156 | %[x2,Rf]=linsolve(S,bs,topts); 157 | %x2=S\bs; 158 | x1=invA11.*(b1-A12*x2); 159 | sx=[x1;x2]; 160 | end 161 | 162 | end 163 | 164 | -------------------------------------------------------------------------------- /Hou_Improved/utils/minDistortionMsk.m: -------------------------------------------------------------------------------- 1 | function [ Pxy,Dav,exitfg,iters] = minDistortionMsk(Px,Dxy,Hy) 2 | % Miniminze average distortion between stego-signal and cover-signal 3 | % 4 | % Input: 5 | % Px : cover-signal probability distribution 6 | % Dxy : distortion matrix 7 | % Hy : expected stego-signal entropy 8 | % 9 | % Output: 10 | % Pxy : conditional probability distribution Py|x 11 | % Dav : corresponding minimized distortion value 12 | % exitfg : exit flag: 0-->success -1-->invalid input 1-->failed 13 | % iters : number of iterations 14 | %%******************************************************************** 15 | % 16 | % author: Xiaocheng Hu 17 | % college: University of Science and Technology of China 18 | % date: 9/2/2012 19 | % 20 | %%********************************************************************* 21 | 22 | [m,n] = size(Dxy); 23 | % input validation 24 | % 25 | if ( abs(sum(Px)-1.0) > 1e-8 ) || (Hy > log(n)) || (Hy < -sum(Px.*log(Px))) 26 | Pxy=zeros(m,n);Dav=0;exitfg=-1; 27 | disp('minDistortionEmr invalid input!'); 28 | return; 29 | end 30 | %} 31 | 32 | % 33 | MPx = Px(:,ones(n,1));%repmat(Px,1,n); 34 | Dxy = MPx.*Dxy; 35 | 36 | %parameters 37 | MAXITERS = 300; 38 | Tol = 1e-8; 39 | NTTol = 1e-8; 40 | MU = 20; 41 | Alpha = 0.01; 42 | Beta = 0.6; 43 | 44 | % initialize x0 45 | x = zeros(n+m+1,1);%+1.0; 46 | x(1:n) = log(1/n)+1.0; 47 | x(n+1:n+m) = abs(x(1))+0.01; 48 | x(n+m+1) = 1.0; 49 | 50 | % initialize t0 with least square 51 | Mfx = Dxy+repmat(x(n+1:n+m),1,n)+Px*(x(1:n)'); 52 | fx = [Mfx(:);x(n+m+1)]; 53 | lA = [exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy]; 54 | lb = [(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 55 | t = (lA'*lb)/(lA'*lA); 56 | t = ceil(t); 57 | %t=1; 58 | 59 | % 60 | for iters=1:MAXITERS 61 | % calculate function value and it's gratitude 62 | val=t*(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1))-sum(log(fx)); 63 | grad=t*([exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy])-[(sum(MPx./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 64 | 65 | 66 | %{ 67 | Hf0=[diag(exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)),zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2); ... 68 | zeros(m,m+n+1); ... 69 | -(exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2))',zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]; 70 | Hfx=[-diag(sum((MPx./Mfx).^2)) , -(MPx./(Mfx.^2))', zeros(n,1); ... 71 | -(MPx./(Mfx.^2)) , -diag(sum(1./(Mfx.^2),2)), zeros(m,1); ... 72 | zeros(1,n) , zeros(1,m) , -1/(x(n+m+1)^2)]; 73 | hess=t*Hf0-Hfx; 74 | Dx=-hess\grad; 75 | %} 76 | % Calculate Newton step, fast 77 | Dx=fast_linear_solver(t*exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)+(sum((MPx./Mfx).^2))', ... 78 | t*[zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2)]+[(MPx./(Mfx.^2))',zeros(n,1)], ... 79 | t*[zeros(m,m),zeros(m,1);zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]+[diag(sum(1./(Mfx.^2),2)),zeros(m,1);zeros(1,m),1/(x(n+m+1)^2)], ... 80 | -grad); 81 | fprime=grad'*Dx; 82 | 83 | % Solved Centering step and update t 84 | if( (-fprime < NTTol)) 85 | gap=(m*n+1)/t; 86 | 87 | % stopping criterion 88 | if( gap < Tol ),break;end; 89 | 90 | % update t and continue the next Centering step 91 | t=MU*t; 92 | continue; 93 | end 94 | 95 | % Backtracking step 1, ensure the domain of fx 96 | step=1; 97 | DMf=repmat(Dx(n+1:n+m),1,n)+Px*(Dx(1:n)');Dff=[DMf(:);Dx(n+m+1)]; 98 | while any((fx+step*Dff)<=0) 99 | step=Beta*step; 100 | end 101 | 102 | newx = x+step*Dx; 103 | newfx = fx+step*Dff; 104 | % Backtracking step 2, decrease fx sufficiently 105 | % 106 | while ( (t*(newx(n+m+1)*sum(exp(newx(1:n)/newx(n+m+1)-1))+sum(newx(n+1:n+m))-Hy*newx(n+m+1))-sum(log(newfx))) > (val+Alpha*step*fprime) ) 107 | step=Beta*step; 108 | newx=x+step*Dx; 109 | newfx=fx+step*Dff; 110 | end 111 | %} 112 | 113 | % update variables 114 | x = newx; 115 | fx = newfx; 116 | Mfx = Mfx+step*DMf; 117 | 118 | 119 | end 120 | 121 | % Output 122 | Py = exp(x(1:n)/x(n+m+1)-1); 123 | %Dav = -(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1)); 124 | Pxy = nonCrossEdge(Px,Py); 125 | %% linear optimization to get Pxy 126 | % A1 = zeros(n,m*n); 127 | % for ii=1:n 128 | % A1(ii,(ii-1)*m+1:ii*m) = Px'; 129 | % end 130 | % blc1 = Py; 131 | % buc1 = Py; 132 | % 133 | % A2 = zeros(m,m*n); 134 | % for ii=1:m 135 | % A2(ii,ii:m:m*n) = 1; 136 | % end 137 | % blc2 = ones(m,1); 138 | % buc2 = ones(m,1); 139 | % 140 | % c = Dxy(:); 141 | % A = [A1;A2]; 142 | % blc = [blc1;blc2]; 143 | % buc = [buc1;buc2]; 144 | % blx = zeros(m*n,1); 145 | % bux = ones(m*n,1); 146 | % 147 | % param = []; 148 | % param.MSK_IPAR_INTPNT_BASIS = 'MSK_BI_NO_ERROR'; 149 | % param.MSK_IPAR_BI_IGNORE_MAX_ITER = 'MSK_ON'; 150 | % param.MSK_IPAR_LOG = 0; 151 | % param.MSK_DPAR_INTPNT_NL_TOL_PFEAS = 1.0e-12; 152 | % param.MSK_DPAR_INTPNT_NL_TOL_DFEAS = 1.0e-12; 153 | % param.MSK_DPAR_INTPNT_NL_TOL_REL_GAP = 1.0e-12; 154 | % 155 | % [res] = msklpopt(c,A,blc,buc,blx,bux,param); 156 | % yy = res.sol.itr.xx; 157 | % yy(abs(yy)<=1e-6)=0;%-4 158 | % Pxy = reshape(yy,m,n); 159 | Dav = trace(Dxy*Pxy'); 160 | 161 | % check if success 162 | if( abs(sum(Py)-1.0) < 1e-8 ) 163 | exitfg=0; 164 | else 165 | exitfg=1; 166 | end 167 | fprintf('minDistortionEmr Iteration: %d\t Distortion: %f\t Sum of Py: %f\n',iters,Dav,sum(Py)); 168 | 169 | %% Block elimination method to solve linear equations 170 | function [sx]=fast_linear_solver(A11,A12,A22,b) 171 | [sn,sm]=size(A12); 172 | b1=b(1:sn); 173 | b2=b(sn+1:sn+sm); 174 | 175 | invA11=1./A11; 176 | Tm=repmat(invA11',sm,1).*(A12'); 177 | S=A22-Tm*A12; 178 | bs=b2-Tm*b1; 179 | % check if S is positive definite 180 | % 181 | [L,p]=chol(S,'lower'); 182 | if (p > 0) 183 | sx=zeros(sn+sm,1); 184 | return; 185 | end 186 | 187 | zz=L\bs; 188 | x2=L'\zz; 189 | %} 190 | %topts.SYM=true;topts.POSDEF=true; 191 | %[x2,Rf]=linsolve(S,bs,topts); 192 | %x2=S\bs; 193 | x1=invA11.*(b1-A12*x2); 194 | sx=[x1;x2]; 195 | end 196 | 197 | end 198 | 199 | -------------------------------------------------------------------------------- /Hou_Improved/utils/min_distortion_br.m: -------------------------------------------------------------------------------- 1 | function [ Py,ef,Dav] = min_distortion_br( Ps,Dsy,Hy ) 2 | % Miniminze average distortion between stego-signal and cover-signal 3 | % 4 | % Input: 5 | % Ps : cover-signal probability distribution 6 | % Dsy : distortion matrix 7 | % Hy : expected stego-signal entropy 8 | % 9 | % Output: 10 | % Py : stego-signal probability distribution 11 | % ef : exit flag: 0-->success -1-->invalid input 1-->failed 12 | % Dav : corresponding minimal distortion value 13 | 14 | % 15 | tic; 16 | 17 | % validation of Hy 18 | [m,n]=size(Dsy); 19 | if (Hy > log(n)) || (Hy < -sum(Ps.*log(Ps))) 20 | disp('invalid entropy input!'); 21 | Py=[]; 22 | Dav=0; 23 | ef=-1; 24 | return; 25 | end 26 | %} 27 | 28 | % 29 | MPs=repmat(Ps,1,n); 30 | Dsy=MPs.*Dsy; 31 | 32 | %parameters 33 | MAXITERS=200; 34 | Tol=1e-4; 35 | NTTol=1e-6; 36 | XTol=1e-4; 37 | MU=20; 38 | Alpha=0.01; 39 | Beta=0.6; 40 | 41 | % initialize x0 42 | x=zeros(n+m+1,1)+1.0; 43 | %x(1:n)=-1.0; 44 | x(1:n)=log(1/n)+1.0; 45 | x(n+1:n+m)=abs(x(1))+0.01; 46 | x(n+m+1)=1.0; 47 | 48 | % initialize t0 with least square 49 | Mfx=Dsy+repmat(x(n+1:n+m),1,n)+Ps*(x(1:n)'); 50 | fx=[Mfx(:);x(n+m+1)]; 51 | lA=[exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy]; 52 | lb=[(sum(MPs./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 53 | t=lA'*lb/(lA'*lA); 54 | t=ceil(t); 55 | %t=1; 56 | 57 | % initialize gap 58 | gap=1; 59 | step=1; 60 | % 61 | for iters=1:MAXITERS 62 | %assert(min(fx)>=0); 63 | iters; 64 | % calculate function value and it's gratitude 65 | val=t*(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1))-sum(log(fx)); 66 | grad=t*([exp(x(1:n)/x(n+m+1)-1);ones(m,1);sum(exp(x(1:n)/x(n+m+1)-1).*(x(n+m+1)-x(1:n)))/x(n+m+1)-Hy])-[(sum(MPs./Mfx))';sum(1./Mfx,2);1/x(n+m+1)]; 67 | 68 | 69 | %{ 70 | Hf0=[diag(exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)),zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2); ... 71 | zeros(m,m+n+1); ... 72 | -(exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2))',zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]; 73 | Hfx=[-diag(sum((MPs./Mfx).^2)) , -(MPs./(Mfx.^2))', zeros(n,1); ... 74 | -(MPs./(Mfx.^2)) , -diag(sum(1./(Mfx.^2),2)), zeros(m,1); ... 75 | zeros(1,n) , zeros(1,m) , -1/(x(n+m+1)^2)]; 76 | hess=t*Hf0-Hfx; 77 | %Dx=-hess\grad; 78 | %} 79 | % Calculate Newton step 80 | Dx=fast_linear_solver(t*exp(x(1:n)/x(n+m+1)-1)/x(n+m+1)+(sum((MPs./Mfx).^2))', ... 81 | t*[zeros(n,m),-exp(x(1:n)/x(n+m+1)-1).*x(1:n)/(x(n+m+1)^2)]+[(MPs./(Mfx.^2))',zeros(n,1)], ... 82 | t*[zeros(m,m),zeros(m,1);zeros(1,m),sum(exp(x(1:n)/x(n+m+1)-1).*(x(1:n).^2))/(x(n+m+1)^3)]+[diag(sum(1./(Mfx.^2),2)),zeros(m,1);zeros(1,m),1/(x(n+m+1)^2)], ... 83 | -grad); 84 | fprime=grad'*Dx; 85 | %if(~fprime),break;end; 86 | %assert(fprime<=0); 87 | 88 | % Solved Centering step and update t 89 | if( (-fprime < NTTol) || (step) < XTol) 90 | step=1; 91 | gap=(m*n+1)/t; 92 | 93 | % stopping criterion 94 | if( gap < Tol ),break;end; 95 | 96 | % update t and continue the next Centering step 97 | t=MU*t; 98 | continue; 99 | end 100 | 101 | % Backtracking step 1, ensure the domain of fx 102 | step=1; 103 | DMf=repmat(Dx(n+1:n+m),1,n)+Ps*(Dx(1:n)');Dff=[DMf(:);Dx(n+m+1)]; 104 | while (min(fx+step*Dff)<=0) 105 | step=Beta*step; 106 | end 107 | 108 | % Backtracking step 2, decrease fx sufficiently 109 | newx=x+step*Dx; 110 | newfx=fx+step*Dff; 111 | %newfx=Dsy+repmat(newx(n+1:n+m),1,n)+Ps*(newx(1:n)');newfx=[newfx(:);newx(n+m+1)]; 112 | while ( (t*(newx(n+m+1)*sum(exp(newx(1:n)/newx(n+m+1)-1))+sum(newx(n+1:n+m))-Hy*newx(n+m+1))-sum(log(newfx))) > (val+Alpha*step*fprime) ) 113 | step=Beta*step; 114 | newx=x+step*Dx; 115 | newfx=fx+step*Dff; 116 | %newfx=Dsy+repmat(newx(n+1:n+m),1,n)+Ps*(newx(1:n)');newfx=[newfx(:);newx(n+m+1)]; 117 | end 118 | %} 119 | step; 120 | 121 | % update variables 122 | x=newx; 123 | fx=newfx; 124 | Mfx=Mfx+step*DMf; 125 | 126 | 127 | end 128 | 129 | % 130 | Py=exp(x(1:n)/x(n+m+1)-1); 131 | if( abs(sum(Py)-1.0) < 1e-8 ) 132 | ef=0; 133 | else 134 | ef=1; 135 | end 136 | Dav=-(x(n+m+1)*sum(exp(x(1:n)/x(n+m+1)-1))+sum(x(n+1:n+m))-Hy*x(n+m+1)); 137 | fprintf('min_distortion_br: #iter %d #gap %f #time(s) %f\n',iters,gap,toc); 138 | 139 | 140 | % Block elimination method to solve linear equations 141 | function [sx]=fast_linear_solver(A11,A12,A22,b) 142 | [sn,sm]=size(A12); 143 | b1=b(1:sn); 144 | b2=b(sn+1:sn+sm); 145 | 146 | invA11=1./A11; 147 | Tm=repmat(invA11',sm,1).*(A12'); 148 | S=A22-Tm*A12; 149 | % check if S is positive definite 150 | % 151 | [L,p]=chol(S,'lower'); 152 | if (p > 0) 153 | sx=zeros(sn+sm,1); 154 | return; 155 | end 156 | %} 157 | 158 | bs=b2-Tm*b1; 159 | zz=L\bs; 160 | x2=L'\zz; 161 | %topts.SYM=true;topts.POSDEF=true; 162 | %[x2,Rf]=linsolve(S,bs,topts); 163 | %x2=S\bs; 164 | %x2=pinv(S)*bs; 165 | x1=invA11.*(b1-A12*x2); 166 | sx=[x1;x2]; 167 | end 168 | 169 | end 170 | 171 | -------------------------------------------------------------------------------- /Hou_Improved/utils/nonCrossEdge.m: -------------------------------------------------------------------------------- 1 | function [Qxy,Qyx]=nonCrossEdge(Px,Py) 2 | 3 | m = length(Px); 4 | CPx = zeros(m+1,1); 5 | for i=1:m 6 | CPx(i+1)=CPx(i)+Px(i); 7 | end 8 | 9 | n = length(Py); 10 | CPy = zeros(n+1,1); 11 | for i=1:n 12 | CPy(i+1)=CPy(i)+Py(i); 13 | end 14 | 15 | Qxy = zeros(m,n); 16 | Qyx = zeros(m,n); 17 | for x=0:(m-1) 18 | for y=0:(n-1) 19 | jval = max(0,min(CPx(x+2),CPy(y+2))-max(CPx(x+1),CPy(y+1))); 20 | 21 | Qxy(x+1,y+1)= jval/(Px(x+1)+eps); 22 | Qyx(x+1,y+1)= jval/(Py(y+1)+eps); 23 | end 24 | end 25 | Qyx=Qyx'; 26 | 27 | end -------------------------------------------------------------------------------- /Hou_Improved/utils/recursiveConstruct.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Hou_Improved/utils/recursiveConstruct.m -------------------------------------------------------------------------------- /Huang/Getzeronum.m: -------------------------------------------------------------------------------- 1 | function [zeronum]=Getzeronum(Blockdct) 2 | [M,N] = size(Blockdct); 3 | zeronum=zeros(M*N,3); 4 | count=1; 5 | for r=1:M 6 | for c=1:N 7 | zeronum(count,1)=r; 8 | zeronum(count,2)=c; 9 | zeronum(count,3)=sum(Blockdct{r,c}(:)==0); 10 | count=count+1; 11 | end 12 | end 13 | zeronum=sortrows(zeronum,-3); 14 | end -------------------------------------------------------------------------------- /Huang/JPEG_Toolbox/jpeg_read.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/JPEG_Toolbox/jpeg_read.mexa64 -------------------------------------------------------------------------------- /Huang/JPEG_Toolbox/jpeg_read.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/JPEG_Toolbox/jpeg_read.mexw64 -------------------------------------------------------------------------------- /Huang/JPEG_Toolbox/jpeg_write.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/JPEG_Toolbox/jpeg_write.mexa64 -------------------------------------------------------------------------------- /Huang/JPEG_Toolbox/jpeg_write.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/JPEG_Toolbox/jpeg_write.mexw64 -------------------------------------------------------------------------------- /Huang/SSIM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/SSIM.m -------------------------------------------------------------------------------- /Huang/Stego/QF30/1.pgm_2000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/Stego/QF30/1.pgm_2000.jpg -------------------------------------------------------------------------------- /Huang/debug_main.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/debug_main.m -------------------------------------------------------------------------------- /Huang/jpeg_emdding.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/jpeg_emdding.m -------------------------------------------------------------------------------- /Huang/jpeg_extract.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/jpeg_extract.m -------------------------------------------------------------------------------- /Huang/jpeg_hist.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/jpeg_hist.m -------------------------------------------------------------------------------- /Huang/name30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/name30.jpg -------------------------------------------------------------------------------- /Huang/process.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/process.m -------------------------------------------------------------------------------- /Huang/psnr.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/psnr.m -------------------------------------------------------------------------------- /Huang/re.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/re.jpg -------------------------------------------------------------------------------- /Huang/stego.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/stego.jpg -------------------------------------------------------------------------------- /Huang/sum_payload.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/sum_payload.m -------------------------------------------------------------------------------- /Huang/testimgs/Airplane.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/testimgs/Airplane.tiff -------------------------------------------------------------------------------- /Huang/testimgs/Baboon.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/testimgs/Baboon.tiff -------------------------------------------------------------------------------- /Huang/testimgs/Lena.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/testimgs/Lena.tiff -------------------------------------------------------------------------------- /Huang/testimgs/Peppers.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang/testimgs/Peppers.tiff -------------------------------------------------------------------------------- /Huang_Improved/IDCT.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/IDCT.m -------------------------------------------------------------------------------- /Huang_Improved/JPEG_Toolbox/jpeg_read.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/JPEG_Toolbox/jpeg_read.mexa64 -------------------------------------------------------------------------------- /Huang_Improved/JPEG_Toolbox/jpeg_read.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/JPEG_Toolbox/jpeg_read.mexw64 -------------------------------------------------------------------------------- /Huang_Improved/JPEG_Toolbox/jpeg_write.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/JPEG_Toolbox/jpeg_write.mexa64 -------------------------------------------------------------------------------- /Huang_Improved/JPEG_Toolbox/jpeg_write.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/JPEG_Toolbox/jpeg_write.mexw64 -------------------------------------------------------------------------------- /Huang_Improved/SSIM.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/SSIM.m -------------------------------------------------------------------------------- /Huang_Improved/Stego/QF30/1.pgm_2000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/Stego/QF30/1.pgm_2000.jpg -------------------------------------------------------------------------------- /Huang_Improved/debug_main.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/debug_main.m -------------------------------------------------------------------------------- /Huang_Improved/getadd_psnr_HS.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/getadd_psnr_HS.m -------------------------------------------------------------------------------- /Huang_Improved/getcodelength.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/getcodelength.m -------------------------------------------------------------------------------- /Huang_Improved/getpayload_HS.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/getpayload_HS.m -------------------------------------------------------------------------------- /Huang_Improved/getsignal.m: -------------------------------------------------------------------------------- 1 | function signal = getsignal(dct_coef) 2 | [m,n] = size(dct_coef); 3 | signal=cell(m/8,n/8); 4 | for i=1:8:m 5 | for j=1:8:n 6 | signal{fix(i/8)+1,fix(j/8)+1}=dct_coef(i:i+7,j:j+7); 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /Huang_Improved/jpeg_emdding_HS.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/jpeg_emdding_HS.m -------------------------------------------------------------------------------- /Huang_Improved/jpeg_extract.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/jpeg_extract.m -------------------------------------------------------------------------------- /Huang_Improved/jpeg_re.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/jpeg_re.jpg -------------------------------------------------------------------------------- /Huang_Improved/name30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/name30.jpg -------------------------------------------------------------------------------- /Huang_Improved/psnr.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/psnr.m -------------------------------------------------------------------------------- /Huang_Improved/testimgs/Airplane.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/testimgs/Airplane.tiff -------------------------------------------------------------------------------- /Huang_Improved/testimgs/Baboon.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/testimgs/Baboon.tiff -------------------------------------------------------------------------------- /Huang_Improved/testimgs/Lena.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/testimgs/Lena.tiff -------------------------------------------------------------------------------- /Huang_Improved/testimgs/Peppers.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edu-yinzhaoxia/Reversible-Data-Hiding-in-JPEG-Images-with-Multi-objective-Optimization/5b95ba6a58b5cd65bc881212fb9e0e4972dfba20/Huang_Improved/testimgs/Peppers.tiff -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reversible Data Hiding in JPEG Images with Multi-objective Optimization 2 | This code is the implementation of the paper "Reversible Data Hiding in JPEG Images with Multi Objective Optimization". 3 | 4 | [Paper Link](https://ieeexplore.ieee.org/abstract/document/8970412/) 5 | 6 | ## Abstract 7 | Among various methods of reversible data hiding (RDH) in JPEG images, only rate-distortion, i.e. the image quality with given payload, is taken into consideration during algorithm designing. However, file size expansion is another important evaluation metric for JPEG RDH methods. Based on this situation, we propose a JPEG RDH method considering both the rate-distortion and the file size expansion at the same time while designing the algorithm. The multi-objective optimization strategy is utilized to realize the balance of the two objectives. Specifically, the cover signal is divided into several nonoverlapping parts firstly, and after that, the embedding costs of each part are calculated. Next, the optimized combination of parts for embedding data is gained by multi-objective optimization. Experimental results show that the proposed algorithm outperforms the state-of-the-art methods in terms of rate-distortion and file size expansion performance. 8 | 9 | ## 摘要 10 | 在JPEG图像中可逆数据隐藏(RDH)的各种方法中,在算法设计过程中仅考虑速率失真,即具有给定有效负载的图像质量。 但是,文件大小扩展是JPEG RDH方法的另一个重要评估指标。 针对这种情况,在设计算法的同时,提出了同时考虑速率失真和文件扩展的JPEG RDH方法。 利用多目标优化策略来实现两个目标的平衡。 具体地,首先将覆盖信号分为几个不重叠的部分,然后,计算每个部分的嵌入成本。 接下来,通过多目标优化获得用于嵌入数据的零件的优化组合。 实验结果表明,所提出的算法在速率失真和文件大小扩展性能方面均优于最新方法。 11 | 12 | ## How to cite our paper 13 | @article{yin2020reversible, 14 | title={Reversible Data Hiding in JPEG Images with Multi-objective Optimization}, 15 | author={Yin, Zhaoxia and Ji, Yuan and Luo, Bin}, 16 | journal={IEEE Transactions on Circuits and Systems for Video Technology}, 17 | year={2020}, 18 | publisher={IEEE} 19 | } 20 | --------------------------------------------------------------------------------