root / pkpgcounter / trunk / pkpgpdls / pdf.py @ 450

Revision 450, 4.4 kB (checked in by jerome, 16 years ago)

Now uses Python's universal newline detection to read input files,
and also uses file objects directly instead of calling their xreadlines()
method.
Fixed an accounting problem in the PDF parser for some type of files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Auth Date Id Rev
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 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 a page counter for PDF documents."""
25
26import sys
27import re
28
29import pdlparser
30
31class PDFObject :
32    """A class for PDF objects."""
33    def __init__(self, major, minor, description) :
34        """Initialize the PDF object."""
35        self.major = major
36        self.minor = minor
37        self.description = description
38        self.comments = []
39        self.content = []
40        self.parent = None
41        self.kids = []
42       
43class Parser(pdlparser.PDLParser) :
44    """A parser for PDF documents."""
45    totiffcommands = [ 'gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(fname)s" -' ]
46    def isValid(self) :   
47        """Returns True if data is PDF, else False."""
48        if self.firstblock.startswith("%PDF-") or \
49           self.firstblock.startswith("\033%-12345X%PDF-") or \
50           ((self.firstblock[:128].find("\033%-12345X") != -1) and (self.firstblock.upper().find("LANGUAGE=PDF") != -1)) or \
51           (self.firstblock.find("%PDF-") != -1) :
52            self.logdebug("DEBUG: Input file is in the PDF format.")
53            return True
54        else :   
55            return False
56       
57    def getJobSize(self) :   
58        """Counts pages in a PDF document."""
59        # First we start with a generic PDF parser.
60        lastcomment = None
61        objects = {}
62        inobject = 0
63        objre = re.compile(r"\s?(\d+)\s+(\d+)\s+obj[<\s/]?")
64        for line in self.infile :
65            line = line.strip()
66            if line.startswith("% ") :   
67                if inobject :
68                    obj.comments.append(line)
69                else :
70                    lastcomment = line[2:]
71            else :
72                # New object begins here
73                result = objre.search(line)
74                if result is not None :
75                    (major, minor) = [int(num) for num in line[result.start():result.end()].split()[:2]]
76                    obj = PDFObject(major, minor, lastcomment)
77                    obj.content.append(line[result.end():])
78                    inobject = 1
79                elif line.startswith("endobj") \
80                  or line.startswith(">> endobj") \
81                  or line.startswith(">>endobj") :
82                    # Handle previous object, if any
83                    if inobject :
84                        # only overwrite older versions of this object
85                        # same minor seems to be possible, so the latest one
86                        # found in the file will be the one we keep.
87                        # if we want the first one, just use > instead of >=
88                        oldobject = objects.setdefault(major, obj)
89                        if minor >= oldobject.minor :
90                            objects[major] = obj
91                        inobject = 0       
92                else :   
93                    if inobject :
94                        obj.content.append(line)
95                       
96        # Now we check each PDF object we've just created.
97        # colorregexp = re.compile(r"(/ColorSpace) ?(/DeviceRGB|/DeviceCMYK)[/ \t\r\n]", re.I)
98        newpageregexp = re.compile(r"(/Type)\s?(/Page)[/>\s]", re.I)
99        pagecount = 0
100        for obj in objects.values() :
101            content = "".join(obj.content)
102            count = len(newpageregexp.findall(content))
103            if count and (content != r"<</Type /Page>>") : # Empty pages which are not rendered ?
104                pagecount += count
105        return pagecount   
106       
107if __name__ == "__main__" :   
108    pdlparser.test(Parser)
Note: See TracBrowser for help on using the browser.