src/reportlab/pdfbase/pdfutils.py
author rptlab
Tue, 30 Apr 2013 14:28:14 +0100
branchpy33
changeset 3723 99aa837b6703
parent 3721 0c93dd8ff567
child 3731 b233dd0577ff
permissions -rwxr-xr-x
second stage of port to Python 3.3; working hello world
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3617
ae5744e97c42 reportlab: copyright date changes
robin
parents: 3431
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2012
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 475
diff changeset
     2
#see license.txt for license details
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 2273
diff changeset
     3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/pdfbase/pdfutils.py
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 2273
diff changeset
     4
__version__=''' $Id$ '''
16
f9c7525619fb Docstring & other fixes
rgbecker
parents: 7
diff changeset
     5
__doc__=''
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
     6
# pdfutils.py - everything to do with images, streams,
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
     7
# compression, and some constants
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
     8
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
     9
import sys
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    10
import os
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
    11
import binascii
1029
6bd2c408f7a1 Use rl_config.verbose
rgbecker
parents: 760
diff changeset
    12
from reportlab import rl_config
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
    13
from reportlab.lib.utils import getBytesIO, ImageReader, isStrType, isUnicodeType, isPython3
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    14
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    15
LINEEND = '\015\012'
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    16
2229
99cb312c5269 Fix transparency & jpeg behaviour
rgbecker
parents: 2200
diff changeset
    17
def _chunker(src,dst=[],chunkSize=60):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    18
    for i in range(0,len(src),chunkSize):
2229
99cb312c5269 Fix transparency & jpeg behaviour
rgbecker
parents: 2200
diff changeset
    19
        dst.append(src[i:i+chunkSize])
99cb312c5269 Fix transparency & jpeg behaviour
rgbecker
parents: 2200
diff changeset
    20
    return dst
99cb312c5269 Fix transparency & jpeg behaviour
rgbecker
parents: 2200
diff changeset
    21
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    22
##########################################################
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    23
#
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
    24
#  Image compression helpers.  Preprocessing a directory
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    25
#  of images will offer a vast speedup.
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    26
#
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
    27
##########################################################
2482
4ae04d1800af CMYK image improvements
rgbecker
parents: 2399
diff changeset
    28
_mode2cs = {'RGB':'RGB', 'CMYK': 'CMYK', 'L': 'G'}
2994
130866f26cb4 reportlab: fix some broken assertions
rgbecker
parents: 2964
diff changeset
    29
_mode2bpp = {'RGB': 3, 'CMYK':4, 'L':1}
2558
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    30
def makeA85Image(filename,IMG=None):
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    31
    import zlib
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    32
    img = ImageReader(filename)
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    33
    if IMG is not None: IMG.append(img)
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    34
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    35
    imgwidth, imgheight = img.getSize()
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    36
    raw = img.getRGBData()
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    37
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    38
    code = []
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    39
    append = code.append
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    40
    # this describes what is in the image itself
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    41
    append('BI')
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    42
    append('/W %s /H %s /BPC 8 /CS /%s /F [/A85 /Fl]' % (imgwidth, imgheight,_mode2cs[img.mode]))
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    43
    append('ID')
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    44
    #use a flate filter and Ascii Base 85
2994
130866f26cb4 reportlab: fix some broken assertions
rgbecker
parents: 2964
diff changeset
    45
    assert len(raw) == imgwidth * imgheight*_mode2bpp[img.mode], "Wrong amount of data for image"
2558
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    46
    compressed = zlib.compress(raw)   #this bit is very fast...
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    47
    encoded = _AsciiBase85Encode(compressed) #...sadly this may not be
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    48
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    49
    #append in blocks of 60 characters
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    50
    _chunker(encoded,code)
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    51
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    52
    append('EI')
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    53
    return code
