root / pkpgcounter / trunk / pkpgpdls / inkcoverage.py @ 443

Revision 443, 4.5 kB (checked in by jerome, 17 years ago)

Changed copyright years.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Revision Id
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3#
4# pkpgcounter : a generic Page Description Language parser
5#
6# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20#
21# $Id$
22#
23
24"""This modules implements the computation of ink coverage in different colorspaces."""
25
26import sys
27
28from PIL import Image
29
30import pdlparser
31
32def getPercent(img, nbpix) :
33    """Extracts the percents per color component from a picture.
34     
35       Faster without Psyco on my own machine.
36    """
37    result = {}     
38    bands = img.split()
39    for (i, bandname) in enumerate(img.getbands()) :
40        result[bandname] = 100.0 * (reduce(lambda current, next: current + (next[1] * next[0]), enumerate(bands[i].histogram()), 0) / 255.0) / nbpix
41    return result   
42   
43def getPercentCMYK(img, nbpix) :
44    """Extracts the percents of Cyan, Magenta, Yellow, and Black from a picture.
45     
46       PIL doesn't produce useable CMYK for our algorithm, so we use the algorithm from PrintBill.
47       Psyco speeds this function up by around 2.5 times on my computer.
48    """
49    if img.mode != "RGB" :
50        img = img.convert("RGB")
51    cyan = magenta = yellow = black = 0   
52    for (r, g, b) in img.getdata() :
53        if r == g == b :
54            black += 255 - r
55        else :   
56            cyan += 255 - r
57            magenta += 255 - g
58            yellow += 255 - b
59    return { "C" : 100.0 * (cyan / 255.0) / nbpix,
60             "M" : 100.0 * (magenta / 255.0) / nbpix,
61             "Y" : 100.0 * (yellow / 255.0) / nbpix,
62             "K" : 100.0 * (black / 255.0) / nbpix,
63           }
64       
65def getPercentGC(img, nbpix) :       
66    """Determines if a page is in grayscale or colour mode."""
67    if img.mode != "RGB" :
68        img = img.convert("RGB")
69    gray = 0
70    for (r, g, b) in img.getdata() :
71        if not (r == g == b) :
72            # optimize : if a single pixel is no gray the whole page is colored.
73            return { "G" : 0.0, "C" : 100.0 }
74    return { "G" : 100.0, "C" : 0.0 }
75   
76def getPercentBW(img, nbpix) :
77    """Extracts the percents of Black from a picture, once converted to gray levels."""
78    if img.mode != "L" :
79        img = img.convert("L")
80    return { "B" : 100.0 - getPercent(img, nbpix)["L"] }
81   
82def getPercentRGB(img, nbpix) :
83    """Extracts the percents of Red, Green, Blue from a picture, once converted to RGB."""
84    if img.mode != "RGB" :
85        img = img.convert("RGB")
86    return getPercent(img, nbpix)   
87   
88def getPercentCMY(img, nbpix) :
89    """Extracts the percents of Cyan, Magenta, and Yellow from a picture once converted to RGB."""
90    result = getPercentRGB(img, nbpix)
91    return { "C" : 100.0 - result["R"],
92             "M" : 100.0 - result["G"],
93             "Y" : 100.0 - result["B"],
94           }
95   
96def getInkCoverage(fname, colorspace) :
97    """Returns a list of dictionnaries containing for each page,
98       for each color component, the percent of ink coverage on
99       that particular page.
100    """
101    result = []
102    colorspace = colorspace.upper()
103    computation = globals()["getPercent%s" % colorspace]
104    if colorspace in ("CMYK", "GC") : # faster with psyco on my machine
105        try :
106            import psyco
107        except ImportError :   
108            pass
109        else :   
110            psyco.bind(getPercentCMYK)
111   
112    index = 0
113    try :
114        image = Image.open(fname)
115    except IOError, msg :   
116        raise pdlparser.PDLParserError, "%s (%s)" % (msg, fname)
117    else :   
118        try :
119            while 1 :
120                nbpixels = image.size[0] * image.size[1]
121                result.append(computation(image, nbpixels))
122                index += 1             
123                image.seek(index)
124        except EOFError :       
125            pass
126        return (colorspace, result)
127
128if __name__ == "__main__" :
129    # NB : length of result gives number of pages !
130    print getInkCoverage(sys.argv[1], "CMYK")
Note: See TracBrowser for help on using the browser.