How to get quality of picture

View: New views
5 Messages — Rating Filter:   Alert me  

How to get quality of picture

by qiaohl :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,all
   Is there any function in PIL to get the value of JPEG quality(1-100)? I know there are functions to set this value, But I found no function to get this value of an existing JPEG file.
 
Thanks!
 
 
2009-09-28

qiaohl

_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig

Re: How to get quality of picture

by Elias Fotinis :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

From: qiaohl
> Is there any function in PIL to get the value of JPEG quality(1-100)? I
> know there are functions to set this value, But I found no function to get
> this value of an existing JPEG file.

You can't get the quality value, because it's not stored anywhere in the
file.

I found a Microsoft article at http://support.microsoft.com/kb/324790,
titled "Determine the JPEG quality factor by using Visual C# .NET", which
states that one could compare the quantization tables against those from the
reference code. However, you can't be sure it'll work for all JPEGs.

_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig

Re: How to get quality of picture

by Fredrik Lundh :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The quality setting is used to create a quantization table which is
then used by the compression algorithm.  There's no pre-defined
mapping between quality and the contents of the quantization table for
JPEG (different implementations do different things), but some
applications attempt to guess by comparing the quantization tables in
the file with known mapping algorithms.  I'm not aware of any such
code for Python.

If you want to tinker with this, you can access the quantization table
of an opened JPEG file via the "quantization" attribute.

</F>

On Mon, Sep 28, 2009 at 9:08 AM, qiaohl <qiaohl@...> wrote:

> Hi,all
>    Is there any function in PIL to get the value of JPEG quality(1-100)? I
> know there are functions to set this value, But I found no function to get
> this value of an existing JPEG file.
>
> Thanks!
>
>
> 2009-09-28
> ________________________________
> qiaohl
> _______________________________________________
> Image-SIG maillist  -  Image-SIG@...
> http://mail.python.org/mailman/listinfo/image-sig
>
>
_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig

Re: How to get quality of picture

by David Berthelot :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.
Here's some code that does the trick.

It returns a tuple:
(coefficient, (luminance_coefficient,luminance_error), (chrominance_coefficient,chrominance_error))

Note:
- 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).
- Fredrik: You can freely use the code and embed it in PIL if you're satisfied with its quality

Code:
def get_jpeg_quantization_tables(f):
    """Returns the JPEG quantization tables of a filename or file descriptor"""
    from functools import partial
    import Image
    import numpy as N
    fd    = Image.open(f)
    if fd.format == 'BMP':
        return N.ones((8,8)),N.ones((8,8))
    q     = fd.quantization
    ql,qc = map(partial(N.array,dtype='uint8'),(q.get(0,N.zeros(64)),q.get(1,N.zeros(64))))
    # Now reorder the JPEG quantification coefficients as 8x8 matrices
    jpeg_natural_order = N.array([ 0,  1,  8, 16,  9,  2,  3, 10, 17, 24, 32, 25, 18, 11,  4,  5, 12,
                                   19, 26, 33, 40, 48, 41, 34, 27, 20, 13,  6,  7, 14, 21, 28, 35, 42,
                                   49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52,
                                   45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63])
    rql = N.zeros(64,'f')
    rqc = N.zeros(64,'f')
    for x,y in N.ndenumerate(jpeg_natural_order):
        rql[y] = ql[x]
        rqc[y] = qc[x]
    return rql.reshape(8,8),rqc.reshape(8,8) # Luminance/Chrominance

