1
from binascii import hexlify
3
from rtfng.document.base import RawCode
6
def _get_jpg_dimensions( fin ):
8
converted from: http://dev.w3.org/cvsweb/Amaya/libjpeg/rdjpgcom.c?rev=1.2
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) */
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,
37
return (ord(b1) << 8) + ord(b2)
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 :
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
53
raise Exception( 'Invalid JPEG' )
55
# BODY OF THE FUNCTION
56
if not ((fin.read(1) == M_FF) and (fin.read(1) == M_SOI)) :
57
raise Exception( 'Invalid Jpeg' )
60
marker = next_marker()
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" )
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
72
image_height = get_length()
73
image_width = get_length()
74
return image_width, image_height
76
# just skip whatever data it contains
77
fin.read( length - 2 )
79
raise Exception( 'Invalid JPEG, end of stream reached' )
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' )
87
width = (ord(data[18]) * 256) + (ord(data[19]))
88
height = (ord(data[22]) * 256) + (ord(data[23]))
92
class Image( RawCode ) :
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
102
PICT_TYPES = { 'png' : PNG_LIB,
105
def __init__( self, file_name, **kwargs ) :
107
fin = file( file_name, 'rb' )
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 ) )
113
width, height = _get_jpg_dimensions( fin )
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 ) ) )
127
# reset back to the start of the file to get all of it and now
131
image = hexlify( fin.read() )
132
for i in range( 0, len( image ), 128 ) :
133
data.append( image[ i : i + 128 ] )
135
data = r'{\pict{\%s}%s}' % ( '\\'.join( codes ), '\n'.join( data ) )
136
RawCode.__init__( self, data )
138
def ToRawCode( self, var_name ) :
139
return '%s = RawCode( """%s""" )' % ( var_name, self.Data )