3359
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    54
def makeRawImage(filename,IMG=None):
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    55
    import zlib
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    56
    img = ImageReader(filename)
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    57
    if IMG is not None: IMG.append(img)
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    58
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    59
    imgwidth, imgheight = img.getSize()
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    60
    raw = img.getRGBData()
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    61
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    62
    code = []
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    63
    append = code.append
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    64
    # this describes what is in the image itself
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    65
    append('BI')
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    66
    append('/W %s /H %s /BPC 8 /CS /%s /F [/Fl]' % (imgwidth, imgheight,_mode2cs[img.mode]))
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    67
    append('ID')
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    68
    #use a flate filter
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    69
    assert len(raw) == imgwidth * imgheight*_mode2bpp[img.mode], "Wrong amount of data for image"
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    70
    compressed = zlib.compress(raw)   #this bit is very fast...
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    71
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    72
    #append in blocks of 60 characters
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    73
    _chunker(compressed,code)
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    74
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    75
    append('EI')
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    76
    return code
2558
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    77
1772
ba6ba46e2370 Added A85 caching possibility to Image XObjects
rgbecker
parents: 1683
diff changeset
    78
def cacheImageFile(filename, returnInMemory=0, IMG=None):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
    79
    "Processes image as if for encoding, saves to a file with .a85 extension."
660
243182bf7988 Removed commented encoding test functions.
dinu_gherman
parents: 658
diff changeset
    80
3359
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    81
    cachedname = os.path.splitext(filename)[0] + (rl_config.useA85 and '.a85' or '.bin')
1368
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    82
    if filename==cachedname:
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    83
        if cachedImageExists(filename):
2558
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
    84
            from reportlab.lib.utils import open_for_read
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
    85
            if returnInMemory: return filter(None,open_for_read(cachedname).read().split(LINEEND))
1368
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    86
        else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
    87
            raise IOError('No such cached image %s' % filename)
1368
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    88
    else:
3359
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    89
        if rl_config.useA85:
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    90
            code = makeA85Image(filename,IMG)
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    91
        else:
171fa15695a8 reportlab: optional A85 patch contributed by Yoann Roman
rgbecker
parents: 3326
diff changeset
    92
            code = makeRawImage(filename,IMG)
1368
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    93
        if returnInMemory: return code
760
0e51a12a0e39 Changed to PIL_Image
rgbecker
parents: 677
diff changeset
    94
1368
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    95
        #save it to a file
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    96
        f = open(cachedname,'wb')
2767
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
    97
        f.write(LINEEND.join(code)+LINEEND)
1368
3d1d1f4f87cb Fixed silly case of caching .a85 when it exists
rgbecker
parents: 1219
diff changeset
    98
        f.close()
1530
1dedd3370a99 rl_config._verbose ==> verbose
rgbecker
parents: 1421
diff changeset
    99
        if rl_config.verbose:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   100
            print('cached image as %s' % cachedname)
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   101
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   102
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   103
def preProcessImages(spec):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   104
    """Preprocesses one or more image files.
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   105
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   106
    Accepts either a filespec ('C:\mydir\*.jpg') or a list
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   107
    of image filenames, crunches them all to save time.  Run this
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   108
    to save huge amounts of time when repeatedly building image
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   109
    documents."""
660
243182bf7988 Removed commented encoding test functions.
dinu_gherman
parents: 658
diff changeset
   110
34
04f3b454ad8b Added missing import glob
rgbecker
parents: 16
diff changeset
   111
    import types, glob
660
243182bf7988 Removed commented encoding test functions.
dinu_gherman
parents: 658
diff changeset
   112
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   113
    if type(spec) is types.StringType:
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   114
        filelist = glob.glob(spec)
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   115
    else:  #list or tuple OK
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   116
        filelist = spec
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   117
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   118
    for filename in filelist:
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   119
        if cachedImageExists(filename):
1530
1dedd3370a99 rl_config._verbose ==> verbose
rgbecker
parents: 1421
diff changeset
   120
            if rl_config.verbose:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   121
                print('cached version of %s already exists' % filename)
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   122
        else:
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   123
            cacheImageFile(filename)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   124
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   125
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   126
def cachedImageExists(filename):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   127
    """Determines if a cached image already exists for a given file.
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   128
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   129
    Determines if a cached image exists which has the same name
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   130
    and equal or newer date to the given file."""
