<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:Courier New,courier,monaco,monospace,sans-serif;font-size:10pt"><div>Here's some code that does the trick.<br><br>It returns a tuple:<br>(coefficient, (luminance_coefficient,luminance_error), (chrominance_coefficient,chrominance_error))<br><br>Note:<br>- The 2nd and 3rd returned items are only useful if you're interested in the error (sometimes the error is 0 if the program used a JPEG table that is the same as the one used by PIL).<br>- Fredrik: You can freely use the code and embed it in PIL if you're satisfied with its quality<br><br>Code:<br>def get_jpeg_quantization_tables(f):<br>&nbsp;&nbsp;&nbsp; """Returns the JPEG quantization tables of a filename or file descriptor"""<br>&nbsp;&nbsp;&nbsp; from functools import partial<br>&nbsp;&nbsp;&nbsp; import Image<br>&nbsp;&nbsp;&nbsp; import numpy as N<br>&nbsp;&nbsp;&nbsp; fd&nbsp;&nbsp;&nbsp; =
 Image.open(f)<br>&nbsp;&nbsp;&nbsp; if fd.format == 'BMP':<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return N.ones((8,8)),N.ones((8,8))<br>&nbsp;&nbsp;&nbsp; q&nbsp;&nbsp;&nbsp;&nbsp; = fd.quantization<br>&nbsp;&nbsp;&nbsp; ql,qc = map(partial(N.array,dtype='uint8'),(q.get(0,N.zeros(64)),q.get(1,N.zeros(64))))<br>&nbsp;&nbsp;&nbsp; # Now reorder the JPEG quantification coefficients as 8x8 matrices<br>&nbsp;&nbsp;&nbsp; jpeg_natural_order = N.array([ 0,&nbsp; 1,&nbsp; 8, 16,&nbsp; 9,&nbsp; 2,&nbsp; 3, 10, 17, 24, 32, 25, 18, 11,&nbsp; 4,&nbsp; 5, 12,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 19, 26, 33, 40, 48, 41, 34, 27, 20, 13,&nbsp; 6,&nbsp; 7, 14, 21, 28, 35,
 42,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63])<br>&nbsp;&nbsp;&nbsp; rql = N.zeros(64,'f')<br>&nbsp;&nbsp;&nbsp; rqc = N.zeros(64,'f')<br>&nbsp;&nbsp;&nbsp; for x,y in N.ndenumerate(jpeg_natural_order):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rql[y] = ql[x]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rqc[y] = qc[x]<br>&nbsp;&nbsp;&nbsp; return rql.reshape(8,8),rqc.reshape(8,8) # Luminance/Chrominance<br><br>def
 guess_jpeg_quality(f,ctables=[]):<br>&nbsp;&nbsp;&nbsp; from StringIO import StringIO<br>&nbsp;&nbsp;&nbsp; import numpy as N<br>&nbsp;&nbsp;&nbsp; import Image<br>&nbsp;&nbsp;&nbsp; # Compute the tables for quality = 1..100 by saving fakes files in memory<br>&nbsp;&nbsp;&nbsp; if not ctables:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tables = N.zeros((100,2,8,8),'f')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for x in xrange(100):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd = StringIO()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Image.new('RGB',(64,64)).save(fd,"jpeg",quality=1+x)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fd.seek(0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ql,qc = get_jpeg_quantization_tables(fd)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tables[x][0] =
 ql<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tables[x][1] = qc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctables.append(tables)<br>&nbsp;&nbsp;&nbsp; else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tables = ctables[0]<br>&nbsp;&nbsp;&nbsp; # Use a weighting matrix w to put more emphasis on the comparison of lower DCT harmonics<br>&nbsp;&nbsp;&nbsp; w&nbsp;&nbsp;&nbsp;&nbsp; = 1./N.outer(1+N.arange(8)/7.,1+N.arange(8)/7.)<br>&nbsp;&nbsp;&nbsp; ql,qc = get_jpeg_quantization_tables(f)<br>&nbsp;&nbsp;&nbsp; # Compute errors on Luminance and Chrominance tables<br>&nbsp;&nbsp;&nbsp; errsl,errsc = [],[]<br>&nbsp;&nbsp;&nbsp; for x in xrange(100):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errsl.append((N.square((ql-tables[x][0])*w).mean(),x))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errsc.append((N.square((qc-tables[x][1])*w).mean(),x))<br>&nbsp;&nbsp;&nbsp; # Select minimal error coefficients<br>&nbsp;&nbsp;&nbsp;
 lmin = min(errsl)<br>&nbsp;&nbsp;&nbsp; cmin = min(errsc)<br>&nbsp;&nbsp;&nbsp; # Weight coefficients average (more emphasis put on luminance since it affects most visual perception)<br>&nbsp;&nbsp;&nbsp; q = int(round(lmin[1]*.8 + cmin[1]*.2))<br>&nbsp;&nbsp;&nbsp; return q,lmin,cmin<br><br><br></div><div style="font-family: Courier New,courier,monaco,monospace,sans-serif; font-size: 10pt;"><br><div style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><font face="Tahoma" size="2"><hr size="1"><b><span style="font-weight: bold;">From:</span></b> Fredrik Lundh &lt;fredrik@pythonware.com&gt;<br><b><span style="font-weight: bold;">To:</span></b> qiaohl &lt;qiaohl@ucweb.com&gt;<br><b><span style="font-weight: bold;">Cc:</span></b> image-sig &lt;image-sig@python.org&gt;<br><b><span style="font-weight: bold;">Sent:</span></b> Monday, September 28, 2009 5:43:00 AM<br><b><span style="font-weight: bold;">Subject:</span></b> Re: [Image-SIG] How to
 get quality of picture<br></font><br>The quality setting is used to create a quantization table which is<br>then used by the compression algorithm.&nbsp; There's no pre-defined<br>mapping between quality and the contents of the quantization table for<br>JPEG (different implementations do different things), but some<br>applications attempt to guess by comparing the quantization tables in<br>the file with known mapping algorithms.&nbsp; I'm not aware of any such<br>code for Python.<br><br>If you want to tinker with this, you can access the quantization table<br>of an opened JPEG file via the "quantization" attribute.<br><br>&lt;/F&gt;<br><br>On Mon, Sep 28, 2009 at 9:08 AM, qiaohl &lt;<a ymailto="mailto:qiaohl@ucweb.com" href="mailto:qiaohl@ucweb.com">qiaohl@ucweb.com</a>&gt; wrote:<br>&gt; Hi,all<br>&gt; &nbsp;&nbsp; Is there any function in PIL to get the value of JPEG quality(1-100)? I<br>&gt; know there are functions&nbsp;to set this value, But I
 found no function to get<br>&gt; this value of an existing JPEG file.<br>&gt;<br>&gt; Thanks!<br>&gt;<br>&gt;<br>&gt; 2009-09-28<br>&gt; ________________________________<br>&gt; qiaohl<br>&gt; _______________________________________________<br>&gt; Image-SIG maillist &nbsp;- &nbsp;<a ymailto="mailto:Image-SIG@python.org" href="mailto:Image-SIG@python.org">Image-SIG@python.org</a><br>&gt; <a href="http://mail.python.org/mailman/listinfo/image-sig" target="_blank">http://mail.python.org/mailman/listinfo/image-sig</a><br>&gt;<br>&gt;<br>_______________________________________________<br>Image-SIG maillist&nbsp; -&nbsp; <a ymailto="mailto:Image-SIG@python.org" href="mailto:Image-SIG@python.org">Image-SIG@python.org</a><br><a href="http://mail.python.org/mailman/listinfo/image-sig" target="_blank">http://mail.python.org/mailman/listinfo/image-sig</a><br></div></div></div><br>



      </body></html>