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

Revision 3578, 4.3 kB (checked in by jerome, 5 years ago)

Clarified dependency wrt PIL/Pillow.
Updated copyright years.
Regenerated manual page.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Revision Id
RevLine 
[3410]1# -*- coding: utf-8 -*-
[277]2#
3# pkpgcounter : a generic Page Description Language parser
4#
[3578]5# (c) 2003-2019 Jerome Alet <alet@librelogiciel.com>
[463]6# This program is free software: you can redistribute it and/or modify
[277]7# it under the terms of the GNU General Public License as published by
[463]8# the Free Software Foundation, either version 3 of the License, or
[277]9# (at your option) any later version.
[3436]10#
[277]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.
[3436]15#
[277]16# You should have received a copy of the GNU General Public License
[463]17# along with this program.  If not, see <http://www.gnu.org/licenses/>.
[277]18#
19# $Id$
20#
21
[357]22"""This modules implements the computation of ink coverage in different colorspaces."""
23
[277]24import sys
25
[433]26import pdlparser
27
[527]28try :
29    from PIL import Image
[3436]30except ImportError :
[3578]31    sys.stderr.write("ERROR: You MUST install the Python Imaging Library (either PIL or Pillow) for pkpgcounter to work.\n")
[527]32    raise pdlparser.PDLParserError, "The Python Imaging Library is missing."
33
[363]34def getPercent(img, nbpix) :
[3573]35    """Extracts the percents per color component from a picture."""
[3436]36    result = {}
[363]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
[3436]40    return result
41
[280]42def getPercentCMYK(img, nbpix) :
43    """Extracts the percents of Cyan, Magenta, Yellow, and Black from a picture.
[3436]44
[280]45       PIL doesn't produce useable CMYK for our algorithm, so we use the algorithm from PrintBill.
46    """
47    if img.mode != "RGB" :
48        img = img.convert("RGB")
[3436]49    cyan = magenta = yellow = black = 0
[442]50    for (r, g, b) in img.getdata() :
[3447]51        pixblack = 255 - max(r, g, b)
52        black += pixblack
53        cyan += 255 - r - pixblack
54        magenta += 255 - g - pixblack
55        yellow += 255 - b - pixblack
56
57    frac = 100.0 / nbpix
58    return { "C" : frac * (cyan / 255.0),
59             "M" : frac * (magenta / 255.0),
60             "Y" : frac * (yellow / 255.0),
61             "K" : frac * (black / 255.0),
[280]62           }
[3436]63
64def getPercentGC(img, nbpix) :
[439]65    """Determines if a page is in grayscale or colour mode."""
[442]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) :
[3443]71            # optimize : if a single pixel is not gray the whole page is colored.
[442]72            return { "G" : 0.0, "C" : 100.0 }
73    return { "G" : 100.0, "C" : 0.0 }
[3436]74
[363]75def getPercentBW(img, nbpix) :
[280]76    """Extracts the percents of Black from a picture, once converted to gray levels."""
[279]77    if img.mode != "L" :
78        img = img.convert("L")
[363]79    return { "B" : 100.0 - getPercent(img, nbpix)["L"] }
[3436]80
[280]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")
[3436]85    return getPercent(img, nbpix)
86
[280]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           }
[3436]94
[363]95def getInkCoverage(fname, colorspace) :
[3436]96    """Returns a list of dictionnaries containing for each page,
97       for each color component, the percent of ink coverage on
[363]98       that particular page.
99    """
[281]100    result = []
[363]101    colorspace = colorspace.upper()
102    computation = globals()["getPercent%s" % colorspace]
[281]103    index = 0
104    try :
[433]105        image = Image.open(fname)
[3436]106    except (IOError, OverflowError), msg :
[433]107        raise pdlparser.PDLParserError, "%s (%s)" % (msg, fname)
[3436]108    else :
[433]109        try :
[492]110            while True :
[433]111                nbpixels = image.size[0] * image.size[1]
112                result.append(computation(image, nbpixels))
[3436]113                index += 1
[433]114                image.seek(index)
[3436]115        except EOFError :
[433]116            pass
117        return (colorspace, result)
[277]118
119if __name__ == "__main__" :
[281]120    # NB : length of result gives number of pages !
[3456]121    sys.stdout.write("%s\n" % getInkCoverage(sys.argv[1], "CMYK"))
Note: See TracBrowser for help on using the browser.