Changeset 731

Show
Ignore:
Timestamp:
05/02/06 10:57:55 (2 years ago)
Author:
mfenniak
Message:

Support inline images in PDF content streams.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • pypdf/trunk/pyPdf/pdf.py

    r729 r731  
    347347                cnt = 0 
    348348                while cnt < size: 
    349                     line = stream.readline(
     349                    line = stream.read(20
    350350                    offset, generation = line[:16].split(" ") 
    351351                    offset, generation = int(offset), int(generation) 
     
    525525    _mergeResources = staticmethod(_mergeResources) 
    526526 
    527     def _contentStreamRename(stream, rename): 
     527    def _contentStreamRename(stream, rename, pdf): 
    528528        if not rename: 
    529529            return stream 
    530         stream = ContentStream(stream
     530        stream = ContentStream(stream, pdf
    531531        for operands,operator in stream.operations: 
    532532            for i in range(len(operands)): 
     
    537537    _contentStreamRename = staticmethod(_contentStreamRename) 
    538538 
    539     def _pushPopGS(contents): 
     539    def _pushPopGS(contents, pdf): 
    540540        # adds a graphics state "push" and "pop" to the beginning and end 
    541541        # of a content stream.  This isolates it from changes such as  
    542542        # transformation matricies. 
    543         stream = ContentStream(contents
     543        stream = ContentStream(contents, pdf
    544544        stream.operations.insert(0, [[], "q"]) 
    545545        stream.operations.append([[], "Q"]) 
     
    581581 
    582582        originalContent = self["/Contents"].getObject() 
    583         newContentArray.append(PageObject._pushPopGS(originalContent)) 
     583        newContentArray.append(PageObject._pushPopGS(originalContent, self.pdf)) 
    584584 
    585585        page2Content = page2['/Contents'].getObject() 
    586         page2Content = PageObject._contentStreamRename(page2Content, rename
    587         page2Content = PageObject._pushPopGS(page2Content
     586        page2Content = PageObject._contentStreamRename(page2Content, rename, self.pdf
     587        page2Content = PageObject._pushPopGS(page2Content, self.pdf
    588588        newContentArray.append(page2Content) 
    589589 
    590         self[NameObject('/Contents')] = ContentStream(newContentArray
     590        self[NameObject('/Contents')] = ContentStream(newContentArray, self.pdf
    591591        self[NameObject('/Resources')] = newResources 
    592592 
     
    602602        content = self["/Contents"].getObject() 
    603603        if not isinstance(content, ContentStream): 
    604             content = ContentStream(content
     604            content = ContentStream(content, self.pdf
    605605        self[NameObject("/Contents")] = content.flateEncode() 
    606606 
     
    645645 
    646646class ContentStream(DecodedStreamObject): 
    647     def __init__(self, stream): 
     647    def __init__(self, stream, pdf): 
     648        self.pdf = pdf 
    648649        self.operations = [] 
    649650        # stream may be a StreamObject or an ArrayObject containing 
     
    660661 
    661662    def __parseContentStream(self, stream): 
     663        # file("f:\\tmp.txt", "w").write(stream.read()) 
     664        stream.seek(0, 0) 
    662665        operands = [] 
    663666        while True: 
     
    666669                break 
    667670            stream.seek(-1, 1) 
    668             if peek.isalpha(): 
    669                 operator = readUntilWhitespace(stream) 
    670                 self.operations.append((operands, operator)) 
    671                 operands = [] 
     671            if peek.isalpha() or peek == "'" or peek == "\"": 
     672                operator = readUntilWhitespace(stream, maxchars=2) 
     673                if operator == "BI": 
     674                    # begin inline image - a completely different parsing 
     675                    # mechanism is required, of course... thanks buddy... 
     676                    assert operands == [] 
     677                    ii = self._readInlineImage(stream) 
     678                    self.operations.append((ii, "INLINE IMAGE")) 
     679                else: 
     680                    self.operations.append((operands, operator)) 
     681                    operands = [] 
    672682            else: 
    673683                operands.append(readObject(stream, None)) 
     684 
     685    def _readInlineImage(self, stream): 
     686        # begin reading just after the "BI" - begin image 
     687        # first read the dictionary of settings. 
     688        settings = DictionaryObject() 
     689        while True: 
     690            tok = readNonWhitespace(stream) 
     691            stream.seek(-1, 1) 
     692            if tok == "I": 
     693                # "ID" - begin of image data 
     694                break 
     695            key = readObject(stream, self.pdf) 
     696            tok = readNonWhitespace(stream) 
     697            stream.seek(-1, 1) 
     698            value = readObject(stream, self.pdf) 
     699            settings[key] = value 
     700        # left at beginning of ID 
     701        tmp = stream.read(3) 
     702        assert tmp[:2] == "ID" 
     703        data = "" 
     704        while True: 
     705            tok = stream.read(1) 
     706            if tok == "E": 
     707                next = stream.read(1) 
     708                if next == "I": 
     709                    break 
     710                else: 
     711                    stream.seek(-1, 1) 
     712                    data += tok 
     713            else: 
     714                data += tok 
     715        x = readNonWhitespace(stream) 
     716        stream.seek(-1, 1) 
     717        return {"settings": settings, "data": data} 
    674718 
    675719    def _getData(self): 
    676720        newdata = StringIO() 
    677721        for operands,operator in self.operations: 
    678             for op in operands: 
    679                 op.writeToStream(newdata) 
    680                 newdata.write(" ") 
    681             newdata.write(operator) 
     722            if operator == "INLINE IMAGE": 
     723                newdata.write("BI") 
     724                dicttext = StringIO() 
     725                operands["settings"].writeToStream(dicttext) 
     726                newdata.write(dicttext.getvalue()[2:-2]) 
     727                newdata.write("ID ") 
     728                newdata.write(operands["data"]) 
     729                newdata.write("EI") 
     730            else: 
     731                for op in operands: 
     732                    op.writeToStream(newdata) 
     733                    newdata.write(" ") 
     734                newdata.write(operator) 
    682735            newdata.write("\n") 
    683736        return newdata.getvalue() 
  • pypdf/trunk/pyPdf/utils.py

    r710 r731  
    3535__author_email__ = "mfenniak@pobox.com" 
    3636 
    37 def readUntilWhitespace(stream): 
     37def readUntilWhitespace(stream, maxchars=None): 
    3838    txt = "" 
    3939    while True: 
     
    4242            break 
    4343        txt += tok 
     44        if len(txt) == maxchars: 
     45            break 
    4446    return txt 
    4547