| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 2 |  |  |  |  |  |  | # File:         PICT.pm | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | # Description:  Read PICT meta information | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | # Revisions:    10/10/2005 - P. Harvey Created | 
| 7 |  |  |  |  |  |  | # | 
| 8 |  |  |  |  |  |  | # Notes:        Extraction of PICT opcodes is still experimental | 
| 9 |  |  |  |  |  |  | # | 
| 10 |  |  |  |  |  |  | # - size difference in PixPat color table?? (imagemagick reads only 1 long per entry) | 
| 11 |  |  |  |  |  |  | # - other differences in the way imagemagick reads 16-bit images | 
| 12 |  |  |  |  |  |  | # | 
| 13 |  |  |  |  |  |  | # References:   1) http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html | 
| 14 |  |  |  |  |  |  | #               2) http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm | 
| 15 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | package Image::ExifTool::PICT; | 
| 18 |  |  |  |  |  |  |  | 
| 19 | 1 |  |  | 1 |  | 4470 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 67 |  | 
| 20 | 1 |  |  | 1 |  | 7 | use vars qw($VERSION); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 41 |  | 
| 21 | 1 |  |  | 1 |  | 5 | use Image::ExifTool qw(:DataAccess :Utils); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3256 |  | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | $VERSION = '1.05'; | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | sub ReadPictValue($$$;$); | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | my ($vers, $extended);  # PICT version number, and extended flag | 
| 28 |  |  |  |  |  |  | my ($verbose, $out, $indent); # used in verbose mode | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | # ranges of reserved opcodes. | 
| 31 |  |  |  |  |  |  | # opcodes at the start of each range must be defined in the tag table | 
| 32 |  |  |  |  |  |  | my @reserved = ( | 
| 33 |  |  |  |  |  |  | 0x0017 => 0x0019, 0x0024 => 0x0027, 0x0035 => 0x0037, 0x003d => 0x003f, | 
| 34 |  |  |  |  |  |  | 0x0045 => 0x0047, 0x004d => 0x004f, 0x0055 => 0x0057, 0x005d => 0x005f, | 
| 35 |  |  |  |  |  |  | 0x0065 => 0x0067, 0x006d => 0x006f, 0x0075 => 0x0077, 0x007d => 0x007f, | 
| 36 |  |  |  |  |  |  | 0x0085 => 0x0087, 0x008d => 0x008f, 0x0092 => 0x0097, 0x00a2 => 0x00af, | 
| 37 |  |  |  |  |  |  | 0x00b0 => 0x00cf, 0x00d0 => 0x00fe, 0x0100 => 0x01ff, 0x0300 => 0x0bfe, | 
| 38 |  |  |  |  |  |  | 0x0c01 => 0x7eff, 0x7f00 => 0x7fff, 0x8000 => 0x80ff, 0x8100 => 0x81ff, | 
| 39 |  |  |  |  |  |  | 0x8201 => 0xffff, | 
| 40 |  |  |  |  |  |  | ); | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | # Apple data structures in PICT images | 
| 43 |  |  |  |  |  |  | my %structs = ( | 
| 44 |  |  |  |  |  |  | Arc => [ | 
| 45 |  |  |  |  |  |  | rect => 'Rect', | 
| 46 |  |  |  |  |  |  | startAng => 'int16s', | 
| 47 |  |  |  |  |  |  | arcAng => 'int16s', | 
| 48 |  |  |  |  |  |  | ], | 
| 49 |  |  |  |  |  |  | BitMap => [ | 
| 50 |  |  |  |  |  |  | # (no baseAddr) | 
| 51 |  |  |  |  |  |  | rowBytes => 'int16u', | 
| 52 |  |  |  |  |  |  | bounds => 'Rect', | 
| 53 |  |  |  |  |  |  | ], | 
| 54 |  |  |  |  |  |  | # BitsRect data for PICT version 1 | 
| 55 |  |  |  |  |  |  | BitsRect1 => [ | 
| 56 |  |  |  |  |  |  | bitMap => 'BitMap', | 
| 57 |  |  |  |  |  |  | srcRect => 'Rect', | 
| 58 |  |  |  |  |  |  | dstRect => 'Rect', | 
| 59 |  |  |  |  |  |  | mode => 'int16u', | 
| 60 |  |  |  |  |  |  | dataSize => 'int16u', | 
| 61 |  |  |  |  |  |  | bitData => 'binary[$val{dataSize}]', | 
| 62 |  |  |  |  |  |  | ], | 
| 63 |  |  |  |  |  |  | # BitsRect data for PICT version 2 | 
| 64 |  |  |  |  |  |  | BitsRect2 => [ | 
| 65 |  |  |  |  |  |  | pixMap => 'PixMap', | 
| 66 |  |  |  |  |  |  | colorTable => 'ColorTable', | 
| 67 |  |  |  |  |  |  | srcRect => 'Rect', | 
| 68 |  |  |  |  |  |  | dstRect => 'Rect', | 
| 69 |  |  |  |  |  |  | mode => 'int16u', | 
| 70 |  |  |  |  |  |  | pixData => \ 'GetPixData($val{pixMap}, $raf)', | 
| 71 |  |  |  |  |  |  | ], | 
| 72 |  |  |  |  |  |  | # BitsRgn data for PICT version 1 | 
| 73 |  |  |  |  |  |  | BitsRgn1 => [ | 
| 74 |  |  |  |  |  |  | bitMap => 'BitMap', | 
| 75 |  |  |  |  |  |  | srcRect => 'Rect', | 
| 76 |  |  |  |  |  |  | dstRect => 'Rect', | 
| 77 |  |  |  |  |  |  | mode => 'int16u', | 
| 78 |  |  |  |  |  |  | maskRgn => 'Rgn', | 
| 79 |  |  |  |  |  |  | dataSize => 'int16u', | 
| 80 |  |  |  |  |  |  | bitData => 'binary[$val{dataSize}]', | 
| 81 |  |  |  |  |  |  | ], | 
| 82 |  |  |  |  |  |  | # BitsRgn data for PICT version 2 | 
| 83 |  |  |  |  |  |  | BitsRgn2 => [ | 
| 84 |  |  |  |  |  |  | pixMap => 'PixMap', | 
| 85 |  |  |  |  |  |  | colorTable => 'ColorTable', | 
| 86 |  |  |  |  |  |  | srcRect => 'Rect', | 
| 87 |  |  |  |  |  |  | dstRect => 'Rect', | 
| 88 |  |  |  |  |  |  | mode => 'int16u', | 
| 89 |  |  |  |  |  |  | maskRgn => 'Rgn', | 
| 90 |  |  |  |  |  |  | pixData => \ 'GetPixData($val{pixMap}, $raf)', | 
| 91 |  |  |  |  |  |  | ], | 
| 92 |  |  |  |  |  |  | ColorSpec => [ | 
| 93 |  |  |  |  |  |  | value => 'int16u', | 
| 94 |  |  |  |  |  |  | rgb => 'RGBColor', | 
| 95 |  |  |  |  |  |  | ], | 
| 96 |  |  |  |  |  |  | ColorTable => [ | 
| 97 |  |  |  |  |  |  | ctSeed => 'int32u', | 
| 98 |  |  |  |  |  |  | ctFlags => 'int16u', | 
| 99 |  |  |  |  |  |  | ctSize => 'int16u', | 
| 100 |  |  |  |  |  |  | ctTable => 'ColorSpec[$val{ctSize}+1]', | 
| 101 |  |  |  |  |  |  | ], | 
| 102 |  |  |  |  |  |  | # http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm | 
| 103 |  |  |  |  |  |  | CompressedQuickTime => [ | 
| 104 |  |  |  |  |  |  | size => 'int32u',   # size NOT including size word | 
| 105 |  |  |  |  |  |  | version => 'int16u', | 
| 106 |  |  |  |  |  |  | matrix => 'int32u[9]', | 
| 107 |  |  |  |  |  |  | matteSize => 'int32u', | 
| 108 |  |  |  |  |  |  | matteRect => 'Rect', | 
| 109 |  |  |  |  |  |  | mode => 'int16u', | 
| 110 |  |  |  |  |  |  | srcRect => 'Rect', | 
| 111 |  |  |  |  |  |  | accuracy => 'int32u', | 
| 112 |  |  |  |  |  |  | maskSize => 'int32u', | 
| 113 |  |  |  |  |  |  | matteDescr => 'Int32uData[$val{matteSize} ? 1 : 0]', | 
| 114 |  |  |  |  |  |  | matteData => 'int8u[$val{matteSize}]', | 
| 115 |  |  |  |  |  |  | maskRgn => 'int8u[$val{maskSize}]', | 
| 116 |  |  |  |  |  |  | imageDescr => 'ImageDescription', | 
| 117 |  |  |  |  |  |  | # size should be $val{imageDescr}->{dataSize}, but this is unreliable | 
| 118 |  |  |  |  |  |  | imageData => q{binary[$val{size} - 68 - $val{maskSize} - $val{imageDescr}->{size} - | 
| 119 |  |  |  |  |  |  | ($val{matteSize} ? $val{mattSize} + $val{matteDescr}->{size} : 0)] | 
| 120 |  |  |  |  |  |  | }, | 
| 121 |  |  |  |  |  |  | ], | 
| 122 |  |  |  |  |  |  | DirectBitsRect => [ | 
| 123 |  |  |  |  |  |  | baseAddr => 'int32u', | 
| 124 |  |  |  |  |  |  | pixMap => 'PixMap', | 
| 125 |  |  |  |  |  |  | srcRect => 'Rect', | 
| 126 |  |  |  |  |  |  | dstRect => 'Rect', | 
| 127 |  |  |  |  |  |  | mode => 'int16u', | 
| 128 |  |  |  |  |  |  | pixData => \ 'GetPixData($val{pixMap}, $raf)', | 
| 129 |  |  |  |  |  |  | ], | 
| 130 |  |  |  |  |  |  | DirectBitsRgn => [ | 
| 131 |  |  |  |  |  |  | baseAddr => 'int32u', | 
| 132 |  |  |  |  |  |  | pixMap => 'PixMap', | 
| 133 |  |  |  |  |  |  | srcRect => 'Rect', | 
| 134 |  |  |  |  |  |  | dstRect => 'Rect', | 
| 135 |  |  |  |  |  |  | mode => 'int16u', | 
| 136 |  |  |  |  |  |  | maskRgn => 'Rgn', | 
| 137 |  |  |  |  |  |  | pixData => \ 'GetPixData($val{pixMap}, $raf)', | 
| 138 |  |  |  |  |  |  | ], | 
| 139 |  |  |  |  |  |  | # http://developer.apple.com/technotes/qd/qd_01.html | 
| 140 |  |  |  |  |  |  | FontName => [ | 
| 141 |  |  |  |  |  |  | size => 'int16u',   # size NOT including size word | 
| 142 |  |  |  |  |  |  | oldFontID => 'int16u', | 
| 143 |  |  |  |  |  |  | nameLen => 'int8u', | 
| 144 |  |  |  |  |  |  | fontName => 'string[$val{nameLen}]', | 
| 145 |  |  |  |  |  |  | padding => 'binary[$val{size} - $val{nameLen} - 3]', | 
| 146 |  |  |  |  |  |  | ], | 
| 147 |  |  |  |  |  |  | # http://developer.apple.com/documentation/QuickTime/APIREF/imagedescription.htm | 
| 148 |  |  |  |  |  |  | ImageDescription => [ | 
| 149 |  |  |  |  |  |  | size => 'int32u',   # size INCLUDING size word | 
| 150 |  |  |  |  |  |  | cType => 'string[4]', | 
| 151 |  |  |  |  |  |  | res1 => 'int32u', | 
| 152 |  |  |  |  |  |  | res2 => 'int16u', | 
| 153 |  |  |  |  |  |  | dataRefIndex => 'int16u', | 
| 154 |  |  |  |  |  |  | version => 'int16u', | 
| 155 |  |  |  |  |  |  | revision => 'int16u', | 
| 156 |  |  |  |  |  |  | vendor => 'string[4]', | 
| 157 |  |  |  |  |  |  | temporalQuality => 'int32u', | 
| 158 |  |  |  |  |  |  | quality => 'int32u', | 
| 159 |  |  |  |  |  |  | width => 'int16u', | 
| 160 |  |  |  |  |  |  | height => 'int16u', | 
| 161 |  |  |  |  |  |  | hRes => 'fixed32u', | 
| 162 |  |  |  |  |  |  | vRes => 'fixed32u', | 
| 163 |  |  |  |  |  |  | dataSize => 'int32u', | 
| 164 |  |  |  |  |  |  | frameCount => 'int16u', | 
| 165 |  |  |  |  |  |  | nameLen => 'int8u', | 
| 166 |  |  |  |  |  |  | compressor => 'string[31]', | 
| 167 |  |  |  |  |  |  | depth => 'int16u', | 
| 168 |  |  |  |  |  |  | clutID => 'int16u', | 
| 169 |  |  |  |  |  |  | clutData => 'binary[$val{size}-86]', | 
| 170 |  |  |  |  |  |  | ], | 
| 171 |  |  |  |  |  |  | Int8uText => [ | 
| 172 |  |  |  |  |  |  | val => 'int8u', | 
| 173 |  |  |  |  |  |  | count => 'int8u', | 
| 174 |  |  |  |  |  |  | text => 'string[$val{count}]', | 
| 175 |  |  |  |  |  |  | ], | 
| 176 |  |  |  |  |  |  | Int8u2Text => [ | 
| 177 |  |  |  |  |  |  | val => 'int8u[2]', | 
| 178 |  |  |  |  |  |  | count => 'int8u', | 
| 179 |  |  |  |  |  |  | text => 'string[$val{count}]', | 
| 180 |  |  |  |  |  |  | ], | 
| 181 |  |  |  |  |  |  | Int16Data => [ | 
| 182 |  |  |  |  |  |  | size => 'int16u',   # size NOT including size word | 
| 183 |  |  |  |  |  |  | data => 'int8u[$val{size}]', | 
| 184 |  |  |  |  |  |  | ], | 
| 185 |  |  |  |  |  |  | Int32uData => [ | 
| 186 |  |  |  |  |  |  | size => 'int32u',   # size NOT including size word | 
| 187 |  |  |  |  |  |  | data => 'int8u[$val{size}]', | 
| 188 |  |  |  |  |  |  | ], | 
| 189 |  |  |  |  |  |  | LongComment => [ | 
| 190 |  |  |  |  |  |  | kind => 'int16u', | 
| 191 |  |  |  |  |  |  | size => 'int16u',   # size of data only | 
| 192 |  |  |  |  |  |  | data => 'binary[$val{size}]', | 
| 193 |  |  |  |  |  |  | ], | 
| 194 |  |  |  |  |  |  | PixMap => [ | 
| 195 |  |  |  |  |  |  | # Note: does not contain baseAddr | 
| 196 |  |  |  |  |  |  | # (except for DirectBits opcodes in which it is loaded separately) | 
| 197 |  |  |  |  |  |  | rowBytes => 'int16u', | 
| 198 |  |  |  |  |  |  | bounds => 'Rect', | 
| 199 |  |  |  |  |  |  | pmVersion => 'int16u', | 
| 200 |  |  |  |  |  |  | packType => 'int16u', | 
| 201 |  |  |  |  |  |  | packSize => 'int32u', | 
| 202 |  |  |  |  |  |  | hRes => 'fixed32s', | 
| 203 |  |  |  |  |  |  | vRes => 'fixed32s', | 
| 204 |  |  |  |  |  |  | pixelType => 'int16u', | 
| 205 |  |  |  |  |  |  | pixelSize => 'int16u', | 
| 206 |  |  |  |  |  |  | cmpCount => 'int16u', | 
| 207 |  |  |  |  |  |  | cmpSize => 'int16u', | 
| 208 |  |  |  |  |  |  | planeBytes => 'int32u', | 
| 209 |  |  |  |  |  |  | pmTable => 'int32u', | 
| 210 |  |  |  |  |  |  | pmReserved => 'int32u', | 
| 211 |  |  |  |  |  |  | ], | 
| 212 |  |  |  |  |  |  | PixPat => [ | 
| 213 |  |  |  |  |  |  | patType => 'int16u',    # 1 = non-dithered, 2 = dithered | 
| 214 |  |  |  |  |  |  | pat1Data => 'int8u[8]', | 
| 215 |  |  |  |  |  |  | # dithered PixPat has RGB entry | 
| 216 |  |  |  |  |  |  | RGB => 'RGBColor[$val{patType} == 2 ? 1 : 0]', | 
| 217 |  |  |  |  |  |  | # non-dithered PixPat has other stuff instead | 
| 218 |  |  |  |  |  |  | nonDithered=> 'PixPatNonDithered[$val{patType} == 2 ? 0 : 1]', | 
| 219 |  |  |  |  |  |  | ], | 
| 220 |  |  |  |  |  |  | PixPatNonDithered => [ | 
| 221 |  |  |  |  |  |  | pixMap => 'PixMap', | 
| 222 |  |  |  |  |  |  | colorTable => 'ColorTable', | 
| 223 |  |  |  |  |  |  | pixData => \ 'GetPixData($val{pixMap}, $raf)', | 
| 224 |  |  |  |  |  |  | ], | 
| 225 |  |  |  |  |  |  | Point => [ | 
| 226 |  |  |  |  |  |  | v => 'int16s', | 
| 227 |  |  |  |  |  |  | h => 'int16s', | 
| 228 |  |  |  |  |  |  | ], | 
| 229 |  |  |  |  |  |  | PointText => [ | 
| 230 |  |  |  |  |  |  | txLoc => 'Point', | 
| 231 |  |  |  |  |  |  | count => 'int8u', | 
| 232 |  |  |  |  |  |  | text => 'string[$val{count}]', | 
| 233 |  |  |  |  |  |  | ], | 
| 234 |  |  |  |  |  |  | Polygon => [ | 
| 235 |  |  |  |  |  |  | polySize => 'int16u', | 
| 236 |  |  |  |  |  |  | polyBBox => 'Rect', | 
| 237 |  |  |  |  |  |  | polyPoints => 'int16u[($val{polySize}-10)/2]', | 
| 238 |  |  |  |  |  |  | ], | 
| 239 |  |  |  |  |  |  | Rect => [ | 
| 240 |  |  |  |  |  |  | topLeft => 'Point', | 
| 241 |  |  |  |  |  |  | botRight => 'Point', | 
| 242 |  |  |  |  |  |  | ], | 
| 243 |  |  |  |  |  |  | RGBColor => [ | 
| 244 |  |  |  |  |  |  | red => 'int16u', | 
| 245 |  |  |  |  |  |  | green => 'int16u', | 
| 246 |  |  |  |  |  |  | blue => 'int16u', | 
| 247 |  |  |  |  |  |  | ], | 
| 248 |  |  |  |  |  |  | Rgn => [ | 
| 249 |  |  |  |  |  |  | rgnSize => 'int16u', | 
| 250 |  |  |  |  |  |  | rgnBBox => 'Rect', | 
| 251 |  |  |  |  |  |  | data => 'int8u[$val{rgnSize}-10]', | 
| 252 |  |  |  |  |  |  | ], | 
| 253 |  |  |  |  |  |  | ShortLine => [ | 
| 254 |  |  |  |  |  |  | pnLoc => 'Point', | 
| 255 |  |  |  |  |  |  | dh => 'int8s', | 
| 256 |  |  |  |  |  |  | dv => 'int8s', | 
| 257 |  |  |  |  |  |  | ], | 
| 258 |  |  |  |  |  |  | # http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm | 
| 259 |  |  |  |  |  |  | UncompressedQuickTime => [ | 
| 260 |  |  |  |  |  |  | size => 'int32u',   # size NOT including size word | 
| 261 |  |  |  |  |  |  | version => 'int16u', | 
| 262 |  |  |  |  |  |  | matrix => 'int32u[9]', | 
| 263 |  |  |  |  |  |  | matteSize => 'int32u', | 
| 264 |  |  |  |  |  |  | matteRect => 'Rect', | 
| 265 |  |  |  |  |  |  | matteDescr => 'Int32uData[$val{matteSize} ? 1 : 0]', | 
| 266 |  |  |  |  |  |  | matteData => 'binary[$val{matteSize}]', | 
| 267 |  |  |  |  |  |  | subOpcodeData => q{ | 
| 268 |  |  |  |  |  |  | binary[ $val{size} - 50 - | 
| 269 |  |  |  |  |  |  | ($val{matteSize} ? $val{mattSize} + $val{matteDescr}->{size} : 0)] | 
| 270 |  |  |  |  |  |  | }, | 
| 271 |  |  |  |  |  |  | ], | 
| 272 |  |  |  |  |  |  | ); | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | # PICT image opcodes | 
| 275 |  |  |  |  |  |  | %Image::ExifTool::PICT::Main = ( | 
| 276 |  |  |  |  |  |  | VARS => { NO_LOOKUP => 1 }, # omit tags from lookup | 
| 277 |  |  |  |  |  |  | NOTES => q{ | 
| 278 |  |  |  |  |  |  | The PICT format contains no true meta information, except for the possible | 
| 279 |  |  |  |  |  |  | exception of the LongComment opcode.  By default, only ImageWidth, | 
| 280 |  |  |  |  |  |  | ImageHeight and X/YResolution are extracted from a PICT image.  Tags in the | 
| 281 |  |  |  |  |  |  | following table represent image opcodes.  Extraction of these tags is | 
| 282 |  |  |  |  |  |  | experimental, and is only enabled with the Verbose or Unknown options. | 
| 283 |  |  |  |  |  |  | }, | 
| 284 |  |  |  |  |  |  | 0x0000 => { | 
| 285 |  |  |  |  |  |  | Name => 'Nop', | 
| 286 |  |  |  |  |  |  | Description => 'No Operation', | 
| 287 |  |  |  |  |  |  | Format => 'null', | 
| 288 |  |  |  |  |  |  | }, | 
| 289 |  |  |  |  |  |  | 0x0001 => { | 
| 290 |  |  |  |  |  |  | Name => 'ClipRgn', | 
| 291 |  |  |  |  |  |  | Description => 'Clipping Region', | 
| 292 |  |  |  |  |  |  | Format => 'Rgn', | 
| 293 |  |  |  |  |  |  | }, | 
| 294 |  |  |  |  |  |  | 0x0002 => { | 
| 295 |  |  |  |  |  |  | Name => 'BkPat', | 
| 296 |  |  |  |  |  |  | Description => 'Background Pattern', | 
| 297 |  |  |  |  |  |  | Format => 'int8u[8]', | 
| 298 |  |  |  |  |  |  | }, | 
| 299 |  |  |  |  |  |  | 0x0003 => { | 
| 300 |  |  |  |  |  |  | Name => 'TxFont', | 
| 301 |  |  |  |  |  |  | Description => 'Font Number', | 
| 302 |  |  |  |  |  |  | Format => 'int16u', | 
| 303 |  |  |  |  |  |  | }, | 
| 304 |  |  |  |  |  |  | 0x0004 => { | 
| 305 |  |  |  |  |  |  | Name => 'TxFace', | 
| 306 |  |  |  |  |  |  | Description => 'Text Font Style', | 
| 307 |  |  |  |  |  |  | Format => 'int8u', | 
| 308 |  |  |  |  |  |  | }, | 
| 309 |  |  |  |  |  |  | 0x0005 => { | 
| 310 |  |  |  |  |  |  | Name => 'TxMode', | 
| 311 |  |  |  |  |  |  | Description => 'Text Source Mode', | 
| 312 |  |  |  |  |  |  | Format => 'int16u', | 
| 313 |  |  |  |  |  |  | }, | 
| 314 |  |  |  |  |  |  | 0x0006 => { | 
| 315 |  |  |  |  |  |  | Name => 'SpExtra', | 
| 316 |  |  |  |  |  |  | Description => 'Extra Space', | 
| 317 |  |  |  |  |  |  | Format => 'fixed32s', | 
| 318 |  |  |  |  |  |  | }, | 
| 319 |  |  |  |  |  |  | 0x0007 => { | 
| 320 |  |  |  |  |  |  | Name => 'PnSize', | 
| 321 |  |  |  |  |  |  | Description => 'Pen Size', | 
| 322 |  |  |  |  |  |  | Format => 'Point', | 
| 323 |  |  |  |  |  |  | }, | 
| 324 |  |  |  |  |  |  | 0x0008 => { | 
| 325 |  |  |  |  |  |  | Name => 'PnMode', | 
| 326 |  |  |  |  |  |  | Description => 'Pen Mode', | 
| 327 |  |  |  |  |  |  | Format => 'int16u', | 
| 328 |  |  |  |  |  |  | }, | 
| 329 |  |  |  |  |  |  | 0x0009 => { | 
| 330 |  |  |  |  |  |  | Name => 'PnPat', | 
| 331 |  |  |  |  |  |  | Description => 'Pen Pattern', | 
| 332 |  |  |  |  |  |  | Format => 'int8u[8]', | 
| 333 |  |  |  |  |  |  | }, | 
| 334 |  |  |  |  |  |  | 0x000a => { | 
| 335 |  |  |  |  |  |  | Name => 'FillPat', | 
| 336 |  |  |  |  |  |  | Description => 'Fill Pattern', | 
| 337 |  |  |  |  |  |  | Format => 'int8u[8]', | 
| 338 |  |  |  |  |  |  | }, | 
| 339 |  |  |  |  |  |  | 0x000b => { | 
| 340 |  |  |  |  |  |  | Name => 'OvSize', | 
| 341 |  |  |  |  |  |  | Description => 'Oval Size', | 
| 342 |  |  |  |  |  |  | Format => 'Point', | 
| 343 |  |  |  |  |  |  | }, | 
| 344 |  |  |  |  |  |  | 0x000c => { | 
| 345 |  |  |  |  |  |  | Name => 'Origin', | 
| 346 |  |  |  |  |  |  | Format => 'Point', | 
| 347 |  |  |  |  |  |  | }, | 
| 348 |  |  |  |  |  |  | 0x000d => { | 
| 349 |  |  |  |  |  |  | Name => 'TxSize', | 
| 350 |  |  |  |  |  |  | Description => 'Text Size', | 
| 351 |  |  |  |  |  |  | Format => 'int16u', | 
| 352 |  |  |  |  |  |  | }, | 
| 353 |  |  |  |  |  |  | 0x000e => { | 
| 354 |  |  |  |  |  |  | Name => 'FgColor', | 
| 355 |  |  |  |  |  |  | Description => 'Foreground Color', | 
| 356 |  |  |  |  |  |  | Format => 'int32u', | 
| 357 |  |  |  |  |  |  | }, | 
| 358 |  |  |  |  |  |  | 0x000f => { | 
| 359 |  |  |  |  |  |  | Name => 'BkColor', | 
| 360 |  |  |  |  |  |  | Description => 'Background Color', | 
| 361 |  |  |  |  |  |  | Format => 'int32u', | 
| 362 |  |  |  |  |  |  | }, | 
| 363 |  |  |  |  |  |  | 0x0010 => { | 
| 364 |  |  |  |  |  |  | Name => 'TxRatio', | 
| 365 |  |  |  |  |  |  | Description => 'Text Ratio', | 
| 366 |  |  |  |  |  |  | Format => 'Rect', | 
| 367 |  |  |  |  |  |  | }, | 
| 368 |  |  |  |  |  |  | 0x0011 => { | 
| 369 |  |  |  |  |  |  | Name => 'VersionOp', | 
| 370 |  |  |  |  |  |  | Description => 'Version', | 
| 371 |  |  |  |  |  |  | Format => 'int8u', | 
| 372 |  |  |  |  |  |  | }, | 
| 373 |  |  |  |  |  |  | 0x0012 => { | 
| 374 |  |  |  |  |  |  | Name => 'BkPixPat', | 
| 375 |  |  |  |  |  |  | Description => 'Background Pixel Pattern', | 
| 376 |  |  |  |  |  |  | Format => 'PixPat', | 
| 377 |  |  |  |  |  |  | }, | 
| 378 |  |  |  |  |  |  | 0x0013 => { | 
| 379 |  |  |  |  |  |  | Name => 'PnPixPat', | 
| 380 |  |  |  |  |  |  | Description => 'Pen Pixel Pattern', | 
| 381 |  |  |  |  |  |  | Format => 'PixPat', | 
| 382 |  |  |  |  |  |  | }, | 
| 383 |  |  |  |  |  |  | 0x0014 => { | 
| 384 |  |  |  |  |  |  | Name => 'FillPixPat', | 
| 385 |  |  |  |  |  |  | Description => 'Fill Pixel Pattern', | 
| 386 |  |  |  |  |  |  | Format => 'PixPat', | 
| 387 |  |  |  |  |  |  | }, | 
| 388 |  |  |  |  |  |  | 0x0015 => { | 
| 389 |  |  |  |  |  |  | Name => 'PnLocHFrac', | 
| 390 |  |  |  |  |  |  | Description => 'Fractional Pen Position', | 
| 391 |  |  |  |  |  |  | Format => 'int16u', | 
| 392 |  |  |  |  |  |  | }, | 
| 393 |  |  |  |  |  |  | 0x0016 => { | 
| 394 |  |  |  |  |  |  | Name => 'ChExtra', | 
| 395 |  |  |  |  |  |  | Description => 'Added Width for NonSpace Characters', | 
| 396 |  |  |  |  |  |  | Format => 'int16u', | 
| 397 |  |  |  |  |  |  | }, | 
| 398 |  |  |  |  |  |  | 0x0017 => { | 
| 399 |  |  |  |  |  |  | Name => 'Reserved', | 
| 400 |  |  |  |  |  |  | Format => 'Unknown', | 
| 401 |  |  |  |  |  |  | }, | 
| 402 |  |  |  |  |  |  | 0x001a => { | 
| 403 |  |  |  |  |  |  | Name => 'RGBFgCol', | 
| 404 |  |  |  |  |  |  | Description => 'Foreground Color', | 
| 405 |  |  |  |  |  |  | Format => 'RGBColor', | 
| 406 |  |  |  |  |  |  | }, | 
| 407 |  |  |  |  |  |  | 0x001b => { | 
| 408 |  |  |  |  |  |  | Name => 'RGBBkCol', | 
| 409 |  |  |  |  |  |  | Description => 'Background Color', | 
| 410 |  |  |  |  |  |  | Format => 'RGBColor', | 
| 411 |  |  |  |  |  |  | }, | 
| 412 |  |  |  |  |  |  | 0x001c => { | 
| 413 |  |  |  |  |  |  | Name => 'HiliteMode', | 
| 414 |  |  |  |  |  |  | Description => 'Highlight Mode Flag', | 
| 415 |  |  |  |  |  |  | Format => 'null', | 
| 416 |  |  |  |  |  |  | }, | 
| 417 |  |  |  |  |  |  | 0x001d => { | 
| 418 |  |  |  |  |  |  | Name => 'HiliteColor', | 
| 419 |  |  |  |  |  |  | Description => 'Highlight Color', | 
| 420 |  |  |  |  |  |  | Format => 'RGBColor', | 
| 421 |  |  |  |  |  |  | }, | 
| 422 |  |  |  |  |  |  | 0x001e => { | 
| 423 |  |  |  |  |  |  | Name => 'DefHilite', | 
| 424 |  |  |  |  |  |  | Description => 'Use Default Highlight Color', | 
| 425 |  |  |  |  |  |  | Format => 'null', | 
| 426 |  |  |  |  |  |  | }, | 
| 427 |  |  |  |  |  |  | 0x001f => { | 
| 428 |  |  |  |  |  |  | Name => 'OpColor', | 
| 429 |  |  |  |  |  |  | Format => 'RGBColor', | 
| 430 |  |  |  |  |  |  | }, | 
| 431 |  |  |  |  |  |  | 0x0020 => { | 
| 432 |  |  |  |  |  |  | Name => 'Line', | 
| 433 |  |  |  |  |  |  | Format => 'Rect', | 
| 434 |  |  |  |  |  |  | }, | 
| 435 |  |  |  |  |  |  | 0x0021 => { | 
| 436 |  |  |  |  |  |  | Name => 'LineFrom', | 
| 437 |  |  |  |  |  |  | Format => 'Point', | 
| 438 |  |  |  |  |  |  | }, | 
| 439 |  |  |  |  |  |  | 0x0022 => { | 
| 440 |  |  |  |  |  |  | Name => 'ShortLine', | 
| 441 |  |  |  |  |  |  | Format => 'ShortLine', | 
| 442 |  |  |  |  |  |  | }, | 
| 443 |  |  |  |  |  |  | 0x0023 => { | 
| 444 |  |  |  |  |  |  | Name => 'ShortLineFrom', | 
| 445 |  |  |  |  |  |  | Format => 'int8u[2]', | 
| 446 |  |  |  |  |  |  | }, | 
| 447 |  |  |  |  |  |  | 0x0024 => { | 
| 448 |  |  |  |  |  |  | Name => 'Reserved', | 
| 449 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 450 |  |  |  |  |  |  | }, | 
| 451 |  |  |  |  |  |  | 0x0028 => { | 
| 452 |  |  |  |  |  |  | Name => 'LongText', | 
| 453 |  |  |  |  |  |  | Format => 'PointText', | 
| 454 |  |  |  |  |  |  | }, | 
| 455 |  |  |  |  |  |  | 0x0029 => { | 
| 456 |  |  |  |  |  |  | Name => 'DHText', | 
| 457 |  |  |  |  |  |  | Format => 'Int8uText', | 
| 458 |  |  |  |  |  |  | }, | 
| 459 |  |  |  |  |  |  | 0x002a => { | 
| 460 |  |  |  |  |  |  | Name => 'DVText', | 
| 461 |  |  |  |  |  |  | Format => 'Int8uText', | 
| 462 |  |  |  |  |  |  | }, | 
| 463 |  |  |  |  |  |  | 0x002b => { | 
| 464 |  |  |  |  |  |  | Name => 'DHDVText', | 
| 465 |  |  |  |  |  |  | Format => 'Int8u2Text', | 
| 466 |  |  |  |  |  |  | }, | 
| 467 |  |  |  |  |  |  | 0x002c => { | 
| 468 |  |  |  |  |  |  | Name => 'FontName', | 
| 469 |  |  |  |  |  |  | Format => 'FontName', | 
| 470 |  |  |  |  |  |  | }, | 
| 471 |  |  |  |  |  |  | 0x002d => { | 
| 472 |  |  |  |  |  |  | Name => 'LineJustify', | 
| 473 |  |  |  |  |  |  | Format => 'int8u[10]', | 
| 474 |  |  |  |  |  |  | }, | 
| 475 |  |  |  |  |  |  | 0x002e => { | 
| 476 |  |  |  |  |  |  | Name => 'GlyphState', | 
| 477 |  |  |  |  |  |  | Format => 'int8u[8]', | 
| 478 |  |  |  |  |  |  | }, | 
| 479 |  |  |  |  |  |  | 0x002f => { | 
| 480 |  |  |  |  |  |  | Name => 'Reserved', | 
| 481 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 482 |  |  |  |  |  |  | }, | 
| 483 |  |  |  |  |  |  | 0x0030 => { | 
| 484 |  |  |  |  |  |  | Name => 'FrameRect', | 
| 485 |  |  |  |  |  |  | Format => 'Rect', | 
| 486 |  |  |  |  |  |  | }, | 
| 487 |  |  |  |  |  |  | 0x0031 => { | 
| 488 |  |  |  |  |  |  | Name => 'PaintRect', | 
| 489 |  |  |  |  |  |  | Format => 'Rect', | 
| 490 |  |  |  |  |  |  | }, | 
| 491 |  |  |  |  |  |  | 0x0032 => { | 
| 492 |  |  |  |  |  |  | Name => 'EraseRect', | 
| 493 |  |  |  |  |  |  | Format => 'Rect', | 
| 494 |  |  |  |  |  |  | }, | 
| 495 |  |  |  |  |  |  | 0x0033 => { | 
| 496 |  |  |  |  |  |  | Name => 'InvertRect', | 
| 497 |  |  |  |  |  |  | Format => 'Rect', | 
| 498 |  |  |  |  |  |  | }, | 
| 499 |  |  |  |  |  |  | 0x0034 => { | 
| 500 |  |  |  |  |  |  | Name => 'FillRect', | 
| 501 |  |  |  |  |  |  | Format => 'Rect', | 
| 502 |  |  |  |  |  |  | }, | 
| 503 |  |  |  |  |  |  | 0x0035 => { | 
| 504 |  |  |  |  |  |  | Name => 'Reserved', | 
| 505 |  |  |  |  |  |  | Format => 'Rect', | 
| 506 |  |  |  |  |  |  | }, | 
| 507 |  |  |  |  |  |  | 0x0038 => { | 
| 508 |  |  |  |  |  |  | Name => 'FrameSameRect', | 
| 509 |  |  |  |  |  |  | Format => 'null', | 
| 510 |  |  |  |  |  |  | }, | 
| 511 |  |  |  |  |  |  | 0x0039 => { | 
| 512 |  |  |  |  |  |  | Name => 'PaintSameRect', | 
| 513 |  |  |  |  |  |  | Format => 'null', | 
| 514 |  |  |  |  |  |  | }, | 
| 515 |  |  |  |  |  |  | 0x003a => { | 
| 516 |  |  |  |  |  |  | Name => 'EraseSameRect', | 
| 517 |  |  |  |  |  |  | Format => 'null', | 
| 518 |  |  |  |  |  |  | }, | 
| 519 |  |  |  |  |  |  | 0x003b => { | 
| 520 |  |  |  |  |  |  | Name => 'InvertSameRect', | 
| 521 |  |  |  |  |  |  | Format => 'null', | 
| 522 |  |  |  |  |  |  | }, | 
| 523 |  |  |  |  |  |  | 0x003c => { | 
| 524 |  |  |  |  |  |  | Name => 'FillSameRect', | 
| 525 |  |  |  |  |  |  | Format => 'null', | 
| 526 |  |  |  |  |  |  | }, | 
| 527 |  |  |  |  |  |  | 0x003d => { | 
| 528 |  |  |  |  |  |  | Name => 'Reserved', | 
| 529 |  |  |  |  |  |  | Format => 'null', | 
| 530 |  |  |  |  |  |  | }, | 
| 531 |  |  |  |  |  |  | 0x0040 => { | 
| 532 |  |  |  |  |  |  | Name => 'FrameRRect', | 
| 533 |  |  |  |  |  |  | Format => 'Rect', | 
| 534 |  |  |  |  |  |  | }, | 
| 535 |  |  |  |  |  |  | 0x0041 => { | 
| 536 |  |  |  |  |  |  | Name => 'PaintRRect', | 
| 537 |  |  |  |  |  |  | Format => 'Rect', | 
| 538 |  |  |  |  |  |  | }, | 
| 539 |  |  |  |  |  |  | 0x0042 => { | 
| 540 |  |  |  |  |  |  | Name => 'EraseRRect', | 
| 541 |  |  |  |  |  |  | Format => 'Rect', | 
| 542 |  |  |  |  |  |  | }, | 
| 543 |  |  |  |  |  |  | 0x0043 => { | 
| 544 |  |  |  |  |  |  | Name => 'InvertRRect', | 
| 545 |  |  |  |  |  |  | Format => 'Rect', | 
| 546 |  |  |  |  |  |  | }, | 
| 547 |  |  |  |  |  |  | 0x0044 => { | 
| 548 |  |  |  |  |  |  | Name => 'FillRRect', | 
| 549 |  |  |  |  |  |  | Format => 'Rect', | 
| 550 |  |  |  |  |  |  | }, | 
| 551 |  |  |  |  |  |  | 0x0045 => { | 
| 552 |  |  |  |  |  |  | Name => 'Reserved', | 
| 553 |  |  |  |  |  |  | Format => 'Rect', | 
| 554 |  |  |  |  |  |  | }, | 
| 555 |  |  |  |  |  |  | 0x0048 => { | 
| 556 |  |  |  |  |  |  | Name => 'FrameSameRRect', | 
| 557 |  |  |  |  |  |  | Format => 'null', | 
| 558 |  |  |  |  |  |  | }, | 
| 559 |  |  |  |  |  |  | 0x0049 => { | 
| 560 |  |  |  |  |  |  | Name => 'PaintSameRRect', | 
| 561 |  |  |  |  |  |  | Format => 'null', | 
| 562 |  |  |  |  |  |  | }, | 
| 563 |  |  |  |  |  |  | 0x004a => { | 
| 564 |  |  |  |  |  |  | Name => 'EraseSameRRect', | 
| 565 |  |  |  |  |  |  | Format => 'null', | 
| 566 |  |  |  |  |  |  | }, | 
| 567 |  |  |  |  |  |  | 0x004b => { | 
| 568 |  |  |  |  |  |  | Name => 'InvertSameRRect', | 
| 569 |  |  |  |  |  |  | Format => 'null', | 
| 570 |  |  |  |  |  |  | }, | 
| 571 |  |  |  |  |  |  | 0x004c => { | 
| 572 |  |  |  |  |  |  | Name => 'FillSameRRect', | 
| 573 |  |  |  |  |  |  | Format => 'null', | 
| 574 |  |  |  |  |  |  | }, | 
| 575 |  |  |  |  |  |  | 0x004d => { | 
| 576 |  |  |  |  |  |  | Name => 'Reserved', | 
| 577 |  |  |  |  |  |  | Format => 'null', | 
| 578 |  |  |  |  |  |  | }, | 
| 579 |  |  |  |  |  |  | 0x0050 => { | 
| 580 |  |  |  |  |  |  | Name => 'FrameOval', | 
| 581 |  |  |  |  |  |  | Format => 'Rect', | 
| 582 |  |  |  |  |  |  | }, | 
| 583 |  |  |  |  |  |  | 0x0051 => { | 
| 584 |  |  |  |  |  |  | Name => 'PaintOval', | 
| 585 |  |  |  |  |  |  | Format => 'Rect', | 
| 586 |  |  |  |  |  |  | }, | 
| 587 |  |  |  |  |  |  | 0x0052 => { | 
| 588 |  |  |  |  |  |  | Name => 'EraseOval', | 
| 589 |  |  |  |  |  |  | Format => 'Rect', | 
| 590 |  |  |  |  |  |  | }, | 
| 591 |  |  |  |  |  |  | 0x0053 => { | 
| 592 |  |  |  |  |  |  | Name => 'InvertOval', | 
| 593 |  |  |  |  |  |  | Format => 'Rect', | 
| 594 |  |  |  |  |  |  | }, | 
| 595 |  |  |  |  |  |  | 0x0054 => { | 
| 596 |  |  |  |  |  |  | Name => 'FillOval', | 
| 597 |  |  |  |  |  |  | Format => 'Rect', | 
| 598 |  |  |  |  |  |  | }, | 
| 599 |  |  |  |  |  |  | 0x0055 => { | 
| 600 |  |  |  |  |  |  | Name => 'Reserved', | 
| 601 |  |  |  |  |  |  | Format => 'Rect', | 
| 602 |  |  |  |  |  |  | }, | 
| 603 |  |  |  |  |  |  | 0x0058 => { | 
| 604 |  |  |  |  |  |  | Name => 'FrameSameOval', | 
| 605 |  |  |  |  |  |  | Format => 'null', | 
| 606 |  |  |  |  |  |  | }, | 
| 607 |  |  |  |  |  |  | 0x0059 => { | 
| 608 |  |  |  |  |  |  | Name => 'PaintSameOval', | 
| 609 |  |  |  |  |  |  | Format => 'null', | 
| 610 |  |  |  |  |  |  | }, | 
| 611 |  |  |  |  |  |  | 0x005a => { | 
| 612 |  |  |  |  |  |  | Name => 'EraseSameOval', | 
| 613 |  |  |  |  |  |  | Format => 'null', | 
| 614 |  |  |  |  |  |  | }, | 
| 615 |  |  |  |  |  |  | 0x005b => { | 
| 616 |  |  |  |  |  |  | Name => 'InvertSameOval', | 
| 617 |  |  |  |  |  |  | Format => 'null', | 
| 618 |  |  |  |  |  |  | }, | 
| 619 |  |  |  |  |  |  | 0x005c => { | 
| 620 |  |  |  |  |  |  | Name => 'FillSameOval', | 
| 621 |  |  |  |  |  |  | Format => 'null', | 
| 622 |  |  |  |  |  |  | }, | 
| 623 |  |  |  |  |  |  | 0x005d => { | 
| 624 |  |  |  |  |  |  | Name => 'Reserved', | 
| 625 |  |  |  |  |  |  | Format => 'null', | 
| 626 |  |  |  |  |  |  | }, | 
| 627 |  |  |  |  |  |  | 0x0060 => { | 
| 628 |  |  |  |  |  |  | Name => 'FrameArc', | 
| 629 |  |  |  |  |  |  | Format => 'Arc', | 
| 630 |  |  |  |  |  |  | }, | 
| 631 |  |  |  |  |  |  | 0x0061 => { | 
| 632 |  |  |  |  |  |  | Name => 'PaintArc', | 
| 633 |  |  |  |  |  |  | Format => 'Arc', | 
| 634 |  |  |  |  |  |  | }, | 
| 635 |  |  |  |  |  |  | 0x0062 => { | 
| 636 |  |  |  |  |  |  | Name => 'EraseArc', | 
| 637 |  |  |  |  |  |  | Format => 'Arc', | 
| 638 |  |  |  |  |  |  | }, | 
| 639 |  |  |  |  |  |  | 0x0063 => { | 
| 640 |  |  |  |  |  |  | Name => 'InvertArc', | 
| 641 |  |  |  |  |  |  | Format => 'Arc', | 
| 642 |  |  |  |  |  |  | }, | 
| 643 |  |  |  |  |  |  | 0x0064 => { | 
| 644 |  |  |  |  |  |  | Name => 'FillArc', | 
| 645 |  |  |  |  |  |  | Format => 'Arc', | 
| 646 |  |  |  |  |  |  | }, | 
| 647 |  |  |  |  |  |  | 0x0065 => { | 
| 648 |  |  |  |  |  |  | Name => 'Reserved', | 
| 649 |  |  |  |  |  |  | Format => 'Arc', | 
| 650 |  |  |  |  |  |  | }, | 
| 651 |  |  |  |  |  |  | 0x0068 => { | 
| 652 |  |  |  |  |  |  | Name => 'FrameSameArc', | 
| 653 |  |  |  |  |  |  | Format => 'Point', | 
| 654 |  |  |  |  |  |  | }, | 
| 655 |  |  |  |  |  |  | 0x0069 => { | 
| 656 |  |  |  |  |  |  | Name => 'PaintSameArc', | 
| 657 |  |  |  |  |  |  | Format => 'Point', | 
| 658 |  |  |  |  |  |  | }, | 
| 659 |  |  |  |  |  |  | 0x006a => { | 
| 660 |  |  |  |  |  |  | Name => 'EraseSameArc', | 
| 661 |  |  |  |  |  |  | Format => 'Point', | 
| 662 |  |  |  |  |  |  | }, | 
| 663 |  |  |  |  |  |  | 0x006b => { | 
| 664 |  |  |  |  |  |  | Name => 'InvertSameArc', | 
| 665 |  |  |  |  |  |  | Format => 'Point', | 
| 666 |  |  |  |  |  |  | }, | 
| 667 |  |  |  |  |  |  | 0x006c => { | 
| 668 |  |  |  |  |  |  | Name => 'FillSameArc', | 
| 669 |  |  |  |  |  |  | Format => 'Point', | 
| 670 |  |  |  |  |  |  | }, | 
| 671 |  |  |  |  |  |  | 0x006d => { | 
| 672 |  |  |  |  |  |  | Name => 'Reserved', | 
| 673 |  |  |  |  |  |  | Format => 'int32u', | 
| 674 |  |  |  |  |  |  | }, | 
| 675 |  |  |  |  |  |  | 0x0070 => { | 
| 676 |  |  |  |  |  |  | Name => 'FramePoly', | 
| 677 |  |  |  |  |  |  | Format => 'Polygon', | 
| 678 |  |  |  |  |  |  | }, | 
| 679 |  |  |  |  |  |  | 0x0071 => { | 
| 680 |  |  |  |  |  |  | Name => 'PaintPoly', | 
| 681 |  |  |  |  |  |  | Format => 'Polygon', | 
| 682 |  |  |  |  |  |  | }, | 
| 683 |  |  |  |  |  |  | 0x0072 => { | 
| 684 |  |  |  |  |  |  | Name => 'ErasePoly', | 
| 685 |  |  |  |  |  |  | Format => 'Polygon', | 
| 686 |  |  |  |  |  |  | }, | 
| 687 |  |  |  |  |  |  | 0x0073 => { | 
| 688 |  |  |  |  |  |  | Name => 'InvertPoly', | 
| 689 |  |  |  |  |  |  | Format => 'Polygon', | 
| 690 |  |  |  |  |  |  | }, | 
| 691 |  |  |  |  |  |  | 0x0074 => { | 
| 692 |  |  |  |  |  |  | Name => 'FillPoly', | 
| 693 |  |  |  |  |  |  | Format => 'Polygon', | 
| 694 |  |  |  |  |  |  | }, | 
| 695 |  |  |  |  |  |  | 0x0075 => { | 
| 696 |  |  |  |  |  |  | Name => 'Reserved', | 
| 697 |  |  |  |  |  |  | Format => 'Polygon', | 
| 698 |  |  |  |  |  |  | }, | 
| 699 |  |  |  |  |  |  | 0x0078 => { | 
| 700 |  |  |  |  |  |  | Name => 'FrameSamePoly', | 
| 701 |  |  |  |  |  |  | Format => 'null', | 
| 702 |  |  |  |  |  |  | }, | 
| 703 |  |  |  |  |  |  | 0x0079 => { | 
| 704 |  |  |  |  |  |  | Name => 'PaintSamePoly', | 
| 705 |  |  |  |  |  |  | Format => 'null', | 
| 706 |  |  |  |  |  |  | }, | 
| 707 |  |  |  |  |  |  | 0x007a => { | 
| 708 |  |  |  |  |  |  | Name => 'EraseSamePoly', | 
| 709 |  |  |  |  |  |  | Format => 'null', | 
| 710 |  |  |  |  |  |  | }, | 
| 711 |  |  |  |  |  |  | 0x007b => { | 
| 712 |  |  |  |  |  |  | Name => 'InvertSamePoly', | 
| 713 |  |  |  |  |  |  | Format => 'null', | 
| 714 |  |  |  |  |  |  | }, | 
| 715 |  |  |  |  |  |  | 0x007c => { | 
| 716 |  |  |  |  |  |  | Name => 'FillSamePoly', | 
| 717 |  |  |  |  |  |  | Format => 'null', | 
| 718 |  |  |  |  |  |  | }, | 
| 719 |  |  |  |  |  |  | 0x007d => { | 
| 720 |  |  |  |  |  |  | Name => 'Reserved', | 
| 721 |  |  |  |  |  |  | Format => 'null', | 
| 722 |  |  |  |  |  |  | }, | 
| 723 |  |  |  |  |  |  | 0x0080 => { | 
| 724 |  |  |  |  |  |  | Name => 'FrameRgn', | 
| 725 |  |  |  |  |  |  | Format => 'Rgn', | 
| 726 |  |  |  |  |  |  | }, | 
| 727 |  |  |  |  |  |  | 0x0081 => { | 
| 728 |  |  |  |  |  |  | Name => 'PaintRgn', | 
| 729 |  |  |  |  |  |  | Format => 'Rgn', | 
| 730 |  |  |  |  |  |  | }, | 
| 731 |  |  |  |  |  |  | 0x0082 => { | 
| 732 |  |  |  |  |  |  | Name => 'EraseRgn', | 
| 733 |  |  |  |  |  |  | Format => 'Rgn', | 
| 734 |  |  |  |  |  |  | }, | 
| 735 |  |  |  |  |  |  | 0x0083 => { | 
| 736 |  |  |  |  |  |  | Name => 'InvertRgn', | 
| 737 |  |  |  |  |  |  | Format => 'Rgn', | 
| 738 |  |  |  |  |  |  | }, | 
| 739 |  |  |  |  |  |  | 0x0084 => { | 
| 740 |  |  |  |  |  |  | Name => 'FillRgn', | 
| 741 |  |  |  |  |  |  | Format => 'Rgn', | 
| 742 |  |  |  |  |  |  | }, | 
| 743 |  |  |  |  |  |  | 0x0085 => { | 
| 744 |  |  |  |  |  |  | Name => 'Reserved', | 
| 745 |  |  |  |  |  |  | Format => 'Rgn', | 
| 746 |  |  |  |  |  |  | }, | 
| 747 |  |  |  |  |  |  | 0x0088 => { | 
| 748 |  |  |  |  |  |  | Name => 'FrameSameRgn', | 
| 749 |  |  |  |  |  |  | Format => 'null', | 
| 750 |  |  |  |  |  |  | }, | 
| 751 |  |  |  |  |  |  | 0x0089 => { | 
| 752 |  |  |  |  |  |  | Name => 'PaintSameRgn', | 
| 753 |  |  |  |  |  |  | Format => 'null', | 
| 754 |  |  |  |  |  |  | }, | 
| 755 |  |  |  |  |  |  | 0x008a => { | 
| 756 |  |  |  |  |  |  | Name => 'EraseSameRgn', | 
| 757 |  |  |  |  |  |  | Format => 'null', | 
| 758 |  |  |  |  |  |  | }, | 
| 759 |  |  |  |  |  |  | 0x008b => { | 
| 760 |  |  |  |  |  |  | Name => 'InvertSameRgn', | 
| 761 |  |  |  |  |  |  | Format => 'null', | 
| 762 |  |  |  |  |  |  | }, | 
| 763 |  |  |  |  |  |  | 0x008c => { | 
| 764 |  |  |  |  |  |  | Name => 'FillSameRgn', | 
| 765 |  |  |  |  |  |  | Format => 'null', | 
| 766 |  |  |  |  |  |  | }, | 
| 767 |  |  |  |  |  |  | 0x008d => { | 
| 768 |  |  |  |  |  |  | Name => 'Reserved', | 
| 769 |  |  |  |  |  |  | Format => 'null', | 
| 770 |  |  |  |  |  |  | }, | 
| 771 |  |  |  |  |  |  | 0x0090 => { | 
| 772 |  |  |  |  |  |  | Name => 'BitsRect', | 
| 773 |  |  |  |  |  |  | Description => 'CopyBits with Clipped Rectangle', | 
| 774 |  |  |  |  |  |  | Format => 'BitsRect#',  # (version-dependent format) | 
| 775 |  |  |  |  |  |  | }, | 
| 776 |  |  |  |  |  |  | 0x0091 => { | 
| 777 |  |  |  |  |  |  | Name => 'BitsRgn', | 
| 778 |  |  |  |  |  |  | Description => 'CopyBits with Clipped Region', | 
| 779 |  |  |  |  |  |  | Format => 'BitsRgn#',   # (version-dependent format) | 
| 780 |  |  |  |  |  |  | }, | 
| 781 |  |  |  |  |  |  | 0x0092 => { | 
| 782 |  |  |  |  |  |  | Name => 'Reserved', | 
| 783 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 784 |  |  |  |  |  |  | }, | 
| 785 |  |  |  |  |  |  | 0x0098 => { | 
| 786 |  |  |  |  |  |  | Name => 'PackBitsRect', | 
| 787 |  |  |  |  |  |  | Description => 'Packed CopyBits with Clipped Rectangle', | 
| 788 |  |  |  |  |  |  | Format => 'BitsRect#',  # (version-dependent format) | 
| 789 |  |  |  |  |  |  | }, | 
| 790 |  |  |  |  |  |  | 0x0099 => { | 
| 791 |  |  |  |  |  |  | Name => 'PackBitsRgn', | 
| 792 |  |  |  |  |  |  | Description => 'Packed CopyBits with Clipped Region', | 
| 793 |  |  |  |  |  |  | Format => 'BitsRgn#',   # (version-dependent format) | 
| 794 |  |  |  |  |  |  | }, | 
| 795 |  |  |  |  |  |  | 0x009a => { | 
| 796 |  |  |  |  |  |  | Name => 'DirectBitsRect', | 
| 797 |  |  |  |  |  |  | Format => 'DirectBitsRect', | 
| 798 |  |  |  |  |  |  | }, | 
| 799 |  |  |  |  |  |  | 0x009b => { | 
| 800 |  |  |  |  |  |  | Name => 'DirectBitsRgn', | 
| 801 |  |  |  |  |  |  | Format => 'DirectBitsRgn', | 
| 802 |  |  |  |  |  |  | }, | 
| 803 |  |  |  |  |  |  | 0x009c => { | 
| 804 |  |  |  |  |  |  | Name => 'Reserved', | 
| 805 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 806 |  |  |  |  |  |  | }, | 
| 807 |  |  |  |  |  |  | 0x009d => { | 
| 808 |  |  |  |  |  |  | Name => 'Reserved', | 
| 809 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 810 |  |  |  |  |  |  | }, | 
| 811 |  |  |  |  |  |  | 0x009e => { | 
| 812 |  |  |  |  |  |  | Name => 'Reserved', | 
| 813 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 814 |  |  |  |  |  |  | }, | 
| 815 |  |  |  |  |  |  | 0x009f => { | 
| 816 |  |  |  |  |  |  | Name => 'Reserved', | 
| 817 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 818 |  |  |  |  |  |  | }, | 
| 819 |  |  |  |  |  |  | 0x00a0 => { | 
| 820 |  |  |  |  |  |  | Name => 'ShortComment', | 
| 821 |  |  |  |  |  |  | Format => 'int16u', | 
| 822 |  |  |  |  |  |  | }, | 
| 823 |  |  |  |  |  |  | 0x00a1 => [ | 
| 824 |  |  |  |  |  |  | # this list for documentation only [currently not extracted] | 
| 825 |  |  |  |  |  |  | { | 
| 826 |  |  |  |  |  |  | # (not actually a full Photohop IRB record it appears, but it does start | 
| 827 |  |  |  |  |  |  | #  with '8BIM', and does contain resolution information at offset 0x0a) | 
| 828 |  |  |  |  |  |  | Name => 'LongComment',  # kind = 498 | 
| 829 |  |  |  |  |  |  | Format => 'LongComment', | 
| 830 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Main' }, | 
| 831 |  |  |  |  |  |  | }, | 
| 832 |  |  |  |  |  |  | { | 
| 833 |  |  |  |  |  |  | Name => 'LongComment',  # kind = 224 | 
| 834 |  |  |  |  |  |  | Format => 'LongComment', | 
| 835 |  |  |  |  |  |  | SubDirectory => { | 
| 836 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::ICC_Profile::Main', | 
| 837 |  |  |  |  |  |  | Start => '$valuePtr + 4', | 
| 838 |  |  |  |  |  |  | }, | 
| 839 |  |  |  |  |  |  | }, | 
| 840 |  |  |  |  |  |  | ], | 
| 841 |  |  |  |  |  |  | 0x00a2 => { | 
| 842 |  |  |  |  |  |  | Name => 'Reserved', | 
| 843 |  |  |  |  |  |  | Format => 'Int16Data', | 
| 844 |  |  |  |  |  |  | }, | 
| 845 |  |  |  |  |  |  | 0x00b0 => { | 
| 846 |  |  |  |  |  |  | Name => 'Reserved', | 
| 847 |  |  |  |  |  |  | Format => 'null', | 
| 848 |  |  |  |  |  |  | }, | 
| 849 |  |  |  |  |  |  | 0x00d0 => { | 
| 850 |  |  |  |  |  |  | Name => 'Reserved', | 
| 851 |  |  |  |  |  |  | Format => 'Int32uData', | 
| 852 |  |  |  |  |  |  | }, | 
| 853 |  |  |  |  |  |  | 0x00ff => { | 
| 854 |  |  |  |  |  |  | Name => 'OpEndPic', | 
| 855 |  |  |  |  |  |  | Description => 'End of picture', | 
| 856 |  |  |  |  |  |  | Format => 'null', # 2 for version 2!? | 
| 857 |  |  |  |  |  |  | }, | 
| 858 |  |  |  |  |  |  | 0x0100 => { | 
| 859 |  |  |  |  |  |  | Name => 'Reserved', | 
| 860 |  |  |  |  |  |  | Format => 'int16u', | 
| 861 |  |  |  |  |  |  | }, | 
| 862 |  |  |  |  |  |  | 0x0200 => { | 
| 863 |  |  |  |  |  |  | Name => 'Reserved', | 
| 864 |  |  |  |  |  |  | Format => 'int32u', | 
| 865 |  |  |  |  |  |  | }, | 
| 866 |  |  |  |  |  |  | 0x02ff => { | 
| 867 |  |  |  |  |  |  | Name => 'Version', | 
| 868 |  |  |  |  |  |  | Description => 'Version number of picture', | 
| 869 |  |  |  |  |  |  | Format => 'int16u', | 
| 870 |  |  |  |  |  |  | }, | 
| 871 |  |  |  |  |  |  | 0x0300 => { | 
| 872 |  |  |  |  |  |  | Name => 'Reserved', | 
| 873 |  |  |  |  |  |  | Format => 'int16u', | 
| 874 |  |  |  |  |  |  | }, | 
| 875 |  |  |  |  |  |  | 0x0bff => { | 
| 876 |  |  |  |  |  |  | Name => 'Reserved', | 
| 877 |  |  |  |  |  |  | Format => 'int8u[22]', | 
| 878 |  |  |  |  |  |  | }, | 
| 879 |  |  |  |  |  |  | 0x0c00 => { | 
| 880 |  |  |  |  |  |  | Name => 'HeaderOp', | 
| 881 |  |  |  |  |  |  | Format => 'int16u[12]', | 
| 882 |  |  |  |  |  |  | }, | 
| 883 |  |  |  |  |  |  | 0x0c01 => { | 
| 884 |  |  |  |  |  |  | Name => 'Reserved', | 
| 885 |  |  |  |  |  |  | Format => 'int8u[24]', | 
| 886 |  |  |  |  |  |  | }, | 
| 887 |  |  |  |  |  |  | 0x7f00 => { | 
| 888 |  |  |  |  |  |  | Name => 'Reserved', | 
| 889 |  |  |  |  |  |  | Format => 'int8u[254]', | 
| 890 |  |  |  |  |  |  | }, | 
| 891 |  |  |  |  |  |  | 0x8000 => { | 
| 892 |  |  |  |  |  |  | Name => 'Reserved', | 
| 893 |  |  |  |  |  |  | Format => 'null', | 
| 894 |  |  |  |  |  |  | }, | 
| 895 |  |  |  |  |  |  | 0x8100 => { | 
| 896 |  |  |  |  |  |  | Name => 'Reserved', | 
| 897 |  |  |  |  |  |  | Format => 'Int32uData', | 
| 898 |  |  |  |  |  |  | }, | 
| 899 |  |  |  |  |  |  | 0x8200 => { | 
| 900 |  |  |  |  |  |  | Name => 'CompressedQuickTime', | 
| 901 |  |  |  |  |  |  | Format => 'CompressedQuickTime', | 
| 902 |  |  |  |  |  |  | }, | 
| 903 |  |  |  |  |  |  | 0x8201 => { | 
| 904 |  |  |  |  |  |  | Name => 'UncompressedQuickTime', | 
| 905 |  |  |  |  |  |  | Format => 'Int32uData', | 
| 906 |  |  |  |  |  |  | }, | 
| 907 |  |  |  |  |  |  | 0xffff => { | 
| 908 |  |  |  |  |  |  | Name => 'Reserved', | 
| 909 |  |  |  |  |  |  | Format => 'Int32uData', | 
| 910 |  |  |  |  |  |  | }, | 
| 911 |  |  |  |  |  |  | ); | 
| 912 |  |  |  |  |  |  |  | 
| 913 |  |  |  |  |  |  | # picture comment 'kind' codes | 
| 914 |  |  |  |  |  |  | # http://developer.apple.com/technotes/qd/qd_10.html | 
| 915 |  |  |  |  |  |  | my %commentKind = ( | 
| 916 |  |  |  |  |  |  | 150 => 'TextBegin', | 
| 917 |  |  |  |  |  |  | 151 => 'TextEnd', | 
| 918 |  |  |  |  |  |  | 152 => 'StringBegin', | 
| 919 |  |  |  |  |  |  | 153 => 'StringEnd', | 
| 920 |  |  |  |  |  |  | 154 => 'TextCenter', | 
| 921 |  |  |  |  |  |  | 155 => 'LineLayoutOff', | 
| 922 |  |  |  |  |  |  | 156 => 'LineLayoutOn', | 
| 923 |  |  |  |  |  |  | 157 => 'ClientLineLayout', | 
| 924 |  |  |  |  |  |  | 160 => 'PolyBegin', | 
| 925 |  |  |  |  |  |  | 161 => 'PolyEnd', | 
| 926 |  |  |  |  |  |  | 163 => 'PolyIgnore', | 
| 927 |  |  |  |  |  |  | 164 => 'PolySmooth', | 
| 928 |  |  |  |  |  |  | 165 => 'PolyClose', | 
| 929 |  |  |  |  |  |  | 180 => 'DashedLine', | 
| 930 |  |  |  |  |  |  | 181 => 'DashedStop', | 
| 931 |  |  |  |  |  |  | 182 => 'SetLineWidth', | 
| 932 |  |  |  |  |  |  | 190 => 'PostScriptBegin', | 
| 933 |  |  |  |  |  |  | 191 => 'PostScriptEnd', | 
| 934 |  |  |  |  |  |  | 192 => 'PostScriptHandle', | 
| 935 |  |  |  |  |  |  | 193 => 'PostScriptFile', | 
| 936 |  |  |  |  |  |  | 194 => 'TextIsPostScript', | 
| 937 |  |  |  |  |  |  | 195 => 'ResourcePS', | 
| 938 |  |  |  |  |  |  | 196 => 'PSBeginNoSave', | 
| 939 |  |  |  |  |  |  | 197 => 'SetGrayLevel', | 
| 940 |  |  |  |  |  |  | 200 => 'RotateBegin', | 
| 941 |  |  |  |  |  |  | 201 => 'RotateEnd', | 
| 942 |  |  |  |  |  |  | 202 => 'RotateCenter', | 
| 943 |  |  |  |  |  |  | 210 => 'FormsPrinting', | 
| 944 |  |  |  |  |  |  | 211 => 'EndFormsPrinting', | 
| 945 |  |  |  |  |  |  | 224 => '', | 
| 946 |  |  |  |  |  |  | 498 => '', | 
| 947 |  |  |  |  |  |  | 1000 => 'BitMapThinningOff', | 
| 948 |  |  |  |  |  |  | 1001 => 'BitMapThinningOn', | 
| 949 |  |  |  |  |  |  | ); | 
| 950 |  |  |  |  |  |  |  | 
| 951 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 952 |  |  |  |  |  |  | # Get PixData data | 
| 953 |  |  |  |  |  |  | # Inputs: 0) reference to PixMap, 1) RAF reference | 
| 954 |  |  |  |  |  |  | # Returns: reference to PixData or undef on error | 
| 955 |  |  |  |  |  |  | sub GetPixData($$) | 
| 956 |  |  |  |  |  |  | { | 
| 957 | 0 |  |  | 0 | 0 | 0 | my ($pixMap, $raf) = @_; | 
| 958 | 0 |  |  |  |  | 0 | my $packType = $pixMap->{packType}; | 
| 959 | 0 |  |  |  |  | 0 | my $rowBytes = $pixMap->{rowBytes} & 0x3fff;    # remove flags bits | 
| 960 |  |  |  |  |  |  | my $height = $pixMap->{bounds}->{botRight}->{v} - | 
| 961 | 0 |  |  |  |  | 0 | $pixMap->{bounds}->{topLeft}->{v}; | 
| 962 | 0 |  |  |  |  | 0 | my ($data, $size, $buff, $i); | 
| 963 |  |  |  |  |  |  |  | 
| 964 | 0 | 0 | 0 |  |  | 0 | if ($packType == 1 or $rowBytes < 8) {  # unpacked data | 
|  |  | 0 |  |  |  |  |  | 
| 965 | 0 |  |  |  |  | 0 | $size = $rowBytes * $height; | 
| 966 | 0 | 0 |  |  |  | 0 | return undef unless $raf->Read($data, $size) == $size; | 
| 967 |  |  |  |  |  |  | } elsif ($packType == 2) {              # pad byte dropped | 
| 968 | 0 |  |  |  |  | 0 | $size = int($rowBytes * $height * 3 / 4 + 0.5); | 
| 969 | 0 | 0 |  |  |  | 0 | return undef unless $raf->Read($data, $size) == $size; | 
| 970 |  |  |  |  |  |  | } else { | 
| 971 | 0 |  |  |  |  | 0 | $data = ''; | 
| 972 | 0 |  |  |  |  | 0 | for ($i=0; $i<$height; ++$i) { | 
| 973 | 0 | 0 |  |  |  | 0 | if ($rowBytes > 250) { | 
| 974 | 0 | 0 |  |  |  | 0 | $raf->Read($buff,2) == 2 or return undef; | 
| 975 | 0 |  |  |  |  | 0 | $size = unpack('n',$buff); | 
| 976 |  |  |  |  |  |  | } else { | 
| 977 | 0 | 0 |  |  |  | 0 | $raf->Read($buff,1) == 1 or return undef; | 
| 978 | 0 |  |  |  |  | 0 | $size = unpack('C',$buff); | 
| 979 |  |  |  |  |  |  | } | 
| 980 | 0 |  |  |  |  | 0 | $data .= $buff; | 
| 981 | 0 | 0 |  |  |  | 0 | $raf->Read($buff,$size) == $size or return undef; | 
| 982 | 0 |  |  |  |  | 0 | $data .= $buff; | 
| 983 |  |  |  |  |  |  | } | 
| 984 |  |  |  |  |  |  | } | 
| 985 | 0 |  |  |  |  | 0 | return \$data; | 
| 986 |  |  |  |  |  |  | } | 
| 987 |  |  |  |  |  |  |  | 
| 988 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 989 |  |  |  |  |  |  | # Read value from PICT file | 
| 990 |  |  |  |  |  |  | # Inputs: 0) RAF reference, 1) tag, 2) format, 3) optional count | 
| 991 |  |  |  |  |  |  | # Returns: value, reference to structure hash, or undef on error | 
| 992 |  |  |  |  |  |  | sub ReadPictValue($$$;$) | 
| 993 |  |  |  |  |  |  | { | 
| 994 | 0 |  |  | 0 | 0 | 0 | my ($raf, $tag, $format, $count) = @_; | 
| 995 | 0 | 0 |  |  |  | 0 | return undef unless $format; | 
| 996 | 0 | 0 |  |  |  | 0 | unless (defined $count) { | 
| 997 | 0 | 0 |  |  |  | 0 | if ($format =~ /(.+)\[(.+)\]/s) { | 
| 998 | 0 |  |  |  |  | 0 | $format = $1; | 
| 999 | 0 |  |  |  |  | 0 | $count = $2; | 
| 1000 |  |  |  |  |  |  | } else { | 
| 1001 | 0 |  |  |  |  | 0 | $count = 1; # count undefined: assume 1 | 
| 1002 |  |  |  |  |  |  | } | 
| 1003 |  |  |  |  |  |  | } | 
| 1004 | 0 | 0 |  |  |  | 0 | my $cntStr = ($count == 1) ? '' : "[$count]"; | 
| 1005 |  |  |  |  |  |  | # no size if count is 0 | 
| 1006 | 0 | 0 |  |  |  | 0 | my $size = $count ? Image::ExifTool::FormatSize($format) : 0; | 
| 1007 | 0 | 0 | 0 |  |  | 0 | if (defined $size or $format eq 'null') { | 
| 1008 | 0 |  |  |  |  | 0 | my $val; | 
| 1009 | 0 | 0 |  |  |  | 0 | if ($size) { | 
| 1010 | 0 |  |  |  |  | 0 | my $buff; | 
| 1011 | 0 |  |  |  |  | 0 | $size *= $count; | 
| 1012 | 0 | 0 |  |  |  | 0 | $raf->Read($buff, $size) == $size or return undef; | 
| 1013 | 0 |  |  |  |  | 0 | $val = ReadValue(\$buff, 0, $format, $count, $size); | 
| 1014 |  |  |  |  |  |  | } else { | 
| 1015 | 0 |  |  |  |  | 0 | $val = ''; | 
| 1016 |  |  |  |  |  |  | } | 
| 1017 | 0 | 0 |  |  |  | 0 | if ($verbose) { | 
| 1018 | 0 |  |  |  |  | 0 | print $out "${indent}$tag ($format$cntStr)"; | 
| 1019 | 0 | 0 |  |  |  | 0 | if ($size) { | 
| 1020 | 0 | 0 |  |  |  | 0 | if (not defined $val) { | 
|  |  | 0 |  |  |  |  |  | 
| 1021 | 0 |  |  |  |  | 0 | print $out " = \n"; | 
| 1022 |  |  |  |  |  |  | } elsif ($format eq 'binary') { | 
| 1023 | 0 |  |  |  |  | 0 | print $out " = \n"; | 
| 1024 | 0 | 0 |  |  |  | 0 | if ($verbose > 2) { | 
| 1025 | 0 |  |  |  |  | 0 | my %parms = ( Out => $out ); | 
| 1026 | 0 | 0 |  |  |  | 0 | $parms{MaxLen} = 96 if $verbose < 4; | 
| 1027 | 0 |  |  |  |  | 0 | HexDump(\$val, undef, %parms); | 
| 1028 |  |  |  |  |  |  | } | 
| 1029 |  |  |  |  |  |  | } else { | 
| 1030 | 0 |  |  |  |  | 0 | print $out " = $val\n"; | 
| 1031 |  |  |  |  |  |  | } | 
| 1032 |  |  |  |  |  |  | } else { | 
| 1033 | 0 |  |  |  |  | 0 | print $out "\n"; | 
| 1034 |  |  |  |  |  |  | } | 
| 1035 |  |  |  |  |  |  | } | 
| 1036 | 0 | 0 | 0 |  |  | 0 | return \$val if $format eq 'binary' and defined $val; | 
| 1037 | 0 |  |  |  |  | 0 | return $val; | 
| 1038 |  |  |  |  |  |  | } | 
| 1039 | 0 | 0 |  |  |  | 0 | $verbose and print $out "${indent}$tag ($format$cntStr):\n"; | 
| 1040 | 0 | 0 |  |  |  | 0 | my $struct = $structs{$format} or return undef; | 
| 1041 | 0 |  |  |  |  | 0 | my ($c, @vals); | 
| 1042 | 0 |  |  |  |  | 0 | for ($c=0; $c<$count; ++$c) { | 
| 1043 | 0 |  |  |  |  | 0 | my (%val, $i); | 
| 1044 | 0 |  |  |  |  | 0 | for ($i=0; ; $i+=2) { | 
| 1045 | 0 | 0 |  |  |  | 0 | my $tag = $$struct[$i] or last; | 
| 1046 | 0 |  |  |  |  | 0 | my $fmt = $$struct[$i+1]; | 
| 1047 | 0 |  |  |  |  | 0 | my ($cnt, $val); | 
| 1048 | 0 |  |  |  |  | 0 | $indent .= '  '; | 
| 1049 | 0 | 0 |  |  |  | 0 | if (ref $fmt) { | 
|  |  | 0 |  |  |  |  |  | 
| 1050 | 0 |  |  |  |  | 0 | $val = eval $$fmt; | 
| 1051 | 0 | 0 |  |  |  | 0 | $@ and warn $@; | 
| 1052 | 0 | 0 | 0 |  |  | 0 | if ($verbose and defined $val) { | 
| 1053 | 0 |  |  |  |  | 0 | printf $out "${indent}$tag (binary[%d]) = \n",length($$val); | 
| 1054 | 0 | 0 |  |  |  | 0 | if ($verbose > 2) { | 
| 1055 | 0 |  |  |  |  | 0 | my %parms = ( Out => $out ); | 
| 1056 | 0 | 0 |  |  |  | 0 | $parms{MaxLen} = 96 if $verbose < 4; | 
| 1057 | 0 |  |  |  |  | 0 | HexDump($val, undef, %parms); | 
| 1058 |  |  |  |  |  |  | } | 
| 1059 |  |  |  |  |  |  | } | 
| 1060 |  |  |  |  |  |  | } elsif ($fmt =~ /(.+)\[(.+)\]/s) { | 
| 1061 | 0 |  |  |  |  | 0 | $fmt = $1; | 
| 1062 | 0 |  |  |  |  | 0 | $cnt = eval $2; | 
| 1063 | 0 | 0 |  |  |  | 0 | $@ and warn $@; | 
| 1064 | 0 |  |  |  |  | 0 | $val = ReadPictValue($raf, $tag, $fmt, $cnt); | 
| 1065 |  |  |  |  |  |  | } else { | 
| 1066 | 0 |  |  |  |  | 0 | $val = ReadPictValue($raf, $tag, $fmt); | 
| 1067 |  |  |  |  |  |  | } | 
| 1068 | 0 |  |  |  |  | 0 | $indent = substr($indent, 2); | 
| 1069 | 0 | 0 |  |  |  | 0 | return undef unless defined $val; | 
| 1070 | 0 |  |  |  |  | 0 | $val{$tag} = $val; | 
| 1071 |  |  |  |  |  |  | } | 
| 1072 | 0 | 0 |  |  |  | 0 | return \%val if $count == 1; | 
| 1073 | 0 |  |  |  |  | 0 | push @vals, \%val; | 
| 1074 |  |  |  |  |  |  | } | 
| 1075 | 0 |  |  |  |  | 0 | return \@vals; | 
| 1076 |  |  |  |  |  |  | } | 
| 1077 |  |  |  |  |  |  |  | 
| 1078 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 1079 |  |  |  |  |  |  | # Extract meta information from a PICT image | 
| 1080 |  |  |  |  |  |  | # Inputs: 0) ExifTool object reference, 1) dirInfo reference | 
| 1081 |  |  |  |  |  |  | # Returns: 1 on success, 0 if this wasn't a valid PICT image | 
| 1082 |  |  |  |  |  |  | sub ProcessPICT($$) | 
| 1083 |  |  |  |  |  |  | { | 
| 1084 | 1 |  |  | 1 | 0 | 3 | my ($et, $dirInfo) = @_; | 
| 1085 | 1 |  |  |  |  | 3 | my $raf = $$dirInfo{RAF}; | 
| 1086 | 1 |  |  |  |  | 4 | $verbose = $et->Options('Verbose'); | 
| 1087 | 1 |  |  |  |  | 7 | $out = $et->Options('TextOut'); | 
| 1088 | 1 |  |  |  |  | 3 | $indent = ''; | 
| 1089 | 1 |  |  |  |  | 5 | my ($buff, $tried, @hdr, $op, $hRes, $vRes); | 
| 1090 |  |  |  |  |  |  |  | 
| 1091 |  |  |  |  |  |  | # recognize both PICT files and PICT resources (PICT files have a | 
| 1092 |  |  |  |  |  |  | # 512-byte header that we ignore, but PICT resources do not) | 
| 1093 | 1 |  |  |  |  | 11 | for (;;) { | 
| 1094 | 1 | 50 |  |  |  | 7 | $raf->Read($buff, 12) == 12 or return 0; | 
| 1095 | 1 |  |  |  |  | 13 | @hdr = unpack('x2n5', $buff); | 
| 1096 | 1 |  |  |  |  | 2 | $op = pop @hdr; | 
| 1097 |  |  |  |  |  |  | # check for PICT version 1 format | 
| 1098 | 1 | 50 |  |  |  | 3 | if ($op == 0x1101) { | 
| 1099 | 0 |  |  |  |  | 0 | $vers = 1; | 
| 1100 | 0 |  |  |  |  | 0 | undef $extended; | 
| 1101 | 0 |  |  |  |  | 0 | last; | 
| 1102 |  |  |  |  |  |  | } | 
| 1103 |  |  |  |  |  |  | # check for PICT version 2 format | 
| 1104 | 1 | 50 |  |  |  | 3 | if ($op == 0x0011) { | 
| 1105 | 1 | 50 |  |  |  | 4 | $raf->Read($buff, 28) == 28 or return 0; | 
| 1106 | 1 | 50 |  |  |  | 9 | if ($buff =~ /^\x02\xff\x0c\x00\xff\xff/) { | 
| 1107 | 0 |  |  |  |  | 0 | $vers = 2; | 
| 1108 | 0 |  |  |  |  | 0 | undef $extended; | 
| 1109 | 0 |  |  |  |  | 0 | last; | 
| 1110 |  |  |  |  |  |  | } | 
| 1111 | 1 | 50 |  |  |  | 6 | if ($buff =~ /^\x02\xff\x0c\x00\xff\xfe/) { | 
| 1112 | 1 |  |  |  |  | 4 | $vers = 2; | 
| 1113 | 1 |  |  |  |  | 2 | $extended = 1; | 
| 1114 | 1 |  |  |  |  | 8 | ($hRes, $vRes) = unpack('x8N2', $buff); | 
| 1115 | 1 |  |  |  |  | 2 | last; | 
| 1116 |  |  |  |  |  |  | } | 
| 1117 |  |  |  |  |  |  | } | 
| 1118 | 0 | 0 |  |  |  | 0 | return 0 if $tried; | 
| 1119 | 0 |  |  |  |  | 0 | $tried = 1; | 
| 1120 | 0 | 0 |  |  |  | 0 | $raf->Seek(512, 0) or return 0; | 
| 1121 |  |  |  |  |  |  | } | 
| 1122 |  |  |  |  |  |  | # make the bounding rect signed | 
| 1123 | 1 |  |  |  |  | 3 | foreach (@hdr) { | 
| 1124 | 4 | 50 |  |  |  | 10 | $_ >= 0x8000 and $_ -= 0x10000; | 
| 1125 |  |  |  |  |  |  | } | 
| 1126 | 1 |  |  |  |  | 2 | my $w = $hdr[3] - $hdr[1]; | 
| 1127 | 1 |  |  |  |  | 4 | my $h = $hdr[2] - $hdr[0]; | 
| 1128 | 1 | 50 | 33 |  |  | 6 | return 0 unless $w > 0 and $h > 0; | 
| 1129 |  |  |  |  |  |  |  | 
| 1130 | 1 |  |  |  |  | 8 | SetByteOrder('MM'); | 
| 1131 |  |  |  |  |  |  |  | 
| 1132 | 1 | 50 |  |  |  | 7 | if ($extended) { | 
| 1133 |  |  |  |  |  |  | # extended version 2 pictures contain resolution information | 
| 1134 |  |  |  |  |  |  | # and image bounds are in 72-dpi equivalent units | 
| 1135 | 1 |  |  |  |  | 6 | $hRes = GetFixed32s(\$buff, 8); | 
| 1136 | 1 |  |  |  |  | 5 | $vRes = GetFixed32s(\$buff, 12); | 
| 1137 | 1 | 50 | 33 |  |  | 7 | return 0 unless $hRes and $vRes; | 
| 1138 | 1 |  |  |  |  | 13 | $w = int($w * $hRes / 72 + 0.5); | 
| 1139 | 1 |  |  |  |  | 6 | $h = int($h * $vRes / 72 + 0.5); | 
| 1140 |  |  |  |  |  |  | } | 
| 1141 | 1 |  |  |  |  | 7 | $et->SetFileType(); | 
| 1142 | 1 |  |  |  |  | 4 | $et->FoundTag('ImageWidth', $w); | 
| 1143 | 1 |  |  |  |  | 3 | $et->FoundTag('ImageHeight', $h); | 
| 1144 | 1 | 50 |  |  |  | 7 | $et->FoundTag('XResolution', $hRes) if $hRes; | 
| 1145 | 1 | 50 |  |  |  | 17 | $et->FoundTag('YResolution', $vRes) if $vRes; | 
| 1146 |  |  |  |  |  |  |  | 
| 1147 |  |  |  |  |  |  | # don't extract image opcodes unless verbose | 
| 1148 | 1 | 50 | 33 |  |  | 6 | return 1 unless $verbose or $et->Options('Unknown'); | 
| 1149 |  |  |  |  |  |  |  | 
| 1150 | 0 | 0 |  |  |  |  | $verbose and printf $out "PICT version $vers%s\n", $extended ? ' extended' : ''; | 
|  |  | 0 |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  |  | 
| 1152 | 0 |  |  |  |  |  | my $tagTablePtr = GetTagTable('Image::ExifTool::PICT::Main'); | 
| 1153 |  |  |  |  |  |  |  | 
| 1154 | 0 |  |  |  |  |  | my $success; | 
| 1155 | 0 |  |  |  |  |  | for (;;) { | 
| 1156 | 0 | 0 |  |  |  |  | if ($vers == 1) { | 
| 1157 | 0 | 0 |  |  |  |  | $raf->Read($buff, 1) == 1 or last; | 
| 1158 | 0 |  |  |  |  |  | $op = ord($buff); | 
| 1159 |  |  |  |  |  |  | } else { | 
| 1160 |  |  |  |  |  |  | # must start version 2 opcode on an even byte | 
| 1161 | 0 | 0 |  |  |  |  | $raf->Read($buff, 1) if $raf->Tell() & 0x01; | 
| 1162 | 0 | 0 |  |  |  |  | $raf->Read($buff, 2) == 2 or last; | 
| 1163 | 0 |  |  |  |  |  | $op = unpack('n', $buff); | 
| 1164 |  |  |  |  |  |  | } | 
| 1165 | 0 |  |  |  |  |  | my $tagInfo = $et->GetTagInfo($tagTablePtr, $op); | 
| 1166 | 0 | 0 |  |  |  |  | unless ($tagInfo) { | 
| 1167 | 0 |  |  |  |  |  | my $i; | 
| 1168 |  |  |  |  |  |  | # search for reserved tag info | 
| 1169 | 0 |  |  |  |  |  | for ($i=0; $i | 
| 1170 | 0 | 0 |  |  |  |  | next unless $op >= $reserved[$i]; | 
| 1171 | 0 | 0 |  |  |  |  | last if $op > $reserved[$i+1]; | 
| 1172 | 0 |  |  |  |  |  | $tagInfo = $et->GetTagInfo($tagTablePtr, $reserved[$i]); | 
| 1173 | 0 |  |  |  |  |  | last; | 
| 1174 |  |  |  |  |  |  | } | 
| 1175 | 0 | 0 |  |  |  |  | last unless $tagInfo; | 
| 1176 |  |  |  |  |  |  | } | 
| 1177 | 0 | 0 |  |  |  |  | if ($op == 0xff) { | 
| 1178 | 0 | 0 |  |  |  |  | $verbose and print $out "End of picture\n"; | 
| 1179 | 0 |  |  |  |  |  | $success = 1; | 
| 1180 | 0 |  |  |  |  |  | last; | 
| 1181 |  |  |  |  |  |  | } | 
| 1182 | 0 |  |  |  |  |  | my $format = $$tagInfo{Format}; | 
| 1183 | 0 | 0 |  |  |  |  | unless ($format) { | 
| 1184 | 0 |  |  |  |  |  | $et->Warn("Missing format for $$tagInfo{Name}"); | 
| 1185 | 0 |  |  |  |  |  | last; | 
| 1186 |  |  |  |  |  |  | } | 
| 1187 |  |  |  |  |  |  | # replace version number for version-dependent formats | 
| 1188 | 0 |  |  |  |  |  | $format =~ s/#$/$vers/; | 
| 1189 | 0 |  |  |  |  |  | my $wid = $vers * 2; | 
| 1190 | 0 | 0 |  |  |  |  | $verbose and printf $out "Tag 0x%.${wid}x, ", $op; | 
| 1191 | 0 |  |  |  |  |  | my $val = ReadPictValue($raf, $$tagInfo{Name}, $format); | 
| 1192 | 0 | 0 |  |  |  |  | unless (defined $val) { | 
| 1193 | 0 |  |  |  |  |  | $et->Warn("Error reading $$tagInfo{Name} information"); | 
| 1194 | 0 |  |  |  |  |  | last; | 
| 1195 |  |  |  |  |  |  | } | 
| 1196 | 0 | 0 |  |  |  |  | if (ref $val eq 'HASH') { | 
| 1197 |  |  |  |  |  |  | # extract JPEG image from CompressedQuickTime imageData | 
| 1198 | 0 | 0 | 0 |  |  |  | if ($$tagInfo{Name} eq 'CompressedQuickTime' and | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 1199 |  |  |  |  |  |  | ref $val->{imageDescr} eq 'HASH' and | 
| 1200 |  |  |  |  |  |  | $val->{imageDescr}->{compressor} and | 
| 1201 |  |  |  |  |  |  | $val->{imageDescr}->{compressor} eq 'Photo - JPEG' and | 
| 1202 |  |  |  |  |  |  | ref $val->{imageData} eq 'SCALAR' and | 
| 1203 |  |  |  |  |  |  | $et->ValidateImage($val->{imageData}, 'PreviewImage')) | 
| 1204 |  |  |  |  |  |  | { | 
| 1205 | 0 |  |  |  |  |  | $et->FoundTag('PreviewImage', $val->{imageData}); | 
| 1206 |  |  |  |  |  |  | } | 
| 1207 |  |  |  |  |  |  | } else { | 
| 1208 |  |  |  |  |  |  | # $et->FoundTag($tagInfo, $val); | 
| 1209 |  |  |  |  |  |  | } | 
| 1210 |  |  |  |  |  |  | } | 
| 1211 | 0 | 0 |  |  |  |  | $success or $et->Warn('End of picture not found'); | 
| 1212 | 0 |  |  |  |  |  | return 1; | 
| 1213 |  |  |  |  |  |  | } | 
| 1214 |  |  |  |  |  |  |  | 
| 1215 |  |  |  |  |  |  | 1;  # end | 
| 1216 |  |  |  |  |  |  |  | 
| 1217 |  |  |  |  |  |  | __END__ |