3431
b92783cd5a73 pdfutils.py: fix 2.5'ism
rgbecker
parents: 3363
diff changeset
   131
    cachedname = os.path.splitext(filename)[0] + (rl_config.useA85 and '.a85' or 'bin')
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   132
    if os.path.isfile(cachedname):
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   133
        #see if it is newer
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   134
        original_date = os.stat(filename)[8]
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   135
        cached_date = os.stat(cachedname)[8]
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   136
        if original_date > cached_date:
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   137
            return 0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   138
        else:
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   139
            return 1
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   140
    else:
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   141
        return 0
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   142
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   143
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   144
##############################################################
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   145
#
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   146
#            PDF Helper functions
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   147
#
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   148
##############################################################
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   149
1064
45e385ce9b6f moved escape functionality from canvas object to pdfutils function (with canvas stub)
aaron_watters
parents: 1029
diff changeset
   150
try:
1066
b189cf3b5cb4 Fixed up _rl_accel imports to new standard
rgbecker
parents: 1064
diff changeset
   151
    from _rl_accel import escapePDF, _instanceEscapePDF
1064
45e385ce9b6f moved escape functionality from canvas object to pdfutils function (with canvas stub)
aaron_watters
parents: 1029
diff changeset
   152
    _escape = escapePDF
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   153
except ImportError:
1066
b189cf3b5cb4 Fixed up _rl_accel imports to new standard
rgbecker
parents: 1064
diff changeset
   154
    try:
b189cf3b5cb4 Fixed up _rl_accel imports to new standard
rgbecker
parents: 1064
diff changeset
   155
        from reportlab.lib._rl_accel import escapePDF, _instanceEscapePDF
b189cf3b5cb4 Fixed up _rl_accel imports to new standard
rgbecker
parents: 1064
diff changeset
   156
        _escape = escapePDF
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   157
    except ImportError:
1066
b189cf3b5cb4 Fixed up _rl_accel imports to new standard
rgbecker
parents: 1064
diff changeset
   158
        _instanceEscapePDF=None
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   159
        _ESCAPEDICT={}
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   160
        for c in range(256):
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   161
            if c<32 or c>=127:
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   162
                _ESCAPEDICT[c]= '\\%03o' % c
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   163
            elif c in (ord('\\'),ord('('),ord(')')):
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   164
                _ESCAPEDICT[c] = '\\'+chr(c)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   165
            else:
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   166
                _ESCAPEDICT[c] = chr(c)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   167
        del c
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   168
        #Michael Hudson donated this
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   169
        def _escape(s):
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   170
            r = []
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   171
            for c in s:
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   172
                if not type(c) is int:
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   173
                    c = ord(c)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   174
                r.append(_ESCAPEDICT[c])
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   175
            return ''.join(r)
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   176
3363
f329def8b08f pdfutils.py: fix bad code
rgbecker
parents: 3359
diff changeset
   177
def _normalizeLineEnds(text,desired=LINEEND,unlikely='\x00\x01\x02\x03'):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   178
    """Normalizes different line end character(s).
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   179
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   180
    Ensures all instances of CR, LF and CRLF end up as
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   181
    the specified one."""
2767
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   182
    
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   183
    return (text
3363
f329def8b08f pdfutils.py: fix bad code
rgbecker
parents: 3359
diff changeset
   184
            .replace('\r\n', unlikely)
f329def8b08f pdfutils.py: fix bad code
rgbecker
parents: 3359
diff changeset
   185
            .replace('\r', unlikely)
f329def8b08f pdfutils.py: fix bad code
rgbecker
parents: 3359
diff changeset
   186
            .replace('\n', unlikely)
f329def8b08f pdfutils.py: fix bad code
rgbecker
parents: 3359
diff changeset
   187
            .replace(unlikely, desired))
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   188
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   189
def _AsciiHexEncode(input):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   190
    """Encodes input using ASCII-Hex coding.
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   191
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   192
    This is a verbose encoding used for binary data within
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   193
    a PDF file.  One byte binary becomes two bytes of ASCII.
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   194
    Helper function used by images."""
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   195
    if isUnicodeType(input):
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   196
        input = input.encode('utf-8')
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   197
    output = getBytesIO()
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   198
    output.write(binascii.b2a_hex(input))
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   199
    output.write(b'>')
