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,7 +2,7 @@ | ||
2 | 2 | ||
3 | from libmjsteg import Jsteg | 3 | from libmjsteg import Jsteg |
4 | 4 | ||
5 | -__all__ = ['Jpeg','colorMap','diffblock','diffblocks'] | 5 | +__all__ = ['Jpeg', 'colorMap', 'diffblock', 'diffblocks'] |
6 | 6 | ||
7 | # We need standard components from :mod:`numpy`, and some auxiliary | 7 | # We need standard components from :mod:`numpy`, and some auxiliary |
8 | # functions from submodules. | 8 | # functions from submodules. |
@@ -16,6 +16,7 @@ import pylab as plt | @@ -16,6 +16,7 @@ import pylab as plt | ||
16 | 16 | ||
17 | import base | 17 | import base |
18 | from dct import bdct, ibdct | 18 | from dct import bdct, ibdct |
19 | +from compress import * | ||
19 | 20 | ||
20 | # The colour codes are defined in the JPEG standard. We store | 21 | # The colour codes are defined in the JPEG standard. We store |
21 | # them here for easy reference by name:: | 22 | # them here for easy reference by name:: |
@@ -55,7 +56,7 @@ class Jpeg(Jsteg): | @@ -55,7 +56,7 @@ class Jpeg(Jsteg): | ||
55 | Jsteg.__init__(self, file, **kw) | 56 | Jsteg.__init__(self, file, **kw) |
56 | self.verbosity = verbosity | 57 | self.verbosity = verbosity |
57 | if verbosity > 0: | 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 | if key != None: | 60 | if key != None: |
60 | self.key = key | 61 | self.key = key |
61 | elif rndkey: | 62 | elif rndkey: |
@@ -290,6 +291,47 @@ class Jpeg(Jsteg): | @@ -290,6 +291,47 @@ class Jpeg(Jsteg): | ||
290 | self.coef_arrays[cID][v:v + 8, h:h + 8] = blocks[i, j] | 291 | self.coef_arrays[cID][v:v + 8, h:h + 8] = blocks[i, j] |
291 | self.Jsetblock(j, i, cID, bytearray(blocks[i, j].astype(np.int16))) | 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 | # Decompression | 335 | # Decompression |
294 | # ------------- | 336 | # ------------- |
295 | 337 | ||
@@ -404,3 +446,13 @@ def diffblocks(a, b): | @@ -404,3 +446,13 @@ def diffblocks(a, b): | ||
404 | cnt += 1 | 446 | cnt += 1 |
405 | return diff, cnt | 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,179 +5,94 @@ from pylab import * | ||
5 | 5 | ||
6 | # The standard quantisation tables for JPEG:: | 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,6 +16,10 @@ import pickle | ||
16 | import cv2 | 16 | import cv2 |
17 | from sklearn import svm | 17 | from sklearn import svm |
18 | 18 | ||
19 | +# from numba import jit | ||
20 | + | ||
21 | + | ||
22 | + | ||
19 | base_dir = '/home/hadoop/data/HeadShoulder/' | 23 | base_dir = '/home/hadoop/data/HeadShoulder/' |
20 | 24 | ||
21 | 25 | ||
@@ -82,7 +86,7 @@ class MPB(StegBase): | @@ -82,7 +86,7 @@ class MPB(StegBase): | ||
82 | # 1.422729s | 86 | # 1.422729s |
83 | return TPM | 87 | return TPM |
84 | 88 | ||
85 | - | 89 | + @jit |
86 | def get_trans_prob_mat(self, ciq, T=4): | 90 | def get_trans_prob_mat(self, ciq, T=4): |
87 | """ | 91 | """ |
88 | Calculate Transition Probability Matrix. | 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 @@ | @@ -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 @@ | @@ -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,7 +167,10 @@ if __name__ == '__main__': | ||
167 | 167 | ||
168 | # test_bitbyte() | 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 | # imb = mjpeg.Jpeg("res/new.jpg",key=sample_key) | 174 | # imb = mjpeg.Jpeg("res/new.jpg",key=sample_key) |
172 | imc = mjpeg.Jpeg("res/steged.jpg", key=sample_key) | 175 | imc = mjpeg.Jpeg("res/steged.jpg", key=sample_key) |
173 | print ima.Jgetcompdim(0) | 176 | print ima.Jgetcompdim(0) |