Commit d3e050d64a6a3e834eb08960286b00f569a51f7b
1 parent
e2c85b43
Exists in
master
and in
2 other branches
staged.
Showing
3 changed files
with
122 additions
and
165 deletions
Show diff stats
.idea/ImageR.iml
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | <module type="PYTHON_MODULE" version="4"> |
3 | 3 | <component name="NewModuleRootManager"> |
4 | 4 | <content url="file://$MODULE_DIR$" /> |
5 | - <orderEntry type="jdk" jdkName="Python 2.7.6 virtualenv at ~/.virtualenvs/env0" jdkType="Python SDK" /> | |
5 | + <orderEntry type="jdk" jdkName="Python 2.7.8 virtualenv at ~/.virtualenvs/env1" jdkType="Python SDK" /> | |
6 | 6 | <orderEntry type="sourceFolder" forTests="false" /> |
7 | 7 | </component> |
8 | 8 | </module> |
9 | 9 | \ No newline at end of file | ... | ... |
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. |
... | ... | @@ -55,7 +55,7 @@ class Jpeg(Jsteg): |
55 | 55 | Jsteg.__init__(self, file, **kw) |
56 | 56 | self.verbosity = verbosity |
57 | 57 | if verbosity > 0: |
58 | - print "[Jpeg.__init__] Image size %ix%i" % (self.coef_arrays[0].shape) | |
58 | + print "[Jpeg.__init__] Image size %ix%i" % (self.image_width, self.image_height) | |
59 | 59 | if key != None: |
60 | 60 | self.key = key |
61 | 61 | elif rndkey: |
... | ... | @@ -290,6 +290,48 @@ class Jpeg(Jsteg): |
290 | 290 | self.coef_arrays[cID][v:v + 8, h:h + 8] = blocks[i, j] |
291 | 291 | self.Jsetblock(j, i, cID, bytearray(blocks[i, j].astype(np.int16))) |
292 | 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 | ... | ... |
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 | ... | ... |