1621
0b7238e56cae Remove stringio reset
rgbecker
parents: 1582
diff changeset
   200
    return output.getvalue()
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   201
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   202
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   203
def _AsciiHexDecode(input):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   204
    """Decodes input using ASCII-Hex coding.
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   205
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   206
    Not used except to provide a test of the inverse function."""
660
243182bf7988 Removed commented encoding test functions.
dinu_gherman
parents: 658
diff changeset
   207
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   208
    #strip out all whitespace
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   209
    if not isStrType(input):
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   210
        input = input.decode('utf-8')
2767
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   211
    stripped = ''.join(input.split())
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   212
    assert stripped[-1] == '>', 'Invalid terminator for Ascii Hex Stream'
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   213
    stripped = stripped[:-1]  #chop off terminator
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   214
    assert len(stripped) % 2 == 0, 'Ascii Hex stream has odd number of bytes'
660
243182bf7988 Removed commented encoding test functions.
dinu_gherman
parents: 658
diff changeset
   215
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   216
    return ''.join([chr(int(stripped[i:i+2],16)) for i in range(0,len(stripped),2)])
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   217
        
1421
ef290ee0aed7 took python implementation of base85 encoding out of conditional
aaron_watters
parents: 1368
diff changeset
   218
if 1: # for testing always define this
ef290ee0aed7 took python implementation of base85 encoding out of conditional
aaron_watters
parents: 1368
diff changeset
   219
    def _AsciiBase85EncodePYTHON(input):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   220
        """Encodes input using ASCII-Base85 coding.
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   221
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   222
        This is a compact encoding used for binary data within
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   223
        a PDF file.  Four bytes of binary data become five bytes of
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   224
        ASCII.  This is the default method used for encoding images."""
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   225
        # special rules apply if not a multiple of four bytes.
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   226
        whole_word_count, remainder_size = divmod(len(input), 4)
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   227
        cut = 4 * whole_word_count
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   228
        body, lastbit = input[0:cut], input[cut:]
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   229
        if isPython3 and isStrType(lastbit):
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   230
            lastbit = lastbit.encode('utf-8')
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   231
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   232
        out = [].append
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   233
        for i in range(whole_word_count):
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   234
            offset = i*4
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   235
            b1 = body[offset]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   236
            b2 = body[offset+1]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   237
            b3 = body[offset+2]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   238
            b4 = body[offset+3]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   239
            if isStrType(b1): b1 = ord(b1)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   240
            if isStrType(b2): b2 = ord(b2)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   241
            if isStrType(b3): b3 = ord(b3)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   242
            if isStrType(b4): b4 = ord(b4)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   243
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   244
            if b1<128:
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   245
                num = (((((b1<<8)|b2)<<8)|b3)<<8)|b4
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   246
            else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   247
                num = 16777216 * b1 + 65536 * b2 + 256 * b3 + b4
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   248
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   249
            if num == 0:
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   250
                #special case
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   251
                out('z')
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   252
            else:
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   253
                #solve for five base-85 numbers
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   254
                temp, c5 = divmod(num, 85)
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   255
                temp, c4 = divmod(temp, 85)
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   256
                temp, c3 = divmod(temp, 85)
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   257
                c1, c2 = divmod(temp, 85)
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   258
                assert ((85**4) * c1) + ((85**3) * c2) + ((85**2) * c3) + (85*c4) + c5 == num, 'dodgy code!'
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   259
                out(chr(c1+33))
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   260
                out(chr(c2+33))
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   261
                out(chr(c3+33))
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   262
                out(chr(c4+33))
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   263
                out(chr(c5+33))
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   264
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   265
        # now we do the final bit at the end.  I repeated this separately as
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   266
        # the loop above is the time-critical part of a script, whereas this
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   267
        # happens only once at the end.
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   268
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   269
        #encode however many bytes we have as usual
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   270
        if remainder_size > 0:
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   271
            while len(lastbit) < 4:
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   272
                lastbit = lastbit + b'\000'
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   273
            b1 = lastbit[0]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   274
            b2 = lastbit[1]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   275
            b3 = lastbit[2]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   276
            b4 = lastbit[3]
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   277
            if isStrType(b1): b1 = ord(b1)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   278
            if isStrType(b2): b2 = ord(b2)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   279
            if isStrType(b3): b3 = ord(b3)
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   280
            if isStrType(b4): b4 = ord(b4)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   281
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   282
            num = 16777216 * b1 + 65536 * b2 + 256 * b3 + b4
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   283
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   284
            #solve for c1..c5
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   285
            temp, c5 = divmod(num, 85)
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   286
            temp, c4 = divmod(temp, 85)
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   287
            temp, c3 = divmod(temp, 85)
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   288
            c1, c2 = divmod(temp, 85)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   289
