~oubiwann/pyrtf/master

« back to all changes in this revision

Viewing changes to rtfng/object/picture.py

  • Committer: Christian R. Simms
  • Date: 2009-11-02 15:20:18 UTC
  • mfrom: (70.1.23)
  • Revision ID: git-v1:5d312e1d38efd162c6023edef6a6f453793df735
* split out object.picture from Elements so that increased coverage in test_pictures passes
* write test of Document.Copy
* add test of Document.NewSection
* add .bzrignore file to ignore pending directory
* add script to test coverage of code base
* write test script which runs nosetest on all unit tests and doctests
* centralize basic initializeDoc in tests
* move comments about test strategy
* delete old temp test code
* comment out unused code
* remove executable bit from tests so that nosetest can detect them

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from binascii import hexlify
 
2
 
 
3
from rtfng.document.base import RawCode
 
4
 
 
5
 
 
6
def _get_jpg_dimensions( fin ):
 
7
    """
 
8
    converted from: http://dev.w3.org/cvsweb/Amaya/libjpeg/rdjpgcom.c?rev=1.2
 
9
    """
 
10
 
 
11
    M_SOF0   = chr( 0xC0 )    #    /* Start Of Frame N */
 
12
    M_SOF1   = chr( 0xC1 )    #    /* N indicates which compression process */
 
13
    M_SOF2   = chr( 0xC2 )    #    /* Only SOF0-SOF2 are now in common use */
 
14
    M_SOF3   = chr( 0xC3 )    #
 
15
    M_SOF5   = chr( 0xC5 )    #    /* NB: codes C4 and CC are NOT SOF markers */
 
16
    M_SOF6   = chr( 0xC6 )    #
 
17
    M_SOF7   = chr( 0xC7 )    #
 
18
    M_SOF9   = chr( 0xC9 )    #
 
19
    M_SOF10  = chr( 0xCA )    #
 
20
    M_SOF11  = chr( 0xCB )    #
 
21
    M_SOF13  = chr( 0xCD )    #
 
22
    M_SOF14  = chr( 0xCE )    #
 
23
    M_SOF15  = chr( 0xCF )    #
 
24
    M_SOI    = chr( 0xD8 )    #    /* Start Of Image (beginning of datastream) */
 
25
    M_EOI    = chr( 0xD9 )  #    /* End Of Image (end of datastream) */
 
26
 
 
27
    M_FF = chr( 0xFF )
 
28
 
 
29
    MARKERS = [ M_SOF0, M_SOF1,  M_SOF2,  M_SOF3,
 
30
                M_SOF5, M_SOF6,  M_SOF7,  M_SOF9,
 
31
                M_SOF10,M_SOF11, M_SOF13, M_SOF14,
 
32
                M_SOF15 ]
 
33
 
 
34
    def get_length() :
 
35
        b1 = fin.read( 1 )
 
36
        b2 = fin.read( 1 )
 
37
        return (ord(b1) << 8) + ord(b2)
 
38
 
 
39
    def next_marker() :
 
40
        #  markers come straight after an 0xFF so skip everything
 
41
        #  up to the first 0xFF that we find
 
42
        while fin.read(1) != M_FF :
 
43
            pass
 
44
 
 
45
        #  there can be more than one 0xFF as they can be used
 
46
        #  for padding so we are now looking for the first byte
 
47
        #  that isn't an 0xFF, this will be the marker
 
48
        while True :
 
49
            result = fin.read(1)
 
50
            if result != M_FF :
 
51
                return result
 
52
 
 
53
        raise Exception( 'Invalid JPEG' )
 
54
 
 
55
    #  BODY OF THE FUNCTION
 
56
    if not ((fin.read(1) == M_FF) and (fin.read(1) == M_SOI)) :
 
57
        raise Exception( 'Invalid Jpeg' )
 
58
 
 
59
    while True :
 
60
        marker = next_marker()
 
61
 
 
62
        #  the marker is always followed by two bytes representing the length of the data field
 
63
        length = get_length ()
 
64
        if length < 2 : raise Exception( "Erroneous JPEG marker length" )
 
65
 
 
66
        #  if it is a compression process marker then it will contain the dimension of the image
 
67
        if marker in MARKERS :
 
68
            #  the next byte is the data precision, just skip it
 
69
            fin.read(1)
 
70
 
 
71
            #  bingo
 
72
            image_height = get_length()
 
73
            image_width  = get_length()
 
74
            return image_width, image_height
 
75
 
 
76
        #  just skip whatever data it contains
 
77
        fin.read( length - 2 )
 
78
 
 
79
    raise Exception( 'Invalid JPEG, end of stream reached' )
 
80
 
 
81
 
 
82
_PNG_HEADER = '\x89\x50\x4e'
 
83
def _get_png_dimensions( data ) :
 
84
    if data[0:3] != _PNG_HEADER :
 
85
        raise Exception( 'Invalid PNG image' )
 
86
 
 
87
    width  = (ord(data[18]) * 256) + (ord(data[19]))
 
88
    height = (ord(data[22]) * 256) + (ord(data[23]))
 
89
    return width, height
 
90
 
 
91
 
 
92
class Image( RawCode ) :
 
93
 
 
94
    #  Need to add in the width and height in twips as it crashes
 
95
    #  word xp with these values.  Still working out the most
 
96
    #  efficient way of getting these values.
 
97
    # \picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0
 
98
    # picwgoal900\pichgoal281
 
99
 
 
100
    PNG_LIB = 'pngblip'
 
101
    JPG_LIB = 'jpegblip'
 
102
    PICT_TYPES = { 'png' : PNG_LIB,
 
103
                   'jpg' : JPG_LIB }
 
104
 
 
105
    def __init__( self, file_name, **kwargs ) :
 
106
 
 
107
        fin = file( file_name, 'rb' )
 
108
 
 
109
        pict_type = self.PICT_TYPES[ file_name[ -3 : ].lower() ]
 
110
        if pict_type == self.PNG_LIB :
 
111
            width, height = _get_png_dimensions( fin.read( 100 ) )
 
112
        else :
 
113
            width, height = _get_jpg_dimensions( fin )
 
114
 
 
115
        codes = [ pict_type,
 
116
                  'picwgoal%s' % (width  * 20),
 
117
                  'pichgoal%s' % (height * 20) ]
 
118
        for kwarg, code, default in [ ( 'scale_x',     'scalex', '100' ),
 
119
                                      ( 'scale_y',     'scaley', '100' ),
 
120
                                      ( 'crop_left',   'cropl',    '0' ),
 
121
                                      ( 'crop_right',  'cropr',    '0' ),
 
122
                                      ( 'crop_top',    'cropt',    '0' ),
 
123
                                      ( 'crop_bottom', 'cropb',    '0' ) ] :
 
124
            codes.append( 'pic%s%s' % ( code, kwargs.pop( kwarg, default ) ) )
 
125
 
 
126
 
 
127
        #  reset back to the start of the file to get all of it and now
 
128
        #  turn it into hex.
 
129
        fin.seek( 0, 0 )
 
130
        data = []
 
131
        image = hexlify( fin.read() )
 
132
        for i in range( 0, len( image ), 128 ) :
 
133
            data.append( image[ i : i + 128 ] )
 
134
 
 
135
        data = r'{\pict{\%s}%s}' % ( '\\'.join( codes ), '\n'.join( data ) )
 
136
        RawCode.__init__( self, data )
 
137
 
 
138
    def ToRawCode( self, var_name ) :
 
139
        return '%s = RawCode( """%s""" )' % ( var_name, self.Data )
 
140