[Image-SIG] Finding image dimension

Fredrik Lundh fredrik at pythonware.com
Wed Jun 21 12:18:34 CEST 2006

andrea_gavana at tin.it wrote:

>    I am using PIL to load and display some pictures (via
> wxPython) in a GUI. I have added the ability for the user to change
> the  linear dimensions of the image (in pixels) and the quality of the
> image in order for the image to be saved in another file. I was
> wondering if is there a way to know in advance, based on the
> pixel dimensions specified by the user and by the image quality,
> which file size (in bytes) I will obtain for the new image

if we're talking about formats like JPEG and PNG, the compression ratio
depends on the image content, so the short answer is "no", and the some-
what longer answer is "it depends".

if you want *very* rough estimates, you can use something like:

    def getroughsize(im, format):
        pixels = im.size[0] * im.size[1]
        if im.mode == "RGB":
            pixels *= 3
        if format == "PNG":
            return pixels / 1.5 # photographic content
        if format == "JPEG":
            if im.mode == "RGB":
                return bytes / 20
            return bytes / 10
        return bytes # assume uncompressed format

the scale factors used above is for typical photographic content; drawings
and other graphics can often be compressed a lot more, while very noisy
pictures result in lower compression ratios.  tweak as necessary.

to get an exact value, you have to compress the file.  the following snippet
uses a stub byte counter class where possible, and falls back on a full in-
memory compression (via StringIO) for encoders that need random access
to the file:

    import Image
    import cStringIO

    class Counter:
        bytes = 0
        def write(self, data):
            self.bytes += len(data)

    def getsize(im, format, **options):
            out = Counter()
            im.save(out, format, **options)
            return out.bytes
        except AttributeError:
            # fall back on full in-memory compression
            out = cStringIO.StringIO()
            im.save(out, format, **options)
            return len(out.getvalue())

a third approach would be a turn this into a statistics problem, and calculate
some global stats (such as RMS etc.) on the image, and compare that to the
achieved compression ratio for a reasonably large set of typical images.  I'm
sure someone has done this already, but I have no time for a literature search


More information about the Image-SIG mailing list