321
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   290
            #print 'encoding: %d %d %d %d -> %d -> %d %d %d %d %d' % (
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   291
            #    b1,b2,b3,b4,num,c1,c2,c3,c4,c5)
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   292
            lastword = chr(c1+33) + chr(c2+33) + chr(c3+33) + chr(c4+33) + chr(c5+33)
a8d81f92b2e7 Ascii85 fixes/additions
rgbecker
parents: 313
diff changeset
   293
            #write out most of the bytes.
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   294
            out(lastword[0:remainder_size + 1])
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   295
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   296
        #terminator code for ascii 85
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   297
        out('~>')
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   298
        return ''.join(out.__self__)
1421
ef290ee0aed7 took python implementation of base85 encoding out of conditional
aaron_watters
parents: 1368
diff changeset
   299
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   300
    def _AsciiBase85DecodePYTHON(input):
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   301
        """Decodes input using ASCII-Base85 coding.
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   302
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   303
        This is not used - Acrobat Reader decodes for you
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   304
        - but a round trip is essential for testing."""
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   305
        #strip all whitespace
2767
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   306
        stripped = ''.join(input.split())
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   307
        #check end
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   308
        assert stripped[-2:] == '~>', 'Invalid terminator for Ascii Base 85 Stream'
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   309
        stripped = stripped[:-2]  #chop off terminator
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   310
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   311
        #may have 'z' in it which complicates matters - expand them
2767
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   312
        stripped = stripped.replace('z','!!!!!')
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   313
        # special rules apply if not a multiple of five bytes.
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   314
        whole_word_count, remainder_size = divmod(len(stripped), 5)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   315
        #print '%d words, %d leftover' % (whole_word_count, remainder_size)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2994