def guess_jpeg_quality(f,ctables=[]):
    from StringIO import StringIO
    import numpy as N
    import Image
    # Compute the tables for quality = 1..100 by saving fakes files in memory
    if not ctables:
        tables = N.zeros((100,2,8,8),'f')
        for x in xrange(100):
            fd = StringIO()
            Image.new('RGB',(64,64)).save(fd,"jpeg",quality=1+x)
            fd.seek(0)
            ql,qc = get_jpeg_quantization_tables(fd)
            tables[x][0] = ql
            tables[x][1] = qc
        ctables.append(tables)
    else:
        tables = ctables[0]
    # Use a weighting matrix w to put more emphasis on the comparison of lower DCT harmonics
    w     = 1./N.outer(1+N.arange(8)/7.,1+N.arange(8)/7.)
    ql,qc = get_jpeg_quantization_tables(f)
    # Compute errors on Luminance and Chrominance tables
    errsl,errsc = [],[]
    for x in xrange(100):
        errsl.append((N.square((ql-tables[x][0])*w).mean(),x))
        errsc.append((N.square((qc-tables[x][1])*w).mean(),x))
    # Select minimal error coefficients
    lmin = min(errsl)
    cmin = min(errsc)
    # Weight coefficients average (more emphasis put on luminance since it affects most visual perception)
    q = int(round(lmin[1]*.8 + cmin[1]*.2))
    return q,lmin,cmin




From: Fredrik Lundh <fredrik@...>
To: qiaohl <qiaohl@...>
Cc: image-sig <image-sig@...>
Sent: Monday, September 28, 2009 5:43:00 AM
Subject: Re: [Image-SIG] How to get quality of picture

The quality setting is used to create a quantization table which is
then used by the compression algorithm.  There's no pre-defined
mapping between quality and the contents of the quantization table for
JPEG (different implementations do different things), but some
applications attempt to guess by comparing the quantization tables in
the file with known mapping algorithms.  I'm not aware of any such
code for Python.

If you want to tinker with this, you can access the quantization table
of an opened JPEG file via the "quantization" attribute.

</F>

On Mon, Sep 28, 2009 at 9:08 AM, qiaohl <qiaohl@...> wrote:

> Hi,all
>    Is there any function in PIL to get the value of JPEG quality(1-100)? I
> know there are functions to set this value, But I found no function to get
> this value of an existing JPEG file.
>
> Thanks!
>
>
> 2009-09-28
> ________________________________
> qiaohl
> _______________________________________________
> Image-SIG maillist  -  Image-SIG@...
> http://mail.python.org/mailman/listinfo/image-sig
>
>
_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig


_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig

Re: How to get quality of picture

by Franz Buchinger :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

As Frederik already mentioned, you can extract the quantisation table of an opened JPEG file with the .quantization attribute.
To determine the quality setting of the jpeg, you can calculate some hash (e.g. md5) for the quantisation table and compare it to hashes from jpeg files saved at different quality settings.

PIL and most other FOSS image processing apps (GIMP, Imagemagick) depend on libjpeg and its builtin quantisation tables. This means that you can easily determine the quality of images processed with these apps.
JPEGs saved in commercial apps like Photoshop, Lightroom or directly taken from a camera however bring their own quality settings and quantisation tables. An image exported with the "Save for Web" dialog in Photoshop for example can come in 12 different quality settings, each corresponding to a different quantisation table which have nothing in common with the ones libjpeg is using.

In short words: you need a huge database of quantisation table hashes to reliably identify the quality setting of an arbitrary jpeg. Therefore, I recommend to make use of exiftool's jpegdigest database, which holds thousands of quantisation table hashes:

http://cpansearch.perl.org/src/EXIFTOOL/Image-ExifTool-7.89/lib/Image/ExifTool/JPEGDigest.pm

You only have to port the jpegdigest hashing algorithm from perl to python and convert the database to a dictionary.

kind regards,

Franz

2009/9/29 David Berthelot <d_berthelot@...>
Here's some code that does the trick.

It returns a tuple:
(coefficient, (luminance_coefficient,luminance_error), (chrominance_coefficient,chrominance_error))

Note:
- 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).
- Fredrik: You can freely use the code and embed it in PIL if you're satisfied with its quality

