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) | ... | ... |