diff changeset
   316
        #assert remainder_size != 1, 'invalid Ascii 85 stream!'
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   317
        cut = 5 * whole_word_count
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   318
        body, lastbit = stripped[0:cut], stripped[cut:]
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   319
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   320
        out = [].append
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   321
        for i in range(whole_word_count):
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   322
            offset = i*5
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   323
            c1 = ord(body[offset]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   324
            c2 = ord(body[offset+1]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   325
            c3 = ord(body[offset+2]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   326
            c4 = ord(body[offset+3]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   327
            c5 = ord(body[offset+4]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   328
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   329
            num = ((85**4) * c1) + ((85**3) * c2) + ((85**2) * c3) + (85*c4) + c5
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   330
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   331
            temp, b4 = divmod(num,256)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   332
            temp, b3 = divmod(temp,256)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   333
            b1, b2 = divmod(temp, 256)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   334
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   335
            assert  num == 16777216 * b1 + 65536 * b2 + 256 * b3 + b4, 'dodgy code!'
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   336
            out(chr(b1))
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   337
            out(chr(b2))
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   338
            out(chr(b3))
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   339
            out(chr(b4))
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   340
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   341
        #decode however many bytes we have as usual
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   342
        if remainder_size > 0:
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   343
            while len(lastbit) < 5:
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   344
                lastbit = lastbit + '!'
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   345
            c1 = ord(lastbit[0]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   346
            c2 = ord(lastbit[1]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   347
            c3 = ord(lastbit[2]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   348
            c4 = ord(lastbit[3]) - 33
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   349
            c5 = ord(lastbit[4]) - 33
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   350
            num = (((85*c1+c2)*85+c3)*85+c4)*85 + (c5
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   351
                     +(0,0,0xFFFFFF,0xFFFF,0xFF)[remainder_size])
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   352
            temp, b4 = divmod(num,256)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   353
            temp, b3 = divmod(temp,256)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   354
            b1, b2 = divmod(temp, 256)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   355
            assert  num == 16777216 * b1 + 65536 * b2 + 256 * b3 + b4, 'dodgy code!'
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   356
            #print 'decoding: %d %d %d %d %d -> %d -> %d %d %d %d' % (
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   357
            #    c1,c2,c3,c4,c5,num,b1,b2,b3,b4)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   358
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   359
            #the last character needs 1 adding; the encoding loses
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   360
            #data by rounding the number to x bytes, and when
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   361
            #divided repeatedly we get one less
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   362
            if remainder_size == 2:
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   363
                lastword = chr(b1)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   364
            elif remainder_size == 3:
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   365
                lastword = chr(b1) + chr(b2)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   366
            elif remainder_size == 4:
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   367
                lastword = chr(b1) + chr(b2) + chr(b3)
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   368
            else:
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   369
                lastword = ''
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   370
            out(lastword)
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   371
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   372
        #terminator code for ascii 85
2853
69fab4f9a4ad pdfutils.py: improvements to en/decoders
rgbecker
parents: 2767
diff changeset
   373
        return ''.join(out.__self__)
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   374
1421
ef290ee0aed7 took python implementation of base85 encoding out of conditional
aaron_watters
parents: 1368
diff changeset
   375
try:
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   376
    from _rl_accel import _AsciiBase85Encode                    # builtin or on the path
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   377
except ImportError:
1421
ef290ee0aed7 took python implementation of base85 encoding out of conditional
aaron_watters
parents: 1368
diff changeset
   378
    try:
ef290ee0aed7 took python implementation of base85 encoding out of conditional
aaron_watters
parents: 1368
diff changeset
   379
        from reportlab.lib._rl_accel import _AsciiBase85Encode  # where we think it should be
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   380
    except ImportError:
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   381
        _AsciiBase85Encode = _AsciiBase85EncodePYTHON
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   382
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   383
try:
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   384
    from _rl_accel import _AsciiBase85Decode                    # builtin or on the path
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   385
except ImportError:
1788
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   386
    try:
406d9b0a6453 Added _rl_accel._Ascii85Decode
rgbecker
parents: 1772
diff changeset
   387
        from reportlab.lib._rl_accel import _AsciiBase85Decode  # where we think it should be
2053
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   388
    except ImportError:
2a962a30dc46 Removed checkImportError
rgbecker
parents: 2045
diff changeset
   389
        _AsciiBase85Decode = _AsciiBase85DecodePYTHON
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   390
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   391
def _wrap(input, columns=60):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   392
    "Wraps input at a given column size by inserting LINEEND characters."
0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   393
    output = []
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   394
    length = len(input)
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   395
    i = 0
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   396
    pos = columns * i
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   397
    while pos < length:
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   398
        output.append(input[pos:pos+columns])
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   399
        i = i + 1
f19e0a2433ab Initial revision
gmcm
parents:
diff changeset
   400
        pos = columns * i
2767
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   401
    #avoid HP printer problem
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   402
    if len(output[-1])==1:
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   403
        output[-2:] = [output[-2][:-1],output[-2][-1]+output[-1]]
2ba5a1d26ad0 reportlab: make a85 wrap optional, add _reset to rl_config
rgbecker
parents: 2558
diff changeset
   404
    return LINEEND.join(output)
657
75f09848334a Commented one test function.
dinu_gherman
parents: 567
diff changeset
   405
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   406
224
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   407
#########################################################################
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   408
#
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   409
#  JPEG processing code - contributed by Eric Johnson
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   410
#
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   411
#########################################################################
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   412
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   413
# Read data from the JPEG file. We should probably be using PIL to
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   414
# get this information for us -- but this way is more fun!
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   415
# Returns (width, height, color components) as a triple
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   416
# This is based on Thomas Merz's code from GhostScript (viewjpeg.ps)
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   417
def readJPEGInfo(image):
567
0c7064b86e9e Modified docstrings.
dinu_gherman
parents: 494
diff changeset
   418
    "Read width, height and number of components from open JPEG file."
660
243182bf7988 Removed commented encoding test functions.
dinu_gherman
parents: 658
diff changeset
   419
224
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   420
    import struct
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   421
    from .pdfdoc import PDFError
224
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   422
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   423
    #Acceptable JPEG Markers:
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   424
    #  SROF0=baseline, SOF1=extended sequential or SOF2=progressive
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   425
    validMarkers = [0xC0, 0xC1, 0xC2]
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   426
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   427
    #JPEG markers without additional parameters
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   428
    noParamMarkers = \
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   429
        [ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0x01 ]
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   430
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   431
    #Unsupported JPEG Markers
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   432
    unsupportedMarkers = \
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   433
        [ 0xC3, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xCF ]
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   434
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   435
    #read JPEG marker segments until we find SOFn marker or EOF
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   436
    done = 0
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   437
    while not done:
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   438
        x = struct.unpack('B', image.read(1))
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   439
        if x[0] == 0xFF:                    #found marker
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   440
            x = struct.unpack('B', image.read(1))
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   441
            #print "Marker: ", '%0.2x' % x[0]
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   442
            #check marker type is acceptable and process it
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   443
            if x[0] in validMarkers:
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   444
                image.seek(2, 1)            #skip segment length
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   445
                x = struct.unpack('B', image.read(1)) #data precision
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   446
                if x[0] != 8:
2558
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
   447
                    raise PDFError('JPEG must have 8 bits per component')
224
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   448
                y = struct.unpack('BB', image.read(2))
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1621
diff changeset
   449
                height = (y[0] << 8) + y[1]
224
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   450
                y = struct.unpack('BB', image.read(2))
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   451
                width =  (y[0] << 8) + y[1]
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   452
                y = struct.unpack('B', image.read(1))
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   453
                color =  y[0]
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   454
                return width, height, color
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   455
            elif x[0] in unsupportedMarkers:
2558
97ae9d8242cd pdfgen: fix badly drawn jpegs which are actually gifs
rgbecker
parents: 2482
diff changeset
   456
                raise PDFError('JPEG Unsupported JPEG marker: %0.2x' % x[0])
224
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   457
            elif x[0] not in noParamMarkers:
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   458
                #skip segments with parameters
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   459
                #read length and skip the data
764725e69f94 readJPEGinfo moved from canvas to pdfutils;
andy_robinson
parents: 34
diff changeset
   460
                x = struct.unpack('BB', image.read(2))
1772
ba6ba46e2370 Added A85 caching possibility to Image XObjects
rgbecker
parents: 1683
diff changeset
   461
                image.seek( (x[0] << 8) + x[1] - 2, 1)
2399
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   462
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   463
class _fusc:
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   464
    def __init__(self,k, n):
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   465
        assert k, 'Argument k should be a non empty string'
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   466
        self._k = k
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   467
        self._klen = len(k)
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   468
        self._n = int(n) or 7
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   469
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   470
    def encrypt(self,s):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   471
        return self.__rotate(_AsciiBase85Encode(''.join(map(chr,self.__fusc(list(map(ord,s)))))),self._n)
2399
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   472
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   473
    def decrypt(self,s):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   474
        return ''.join(map(chr,self.__fusc(list(map(ord,_AsciiBase85Decode(self.__rotate(s,-self._n)))))))
2399
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   475
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   476
    def __rotate(self,s,n):
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   477
        l = len(s)
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   478
        if n<0: n = l+n
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   479
        n %= l
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   480
        if not n: return s
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   481
        return s[-n:]+s[:l-n]
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   482
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   483
    def __fusc(self,s):
41c1b1d88a33 pdfutils.py: added _fusc
rgbecker
parents: 2332
diff changeset
   484
        slen = len(s)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   485
        return list(map(lambda x,y: x ^ y,s,list(map(ord,((int(slen/self._klen)+1)*self._k)[:slen]))))