source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/PICT.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

File size: 33.3 KB
Line 
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
17package Image::ExifTool::PICT;
18
19use strict;
20use vars qw($VERSION);
21use Image::ExifTool qw(:DataAccess :Utils);
22
23$VERSION = '1.03';
24
25sub ReadPictValue($$$;$);
26
27my ($vers, $extended); # PICT version number, and extended flag
28my ($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
32my @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
43my %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 PROCESS_PROC => 0, # set this to zero to omit tags from lookup
277 NOTES => q{
278The PICT format contains no true meta information, except for the possible
279exception of the LongComment opcode. By default, only ImageWidth,
280ImageHeight and X/YResolution are extracted from a PICT image. Tags in the
281following table represent image opcodes. Extraction of these tags is
282experimental, 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 [not currently 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
915my %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 => '<ICC Profile>',
946 498 => '<Photoshop Data>',
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
955sub GetPixData($$)
956{
957 my ($pixMap, $raf) = @_;
958 my $packType = $pixMap->{packType};
959 my $rowBytes = $pixMap->{rowBytes} & 0x3fff; # remove flags bits
960 my $height = $pixMap->{bounds}->{botRight}->{v} -
961 $pixMap->{bounds}->{topLeft}->{v};
962 my ($data, $size, $buff, $i);
963
964 if ($packType == 1 or $rowBytes < 8) { # unpacked data
965 $size = $rowBytes * $height;
966 return undef unless $raf->Read($data, $size) == $size;
967 } elsif ($packType == 2) { # pad byte dropped
968 $size = int($rowBytes * $height * 3 / 4 + 0.5);
969 return undef unless $raf->Read($data, $size) == $size;
970 } else {
971 $data = '';
972 for ($i=0; $i<$height; ++$i) {
973 if ($rowBytes > 250) {
974 $raf->Read($buff,2) == 2 or return undef;
975 $size = unpack('n',$buff);
976 } else {
977 $raf->Read($buff,1) == 1 or return undef;
978 $size = unpack('C',$buff);
979 }
980 $data .= $buff;
981 $raf->Read($buff,$size) == $size or return undef;
982 $data .= $buff;
983 }
984 }
985 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
992sub ReadPictValue($$$;$)
993{
994 my ($raf, $tag, $format, $count) = @_;
995 return undef unless $format;
996 unless (defined $count) {
997 if ($format =~ /(.+)\[(.+)\]/s) {
998 $format = $1;
999 $count = $2;
1000 } else {
1001 $count = 1; # count undefined: assume 1
1002 }
1003 }
1004 my $cntStr = ($count == 1) ? '' : "[$count]";
1005 # no size if count is 0
1006 my $size = $count ? Image::ExifTool::FormatSize($format) : 0;
1007 if (defined $size or $format eq 'null') {
1008 my $val;
1009 if ($size) {
1010 my $buff;
1011 $size *= $count;
1012 $raf->Read($buff, $size) == $size or return undef;
1013 $val = ReadValue(\$buff, 0, $format, $count, $size);
1014 } else {
1015 $val = '';
1016 }
1017 if ($verbose) {
1018 print $out "${indent}$tag ($format$cntStr)";
1019 if ($size) {
1020 if (not defined $val) {
1021 print $out " = <undef>\n";
1022 } elsif ($format eq 'binary') {
1023 print $out " = <binary data>\n";
1024 if ($verbose > 2) {
1025 my %parms = ( Out => $out );
1026 $parms{MaxLen} = 96 if $verbose < 4;
1027 Image::ExifTool::HexDump(\$val, undef, %parms);
1028 }
1029 } else {
1030 print $out " = $val\n";
1031 }
1032 } else {
1033 print $out "\n";
1034 }
1035 }
1036 return \$val if $format eq 'binary' and defined $val;
1037 return $val;
1038 }
1039 $verbose and print $out "${indent}$tag ($format$cntStr):\n";
1040 my $struct = $structs{$format} or return undef;
1041 my ($c, @vals);
1042 for ($c=0; $c<$count; ++$c) {
1043 my (%val, $i);
1044 for ($i=0; ; $i+=2) {
1045 my $tag = $$struct[$i] or last;
1046 my $fmt = $$struct[$i+1];
1047 my ($cnt, $val);
1048 $indent .= ' ';
1049 if (ref $fmt) {
1050 $val = eval $$fmt;
1051 $@ and warn $@;
1052 if ($verbose and defined $val) {
1053 printf $out "${indent}$tag (binary[%d]) = <binary data>\n",length($$val);
1054 if ($verbose > 2) {
1055 my %parms = ( Out => $out );
1056 $parms{MaxLen} = 96 if $verbose < 4;
1057 Image::ExifTool::HexDump($val, undef, %parms);
1058 }
1059 }
1060 } elsif ($fmt =~ /(.+)\[(.+)\]/s) {
1061 $fmt = $1;
1062 $cnt = eval $2;
1063 $@ and warn $@;
1064 $val = ReadPictValue($raf, $tag, $fmt, $cnt);
1065 } else {
1066 $val = ReadPictValue($raf, $tag, $fmt);
1067 }
1068 $indent = substr($indent, 2);
1069 return undef unless defined $val;
1070 $val{$tag} = $val;
1071 }
1072 return \%val if $count == 1;
1073 push @vals, \%val;
1074 }
1075 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
1082sub ProcessPICT($$)
1083{
1084 my ($exifTool, $dirInfo) = @_;
1085 my $raf = $$dirInfo{RAF};
1086 $verbose = $exifTool->Options('Verbose');
1087 $out = $exifTool->Options('TextOut');
1088 $indent = '';
1089 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 for (;;) {
1094 $raf->Read($buff, 12) == 12 or return 0;
1095 @hdr = unpack('x2n5', $buff);
1096 $op = pop @hdr;
1097 # check for PICT version 1 format
1098 if ($op eq 0x1101) {
1099 $vers = 1;
1100 undef $extended;
1101 last;
1102 }
1103 # check for PICT version 2 format
1104 if ($op eq 0x0011) {
1105 $raf->Read($buff, 28) == 28 or return 0;
1106 if ($buff =~ /^\x02\xff\x0c\x00\xff\xff/) {
1107 $vers = 2;
1108 undef $extended;
1109 last;
1110 }
1111 if ($buff =~ /^\x02\xff\x0c\x00\xff\xfe/) {
1112 $vers = 2;
1113 $extended = 1;
1114 ($hRes, $vRes) = unpack('x8N2', $buff);
1115 last;
1116 }
1117 }
1118 return 0 if $tried;
1119 $tried = 1;
1120 $raf->Seek(512, 0) or return 0;
1121 }
1122 # make the bounding rect signed
1123 foreach (@hdr) {
1124 $_ >= 0x8000 and $_ -= 0x10000;
1125 }
1126 my $w = $hdr[3] - $hdr[1];
1127 my $h = $hdr[2] - $hdr[0];
1128 return 0 unless $w > 0 and $h > 0;
1129
1130 SetByteOrder('MM');
1131
1132 if ($extended) {
1133 # extended version 2 pictures contain resolution information
1134 # and image bounds are in 72-dpi equivalent units
1135 $hRes = GetFixed32s(\$buff, 8);
1136 $vRes = GetFixed32s(\$buff, 12);
1137 return 0 unless $hRes and $vRes;
1138 $w = int($w * $hRes / 72 + 0.5);
1139 $h = int($h * $vRes / 72 + 0.5);
1140 }
1141 $exifTool->SetFileType();
1142 $exifTool->FoundTag('ImageWidth', $w);
1143 $exifTool->FoundTag('ImageHeight', $h);
1144 $exifTool->FoundTag('XResolution', $hRes) if $hRes;
1145 $exifTool->FoundTag('YResolution', $vRes) if $vRes;
1146
1147 # don't extract image opcodes unless verbose
1148 return 1 unless $verbose or $exifTool->Options('Unknown');
1149
1150 $verbose and printf $out "PICT version $vers%s\n", $extended ? ' extended' : '';
1151
1152 my $tagTablePtr = GetTagTable('Image::ExifTool::PICT::Main');
1153
1154 my $success;
1155 for (;;) {
1156 if ($vers == 1) {
1157 $raf->Read($buff, 1) == 1 or last;
1158 $op = ord($buff);
1159 } else {
1160 # must start version 2 opcode on an even byte
1161 $raf->Read($buff, 1) if $raf->Tell() & 0x01;
1162 $raf->Read($buff, 2) == 2 or last;
1163 $op = unpack('n', $buff);
1164 }
1165 my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $op);
1166 unless ($tagInfo) {
1167 my $i;
1168 # search for reserved tag info
1169 for ($i=0; $i<scalar(@reserved); $i+=2) {
1170 next unless $op >= $reserved[$i];
1171 last if $op > $reserved[$i+1];
1172 $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $reserved[$i]);
1173 last;
1174 }
1175 last unless $tagInfo;
1176 }
1177 if ($op eq 0xff) {
1178 $verbose and print $out "End of picture\n";
1179 $success = 1;
1180 last;
1181 }
1182 my $format = $$tagInfo{Format};
1183 unless ($format) {
1184 $exifTool->Warn("Missing format for $$tagInfo{Name}");
1185 last;
1186 }
1187 # replace version number for version-dependent formats
1188 $format =~ s/#$/$vers/;
1189 my $wid = $vers * 2;
1190 $verbose and printf $out "Tag 0x%.${wid}x, ", $op;
1191 my $val = ReadPictValue($raf, $$tagInfo{Name}, $format);
1192 unless (defined $val) {
1193 $exifTool->Warn("Error reading $$tagInfo{Name} information");
1194 last;
1195 }
1196 if (ref $val eq 'HASH') {
1197 # extract JPEG image from CompressedQuickTime imageData
1198 if ($$tagInfo{Name} eq 'CompressedQuickTime' and
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 $exifTool->ValidateImage($val->{imageData}, 'PreviewImage'))
1204 {
1205 $exifTool->FoundTag('PreviewImage', $val->{imageData});
1206 }
1207 } else {
1208 # $exifTool->FoundTag($tagInfo, $val);
1209 }
1210 }
1211 $success or $exifTool->Warn('End of picture not found');
1212 return 1;
1213}
1214
12151; # end
1216
1217__END__
1218
1219=head1 NAME
1220
1221Image::ExifTool::PICT - Read PICT meta information
1222
1223=head1 SYNOPSIS
1224
1225This module is used by Image::ExifTool
1226
1227=head1 DESCRIPTION
1228
1229This module contains routines required by Image::ExifTool to read PICT
1230(Apple Picture) images.
1231
1232=head1 NOTES
1233
1234Extraction of PICT opcodes is experimental, and is only enabled with the
1235Verbose or the Unknown option.
1236
1237=head1 AUTHOR
1238
1239Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
1240
1241This library is free software; you can redistribute it and/or modify it
1242under the same terms as Perl itself.
1243
1244=head1 REFERENCES
1245
1246=over 4
1247
1248=item L<http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html>
1249
1250=item L<http://developer.apple.com/documentation/QuickTime/INMAC/QT/iqImageCompMgr.a.htm>
1251
1252=back
1253
1254=head1 SEE ALSO
1255
1256L<Image::ExifTool::TagNames/PICT Tags>,
1257L<Image::ExifTool(3pm)|Image::ExifTool>
1258
1259=cut
1260
Note: See TracBrowser for help on using the repository browser.