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

Revision 527, 4.7 kB (checked in by jerome, 16 years ago)

Now the presence of executable dependencies is tested at runtime.

  • 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 3 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, see <http://www.gnu.org/licenses/>.
19#
20# $Id$
21#
22
23"""This modules implements the computation of ink coverage in different colorspaces."""
24
25import sys
26
27import pdlparser
28
29try :
30    from PIL import Image
31except ImportError :   
32    sys.stderr.write("ERROR: You MUST install the Python Imaging Library (python-imaging) for pkpgcounter to work.\n")
33    raise pdlparser.PDLParserError, "The Python Imaging Library is missing."
34
35def getPercent(img, nbpix) :
36    """Extracts the percents per color component from a picture.
37     
38       Faster without Psyco on my own machine.
39    """
40    result = {}     
41    bands = img.split()
42    for (i, bandname) in enumerate(img.getbands()) :
43        result[bandname] = 100.0 * (reduce(lambda current, next: current + (next[1] * next[0]), enumerate(bands[i].histogram()), 0) / 255.0) / nbpix
44    return result   
45   
46def getPercentCMYK(img, nbpix) :
47    """Extracts the percents of Cyan, Magenta, Yellow, and Black from a picture.
48     
49       PIL doesn't produce useable CMYK for our algorithm, so we use the algorithm from PrintBill.
50       Psyco speeds this function up by around 2.5 times on my computer.
51    """
52    if img.mode != "RGB" :
53        img = img.convert("RGB")
54    cyan = magenta = yellow = black = 0   
55    for (r, g, b) in img.getdata() :
56        if r == g == b :
57            black += 255 - r
58        else :   
59            cyan += 255 - r
60            magenta += 255 - g
61            yellow += 255 - b
62    return { "C" : 100.0 * (cyan / 255.0) / nbpix,
63             "M" : 100.0 * (magenta / 255.0) / nbpix,
64             "Y" : 100.0 * (yellow / 255.0) / nbpix,
65             "K" : 100.0 * (black / 255.0) / nbpix,
66           }
67       
68def getPercentGC(img, nbpix) :       
69    """Determines if a page is in grayscale or colour mode."""
70    if img.mode != "RGB" :
71        img = img.convert("RGB")
72    gray = 0
73    for (r, g, b) in img.getdata() :
74        if not (r == g == b) :
75            # optimize : if a single pixel is no gray the whole page is colored.
76            return { "G" : 0.0, "C" : 100.0 }
77    return { "G" : 100.0, "C" : 0.0 }
78   
79def getPercentBW(img, nbpix) :
80    """Extracts the percents of Black from a picture, once converted to gray levels."""
81    if img.mode != "L" :
82        img = img.convert("L")
83    return { "B" : 100.0 - getPercent(img, nbpix)["L"] }
84   
85def getPercentRGB(img, nbpix) :
86    """Extracts the percents of Red, Green, Blue from a picture, once converted to RGB."""
87    if img.mode != "RGB" :
88        img = img.convert("RGB")
89    return getPercent(img, nbpix)   
90   
91def getPercentCMY(img, nbpix) :
92    """Extracts the percents of Cyan, Magenta, and Yellow from a picture once converted to RGB."""
93    result = getPercentRGB(img, nbpix)
94    return { "C" : 100.0 - result["R"],
95             "M" : 100.0 - result["G"],
96             "Y" : 100.0 - result["B"],
97           }
98   
99def getInkCoverage(fname, colorspace) :
100    """Returns a list of dictionnaries containing for each page,
101       for each color component, the percent of ink coverage on
102       that particular page.
103    """
104    result = []
105    colorspace = colorspace.upper()
106    computation = globals()["getPercent%s" % colorspace]
107    if colorspace in ("CMYK", "GC") : # faster with psyco on my machine
108        try :
109            import psyco
110        except ImportError :   
111            pass
112        else :   
113            psyco.bind(getPercentCMYK)
114   
115    index = 0
116    try :
117        image = Image.open(fname)
118    except (IOError, OverflowError), msg :   
119        raise pdlparser.PDLParserError, "%s (%s)" % (msg, fname)
120    else :   
121        try :
122            while True :
123                nbpixels = image.size[0] * image.size[1]
124                result.append(computation(image, nbpixels))
125                index += 1             
126                image.seek(index)
127        except EOFError :       
128            pass
129        return (colorspace, result)
130
131if __name__ == "__main__" :
132    # NB : length of result gives number of pages !
133    print getInkCoverage(sys.argv[1], "CMYK")
Note: See TracBrowser for help on using the browser.