Commit f4b5291c4ab2420e057808163367ddaf70743752
1 parent
f8dfbefc
Exists in
master
Qaulity Calculatiing!
Showing
13 changed files
with
457 additions
and
166 deletions
Show diff stats
mjpeg/__init__.py
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | from libmjsteg import Jsteg |
| 4 | 4 | |
| 5 | -__all__ = ['Jpeg','colorMap','diffblock','diffblocks'] | |
| 5 | +__all__ = ['Jpeg', 'colorMap', 'diffblock', 'diffblocks'] | |
| 6 | 6 | |
| 7 | 7 | # We need standard components from :mod:`numpy`, and some auxiliary |
| 8 | 8 | # functions from submodules. |
| ... | ... | @@ -16,6 +16,7 @@ import pylab as plt |
| 16 | 16 | |
| 17 | 17 | import base |
| 18 | 18 | from dct import bdct, ibdct |
| 19 | +from compress import * | |
| 19 | 20 | |
| 20 | 21 | # The colour codes are defined in the JPEG standard. We store |
| 21 | 22 | # them here for easy reference by name:: |
| ... | ... | @@ -55,7 +56,7 @@ class Jpeg(Jsteg): |
| 55 | 56 | Jsteg.__init__(self, file, **kw) |
| 56 | 57 | self.verbosity = verbosity |
| 57 | 58 | if verbosity > 0: |
| 58 | - print "[Jpeg.__init__] Image size %ix%i" % (self.coef_arrays[0].shape) | |
| 59 | + print "[Jpeg.__init__] Image size %ix%i" % (self.image_width, self.image_height) | |
| 59 | 60 | if key != None: |
| 60 | 61 | self.key = key |
| 61 | 62 | elif rndkey: |
| ... | ... | @@ -290,6 +291,47 @@ class Jpeg(Jsteg): |
| 290 | 291 | self.coef_arrays[cID][v:v + 8, h:h + 8] = blocks[i, j] |
| 291 | 292 | self.Jsetblock(j, i, cID, bytearray(blocks[i, j].astype(np.int16))) |
| 292 | 293 | |
| 294 | + def getSize(self): | |
| 295 | + return self.image_width, self.image_height | |
| 296 | + | |
| 297 | + def getQuality(self): | |
| 298 | + """ | |
| 299 | + Qaulity rating algorithm from ImageMagick. | |
| 300 | + | |
| 301 | + e.g. | |
| 302 | + find ./ -name "*.jpg" | xargs -i sh -c "echo -n {} && identify -quiet -verbose {} |grep -E 'Quality' " | |
| 303 | + | |
| 304 | + Ref - http://stackoverflow.com/questions/2024947/is-it-possible-to-tell-the-quality-level-of-a-jpeg,http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=20235 | |
| 305 | + """ | |
| 306 | + table0 = self.quant_tables[0].ravel() | |
| 307 | + table1 = self.quant_tables[1].ravel() | |
| 308 | + sum0 = np.sum(table0) | |
| 309 | + sum1 = np.sum(table1) | |
| 310 | + quality = None | |
| 311 | + | |
| 312 | + if sum0 != None: | |
| 313 | + if sum1 != None: | |
| 314 | + sum = sum0 + sum1 | |
| 315 | + qvalue = table0[2] + table0[53] + table1[0] + table1[-1] | |
| 316 | + hashtable = bi_hash | |
| 317 | + sumtable = bi_sum | |
| 318 | + else: | |
| 319 | + sum = sum0 | |
| 320 | + qvalue = table0[2] + table0[53] | |
| 321 | + hashtable = single_hash | |
| 322 | + sumtable = single_sum | |
| 323 | + else: | |
| 324 | + raise Exception("Quantization Tables Illegal") | |
| 325 | + return None | |
| 326 | + | |
| 327 | + for i in range(100): | |
| 328 | + if qvalue >= hashtable[i] or sum >= sumtable[i]: | |
| 329 | + break | |
| 330 | + quality = i + 1 | |
| 331 | + | |
| 332 | + return quality | |
| 333 | + | |
| 334 | + | |
| 293 | 335 | # Decompression |
| 294 | 336 | # ------------- |
| 295 | 337 | |
| ... | ... | @@ -404,3 +446,13 @@ def diffblocks(a, b): |
| 404 | 446 | cnt += 1 |
| 405 | 447 | return diff, cnt |
| 406 | 448 | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | ... | ... |
mjpeg/__init__.pyc
No preview for this file type
mjpeg/compress.py
| ... | ... | @@ -5,179 +5,94 @@ from pylab import * |
| 5 | 5 | |
| 6 | 6 | # The standard quantisation tables for JPEG:: |
| 7 | 7 | |
| 8 | -table0 = array( | |
| 9 | - [ [ 16, 11, 10, 16, 24, 40, 51, 61 ], | |
| 10 | - [ 12, 12, 14, 19, 26, 58, 60, 55 ], | |
| 11 | - [ 14, 13, 16, 24, 40, 57, 69, 56 ], | |
| 12 | - [ 14, 17, 22, 29, 51, 87, 80, 62 ], | |
| 13 | - [ 18, 22, 37, 56, 68, 109, 103, 77 ], | |
| 14 | - [ 24, 35, 55, 64, 81, 104, 113, 92 ], | |
| 15 | - [ 49, 64, 78, 87, 103, 121, 120, 101 ], | |
| 16 | - [ 72, 92, 95, 98, 112, 100, 103, 99 ] ] ) | |
| 8 | +orig_table0 = array( | |
| 9 | + [[16, 11, 10, 16, 24, 40, 51, 61], | |
| 10 | + [12, 12, 14, 19, 26, 58, 60, 55], | |
| 11 | + [14, 13, 16, 24, 40, 57, 69, 56], | |
| 12 | + [14, 17, 22, 29, 51, 87, 80, 62], | |
| 13 | + [18, 22, 37, 56, 68, 109, 103, 77], | |
| 14 | + [24, 35, 55, 64, 81, 104, 113, 92], | |
| 15 | + [49, 64, 78, 87, 103, 121, 120, 101], | |
| 16 | + [72, 92, 95, 98, 112, 100, 103, 99]]) | |
| 17 | + | |
| 18 | +orig_table1 = array( | |
| 19 | + [[17, 18, 24, 47, 99, 99, 99, 99], | |
| 20 | + [18, 21, 26, 66, 99, 99, 99, 99], | |
| 21 | + [24, 26, 56, 99, 99, 99, 99, 99], | |
| 22 | + [47, 66, 99, 99, 99, 99, 99, 99], | |
| 23 | + [99, 99, 99, 99, 99, 99, 99, 99], | |
| 24 | + [99, 99, 99, 99, 99, 99, 99, 99], | |
| 25 | + [99, 99, 99, 99, 99, 99, 99, 99], | |
| 26 | + [99, 99, 99, 99, 99, 99, 99, 99]]) | |
| 27 | + | |
| 28 | +bi_hash = [ | |
| 29 | + 1020, 1015, 932, 848, 780, 735, 702, 679, 660, 645, | |
| 30 | + 632, 623, 613, 607, 600, 594, 589, 585, 581, 571, | |
| 31 | + 555, 542, 529, 514, 494, 474, 457, 439, 424, 410, | |
| 32 | + 397, 386, 373, 364, 351, 341, 334, 324, 317, 309, | |
| 33 | + 299, 294, 287, 279, 274, 267, 262, 257, 251, 247, | |
| 34 | + 243, 237, 232, 227, 222, 217, 213, 207, 202, 198, | |
| 35 | + 192, 188, 183, 177, 173, 168, 163, 157, 153, 148, | |
| 36 | + 143, 139, 132, 128, 125, 119, 115, 108, 104, 99, | |
| 37 | + 94, 90, 84, 79, 74, 70, 64, 59, 55, 49, | |
| 38 | + 45, 40, 34, 30, 25, 20, 15, 11, 6, 4, | |
| 39 | + 0 | |
| 40 | +] | |
| 41 | + | |
| 42 | +bi_sum = [ | |
| 43 | + 32640, 32635, 32266, 31495, 30665, 29804, 29146, 28599, 28104, | |
| 44 | + 27670, 27225, 26725, 26210, 25716, 25240, 24789, 24373, 23946, | |
| 45 | + 23572, 22846, 21801, 20842, 19949, 19121, 18386, 17651, 16998, | |
| 46 | + 16349, 15800, 15247, 14783, 14321, 13859, 13535, 13081, 12702, | |
| 47 | + 12423, 12056, 11779, 11513, 11135, 10955, 10676, 10392, 10208, | |
| 48 | + 9928, 9747, 9564, 9369, 9193, 9017, 8822, 8639, 8458, | |
| 49 | + 8270, 8084, 7896, 7710, 7527, 7347, 7156, 6977, 6788, | |
| 50 | + 6607, 6422, 6236, 6054, 5867, 5684, 5495, 5305, 5128, | |
| 51 | + 4945, 4751, 4638, 4442, 4248, 4065, 3888, 3698, 3509, | |
| 52 | + 3326, 3139, 2957, 2775, 2586, 2405, 2216, 2037, 1846, | |
| 53 | + 1666, 1483, 1297, 1109, 927, 735, 554, 375, 201, | |
| 54 | + 128, 0 | |
| 55 | +] | |
| 56 | + | |
| 57 | +single_hash = [ | |
| 58 | + 510, 505, 422, 380, 355, 338, 326, 318, 311, 305, | |
| 59 | + 300, 297, 293, 291, 288, 286, 284, 283, 281, 280, | |
| 60 | + 279, 278, 277, 273, 262, 251, 243, 233, 225, 218, | |
| 61 | + 211, 205, 198, 193, 186, 181, 177, 172, 168, 164, | |
| 62 | + 158, 156, 152, 148, 145, 142, 139, 136, 133, 131, | |
| 63 | + 129, 126, 123, 120, 118, 115, 113, 110, 107, 105, | |
| 64 | + 102, 100, 97, 94, 92, 89, 87, 83, 81, 79, | |
| 65 | + 76, 74, 70, 68, 66, 63, 61, 57, 55, 52, | |
| 66 | + 50, 48, 44, 42, 39, 37, 34, 31, 29, 26, | |
| 67 | + 24, 21, 18, 16, 13, 11, 8, 6, 3, 2, | |
| 68 | + 0 | |
| 69 | +] | |
| 70 | + | |
| 71 | +single_sum = [ | |
| 72 | + 16320, 16315, 15946, 15277, 14655, 14073, 13623, 13230, 12859, | |
| 73 | + 12560, 12240, 11861, 11456, 11081, 10714, 10360, 10027, 9679, | |
| 74 | + 9368, 9056, 8680, 8331, 7995, 7668, 7376, 7084, 6823, | |
| 75 | + 6562, 6345, 6125, 5939, 5756, 5571, 5421, 5240, 5086, | |
| 76 | + 4976, 4829, 4719, 4616, 4463, 4393, 4280, 4166, 4092, | |
| 77 | + 3980, 3909, 3835, 3755, 3688, 3621, 3541, 3467, 3396, | |
| 78 | + 3323, 3247, 3170, 3096, 3021, 2952, 2874, 2804, 2727, | |
| 79 | + 2657, 2583, 2509, 2437, 2362, 2290, 2211, 2136, 2068, | |
| 80 | + 1996, 1915, 1858, 1773, 1692, 1620, 1552, 1477, 1398, | |
| 81 | + 1326, 1251, 1179, 1109, 1031, 961, 884, 814, 736, | |
| 82 | + 667, 592, 518, 441, 369, 292, 221, 151, 86, | |
| 83 | + 64, 0 | |
| 84 | +] | |
| 17 | 85 | |
| 18 | -table1 = array( | |
| 19 | - [ [ 17, 18, 24, 47, 99, 99, 99, 99 ], | |
| 20 | - [ 18, 21, 26, 66, 99, 99, 99, 99 ], | |
| 21 | - [ 24, 26, 56, 99, 99, 99, 99, 99 ], | |
| 22 | - [ 47, 66, 99, 99, 99, 99, 99, 99 ], | |
| 23 | - [ 99, 99, 99, 99, 99, 99, 99, 99 ], | |
| 24 | - [ 99, 99, 99, 99, 99, 99, 99, 99 ], | |
| 25 | - [ 99, 99, 99, 99, 99, 99, 99, 99 ], | |
| 26 | - [ 99, 99, 99, 99, 99, 99, 99, 99 ] ] ) | |
| 27 | 86 | |
| 28 | -# The quantTable function seems straight forward, | |
| 29 | -# but has not been tested. | |
| 30 | 87 | |
| 31 | -def quantTable(quality=50,tnum=0,force_baseline=False): | |
| 32 | - if quality <= 0: quality = 1 | |
| 33 | - elif quality > 100: quality = 100 | |
| 34 | - if quality < 50: quality = 5000 / quality | |
| 35 | - else: quality = 200 - quality*2 | |
| 36 | 88 | |
| 37 | - t = floor( (t * quality + 50) /100 ) | |
| 38 | 89 | |
| 39 | - t[t<1] = 1 | |
| 40 | 90 | |
| 41 | - if (force_baseline): t[t>255] = 255 | |
| 42 | - else: t[t>32767] = 32767 # max quantizer needed for 12 bits | |
| 43 | 91 | |
| 44 | - return t | |
| 45 | 92 | |
| 46 | -# I don't think this works. | |
| 47 | 93 | |
| 48 | -def bdctmtx(n=8): | |
| 49 | - (c,r) = meshgrid(range(n), range(n)) | |
| 50 | - (c0,r0) = meshgrid(r.flatten()); | |
| 51 | - (c1,r1) = meshgrid(c.flatten()); | |
| 52 | 94 | |
| 53 | - x = sqrt(float(2) / n) | |
| 54 | - x *= cos( pi * (2*c + 1) * r / (2 * n)); | |
| 55 | - x[1,:] = x[1,:] / sqrt(2); | |
| 56 | 95 | |
| 57 | - return x[r0+c0*n+1] * x[r1+c1*n+1] | |
| 58 | 96 | |
| 59 | -def im2vec(im,blksize=8,padsize=0): | |
| 60 | - """Reshape 2D image blocks into an array of column vectors | |
| 61 | 97 | |
| 62 | - V=im2vec(im,blksize=8,padsize=0) | |
| 63 | - | |
| 64 | - IM is an image to be separated into non-overlapping blocks and | |
| 65 | - reshaped into an MxN array containing N blocks reshaped into Mx1 | |
| 66 | - column vectors. im2vec is designed to be the inverse of vec2im. | |
| 67 | - | |
| 68 | - BLKSIZE is a scalar or 1x2 vector indicating the size of the blocks. | |
| 69 | - | |
| 70 | - PADSIZE is a scalar or 1x2 vector indicating the amount of vertical | |
| 71 | - and horizontal space to be skipped between blocks in the image. | |
| 72 | - Default is [0 0]. If PADSIZE is a scalar, the same amount of space | |
| 73 | - is used for both directions. PADSIZE must be non-negative (blocks | |
| 74 | - must be non-overlapping). | |
| 75 | - | |
| 76 | - ROWS indicates the number of rows of blocks found in the image. | |
| 77 | - COLS indicates the number of columns of blocks found in the image. | |
| 78 | - """ | |
| 79 | - | |
| 80 | - blksize=blksize + array( [0,0] ) | |
| 81 | - padsize=padsize + array( [0,0] ) | |
| 82 | - if ( any( padsize < 0 ) ): | |
| 83 | - raise InputException, "Pad size must be non-negative." | |
| 84 | - | |
| 85 | - (height,width) = im.shape | |
| 86 | - (y,x) = blksize + padsize | |
| 87 | - | |
| 88 | - rows = int( ( height + padsize[0] ) / y ) | |
| 89 | - cols = int( ( width + padsize[1] ) / x ) | |
| 90 | - | |
| 91 | - T = zeros( [y*rows,x*cols] ) | |
| 92 | - | |
| 93 | - imy = y*rows - padsize[0] | |
| 94 | - imx = x*cols - padsize[1] | |
| 95 | - | |
| 96 | - T[0:imy,0:imx] = im[0:imy,0:imx] | |
| 97 | - | |
| 98 | - T = reshape(T, [ cols, y, rows, x ] ) | |
| 99 | - T = transpose( T, [0,2,1,3]) | |
| 100 | - T = reshape( T, [ y, x, rows*cols ] ) | |
| 101 | - V = T[0:blksize[0], 0:blksize[1], 0:(rows*cols) ] | |
| 102 | - | |
| 103 | - return (reshape( V, [ rows*cols, y*x ] ), rows, cols) | |
| 104 | - | |
| 105 | -def vec2im(V,blksize=None,padsize=0,rows=None,cols=None): | |
| 106 | - """Reshape and combine column vectors into a 2D image | |
| 107 | - | |
| 108 | - V is an MxN array containing N Mx1 column vectors which will be reshaped | |
| 109 | - and combined to form image IM. | |
| 110 | - | |
| 111 | - PADSIZE is a scalar or a 1x2 vector indicating the amount of vertical and | |
| 112 | - horizontal space to be added as a border between the reshaped vectors. | |
| 113 | - Default is [0 0]. If PADSIZE is a scalar, the same amount of space is used | |
| 114 | - for both directions. | |
| 115 | - | |
| 116 | - BLKSIZE is a scalar or a 1x2 vector indicating the size of the blocks. | |
| 117 | - Default is sqrt(M). | |
| 118 | - | |
| 119 | - ROWS indicates the number of rows of blocks in the image. Default is | |
| 120 | - floor(sqrt(N)). | |
| 121 | - | |
| 122 | - COLS indicates the number of columns of blocks in the image. Default | |
| 123 | - is ceil(N/ROWS). | |
| 124 | - """ | |
| 125 | - | |
| 126 | - (n,m) = V.shape | |
| 127 | - | |
| 128 | - padsize = padsize + array( [0,0] ) | |
| 129 | - if ( any( padsize < 0 ) ): | |
| 130 | - raise InputException, "Pad size must be non-negative." | |
| 131 | - | |
| 132 | - if blksize == None: | |
| 133 | - bsize = floor(sqrt(m)) | |
| 134 | - | |
| 135 | - blksize = blksize + array([0,0]) | |
| 136 | - if prod(blksize) != m: | |
| 137 | - print m, blksize | |
| 138 | - raise InputException, 'Block size does not match size of input vectors.' | |
| 139 | - | |
| 140 | - if rows == None: | |
| 141 | - rows = floor(sqrt(n)) | |
| 142 | - if cols == None: | |
| 143 | - cols = ceil(n/rows) | |
| 144 | - | |
| 145 | -# make image | |
| 146 | -# | |
| 147 | -# :: | |
| 148 | - | |
| 149 | - (y,x) = blksize + padsize | |
| 150 | - | |
| 151 | -# zero() returns float64 and causes T to become a floating point array | |
| 152 | -# This is a bug; integer input should give integer return | |
| 153 | -# | |
| 154 | -# :: | |
| 155 | - | |
| 156 | - T = zeros( [rows*cols, y, x] ) | |
| 157 | - T[0:n, 0:blksize[0], 0:blksize[1]] = \ | |
| 158 | - reshape( V, [n, blksize[0], blksize[1] ] ) | |
| 159 | - T = reshape(T, [rows,cols,y,x] ) | |
| 160 | - T = transpose( T, [0,2,1,3] ) | |
| 161 | - T = reshape(T, [y*rows,x*cols] ) | |
| 162 | - return T[0:(y*rows-padsize[0]), 0:(x*cols-padsize[1]) ] | |
| 163 | - | |
| 164 | -def quantise(C,Q): | |
| 165 | - """Quantise DCT coefficients using the quantisation matrix Q.""" | |
| 166 | - return C / repmat( Q, C.shape / Q.shape ) | |
| 167 | - | |
| 168 | -def dequantise(C,Q): | |
| 169 | - """Dequantise JPEG coefficients using the quantisation matrix Q.""" | |
| 170 | - return C * repmat( Q, C.shape / Q.shape ) | |
| 171 | - | |
| 172 | -def bdct(A,blksize=8): | |
| 173 | - """Blocked discrete cosine transform for JPEG compression.""" | |
| 174 | - dctm = bdctmtx(blksize) | |
| 175 | - (v,r,c) = im2vec(a,blksize) | |
| 176 | - return vec2im(dot(dctm,v),blksize,rows=r,cols=c) | |
| 177 | - | |
| 178 | -def ibdct(A,blksize=8): | |
| 179 | - """Inverse blocked discrete cosine transform""" | |
| 180 | - dctm = bdctmtx(blksize) | |
| 181 | - (v,r,c) = im2vec(a,blksize) | |
| 182 | - return vec2im(dot(transpose(dctm),v),blksize,rows=r,cols=c) | |
| 183 | 98 | ... | ... |
No preview for this file type
msteg/steganalysis/MPB.py
| ... | ... | @@ -16,6 +16,10 @@ import pickle |
| 16 | 16 | import cv2 |
| 17 | 17 | from sklearn import svm |
| 18 | 18 | |
| 19 | +# from numba import jit | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 19 | 23 | base_dir = '/home/hadoop/data/HeadShoulder/' |
| 20 | 24 | |
| 21 | 25 | |
| ... | ... | @@ -82,7 +86,7 @@ class MPB(StegBase): |
| 82 | 86 | # 1.422729s |
| 83 | 87 | return TPM |
| 84 | 88 | |
| 85 | - | |
| 89 | + @jit | |
| 86 | 90 | def get_trans_prob_mat(self, ciq, T=4): |
| 87 | 91 | """ |
| 88 | 92 | Calculate Transition Probability Matrix. | ... | ... |
msteg/steganalysis/MPB.pyc
No preview for this file type
msteg/steganalysis/__init__.pyc
No preview for this file type
msteg/steganography/F4.pyc
No preview for this file type
msteg/steganography/F5.pyc
No preview for this file type
msteg/steganography/__init__.pyc
No preview for this file type
| ... | ... | @@ -0,0 +1,183 @@ |
| 1 | +## -*- coding: utf-8 -*- | |
| 2 | + | |
| 3 | + | |
| 4 | +from pylab import * | |
| 5 | + | |
| 6 | +# The standard quantisation tables for JPEG:: | |
| 7 | + | |
| 8 | +table0 = array( | |
| 9 | + [ [ 16, 11, 10, 16, 24, 40, 51, 61 ], | |
| 10 | + [ 12, 12, 14, 19, 26, 58, 60, 55 ], | |
| 11 | + [ 14, 13, 16, 24, 40, 57, 69, 56 ], | |
| 12 | + [ 14, 17, 22, 29, 51, 87, 80, 62 ], | |
| 13 | + [ 18, 22, 37, 56, 68, 109, 103, 77 ], | |
| 14 | + [ 24, 35, 55, 64, 81, 104, 113, 92 ], | |
| 15 | + [ 49, 64, 78, 87, 103, 121, 120, 101 ], | |
| 16 | + [ 72, 92, 95, 98, 112, 100, 103, 99 ] ] ) | |
| 17 | + | |
| 18 | +table1 = array( | |
| 19 | + [ [ 17, 18, 24, 47, 99, 99, 99, 99 ], | |
| 20 | + [ 18, 21, 26, 66, 99, 99, 99, 99 ], | |
| 21 | + [ 24, 26, 56, 99, 99, 99, 99, 99 ], | |
| 22 | + [ 47, 66, 99, 99, 99, 99, 99, 99 ], | |
| 23 | + [ 99, 99, 99, 99, 99, 99, 99, 99 ], | |
| 24 | + [ 99, 99, 99, 99, 99, 99, 99, 99 ], | |
| 25 | + [ 99, 99, 99, 99, 99, 99, 99, 99 ], | |
| 26 | + [ 99, 99, 99, 99, 99, 99, 99, 99 ] ] ) | |
| 27 | + | |
| 28 | +# The quantTable function seems straight forward, | |
| 29 | +# but has not been tested. | |
| 30 | + | |
| 31 | +def quantTable(quality=50,tnum=0,force_baseline=False): | |
| 32 | + if quality <= 0: quality = 1 | |
| 33 | + elif quality > 100: quality = 100 | |
| 34 | + if quality < 50: quality = 5000 / quality | |
| 35 | + else: quality = 200 - quality*2 | |
| 36 | + | |
| 37 | + t = floor( (t * quality + 50) /100 ) | |
| 38 | + | |
| 39 | + t[t<1] = 1 | |
| 40 | + | |
| 41 | + if (force_baseline): t[t>255] = 255 | |
| 42 | + else: t[t>32767] = 32767 # max quantizer needed for 12 bits | |
| 43 | + | |
| 44 | + return t | |
| 45 | + | |
| 46 | +# I don't think this works. | |
| 47 | + | |
| 48 | +def bdctmtx(n=8): | |
| 49 | + (c,r) = meshgrid(range(n), range(n)) | |
| 50 | + (c0,r0) = meshgrid(r.flatten()); | |
| 51 | + (c1,r1) = meshgrid(c.flatten()); | |
| 52 | + | |
| 53 | + x = sqrt(float(2) / n) | |
| 54 | + x *= cos( pi * (2*c + 1) * r / (2 * n)); | |
| 55 | + x[1,:] = x[1,:] / sqrt(2); | |
| 56 | + | |
| 57 | + return x[r0+c0*n+1] * x[r1+c1*n+1] | |
| 58 | + | |
| 59 | +def im2vec(im,blksize=8,padsize=0): | |
| 60 | + """Reshape 2D image blocks into an array of column vectors | |
| 61 | + | |
| 62 | + V=im2vec(im,blksize=8,padsize=0) | |
| 63 | + | |
| 64 | + IM is an image to be separated into non-overlapping blocks and | |
| 65 | + reshaped into an MxN array containing N blocks reshaped into Mx1 | |
| 66 | + column vectors. im2vec is designed to be the inverse of vec2im. | |
| 67 | + | |
| 68 | + BLKSIZE is a scalar or 1x2 vector indicating the size of the blocks. | |
| 69 | + | |
| 70 | + PADSIZE is a scalar or 1x2 vector indicating the amount of vertical | |
| 71 | + and horizontal space to be skipped between blocks in the image. | |
| 72 | + Default is [0 0]. If PADSIZE is a scalar, the same amount of space | |
| 73 | + is used for both directions. PADSIZE must be non-negative (blocks | |
| 74 | + must be non-overlapping). | |
| 75 | + | |
| 76 | + ROWS indicates the number of rows of blocks found in the image. | |
| 77 | + COLS indicates the number of columns of blocks found in the image. | |
| 78 | + """ | |
| 79 | + | |
| 80 | + blksize=blksize + array( [0,0] ) | |
| 81 | + padsize=padsize + array( [0,0] ) | |
| 82 | + if ( any( padsize < 0 ) ): | |
| 83 | + raise InputException, "Pad size must be non-negative." | |
| 84 | + | |
| 85 | + (height,width) = im.shape | |
| 86 | + (y,x) = blksize + padsize | |
| 87 | + | |
| 88 | + rows = int( ( height + padsize[0] ) / y ) | |
| 89 | + cols = int( ( width + padsize[1] ) / x ) | |
| 90 | + | |
| 91 | + T = zeros( [y*rows,x*cols] ) | |
| 92 | + | |
| 93 | + imy = y*rows - padsize[0] | |
| 94 | + imx = x*cols - padsize[1] | |
| 95 | + | |
| 96 | + T[0:imy,0:imx] = im[0:imy,0:imx] | |
| 97 | + | |
| 98 | + T = reshape(T, [ cols, y, rows, x ] ) | |
| 99 | + T = transpose( T, [0,2,1,3]) | |
| 100 | + T = reshape( T, [ y, x, rows*cols ] ) | |
| 101 | + V = T[0:blksize[0], 0:blksize[1], 0:(rows*cols) ] | |
| 102 | + | |
| 103 | + return (reshape( V, [ rows*cols, y*x ] ), rows, cols) | |
| 104 | + | |
| 105 | +def vec2im(V,blksize=None,padsize=0,rows=None,cols=None): | |
| 106 | + """Reshape and combine column vectors into a 2D image | |
| 107 | + | |
| 108 | + V is an MxN array containing N Mx1 column vectors which will be reshaped | |
| 109 | + and combined to form image IM. | |
| 110 | + | |
| 111 | + PADSIZE is a scalar or a 1x2 vector indicating the amount of vertical and | |
| 112 | + horizontal space to be added as a border between the reshaped vectors. | |
| 113 | + Default is [0 0]. If PADSIZE is a scalar, the same amount of space is used | |
| 114 | + for both directions. | |
| 115 | + | |
| 116 | + BLKSIZE is a scalar or a 1x2 vector indicating the size of the blocks. | |
| 117 | + Default is sqrt(M). | |
| 118 | + | |
| 119 | + ROWS indicates the number of rows of blocks in the image. Default is | |
| 120 | + floor(sqrt(N)). | |
| 121 | + | |
| 122 | + COLS indicates the number of columns of blocks in the image. Default | |
| 123 | + is ceil(N/ROWS). | |
| 124 | + """ | |
| 125 | + | |
| 126 | + (n,m) = V.shape | |
| 127 | + | |
| 128 | + padsize = padsize + array( [0,0] ) | |
| 129 | + if ( any( padsize < 0 ) ): | |
| 130 | + raise InputException, "Pad size must be non-negative." | |
| 131 | + | |
| 132 | + if blksize == None: | |
| 133 | + bsize = floor(sqrt(m)) | |
| 134 | + | |
| 135 | + blksize = blksize + array([0,0]) | |
| 136 | + if prod(blksize) != m: | |
| 137 | + print m, blksize | |
| 138 | + raise InputException, 'Block size does not match size of input vectors.' | |
| 139 | + | |
| 140 | + if rows == None: | |
| 141 | + rows = floor(sqrt(n)) | |
| 142 | + if cols == None: | |
| 143 | + cols = ceil(n/rows) | |
| 144 | + | |
| 145 | +# make image | |
| 146 | +# | |
| 147 | +# :: | |
| 148 | + | |
| 149 | + (y,x) = blksize + padsize | |
| 150 | + | |
| 151 | +# zero() returns float64 and causes T to become a floating point array | |
| 152 | +# This is a bug; integer input should give integer return | |
| 153 | +# | |
| 154 | +# :: | |
| 155 | + | |
| 156 | + T = zeros( [rows*cols, y, x] ) | |
| 157 | + T[0:n, 0:blksize[0], 0:blksize[1]] = \ | |
| 158 | + reshape( V, [n, blksize[0], blksize[1] ] ) | |
| 159 | + T = reshape(T, [rows,cols,y,x] ) | |
| 160 | + T = transpose( T, [0,2,1,3] ) | |
| 161 | + T = reshape(T, [y*rows,x*cols] ) | |
| 162 | + return T[0:(y*rows-padsize[0]), 0:(x*cols-padsize[1]) ] | |
| 163 | + | |
| 164 | +def quantise(C,Q): | |
| 165 | + """Quantise DCT coefficients using the quantisation matrix Q.""" | |
| 166 | + return C / repmat( Q, C.shape / Q.shape ) | |
| 167 | + | |
| 168 | +def dequantise(C,Q): | |
| 169 | + """Dequantise JPEG coefficients using the quantisation matrix Q.""" | |
| 170 | + return C * repmat( Q, C.shape / Q.shape ) | |
| 171 | + | |
| 172 | +def bdct(A,blksize=8): | |
| 173 | + """Blocked discrete cosine transform for JPEG compression.""" | |
| 174 | + dctm = bdctmtx(blksize) | |
| 175 | + (v,r,c) = im2vec(a,blksize) | |
| 176 | + return vec2im(dot(dctm,v),blksize,rows=r,cols=c) | |
| 177 | + | |
| 178 | +def ibdct(A,blksize=8): | |
| 179 | + """Inverse blocked discrete cosine transform""" | |
| 180 | + dctm = bdctmtx(blksize) | |
| 181 | + (v,r,c) = im2vec(a,blksize) | |
| 182 | + return vec2im(dot(transpose(dctm),v),blksize,rows=r,cols=c) | |
| 183 | + | ... | ... |
| ... | ... | @@ -0,0 +1,134 @@ |
| 1 | +static void JPEGSetImageQuality(struct jpeg_decompress_struct *jpeg_info, | |
| 2 | + Image *image) | |
| 3 | +{ | |
| 4 | + image->quality=UndefinedCompressionQuality; | |
| 5 | +#if defined(D_PROGRESSIVE_SUPPORTED) | |
| 6 | + if (image->compression == LosslessJPEGCompression) | |
| 7 | + { | |
| 8 | + image->quality=100; | |
| 9 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
| 10 | + "Quality: 100 (lossless)"); | |
| 11 | + } | |
| 12 | + else | |
| 13 | +#endif | |
| 14 | + { | |
| 15 | + ssize_t | |
| 16 | + j, | |
| 17 | + qvalue, | |
| 18 | + sum; | |
| 19 | + | |
| 20 | + register ssize_t | |
| 21 | + i; | |
| 22 | + | |
| 23 | + /* | |
| 24 | + Determine the JPEG compression quality from the quantization tables. | |
| 25 | + */ | |
| 26 | + sum=0; | |
| 27 | + for (i=0; i < NUM_QUANT_TBLS; i++) | |
| 28 | + { | |
| 29 | + if (jpeg_info->quant_tbl_ptrs[i] != NULL) | |
| 30 | + for (j=0; j < DCTSIZE2; j++) | |
| 31 | + sum+=jpeg_info->quant_tbl_ptrs[i]->quantval[j]; | |
| 32 | + } | |
| 33 | + if ((jpeg_info->quant_tbl_ptrs[0] != NULL) && | |
| 34 | + (jpeg_info->quant_tbl_ptrs[1] != NULL)) | |
| 35 | + { | |
| 36 | + ssize_t | |
| 37 | + hash[101] = | |
| 38 | + { | |
| 39 | + 1020, 1015, 932, 848, 780, 735, 702, 679, 660, 645, | |
| 40 | + 632, 623, 613, 607, 600, 594, 589, 585, 581, 571, | |
| 41 | + 555, 542, 529, 514, 494, 474, 457, 439, 424, 410, | |
| 42 | + 397, 386, 373, 364, 351, 341, 334, 324, 317, 309, | |
| 43 | + 299, 294, 287, 279, 274, 267, 262, 257, 251, 247, | |
| 44 | + 243, 237, 232, 227, 222, 217, 213, 207, 202, 198, | |
| 45 | + 192, 188, 183, 177, 173, 168, 163, 157, 153, 148, | |
| 46 | + 143, 139, 132, 128, 125, 119, 115, 108, 104, 99, | |
| 47 | + 94, 90, 84, 79, 74, 70, 64, 59, 55, 49, | |
| 48 | + 45, 40, 34, 30, 25, 20, 15, 11, 6, 4, | |
| 49 | + 0 | |
| 50 | + }, | |
| 51 | + sums[101] = | |
| 52 | + { | |
| 53 | + 32640, 32635, 32266, 31495, 30665, 29804, 29146, 28599, 28104, | |
| 54 | + 27670, 27225, 26725, 26210, 25716, 25240, 24789, 24373, 23946, | |
| 55 | + 23572, 22846, 21801, 20842, 19949, 19121, 18386, 17651, 16998, | |
| 56 | + 16349, 15800, 15247, 14783, 14321, 13859, 13535, 13081, 12702, | |
| 57 | + 12423, 12056, 11779, 11513, 11135, 10955, 10676, 10392, 10208, | |
| 58 | + 9928, 9747, 9564, 9369, 9193, 9017, 8822, 8639, 8458, | |
| 59 | + 8270, 8084, 7896, 7710, 7527, 7347, 7156, 6977, 6788, | |
| 60 | + 6607, 6422, 6236, 6054, 5867, 5684, 5495, 5305, 5128, | |
| 61 | + 4945, 4751, 4638, 4442, 4248, 4065, 3888, 3698, 3509, | |
| 62 | + 3326, 3139, 2957, 2775, 2586, 2405, 2216, 2037, 1846, | |
| 63 | + 1666, 1483, 1297, 1109, 927, 735, 554, 375, 201, | |
| 64 | + 128, 0 | |
| 65 | + }; | |
| 66 | + | |
| 67 | + qvalue=(ssize_t) (jpeg_info->quant_tbl_ptrs[0]->quantval[2]+ | |
| 68 | + jpeg_info->quant_tbl_ptrs[0]->quantval[53]+ | |
| 69 | + jpeg_info->quant_tbl_ptrs[1]->quantval[0]+ | |
| 70 | + jpeg_info->quant_tbl_ptrs[1]->quantval[DCTSIZE2-1]); | |
| 71 | + for (i=0; i < 100; i++) | |
| 72 | + { | |
| 73 | + if ((qvalue < hash[i]) && (sum < sums[i])) | |
| 74 | + continue; | |
| 75 | + if (((qvalue <= hash[i]) && (sum <= sums[i])) || (i >= 50)) | |
| 76 | + image->quality=(size_t) i+1; | |
| 77 | + if (image->debug != MagickFalse) | |
| 78 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
| 79 | + "Quality: %.20g (%s)",(double) i+1,(qvalue <= hash[i]) && | |
| 80 | + (sum <= sums[i]) ? "exact" : "approximate"); | |
| 81 | + break; | |
| 82 | + } | |
| 83 | + } | |
| 84 | + else | |
| 85 | + if (jpeg_info->quant_tbl_ptrs[0] != NULL) | |
| 86 | + { | |
| 87 | + ssize_t | |
| 88 | + hash[101] = | |
| 89 | + { | |
| 90 | + 510, 505, 422, 380, 355, 338, 326, 318, 311, 305, | |
| 91 | + 300, 297, 293, 291, 288, 286, 284, 283, 281, 280, | |
| 92 | + 279, 278, 277, 273, 262, 251, 243, 233, 225, 218, | |
| 93 | + 211, 205, 198, 193, 186, 181, 177, 172, 168, 164, | |
| 94 | + 158, 156, 152, 148, 145, 142, 139, 136, 133, 131, | |
| 95 | + 129, 126, 123, 120, 118, 115, 113, 110, 107, 105, | |
| 96 | + 102, 100, 97, 94, 92, 89, 87, 83, 81, 79, | |
| 97 | + 76, 74, 70, 68, 66, 63, 61, 57, 55, 52, | |
| 98 | + 50, 48, 44, 42, 39, 37, 34, 31, 29, 26, | |
| 99 | + 24, 21, 18, 16, 13, 11, 8, 6, 3, 2, | |
| 100 | + 0 | |
| 101 | + }, | |
| 102 | + sums[101] = | |
| 103 | + { | |
| 104 | + 16320, 16315, 15946, 15277, 14655, 14073, 13623, 13230, 12859, | |
| 105 | + 12560, 12240, 11861, 11456, 11081, 10714, 10360, 10027, 9679, | |
| 106 | + 9368, 9056, 8680, 8331, 7995, 7668, 7376, 7084, 6823, | |
| 107 | + 6562, 6345, 6125, 5939, 5756, 5571, 5421, 5240, 5086, | |
| 108 | + 4976, 4829, 4719, 4616, 4463, 4393, 4280, 4166, 4092, | |
| 109 | + 3980, 3909, 3835, 3755, 3688, 3621, 3541, 3467, 3396, | |
| 110 | + 3323, 3247, 3170, 3096, 3021, 2952, 2874, 2804, 2727, | |
| 111 | + 2657, 2583, 2509, 2437, 2362, 2290, 2211, 2136, 2068, | |
| 112 | + 1996, 1915, 1858, 1773, 1692, 1620, 1552, 1477, 1398, | |
| 113 | + 1326, 1251, 1179, 1109, 1031, 961, 884, 814, 736, | |
| 114 | + 667, 592, 518, 441, 369, 292, 221, 151, 86, | |
| 115 | + 64, 0 | |
| 116 | + }; | |
| 117 | + | |
| 118 | + qvalue=(ssize_t) (jpeg_info->quant_tbl_ptrs[0]->quantval[2]+ | |
| 119 | + jpeg_info->quant_tbl_ptrs[0]->quantval[53]); | |
| 120 | + for (i=0; i < 100; i++) | |
| 121 | + { | |
| 122 | + if ((qvalue < hash[i]) && (sum < sums[i])) | |
| 123 | + continue; | |
| 124 | + if (((qvalue <= hash[i]) && (sum <= sums[i])) || (i >= 50)) | |
| 125 | + image->quality=(size_t) i+1; | |
| 126 | + if (image->debug != MagickFalse) | |
| 127 | + (void) LogMagickEvent(CoderEvent,GetMagickModule(), | |
| 128 | + "Quality: %.20g (%s)",(double) i+1,(qvalue <= hash[i]) && | |
| 129 | + (sum <= sums[i]) ? "exact" : "approximate"); | |
| 130 | + break; | |
| 131 | + } | |
| 132 | + } | |
| 133 | + } | |
| 134 | +} | ... | ... |
test_jpeg.py
| ... | ... | @@ -167,7 +167,10 @@ if __name__ == '__main__': |
| 167 | 167 | |
| 168 | 168 | # test_bitbyte() |
| 169 | 169 | |
| 170 | - ima = mjpeg.Jpeg("res/test3.jpg", key=sample_key) | |
| 170 | + ima = mjpeg.Jpeg("res/lena.jpg", key=sample_key) | |
| 171 | + print ima.getQuality() | |
| 172 | + sys.exit(0) | |
| 173 | + | |
| 171 | 174 | # imb = mjpeg.Jpeg("res/new.jpg",key=sample_key) |
| 172 | 175 | imc = mjpeg.Jpeg("res/steged.jpg", key=sample_key) |
| 173 | 176 | print ima.Jgetcompdim(0) | ... | ... |