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

Revision 564, 4.7 kB (checked in by jerome, 17 years ago)

Changed copyright years.
Removed unnecessary shebang lines.
Changed default encoding to UTF-8 from ISO-8859-15 (only
ascii is used anyway).

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