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

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

Even more code cleaning : we use named temporary files now, so no need for pipes.

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