Code:
def get_jpeg_quantization_tables(f):
    """Returns the JPEG quantization tables of a filename or file descriptor"""
    from functools import partial
    import Image
    import numpy as N
    fd    = Image.open(f)
    if fd.format == 'BMP':
        return N.ones((8,8)),N.ones((8,8))
    q     = fd.quantization
    ql,qc = map(partial(N.array,dtype='uint8'),(q.get(0,N.zeros(64)),q.get(1,N.zeros(64))))
    # Now reorder the JPEG quantification coefficients as 8x8 matrices
    jpeg_natural_order = N.array([ 0,  1,  8, 16,  9,  2,  3, 10, 17, 24, 32, 25, 18, 11,  4,  5, 12,
                                   19, 26, 33, 40, 48, 41, 34, 27, 20, 13,  6,  7, 14, 21, 28, 35, 42,
                                   49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52,
                                   45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63])
    rql = N.zeros(64,'f')
    rqc = N.zeros(64,'f')
    for x,y in N.ndenumerate(jpeg_natural_order):
        rql[y] = ql[x]
        rqc[y] = qc[x]
    return rql.reshape(8,8),rqc.reshape(8,8) # Luminance/Chrominance

def guess_jpeg_quality(f,ctables=[]):
    from StringIO import StringIO
    import numpy as N
    import Image
    # Compute the tables for quality = 1..100 by saving fakes files in memory
    if not ctables:
        tables = N.zeros((100,2,8,8),'f')
        for x in xrange(100):
            fd = StringIO()
            Image.new('RGB',(64,64)).save(fd,"jpeg",quality=1+x)
            fd.seek(0)
            ql,qc = get_jpeg_quantization_tables(fd)
            tables[x][0] = ql
            tables[x][1] = qc
        ctables.append(tables)
    else:
        tables = ctables[0]
    # Use a weighting matrix w to put more emphasis on the comparison of lower DCT harmonics
    w     = 1./N.outer(1+N.arange(8)/7.,1+N.arange(8)/7.)
    ql,qc = get_jpeg_quantization_tables(f)
    # Compute errors on Luminance and Chrominance tables
    errsl,errsc = [],[]
    for x in xrange(100):
        errsl.append((N.square((ql-tables[x][0])*w).mean(),x))
        errsc.append((N.square((qc-tables[x][1])*w).mean(),x))
    # Select minimal error coefficients
    lmin = min(errsl)
    cmin = min(errsc)
    # Weight coefficients average (more emphasis put on luminance since it affects most visual perception)
    q = int(round(lmin[1]*.8 + cmin[1]*.2))
    return q,lmin,cmin




From: Fredrik Lundh <fredrik@...>
To: qiaohl <qiaohl@...>
Cc: image-sig <image-sig@...>
Sent: Monday, September 28, 2009 5:43:00 AM
Subject: Re: [Image-SIG] How to get quality of picture

The quality setting is used to create a quantization table which is
then used by the compression algorithm.  There's no pre-defined
mapping between quality and the contents of the quantization table for
JPEG (different implementations do different things), but some
applications attempt to guess by comparing the quantization tables in
the file with known mapping algorithms.  I'm not aware of any such
code for Python.

If you want to tinker with this, you can access the quantization table
of an opened JPEG file via the "quantization" attribute.

</F>

On Mon, Sep 28, 2009 at 9:08 AM, qiaohl <qiaohl@...> wrote:
> Hi,all

>    Is there any function in PIL to get the value of JPEG quality(1-100)? I
> know there are functions to set this value, But I found no function to get
> this value of an existing JPEG file.
>
> Thanks!
>
>
> 2009-09-28
> ________________________________
> qiaohl
> _______________________________________________
> Image-SIG maillist  -  Image-SIG@...
> http://mail.python.org/mailman/listinfo/image-sig
>
>
_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig


_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig



_______________________________________________
Image-SIG maillist  -  Image-SIG@...
http://mail.python.org/mailman/listinfo/image-sig