source: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/ICC_Profile.pm@ 34921

Last change on this file since 34921 was 34921, checked in by anupama, 3 years ago

Committing the improvements to EmbeddedMetaPlugin's processing of Keywords vs other metadata fields. Keywords were literally stored as arrays of words rather than phrases in PDFs (at least in Diego's sample PDF), whereas other meta fields like Subjects and Creators stored them as arrays of phrases. To get both to work, Kathy updated EXIF to a newer version, to retrieve the actual EXIF values stored in the PDF. And Kathy and Dr Bainbridge came up with a new option that I added called apply_join_before_split_to_metafields that's a regex which can list the metadata fields to apply the join_before_split to and whcih previously always got applied to all metadata fields. Now it's applied to any *Keywords metafields by default, as that's the metafield we have experience of that behaves differently to the others, as it stores by word instead of phrases. Tested on Diego's sample PDF. Diego has double-checked it to works on his sample PDF too, setting the split char to ; and turning on the join_before_split and leaving apply_join_before_split_to_metafields at its default of .*Keywords. File changes are strings.properties for the tooltip, the plugin introducing the option and working with it and Kathy's EXIF updates affecting cpan/File and cpan/Image.

File size: 42.9 KB
Line 
1#------------------------------------------------------------------------------
2# File: ICC_Profile.pm
3#
4# Description: Read ICC Profile meta information
5#
6# Revisions: 11/16/2004 - P. Harvey Created
7#
8# References: 1) http://www.color.org/icc_specs2.html (ICC.1:2003-09)
9# 2) http://www.color.org/icc_specs2.html (ICC.1:2001-04)
10# 3) http://developer.apple.com/documentation/GraphicsImaging/Reference/ColorSync_Manager/ColorSync_Manager.pdf
11# 4) http://www.color.org/privatetag2007-01.pdf
12# 5) http://www.color.org/icc_specs2.xalter (approved revisions, 2010-07-16)
13# 6) Eef Vreeland private communication
14#
15# Notes: The ICC profile information is different: the format of each
16# tag is embedded in the information instead of in the directory
17# structure. This makes things a bit more complex because I need
18# an extra level of logic to decode the variable-format tags.
19#------------------------------------------------------------------------------
20
21package Image::ExifTool::ICC_Profile;
22
23use strict;
24use vars qw($VERSION);
25use Image::ExifTool qw(:DataAccess :Utils);
26
27$VERSION = '1.36';
28
29sub ProcessICC($$);
30sub ProcessICC_Profile($$$);
31sub WriteICC_Profile($$;$);
32sub ProcessMetadata($$$);
33sub ValidateICC($);
34
35# illuminant type definitions
36my %illuminantType = (
37 1 => 'D50',
38 2 => 'D65',
39 3 => 'D93',
40 4 => 'F2',
41 5 => 'D55',
42 6 => 'A',
43 7 => 'Equi-Power (E)',
44 8 => 'F8',
45);
46my %profileClass = (
47 scnr => 'Input Device Profile',
48 mntr => 'Display Device Profile',
49 prtr => 'Output Device Profile',
50 'link'=> 'DeviceLink Profile',
51 spac => 'ColorSpace Conversion Profile',
52 abst => 'Abstract Profile',
53 nmcl => 'NamedColor Profile',
54 nkpf => 'Nikon Input Device Profile (NON-STANDARD!)', # (written by Nikon utilities)
55);
56my %manuSig = ( #6
57 'NONE' => 'none',
58 'none' => 'none', #PH
59 '' => '', #PH
60 '4d2p' => 'Erdt Systems GmbH & Co KG',
61 'AAMA' => 'Aamazing Technologies, Inc.',
62 'ACER' => 'Acer Peripherals',
63 'ACLT' => 'Acolyte Color Research',
64 'ACTI' => 'Actix Systems, Inc.',
65 'ADAR' => 'Adara Technology, Inc.',
66 'ADBE' => 'Adobe Systems Inc.',
67 'ADI ' => 'ADI Systems, Inc.',
68 'AGFA' => 'Agfa Graphics N.V.',
69 'ALMD' => 'Alps Electric USA, Inc.',
70 'ALPS' => 'Alps Electric USA, Inc.',
71 'ALWN' => 'Alwan Color Expertise',
72 'AMTI' => 'Amiable Technologies, Inc.',
73 'AOC ' => 'AOC International (U.S.A), Ltd.',
74 'APAG' => 'Apago',
75 'APPL' => 'Apple Computer Inc.',
76 'appl' => 'Apple Computer Inc.',
77 'AST ' => 'AST',
78 'AT&T' => 'AT&T Computer Systems',
79 'BAEL' => 'BARBIERI electronic',
80 'berg' => 'bergdesign incorporated',
81 'bICC' => 'basICColor GmbH',
82 'BRCO' => 'Barco NV',
83 'BRKP' => 'Breakpoint Pty Limited',
84 'BROT' => 'Brother Industries, LTD',
85 'BULL' => 'Bull',
86 'BUS ' => 'Bus Computer Systems',
87 'C-IT' => 'C-Itoh',
88 'CAMR' => 'Intel Corporation',
89 'CANO' => 'Canon, Inc. (Canon Development Americas, Inc.)',
90 'CARR' => 'Carroll Touch',
91 'CASI' => 'Casio Computer Co., Ltd.',
92 'CBUS' => 'Colorbus PL',
93 'CEL ' => 'Crossfield',
94 'CELx' => 'Crossfield',
95 'ceyd' => 'Integrated Color Solutions, Inc.',
96 'CGS ' => 'CGS Publishing Technologies International GmbH',
97 'CHM ' => 'Rochester Robotics',
98 'CIGL' => 'Colour Imaging Group, London',
99 'CITI' => 'Citizen',
100 'CL00' => 'Candela, Ltd.',
101 'CLIQ' => 'Color IQ',
102 'clsp' => 'MacDermid ColorSpan, Inc.',
103 'CMCO' => 'Chromaco, Inc.',
104 'CMiX' => 'CHROMiX',
105 'COLO' => 'Colorgraphic Communications Corporation',
106 'COMP' => 'COMPAQ Computer Corporation',
107 'COMp' => 'Compeq USA/Focus Technology',
108 'CONR' => 'Conrac Display Products',
109 'CORD' => 'Cordata Technologies, Inc.',
110 'CPQ ' => 'Compaq Computer Corporation',
111 'CPRO' => 'ColorPro',
112 'CRN ' => 'Cornerstone',
113 'CTX ' => 'CTX International, Inc.',
114 'CVIS' => 'ColorVision',
115 'CWC ' => 'Fujitsu Laboratories, Ltd.',
116 'DARI' => 'Darius Technology, Ltd.',
117 'DATA' => 'Dataproducts',
118 'DCP ' => 'Dry Creek Photo',
119 'DCRC' => 'Digital Contents Resource Center, Chung-Ang University',
120 'DELL' => 'Dell Computer Corporation',
121 'DIC ' => 'Dainippon Ink and Chemicals',
122 'DICO' => 'Diconix',
123 'DIGI' => 'Digital',
124 'DL&C' => 'Digital Light & Color',
125 'DPLG' => 'Doppelganger, LLC',
126 'DS ' => 'Dainippon Screen',
127 'ds ' => 'Dainippon Screen',
128 'DSOL' => 'DOOSOL',
129 'DUPN' => 'DuPont',
130 'dupn' => 'DuPont',
131 'Eizo' => 'EIZO NANAO CORPORATION',
132 'EPSO' => 'Epson',
133 'ESKO' => 'Esko-Graphics',
134 'ETRI' => 'Electronics and Telecommunications Research Institute',
135 'EVER' => 'Everex Systems, Inc.',
136 'EXAC' => 'ExactCODE GmbH',
137 'FALC' => 'Falco Data Products, Inc.',
138 'FF ' => 'Fuji Photo Film Co.,LTD',
139 'FFEI' => 'FujiFilm Electronic Imaging, Ltd.',
140 'ffei' => 'FujiFilm Electronic Imaging, Ltd.',
141 'flux' => 'FluxData Corporation',
142 'FNRD' => 'fnord software',
143 'FORA' => 'Fora, Inc.',
144 'FORE' => 'Forefront Technology Corporation',
145 'FP ' => 'Fujitsu',
146 'FPA ' => 'WayTech Development, Inc.',
147 'FUJI' => 'Fujitsu',
148 'FX ' => 'Fuji Xerox Co., Ltd.',
149 'GCC ' => 'GCC Technologies, Inc.',
150 'GGSL' => 'Global Graphics Software Limited',
151 'GMB ' => 'Gretagmacbeth',
152 'GMG ' => 'GMG GmbH & Co. KG',
153 'GOLD' => 'GoldStar Technology, Inc.',
154 'GOOG' => 'Google', #PH
155 'GPRT' => 'Giantprint Pty Ltd',
156 'GTMB' => 'Gretagmacbeth',
157 'GVC ' => 'WayTech Development, Inc.',
158 'GW2K' => 'Sony Corporation',
159 'HCI ' => 'HCI',
160 'HDM ' => 'Heidelberger Druckmaschinen AG',
161 'HERM' => 'Hermes',
162 'HITA' => 'Hitachi America, Ltd.',
163 'HiTi' => 'HiTi Digital, Inc.',
164 'HP ' => 'Hewlett-Packard',
165 'HTC ' => 'Hitachi, Ltd.',
166 'IBM ' => 'IBM Corporation',
167 'IDNT' => 'Scitex Corporation, Ltd.',
168 'Idnt' => 'Scitex Corporation, Ltd.',
169 'IEC ' => 'Hewlett-Packard',
170 'IIYA' => 'Iiyama North America, Inc.',
171 'IKEG' => 'Ikegami Electronics, Inc.',
172 'IMAG' => 'Image Systems Corporation',
173 'IMI ' => 'Ingram Micro, Inc.',
174 'Inca' => 'Inca Digital Printers Ltd.',
175 'INTC' => 'Intel Corporation',
176 'INTL' => 'N/A (INTL)',
177 'INTR' => 'Intra Electronics USA, Inc.',
178 'IOCO' => 'Iocomm International Technology Corporation',
179 'IPS ' => 'InfoPrint Solutions Company',
180 'IRIS' => 'Scitex Corporation, Ltd.',
181 'Iris' => 'Scitex Corporation, Ltd.',
182 'iris' => 'Scitex Corporation, Ltd.',
183 'ISL ' => 'Ichikawa Soft Laboratory',
184 'ITNL' => 'N/A (ITNL)',
185 'IVM ' => 'IVM',
186 'IWAT' => 'Iwatsu Electric Co., Ltd.',
187 'JPEG' => 'Joint Photographic Experts Group', #PH
188 'JSFT' => 'Jetsoft Development',
189 'JVC ' => 'JVC Information Products Co.',
190 'KART' => 'Scitex Corporation, Ltd.',
191 'Kart' => 'Scitex Corporation, Ltd.',
192 'kart' => 'Scitex Corporation, Ltd.',
193 'KFC ' => 'KFC Computek Components Corporation',
194 'KLH ' => 'KLH Computers',
195 'KMHD' => 'Konica Minolta Holdings, Inc.',
196 'KNCA' => 'Konica Corporation',
197 'KODA' => 'Kodak',
198 'KYOC' => 'Kyocera',
199 'LCAG' => 'Leica Camera AG',
200 'LCCD' => 'Leeds Colour',
201 'lcms' => 'Little CMS', #NealKrawetz
202 'LDAK' => 'Left Dakota',
203 'LEAD' => 'Leading Technology, Inc.',
204 'Leaf' => 'Leaf', #PH
205 'LEXM' => 'Lexmark International, Inc.',
206 'LINK' => 'Link Computer, Inc.',
207 'LINO' => 'Linotronic',
208 'Lino' => 'Linotronic', #PH (NC)
209 'lino' => 'Linotronic', #PH (NC)
210 'LITE' => 'Lite-On, Inc.',
211 'MAGC' => 'Mag Computronic (USA) Inc.',
212 'MAGI' => 'MAG Innovision, Inc.',
213 'MANN' => 'Mannesmann',
214 'MICN' => 'Micron Technology, Inc.',
215 'MICR' => 'Microtek',
216 'MICV' => 'Microvitec, Inc.',
217 'MINO' => 'Minolta',
218 'MITS' => 'Mitsubishi Electronics America, Inc.',
219 'MITs' => 'Mitsuba Corporation',
220 'Mits' => 'Mitsubishi Electric Corporation Kyoto Works',
221 'MNLT' => 'Minolta',
222 'MODG' => 'Modgraph, Inc.',
223 'MONI' => 'Monitronix, Inc.',
224 'MONS' => 'Monaco Systems Inc.',
225 'MORS' => 'Morse Technology, Inc.',
226 'MOTI' => 'Motive Systems',
227 'MSFT' => 'Microsoft Corporation',
228 'MUTO' => 'MUTOH INDUSTRIES LTD.',
229 'NANA' => 'NANAO USA Corporation',
230 'NEC ' => 'NEC Corporation',
231 'NEXP' => 'NexPress Solutions LLC',
232 'NISS' => 'Nissei Sangyo America, Ltd.',
233 'NKON' => 'Nikon Corporation',
234 'ob4d' => 'Erdt Systems GmbH & Co KG',
235 'obic' => 'Medigraph GmbH',
236 'OCE ' => 'Oce Technologies B.V.',
237 'OCEC' => 'OceColor',
238 'OKI ' => 'Oki',
239 'OKID' => 'Okidata',
240 'OKIP' => 'Okidata',
241 'OLIV' => 'Olivetti',
242 'OLYM' => 'OLYMPUS OPTICAL CO., LTD',
243 'ONYX' => 'Onyx Graphics',
244 'OPTI' => 'Optiquest',
245 'PACK' => 'Packard Bell',
246 'PANA' => 'Matsushita Electric Industrial Co., Ltd.',
247 'PANT' => 'Pantone, Inc.',
248 'PBN ' => 'Packard Bell',
249 'PFU ' => 'PFU Limited',
250 'PHIL' => 'Philips Consumer Electronics Co.',
251 'PNTX' => 'HOYA Corporation PENTAX Imaging Systems Division',
252 'POne' => 'Phase One A/S',
253 'PREM' => 'Premier Computer Innovations',
254 'PRIN' => 'Princeton Graphic Systems',
255 'PRIP' => 'Princeton Publishing Labs',
256 'QLUX' => 'Hong Kong',
257 'QMS ' => 'QMS, Inc.',
258 'QPCD' => 'QPcard AB',
259 'QUAD' => 'QuadLaser',
260 'quby' => 'Qubyx Sarl',
261 'QUME' => 'Qume Corporation',
262 'RADI' => 'Radius, Inc.',
263 'RDDx' => 'Integrated Color Solutions, Inc.',
264 'RDG ' => 'Roland DG Corporation',
265 'REDM' => 'REDMS Group, Inc.',
266 'RELI' => 'Relisys',
267 'RGMS' => 'Rolf Gierling Multitools',
268 'RICO' => 'Ricoh Corporation',
269 'RNLD' => 'Edmund Ronald',
270 'ROYA' => 'Royal',
271 'RPC ' => 'Ricoh Printing Systems,Ltd.',
272 'RTL ' => 'Royal Information Electronics Co., Ltd.',
273 'SAMP' => 'Sampo Corporation of America',
274 'SAMS' => 'Samsung, Inc.',
275 'SANT' => 'Jaime Santana Pomares',
276 'SCIT' => 'Scitex Corporation, Ltd.',
277 'Scit' => 'Scitex Corporation, Ltd.',
278 'scit' => 'Scitex Corporation, Ltd.',
279 'SCRN' => 'Dainippon Screen',
280 'scrn' => 'Dainippon Screen',
281 'SDP ' => 'Scitex Corporation, Ltd.',
282 'Sdp ' => 'Scitex Corporation, Ltd.',
283 'sdp ' => 'Scitex Corporation, Ltd.',
284 'SEC ' => 'SAMSUNG ELECTRONICS CO.,LTD',
285 'SEIK' => 'Seiko Instruments U.S.A., Inc.',
286 'SEIk' => 'Seikosha',
287 'SGUY' => 'ScanGuy.com',
288 'SHAR' => 'Sharp Laboratories',
289 'SICC' => 'International Color Consortium',
290 'siwi' => 'SIWI GRAFIKA CORPORATION',
291 'SONY' => 'SONY Corporation',
292 'Sony' => 'Sony Corporation',
293 'SPCL' => 'SpectraCal',
294 'STAR' => 'Star',
295 'STC ' => 'Sampo Technology Corporation',
296 'TALO' => 'Talon Technology Corporation',
297 'TAND' => 'Tandy',
298 'TATU' => 'Tatung Co. of America, Inc.',
299 'TAXA' => 'TAXAN America, Inc.',
300 'TDS ' => 'Tokyo Denshi Sekei K.K.',
301 'TECO' => 'TECO Information Systems, Inc.',
302 'TEGR' => 'Tegra',
303 'TEKT' => 'Tektronix, Inc.',
304 'TI ' => 'Texas Instruments',
305 'TMKR' => 'TypeMaker Ltd.',
306 'TOSB' => 'TOSHIBA corp.',
307 'TOSH' => 'Toshiba, Inc.',
308 'TOTK' => 'TOTOKU ELECTRIC Co., LTD',
309 'TRIU' => 'Triumph',
310 'TSBT' => 'TOSHIBA TEC CORPORATION',
311 'TTX ' => 'TTX Computer Products, Inc.',
312 'TVM ' => 'TVM Professional Monitor Corporation',
313 'TW ' => 'TW Casper Corporation',
314 'ULSX' => 'Ulead Systems',
315 'UNIS' => 'Unisys',
316 'UTZF' => 'Utz Fehlau & Sohn',
317 'VARI' => 'Varityper',
318 'VIEW' => 'Viewsonic',
319 'VISL' => 'Visual communication',
320 'VIVO' => 'Vivo Mobile Communication Co., Ltd',
321 'WANG' => 'Wang',
322 'WLBR' => 'Wilbur Imaging',
323 'WTG2' => 'Ware To Go',
324 'WYSE' => 'WYSE Technology',
325 'XERX' => 'Xerox Corporation',
326 'XRIT' => 'X-Rite',
327 'yxym' => 'YxyMaster GmbH',
328 'Z123' => "Lavanya's test Company",
329 'Zebr' => 'Zebra Technologies Inc',
330 'ZRAN' => 'Zoran Corporation',
331 # also seen: " ",ACMS,KCMS,UCCM,etc2,SCTX
332);
333
334# ICC_Profile tag table
335%Image::ExifTool::ICC_Profile::Main = (
336 GROUPS => { 2 => 'Image' },
337 PROCESS_PROC => \&ProcessICC_Profile,
338 WRITE_PROC => \&WriteICC_Profile,
339 NOTES => q{
340 ICC profile information is used in many different file types including JPEG,
341 TIFF, PDF, PostScript, Photoshop, PNG, MIFF, PICT, QuickTime, XCF and some
342 RAW formats. While the tags listed below are not individually writable, the
343 entire profile itself can be accessed via the extra 'ICC_Profile' tag, but
344 this tag is neither extracted nor written unless specified explicitly. See
345 L<http://www.color.org/icc_specs2.xalter> for the official ICC
346 specification.
347 },
348 A2B0 => 'AToB0',
349 A2B1 => 'AToB1',
350 A2B2 => 'AToB2',
351 bXYZ => 'BlueMatrixColumn', # (called BlueColorant in ref 2)
352 bTRC => {
353 Name => 'BlueTRC',
354 Description => 'Blue Tone Reproduction Curve',
355 },
356 B2A0 => 'BToA0',
357 B2A1 => 'BToA1',
358 B2A2 => 'BToA2',
359 calt => {
360 Name => 'CalibrationDateTime',
361 Groups => { 2 => 'Time' },
362 PrintConv => '$self->ConvertDateTime($val)',
363 },
364 targ => {
365 Name => 'CharTarget',
366 ValueConv => '$val=~s/\0.*//; length $val > 128 ? \$val : $val',
367 },
368 chad => 'ChromaticAdaptation',
369 chrm => {
370 Name => 'Chromaticity',
371 Groups => { 1 => 'ICC_Profile#' }, #(just for the group list)
372 SubDirectory => {
373 TagTable => 'Image::ExifTool::ICC_Profile::Chromaticity',
374 Validate => '$type eq "chrm"',
375 },
376 },
377 clro => 'ColorantOrder',
378 clrt => {
379 Name => 'ColorantTable',
380 SubDirectory => {
381 TagTable => 'Image::ExifTool::ICC_Profile::ColorantTable',
382 Validate => '$type eq "clrt"',
383 },
384 },
385 clot => { # new in version 4.2
386 Name => 'ColorantTableOut',
387 Binary => 1,
388 },
389 cprt => {
390 Name => 'ProfileCopyright',
391 ValueConv => '$val=~s/\0.*//; $val', # may be null terminated
392 },
393 crdi => 'CRDInfo', #2
394 dmnd => {
395 Name => 'DeviceMfgDesc',
396 Groups => { 2 => 'Camera' },
397 },
398 dmdd => {
399 Name => 'DeviceModelDesc',
400 Groups => { 2 => 'Camera' },
401 },
402 devs => {
403 Name => 'DeviceSettings', #2
404 Groups => { 2 => 'Camera' },
405 },
406 gamt => 'Gamut',
407 kTRC => {
408 Name => 'GrayTRC',
409 Description => 'Gray Tone Reproduction Curve',
410 },
411 gXYZ => 'GreenMatrixColumn', # (called GreenColorant in ref 2)
412 gTRC => {
413 Name => 'GreenTRC',
414 Description => 'Green Tone Reproduction Curve',
415 },
416 lumi => 'Luminance',
417 meas => {
418 Name => 'Measurement',
419 SubDirectory => {
420 TagTable => 'Image::ExifTool::ICC_Profile::Measurement',
421 Validate => '$type eq "meas"',
422 },
423 },
424 bkpt => 'MediaBlackPoint',
425 wtpt => 'MediaWhitePoint',
426 ncol => 'NamedColor', #2
427 ncl2 => 'NamedColor2',
428 resp => 'OutputResponse',
429 pre0 => 'Preview0',
430 pre1 => 'Preview1',
431 pre2 => 'Preview2',
432 desc => 'ProfileDescription',
433 pseq => 'ProfileSequenceDesc',
434 psd0 => 'PostScript2CRD0', #2
435 psd1 => 'PostScript2CRD1', #2
436 psd2 => 'PostScript2CRD2', #2
437 ps2s => 'PostScript2CSA', #2
438 ps2i => 'PS2RenderingIntent', #2
439 rXYZ => 'RedMatrixColumn', # (called RedColorant in ref 2)
440 rTRC => {
441 Name => 'RedTRC',
442 Description => 'Red Tone Reproduction Curve',
443 },
444 scrd => 'ScreeningDesc',
445 scrn => 'Screening',
446 'bfd '=> {
447 Name => 'UCRBG',
448 Description => 'Under Color Removal and Black Gen.',
449 },
450 tech => {
451 Name => 'Technology',
452 PrintConv => {
453 fscn => 'Film Scanner',
454 dcam => 'Digital Camera',
455 rscn => 'Reflective Scanner',
456 ijet => 'Ink Jet Printer',
457 twax => 'Thermal Wax Printer',
458 epho => 'Electrophotographic Printer',
459 esta => 'Electrostatic Printer',
460 dsub => 'Dye Sublimation Printer',
461 rpho => 'Photographic Paper Printer',
462 fprn => 'Film Writer',
463 vidm => 'Video Monitor',
464 vidc => 'Video Camera',
465 pjtv => 'Projection Television',
466 'CRT '=> 'Cathode Ray Tube Display',
467 'PMD '=> 'Passive Matrix Display',
468 'AMD '=> 'Active Matrix Display',
469 KPCD => 'Photo CD',
470 imgs => 'Photo Image Setter',
471 grav => 'Gravure',
472 offs => 'Offset Lithography',
473 silk => 'Silkscreen',
474 flex => 'Flexography',
475 mpfs => 'Motion Picture Film Scanner', #5
476 mpfr => 'Motion Picture Film Recorder', #5
477 dmpc => 'Digital Motion Picture Camera', #5
478 dcpj => 'Digital Cinema Projector', #5
479 },
480 },
481 vued => 'ViewingCondDesc',
482 view => {
483 Name => 'ViewingConditions',
484 SubDirectory => {
485 TagTable => 'Image::ExifTool::ICC_Profile::ViewingConditions',
486 Validate => '$type eq "view"',
487 },
488 },
489 ciis => 'ColorimetricIntentImageState', #5
490 scoe => 'SceneColorimetryEstimates', #5
491 sape => 'SceneAppearanceEstimates', #5
492 fpce => 'FocalPlaneColorimetryEstimates', #5
493 rhoc => 'ReflectionHardcopyOrigColorimetry', #5
494 rpoc => 'ReflectionPrintOutputColorimetry', #5
495 psid => { #5
496 Name => 'ProfileSequenceIdentifier',
497 Binary => 1,
498 },
499 B2D0 => { Name => 'BToD0', Binary => 1 }, #5
500 B2D1 => { Name => 'BToD1', Binary => 1 }, #5
501 B2D2 => { Name => 'BToD2', Binary => 1 }, #5
502 B2D3 => { Name => 'BToD3', Binary => 1 }, #5
503 D2B0 => { Name => 'DToB0', Binary => 1 }, #5
504 D2B1 => { Name => 'DToB1', Binary => 1 }, #5
505 D2B2 => { Name => 'DToB2', Binary => 1 }, #5
506 D2B3 => { Name => 'DToB3', Binary => 1 }, #5
507 rig0 => { #5
508 Name => 'PerceptualRenderingIntentGamut',
509 PrintConv => {
510 prmg => 'Perceptual Reference Medium Gamut',
511 },
512 },
513 rig2 => { #5
514 Name => 'SaturationRenderingIntentGamut',
515 PrintConv => {
516 prmg => 'Perceptual Reference Medium Gamut',
517 },
518 },
519 meta => { #5 (EVENTUALLY DECODE THIS ONCE WE HAVE A SAMPLE!!)
520 Name => 'Metadata',
521 SubDirectory => {
522 TagTable => 'Image::ExifTool::ICC_Profile::Metadata',
523 Validate => '$type eq "meta"',
524 },
525 },
526
527 # ColorSync custom tags (ref 3)
528 psvm => 'PS2CRDVMSize',
529 vcgt => 'VideoCardGamma',
530 mmod => 'MakeAndModel',
531 dscm => 'ProfileDescriptionML',
532 ndin => 'NativeDisplayInfo',
533
534 # Microsoft custom tags (ref http://msdn2.microsoft.com/en-us/library/ms536870.aspx)
535 MS00 => 'WCSProfiles',
536
537 psd3 => { #6
538 Name => 'PostScript2CRD3',
539 Binary => 1, # (NC)
540 },
541
542 # the following entry represents the ICC profile header, and doesn't
543 # exist as a tag in the directory. It is only in this table to provide
544 # a link so ExifTool can locate the header tags
545 Header => {
546 Name => 'ProfileHeader',
547 SubDirectory => {
548 TagTable => 'Image::ExifTool::ICC_Profile::Header',
549 },
550 },
551);
552
553# ICC profile header definition
554%Image::ExifTool::ICC_Profile::Header = (
555 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
556 GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-header', 2 => 'Image' },
557 4 => {
558 Name => 'ProfileCMMType',
559 Format => 'string[4]',
560 SeparateTable => 'ManuSig',
561 PrintConv => \%manuSig,
562 },
563 8 => {
564 Name => 'ProfileVersion',
565 Format => 'int16s',
566 PrintConv => '($val >> 8).".".(($val & 0xf0)>>4).".".($val & 0x0f)',
567 },
568 12 => {
569 Name => 'ProfileClass',
570 Format => 'string[4]',
571 PrintConv => \%profileClass,
572 },
573 16 => {
574 Name => 'ColorSpaceData',
575 Format => 'string[4]',
576 },
577 20 => {
578 Name => 'ProfileConnectionSpace',
579 Format => 'string[4]',
580 },
581 24 => {
582 Name => 'ProfileDateTime',
583 Groups => { 2 => 'Time' },
584 Format => 'int16u[6]',
585 ValueConv => 'sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d",split(" ",$val));',
586 PrintConv => '$self->ConvertDateTime($val)',
587 },
588 36 => {
589 Name => 'ProfileFileSignature',
590 Format => 'string[4]',
591 },
592 40 => {
593 Name => 'PrimaryPlatform',
594 Format => 'string[4]',
595 PrintConv => {
596 'APPL' => 'Apple Computer Inc.',
597 'MSFT' => 'Microsoft Corporation',
598 'SGI ' => 'Silicon Graphics Inc.',
599 'SUNW' => 'Sun Microsystems Inc.',
600 'TGNT' => 'Taligent Inc.',
601 },
602 },
603 44 => {
604 Name => 'CMMFlags',
605 Format => 'int32u',
606 PrintConv => q[
607 ($val & 0x01 ? "Embedded, " : "Not Embedded, ") .
608 ($val & 0x02 ? "Not Independent" : "Independent")
609 ],
610 },
611 48 => {
612 Name => 'DeviceManufacturer',
613 Format => 'string[4]',
614 SeparateTable => 'ManuSig',
615 PrintConv => \%manuSig,
616 },
617 52 => {
618 Name => 'DeviceModel',
619 Format => 'string[4]',
620 # ROMM = Reference Output Medium Metric
621 },
622 56 => {
623 Name => 'DeviceAttributes',
624 Format => 'int32u[2]',
625 PrintConv => q[
626 my @v = split ' ', $val;
627 ($v[1] & 0x01 ? "Transparency, " : "Reflective, ") .
628 ($v[1] & 0x02 ? "Matte, " : "Glossy, ") .
629 ($v[1] & 0x04 ? "Negative, " : "Positive, ") .
630 ($v[1] & 0x08 ? "B&W" : "Color");
631 ],
632 },
633 64 => {
634 Name => 'RenderingIntent',
635 Format => 'int32u',
636 PrintConv => {
637 0 => 'Perceptual',
638 1 => 'Media-Relative Colorimetric',
639 2 => 'Saturation',
640 3 => 'ICC-Absolute Colorimetric',
641 },
642 },
643 68 => {
644 Name => 'ConnectionSpaceIlluminant',
645 Format => 'fixed32s[3]', # xyz
646 },
647 80 => {
648 Name => 'ProfileCreator',
649 Format => 'string[4]',
650 SeparateTable => 'ManuSig',
651 PrintConv => \%manuSig,
652 },
653 84 => {
654 Name => 'ProfileID',
655 Format => 'int8u[16]',
656 PrintConv => 'Image::ExifTool::ICC_Profile::HexID($val)',
657 },
658);
659
660# viewingConditionsType (view) definition
661%Image::ExifTool::ICC_Profile::ViewingConditions = (
662 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
663 GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-view', 2 => 'Image' },
664 8 => {
665 Name => 'ViewingCondIlluminant',
666 Format => 'fixed32s[3]', # xyz
667 },
668 20 => {
669 Name => 'ViewingCondSurround',
670 Format => 'fixed32s[3]', # xyz
671 },
672 32 => {
673 Name => 'ViewingCondIlluminantType',
674 Format => 'int32u',
675 PrintConv => \%illuminantType,
676 },
677);
678
679# measurementType (meas) definition
680%Image::ExifTool::ICC_Profile::Measurement = (
681 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
682 GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-meas', 2 => 'Image' },
683 8 => {
684 Name => 'MeasurementObserver',
685 Format => 'int32u',
686 PrintConv => {
687 1 => 'CIE 1931',
688 2 => 'CIE 1964',
689 },
690 },
691 12 => {
692 Name => 'MeasurementBacking',
693 Format => 'fixed32s[3]', # xyz
694 },
695 24 => {
696 Name => 'MeasurementGeometry',
697 Format => 'int32u',
698 PrintConv => {
699 0 => 'Unknown',
700 1 => '0/45 or 45/0',
701 2 => '0/d or d/0',
702 },
703 },
704 28 => {
705 Name => 'MeasurementFlare',
706 Format => 'fixed32u',
707 PrintConv => '$val*100 . "%"', # change into a percent
708 },
709 32 => {
710 Name => 'MeasurementIlluminant',
711 Format => 'int32u',
712 PrintConv => \%illuminantType,
713 },
714);
715
716# chromaticity (chrm) definition
717%Image::ExifTool::ICC_Profile::Chromaticity = (
718 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
719 GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-chrm', 2 => 'Image' },
720 8 => {
721 Name => 'ChromaticityChannels',
722 Format => 'int16u',
723 },
724 10 => {
725 Name => 'ChromaticityColorant',
726 Format => 'int16u',
727 PrintConv => {
728 1 => 'ITU-R BT.709',
729 2 => 'SMPTE RP145-1994',
730 3 => 'EBU Tech.3213-E',
731 4 => 'P22',
732 },
733 },
734 # include definitions for 4 channels -- if there are
735 # fewer then the ProcessBinaryData logic won't print them.
736 # If there are more, oh well.
737 12 => {
738 Name => 'ChromaticityChannel1',
739 Format => 'fixed32u[2]',
740 },
741 20 => {
742 Name => 'ChromaticityChannel2',
743 Format => 'fixed32u[2]',
744 },
745 28 => {
746 Name => 'ChromaticityChannel3',
747 Format => 'fixed32u[2]',
748 },
749 36 => {
750 Name => 'ChromaticityChannel4',
751 Format => 'fixed32u[2]',
752 },
753);
754
755# colorantTable (clrt) definition
756%Image::ExifTool::ICC_Profile::ColorantTable = (
757 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
758 GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-clrt', 2 => 'Image' },
759 8 => {
760 Name => 'ColorantCount',
761 Format => 'int32u',
762 },
763 # include definitions for 3 colorants -- if there are
764 # fewer then the ProcessBinaryData logic won't print them.
765 # If there are more, oh well.
766 12 => {
767 Name => 'Colorant1Name',
768 Format => 'string[32]',
769 },
770 44 => {
771 Name => 'Colorant1Coordinates',
772 Format => 'int16u[3]',
773 },
774 50 => {
775 Name => 'Colorant2Name',
776 Format => 'string[32]',
777 },
778 82 => {
779 Name => 'Colorant2Coordinates',
780 Format => 'int16u[3]',
781 },
782 88 => {
783 Name => 'Colorant3Name',
784 Format => 'string[32]',
785 },
786 120 => {
787 Name => 'Colorant3Coordinates',
788 Format => 'int16u[3]',
789 },
790);
791
792# metadata (meta) tags
793%Image::ExifTool::ICC_Profile::Metadata = (
794 PROCESS_PROC => \&ProcessMetadata,
795 GROUPS => { 0 => 'ICC_Profile', 1 => 'ICC-meta', 2 => 'Image' },
796 VARS => { NO_ID => 1 },
797 NOTES => q{
798 Only these few tags have been pre-defined, but ExifTool will extract any
799 Metadata tags that exist.
800 },
801 ManufacturerName => { },
802 MediaColor => { },
803 MediaWeight => { },
804);
805
806#------------------------------------------------------------------------------
807# Print ICC Profile ID in hex
808# Inputs: 1) string of numbers
809# Returns: string of hex digits
810sub HexID($)
811{
812 my $val = shift;
813 my @vals = split(' ', $val);
814 # return a simple zero if no MD5 done
815 return 0 unless grep(!/^0/, @vals);
816 $val = '';
817 foreach (@vals) { $val .= sprintf("%.2x",$_); }
818 return $val;
819}
820
821#------------------------------------------------------------------------------
822# Get formatted value from ICC tag (which has the type embedded)
823# Inputs: 0) data reference, 1) offset to tag data, 2) tag data size
824# Returns: Formatted value or undefined if format not supported
825# Notes: The following types are handled by BinaryTables:
826# chromaticityType, colorantTableType, measurementType, viewingConditionsType
827# The following types are currently not handled (most are large tables):
828# curveType, lut16Type, lut8Type, lutAtoBType, lutBtoAType, namedColor2Type,
829# parametricCurveType, profileSeqDescType, responseCurveSet16Type
830# The multiLocalizedUnicodeType must be handled by the calling routine.
831sub FormatICCTag($$$)
832{
833 my ($dataPt, $offset, $size) = @_;
834
835 my $type;
836 if ($size >= 8) {
837 # get data type from start of tag data
838 $type = substr($$dataPt, $offset, 4);
839 } else {
840 $type = 'err';
841 }
842 # colorantOrderType
843 if ($type eq 'clro' and $size >= 12) {
844 my $num = Get32u($dataPt, $offset+8);
845 if ($size >= $num + 12) {
846 my $pos = $offset + 12;
847 return join(' ',unpack("x$pos c$num", $$dataPt));
848 }
849 }
850 # dataType
851 if ($type eq 'data' and $size >= 12) {
852 my $form = Get32u($dataPt, $offset+8);
853 # format 0 is ASCII data
854 $form == 0 and return substr($$dataPt, $offset+12, $size-12);
855 # binary data and other data types treat as binary (ie. don't format)
856 }
857 # dateTimeType
858 if ($type eq 'dtim' and $size >= 20) {
859 return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:%.2d",
860 Get16u($dataPt, $offset+8), Get16u($dataPt, $offset+10),
861 Get16u($dataPt, $offset+12), Get16u($dataPt, $offset+14),
862 Get16u($dataPt, $offset+16), Get16u($dataPt, $offset+18));
863 }
864 # s15Fixed16ArrayType
865 if ($type eq 'sf32') {
866 return ReadValue($dataPt,$offset+8,'fixed32s',($size-8)/4,$size-8);
867 }
868 # signatureType
869 if ($type eq 'sig ' and $size >= 12) {
870 return substr($$dataPt, $offset+8, 4);
871 }
872 # textType
873 $type eq 'text' and return substr($$dataPt, $offset+8, $size-8);
874 # textDescriptionType (ref 2, replaced by multiLocalizedUnicodeType)
875 if ($type eq 'desc' and $size >= 12) {
876 my $len = Get32u($dataPt, $offset+8);
877 if ($size >= $len + 12) {
878 my $str = substr($$dataPt, $offset+12, $len);
879 $str =~ s/\0.*//s; # truncate at null terminator
880 return $str;
881 }
882 }
883 # u16Fixed16ArrayType
884 if ($type eq 'uf32') {
885 return ReadValue($dataPt,$offset+8,'fixed32u',($size-8)/4,$size-8);
886 }
887 # uInt32ArrayType
888 if ($type eq 'ui32') {
889 return ReadValue($dataPt,$offset+8,'int32u',($size-8)/4,$size-8);
890 }
891 # uInt64ArrayType
892 if ($type eq 'ui64') {
893 return ReadValue($dataPt,$offset+8,'int64u',($size-8)/8,$size-8);
894 }
895 # uInt8ArrayType
896 if ($type eq 'ui08') {
897 return ReadValue($dataPt,$offset+8,'int8u',$size-8,$size-8);
898 }
899 # XYZType
900 if ($type eq 'XYZ ') {
901 my $str = '';
902 my $pos;
903 for ($pos=8; $pos+12<=$size; $pos+=12) {
904 $str and $str .= ', ';
905 $str .= ReadValue($dataPt,$offset+$pos,'fixed32s',3,$size-$pos);
906 }
907 return $str;
908 }
909 return undef; # data type is not supported
910}
911
912#------------------------------------------------------------------------------
913# Process ICC metadata record (ref 5) (UNTESTED!)
914# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
915# Returns: 1 on success
916sub ProcessMetadata($$$)
917{
918 my ($et, $dirInfo, $tagTablePtr) = @_;
919 my $dataPt = $$dirInfo{DataPt};
920 my $dirStart = $$dirInfo{DirStart};
921 my $dirLen = $$dirInfo{DirLen};
922 my $dirEnd = $dirStart + $dirLen;
923
924 if ($dirLen < 16 or substr($$dataPt, $dirStart, 4) ne 'dict') {
925 $et->Warn('Invalid ICC meta dictionary');
926 return 0;
927 }
928 my $num = Get32u($dataPt, $dirStart + 8);
929 $et->VerboseDir('Metadata', $num);
930 my $size = Get32u($dataPt, $dirStart + 12);
931 $size < 16 and $et->Warn('Invalid ICC meta record size'), return 0;
932 # NOTE: In the example the minimum offset is 20,
933 # but this doesn't jive with the table (both in ref 5)
934 my $minPtr = 16 + $size * $num;
935 my $index;
936 for ($index=0; $index<$num; ++$index) {
937 my $entry = $dirStart + 16 + $size * $index;
938 if ($entry + $size > $dirEnd) {
939 $et->Warn('Truncated ICC meta dictionary');
940 last;
941 }
942 my $namePtr = Get32u($dataPt, $entry);
943 my $nameLen = Get32u($dataPt, $entry + 4);
944 my $valuePtr = Get32u($dataPt, $entry + 8);
945 my $valueLen = Get32u($dataPt, $entry + 16);
946 next unless $namePtr and $valuePtr; # ignore if offsets are zero
947 if ($namePtr < $minPtr or $namePtr + $nameLen > $dirLen or
948 $valuePtr < $minPtr or $valuePtr + $valueLen > $dirLen)
949 {
950 $et->Warn('Corrupted ICC meta dictionary');
951 last;
952 }
953 my $tag = substr($dataPt, $dirStart + $namePtr, $nameLen);
954 my $val = substr($dataPt, $dirStart + $valuePtr, $valueLen);
955 $tag = $et->Decode($tag, 'UTF16', 'MM', 'UTF8');
956 $val = $et->Decode($val, 'UTF16', 'MM');
957 # generate tagInfo if it doesn't exist
958 unless ($$tagTablePtr{$tag}) {
959 my $name = ucfirst $tag;
960 $name =~ s/\s+(.)/\u$1/g;
961 $name =~ tr/-_a-zA-Z0-9//dc;
962 next unless length $name;
963 AddTagToTable($tagTablePtr, $tag, { Name => $name });
964 }
965 $et->HandleTag($tagTablePtr, $tag, $val);
966 }
967 return 1;
968}
969
970#------------------------------------------------------------------------------
971# Write ICC profile file
972# Inputs: 0) ExifTool object reference, 1) Reference to directory information
973# Returns: 1 on success, 0 if this wasn't a valid ICC file,
974# or -1 if a write error occurred
975sub WriteICC($$)
976{
977 my ($et, $dirInfo) = @_;
978 # first make sure this is a valid ICC file (or no file at all)
979 my $raf = $$dirInfo{RAF};
980 my $buff;
981 return 0 if $raf->Read($buff, 24) and ValidateICC(\$buff);
982 # now write the new ICC
983 $buff = WriteICC_Profile($et, $dirInfo);
984 if (defined $buff and length $buff) {
985 Write($$dirInfo{OutFile}, $buff) or return -1;
986 } else {
987 $et->Error('No ICC information to write');
988 }
989 return 1;
990}
991
992#------------------------------------------------------------------------------
993# Write ICC data as a block
994# Inputs: 0) ExifTool object reference, 1) source dirInfo reference,
995# 2) tag table reference
996# Returns: ICC data block (may be empty if no ICC data)
997# Notes: Increments ExifTool CHANGED flag if changed
998sub WriteICC_Profile($$;$)
999{
1000 my ($et, $dirInfo, $tagTablePtr) = @_;
1001 $et or return 1; # allow dummy access
1002 my $dirName = $$dirInfo{DirName} || 'ICC_Profile';
1003 # (don't write AsShotICCProfile or CurrentICCProfile here)
1004 return undef unless $dirName eq 'ICC_Profile';
1005 my $nvHash = $et->GetNewValueHash($Image::ExifTool::Extra{$dirName});
1006 my $val = $et->GetNewValue($nvHash);
1007 $val = '' unless defined $val;
1008 return undef unless $et->IsOverwriting($nvHash, $val);
1009 ++$$et{CHANGED};
1010 return $val;
1011}
1012
1013#------------------------------------------------------------------------------
1014# Validate ICC data
1015# Inputs: 0) ICC data reference
1016# Returns: error string or undef on success
1017sub ValidateICC($)
1018{
1019 my $valPtr = shift;
1020 my $err;
1021 length($$valPtr) < 24 and return 'Invalid ICC profile';
1022 $profileClass{substr($$valPtr, 12, 4)} or $err = 'profile class';
1023 my $col = substr($$valPtr, 16, 4); # ColorSpaceData
1024 my $con = substr($$valPtr, 20, 4); # ConnectionSpace
1025 my $match = '(XYZ |Lab |Luv |YCbr|Yxy |RGB |GRAY|HSV |HLS |CMYK|CMY |[2-9A-F]CLR)';
1026 $col =~ /$match/ or $err = 'color space';
1027 $con =~ /$match/ or $err = 'connection space';
1028 return $err ? "Invalid ICC profile (bad $err)" : undef;
1029}
1030
1031#------------------------------------------------------------------------------
1032# Process ICC profile file
1033# Inputs: 0) ExifTool object reference, 1) Reference to directory information
1034# Returns: 1 if this was an ICC file
1035sub ProcessICC($$)
1036{
1037 my ($et, $dirInfo) = @_;
1038 my $raf = $$dirInfo{RAF};
1039 my $buff;
1040 $raf->Read($buff, 24) == 24 or return 0;
1041 # check to see if this is a valid ICC profile file
1042 return 0 if ValidateICC(\$buff);
1043 $et->SetFileType();
1044 # read the profile
1045 my $size = unpack('N', $buff);
1046 if ($size < 128 or $size & 0x80000000) {
1047 $et->Error("Bad ICC Profile length ($size)");
1048 return 1;
1049 }
1050 $raf->Seek(0, 0);
1051 unless ($raf->Read($buff, $size) == $size) {
1052 $et->Error('Truncated ICC profile');
1053 return 1;
1054 }
1055 my %dirInfo = (
1056 DataPt => \$buff,
1057 DataLen => $size,
1058 DirStart => 0,
1059 DirLen => $size,
1060 );
1061 my $tagTablePtr = GetTagTable('Image::ExifTool::ICC_Profile::Main');
1062 return ProcessICC_Profile($et, \%dirInfo, $tagTablePtr);
1063}
1064
1065#------------------------------------------------------------------------------
1066# Process ICC_Profile APP13 record
1067# Inputs: 0) ExifTool object reference, 1) Reference to directory information
1068# 2) Tag table reference (undefined to read ICC file)
1069# Returns: 1 on success
1070sub ProcessICC_Profile($$$)
1071{
1072 my ($et, $dirInfo, $tagTablePtr) = @_;
1073 my $dataPt = $$dirInfo{DataPt};
1074 my $dirStart = $$dirInfo{DirStart} || 0;
1075 my $dirLen = $$dirInfo{DirLen};
1076 my $verbose = $et->Options('Verbose');
1077
1078 return 0 if $dirLen < 4;
1079
1080 # extract binary ICC_Profile data block if binary mode or requested
1081 if ((($$et{TAGS_FROM_FILE} and not $$et{EXCL_TAG_LOOKUP}{icc_profile}) or
1082 $$et{REQ_TAG_LOOKUP}{icc_profile}) and
1083 # (don't extract from AsShotICCProfile or CurrentICCProfile)
1084 (not $$dirInfo{Name} or $$dirInfo{Name} eq 'ICC_Profile'))
1085 {
1086 $et->FoundTag('ICC_Profile', substr($$dataPt, $dirStart, $dirLen));
1087 }
1088
1089 SetByteOrder('MM'); # ICC_Profile is always big-endian
1090
1091 # check length of table
1092 my $len = Get32u($dataPt, $dirStart);
1093 if ($len != $dirLen or $len < 128) {
1094 $et->Warn("Bad length ICC_Profile (length $len)");
1095 return 0 if $len < 128 or $dirLen < $len;
1096 }
1097 my $pos = $dirStart + 128; # position at start of table
1098 my $numEntries = Get32u($dataPt, $pos);
1099 if ($numEntries < 1 or $numEntries >= 0x100
1100 or $numEntries * 12 + 132 > $dirLen)
1101 {
1102 $et->Warn("Bad ICC_Profile table ($numEntries entries)");
1103 return 0;
1104 }
1105
1106 if ($verbose) {
1107 $et->VerboseDir('ICC_Profile', $numEntries, $dirLen);
1108 my $fakeInfo = { Name=>'ProfileHeader', SubDirectory => { } };
1109 $et->VerboseInfo(undef, $fakeInfo);
1110 }
1111 # increment ICC dir count
1112 my $dirCount = $$et{DIR_COUNT}{ICC} = ($$et{DIR_COUNT}{ICC} || 0) + 1;
1113 $$et{SET_GROUP1} = '+' . $dirCount if $dirCount > 1;
1114 # process the header block
1115 my %subdirInfo = (
1116 Name => 'ProfileHeader',
1117 DataPt => $dataPt,
1118 DataLen => $$dirInfo{DataLen},
1119 DirStart => $dirStart,
1120 DirLen => 128,
1121 Parent => $$dirInfo{DirName},
1122 DirName => 'Header',
1123 );
1124 my $newTagTable = GetTagTable('Image::ExifTool::ICC_Profile::Header');
1125 $et->ProcessDirectory(\%subdirInfo, $newTagTable);
1126
1127 $pos += 4; # skip item count
1128 my $index;
1129 for ($index=0; $index<$numEntries; ++$index) {
1130 my $tagID = substr($$dataPt, $pos, 4);
1131 my $offset = Get32u($dataPt, $pos + 4);
1132 my $size = Get32u($dataPt, $pos + 8);
1133 $pos += 12;
1134 my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID);
1135 # unknown tags aren't generated automatically by GetTagInfo()
1136 # if the tagID's aren't numeric, so we must do this manually:
1137 if (not $tagInfo and $$et{OPTIONS}{Unknown}) {
1138 $tagInfo = { Unknown => 1 };
1139 AddTagToTable($tagTablePtr, $tagID, $tagInfo);
1140 }
1141 next unless defined $tagInfo;
1142
1143 if ($offset + $size > $dirLen) {
1144 $et->Warn("Bad ICC_Profile table (truncated)");
1145 last;
1146 }
1147 my $valuePtr = $dirStart + $offset;
1148
1149 my $subdir = $$tagInfo{SubDirectory};
1150 # format the value unless this is a subdirectory
1151 my ($value, $fmt);
1152 if ($size > 4) {
1153 $fmt = substr($$dataPt, $valuePtr, 4);
1154 # handle multiLocalizedUnicodeType
1155 if ($fmt eq 'mluc' and not $subdir) {
1156 next if $size < 28;
1157 my $count = Get32u($dataPt, $valuePtr + 8);
1158 my $recLen = Get32u($dataPt, $valuePtr + 12);
1159 next if $recLen < 12;
1160 my $i;
1161 for ($i=0; $i<$count; ++$i) {
1162 my $recPos = $valuePtr + 16 + $i * $recLen;
1163 last if $recPos + $recLen > $valuePtr + $size;
1164 my $lang = substr($$dataPt, $recPos, 4);
1165 my $langInfo;
1166 # validate language code and change to standard case (just in case)
1167 if ($lang =~ s/^([a-z]{2})([A-Z]{2})$/\L$1-\U$2/i and $lang ne 'en-US') {
1168 $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang);
1169 }
1170 my $strLen = Get32u($dataPt, $recPos + 4);
1171 my $strPos = Get32u($dataPt, $recPos + 8);
1172 last if $strPos + $strLen > $size;
1173 my $str = substr($$dataPt, $valuePtr + $strPos, $strLen);
1174 $str = $et->Decode($str, 'UTF16');
1175 $et->HandleTag($tagTablePtr, $tagID, $str,
1176 TagInfo => $langInfo || $tagInfo,
1177 Table => $tagTablePtr,
1178 Index => $index,
1179 Value => $str,
1180 DataPt => $dataPt,
1181 Size => $strLen,
1182 Start => $valuePtr + $strPos,
1183 Format => "type '${fmt}'",
1184 );
1185 }
1186 $et->Warn("Corrupted $$tagInfo{Name} data") if $i < $count;
1187 next;
1188 }
1189 } else {
1190 $fmt = 'err ';
1191 }
1192 $value = FormatICCTag($dataPt, $valuePtr, $size) unless $subdir;
1193 $verbose and $et->VerboseInfo($tagID, $tagInfo,
1194 Table => $tagTablePtr,
1195 Index => $index,
1196 Value => $value,
1197 DataPt => $dataPt,
1198 Size => $size,
1199 Start => $valuePtr,
1200 Format => "type '${fmt}'",
1201 );
1202 if ($subdir) {
1203 my $name = $$tagInfo{Name};
1204 undef $newTagTable;
1205 if ($$subdir{TagTable}) {
1206 $newTagTable = GetTagTable($$subdir{TagTable});
1207 unless ($newTagTable) {
1208 warn "Unknown tag table $$subdir{TagTable}\n";
1209 next;
1210 }
1211 } else {
1212 warn "Must specify TagTable for SubDirectory $name\n";
1213 next;
1214 }
1215 %subdirInfo = (
1216 Name => $name,
1217 DataPt => $dataPt,
1218 DataPos => $$dirInfo{DataPos},
1219 DataLen => $$dirInfo{DataLen},
1220 DirStart => $valuePtr,
1221 DirLen => $size,
1222 DirName => $name,
1223 Parent => $$dirInfo{DirName},
1224 );
1225 my $type = substr($$dataPt, $valuePtr, 4);
1226 #### eval Validate ($type)
1227 if (defined $$subdir{Validate} and not eval $$subdir{Validate}) {
1228 $et->Warn("Invalid ICC $name data");
1229 } else {
1230 $et->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc});
1231 }
1232 } elsif (defined $value) {
1233 $et->FoundTag($tagInfo, $value);
1234 } else {
1235 $value = substr($$dataPt, $valuePtr, $size);
1236 # treat unsupported formats as binary data
1237 $$tagInfo{ValueConv} = '\$val' unless defined $$tagInfo{ValueConv};
1238 $et->FoundTag($tagInfo, $value);
1239 }
1240 }
1241 delete $$et{SET_GROUP1};
1242 return 1;
1243}
1244
1245
12461; # end
1247
1248
1249__END__
1250
1251=head1 NAME
1252
1253Image::ExifTool::ICC_Profile - Read ICC Profile meta information
1254
1255=head1 SYNOPSIS
1256
1257This module is loaded automatically by Image::ExifTool when required.
1258
1259=head1 DESCRIPTION
1260
1261This module contains the definitions to read information from ICC profiles.
1262ICC (International Color Consortium) profiles are used to translate color
1263data created on one device into another device's native color space.
1264
1265=head1 AUTHOR
1266
1267Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
1268
1269This library is free software; you can redistribute it and/or modify it
1270under the same terms as Perl itself.
1271
1272=head1 REFERENCES
1273
1274=over 4
1275
1276=item L<http://www.color.org/icc_specs2.html>
1277
1278=item L<http://developer.apple.com/documentation/GraphicsImaging/Reference/ColorSync_Manager/ColorSync_Manager.pdf>
1279
1280=back
1281
1282=head1 SEE ALSO
1283
1284L<Image::ExifTool::TagNames/ICC_Profile Tags>,
1285L<Image::ExifTool(3pm)|Image::ExifTool>
1286
1287=cut
Note: See TracBrowser for help on using the repository browser.