JPEG再考(その3)
DC,ACの符号量を量るために,Independet Jpeg Groupの"jpeg-6b"に改変したところを残しておきます.
jpeglib.hにはdcbitsとacbits,どの係数を残すかを決めるmaskを追加しました.
jchuff.cが,実際に符号量を計算しているところ.
cjpeg.cで,maskをコマンドラインから取得しています.かなり秀逸な指定方法だと自負しているんだけど,どうだろう?
--- jpeglib.h 1998-02-22 04:48:14.000000000 +0900 +++ jpeglib.h 2007-11-21 20:01:26.000000000 +0900 @@ -403,6 +403,8 @@ struct jpeg_entropy_encoder * entropy; jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ int script_space_size; + int dcbits, acbits; + JCOEF mask[DCTSIZE2]; };
--- jchuff.c 1997-10-21 09:20:39.000000000 +0900 +++ jchuff.c 2007-11-21 20:33:42.000000000 +0900 @@ -356,9 +356,13 @@ register int temp, temp2; register int nbits; register int k, r, i; + register int acbits; + + acbits = 0; /* Encode the DC coefficient difference per section F.1.2.1 */ + block[0] &= state->cinfo->mask[0]; temp = temp2 = block[0] - last_dc_val; if (temp < 0) { @@ -383,6 +387,7 @@ /* Emit the Huffman-coded symbol for the number of bits */ if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) return FALSE; + state->cinfo->dcbits += dctbl->ehufsi[nbits] + (nbits?nbits:0); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ @@ -395,6 +400,7 @@ r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { + block[jpeg_natural_order[k]] &= state->cinfo->mask[k]; if ((temp = block[jpeg_natural_order[k]]) == 0) { r++; } else { @@ -403,6 +409,7 @@ if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) return FALSE; r -= 16; + acbits += actbl->ehufsi[0xF0]; } temp2 = temp; @@ -424,11 +431,13 @@ i = (r << 4) + nbits; if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) return FALSE; + acbits += actbl->ehufsi[i]; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (! emit_bits(state, (unsigned int) temp2, nbits)) return FALSE; + acbits += nbits; r = 0; } @@ -438,6 +447,9 @@ if (r > 0) if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) return FALSE; + if (r > 0) + acbits += actbl->ehufsi[0]; + state->cinfo->acbits += acbits; return TRUE; }
--- cjpeg.c 1998-03-21 10:21:49.000000000 +0900 +++ cjpeg.c 2007-11-23 12:29:18.000000000 +0900 @@ -411,6 +411,39 @@ /* Input file is Targa format. */ is_targa = TRUE; + } else if (keymatch(arg, "mask", 2)) { + /* Mask tables */ + int i, c; + if (++argn >= argc) /* advance to next argument */ + usage(); + i = 0; + while ((c = argv[argn][i]) && (i < 16)) { + if ('0'<= c && c <= '9') {c -= '0'; } + else if ('A'<= c && c <= 'F') {c -= 'A'-10; } + else if ('a'<= c && c <= 'f') {c -= 'a'-10; } + else {usage(); break;} + cinfo->mask[i*4+0] = (c&8)?(~0):(0); + cinfo->mask[i*4+1] = (c&4)?(~0):(0); + cinfo->mask[i*4+2] = (c&2)?(~0):(0); + cinfo->mask[i*4+3] = (c&1)?(~0):(0); + i++; + } + if (i < 16) { + c = argv[argn][i-1]; + if ('0'<= c && c <= '9') {c -= '0'; } + else if ('A'<= c && c <= 'F') {c -= 'A'-10; } + else if ('a'<= c && c <= 'f') {c -= 'a'-10; } + else {usage(); break;} + c &= 1; + for (;i < 16; i++) { + cinfo->mask[i*4+0] = (c)?(~0):(0); + cinfo->mask[i*4+1] = (c)?(~0):(0); + cinfo->mask[i*4+2] = (c)?(~0):(0); + cinfo->mask[i*4+3] = (c)?(~0):(0); + } + } + //for (i=0;i<DCTSIZE2;i++) fprintf(stderr, "%d", cinfo->mask[i]&1); + } else { usage(); /* bogus switch */ } @@ -483,6 +516,8 @@ /* Initialize the JPEG compression object with default error handling. */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); + cinfo.acbits = cinfo.dcbits = 0; + int i; for (i=0;i<DCTSIZE2;i++) cinfo.mask[i]=~0; /* Add some application-specific error messages (from cderror.h) */ jerr.addon_message_table = cdjpeg_message_table; jerr.first_addon_message = JMSG_FIRSTADDONCODE; @@ -599,6 +634,9 @@ #ifdef PROGRESS_REPORT end_progress_monitor((j_common_ptr) &cinfo); #endif + int blks; + blks = cinfo.image_height*cinfo.image_width/DCTSIZE2; + fprintf(stderr, " %f %f\n", (double)cinfo.dcbits/blks, (double)cinfo.acbits/blks); /* All done. */ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);