File Coverage

blib/lib/Image/ExifTool/JPEG.pm
Criterion Covered Total %
statement 21 32 65.6
branch 2 8 25.0
condition n/a
subroutine 4 5 80.0
pod 0 2 0.0
total 27 47 57.4


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             # File: JPEG.pm
3             #
4             # Description: Definitions for uncommon JPEG segments
5             #
6             # Revisions: 10/06/2006 - P. Harvey Created
7             #------------------------------------------------------------------------------
8              
9             package Image::ExifTool::JPEG;
10 11     11   112 use strict;
  11         22  
  11         376  
11 11     11   62 use vars qw($VERSION);
  11         19  
  11         474  
12 11     11   55 use Image::ExifTool qw(:DataAccess :Utils);
  11         20  
  11         17720  
13              
14             $VERSION = '1.33';
15              
16             sub ProcessOcad($$$);
17             sub ProcessJPEG_HDR($$$);
18              
19             # (most of the tags in this table are for documentation purposes only)
20             %Image::ExifTool::JPEG::Main = (
21             NOTES => q{
22             This table lists information extracted by ExifTool from JPEG images. See
23             L for the JPEG specification.
24             },
25             APP0 => [{
26             Name => 'JFIF',
27             Condition => '$$valPt =~ /^JFIF\0/',
28             SubDirectory => { TagTable => 'Image::ExifTool::JFIF::Main' },
29             }, {
30             Name => 'JFXX',
31             Condition => '$$valPt =~ /^JFXX\0\x10/',
32             SubDirectory => { TagTable => 'Image::ExifTool::JFIF::Extension' },
33             }, {
34             Name => 'CIFF',
35             Condition => '$$valPt =~ /^(II|MM).{4}HEAPJPGM/s',
36             SubDirectory => { TagTable => 'Image::ExifTool::CanonRaw::Main' },
37             }, {
38             Name => 'AVI1',
39             Condition => '$$valPt =~ /^AVI1/',
40             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::AVI1' },
41             }, {
42             Name => 'Ocad',
43             Condition => '$$valPt =~ /^Ocad/',
44             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::Ocad' },
45             }],
46             APP1 => [{
47             Name => 'EXIF',
48             Condition => '$$valPt =~ /^Exif\0/',
49             SubDirectory => { TagTable => 'Image::ExifTool::Exif::Main' },
50             }, {
51             Name => 'ExtendedXMP',
52             Condition => '$$valPt =~ m{^http://ns.adobe.com/xmp/extension/\0}',
53             SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' },
54             }, {
55             Name => 'XMP',
56             Condition => '$$valPt =~ /^http/ or $$valPt =~ /
57             SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' },
58             }, {
59             Name => 'QVCI',
60             Condition => '$$valPt =~ /^QVCI\0/',
61             SubDirectory => { TagTable => 'Image::ExifTool::Casio::QVCI' },
62             }, {
63             Name => 'FLIR',
64             Condition => '$$valPt =~ /^FLIR\0/',
65             SubDirectory => { TagTable => 'Image::ExifTool::FLIR::FFF' },
66             }, {
67             Name => 'RawThermalImage', # (from Parrot Bebop-Pro Thermal drone)
68             Condition => '$$valPt =~ /^PARROT\0(II\x2a\0|MM\0\x2a)/',
69             Groups => { 0 => 'APP1', 1 => 'Parrot', 2 => 'Preview' },
70             Notes => 'thermal image from Parrot Bebop-Pro Thermal drone',
71             RawConv => 'substr($val, 7)',
72             Binary => 1,
73             }],
74             APP2 => [{
75             Name => 'ICC_Profile',
76             Condition => '$$valPt =~ /^ICC_PROFILE\0/',
77             SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
78             }, {
79             Name => 'FPXR',
80             Condition => '$$valPt =~ /^FPXR\0/',
81             SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::Main' },
82             }, {
83             Name => 'MPF',
84             Condition => '$$valPt =~ /^MPF\0/',
85             SubDirectory => { TagTable => 'Image::ExifTool::MPF::Main' },
86             }, {
87             Name => 'PreviewImage',
88             Condition => '$$valPt =~ /^(|QVGA\0|BGTH)\xff\xd8\xff\xdb/',
89             Notes => 'Samsung APP2 preview image', # (Samsung/GoPro="", BenQ="QVGA\0", Digilife="BGTH")
90             }],
91             APP3 => [{
92             Name => 'Meta',
93             Condition => '$$valPt =~ /^(Meta|META|Exif)\0\0/',
94             SubDirectory => { TagTable => 'Image::ExifTool::Kodak::Meta' },
95             }, {
96             Name => 'Stim',
97             Condition => '$$valPt =~ /^Stim\0/',
98             SubDirectory => { TagTable => 'Image::ExifTool::Stim::Main' },
99             }, {
100             Name => 'JPS',
101             Condition => '$$valPt =~ /^_JPSJPS_/',
102             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::JPS' },
103             }, {
104             Name => 'ThermalData', # (written by DJI FLIR models)
105             Condition => '$$self{Make} eq "DJI"',
106             Notes => 'DJI raw thermal data',
107             Groups => { 0 => 'APP3', 1 => 'DJI', 2 => 'Image' },
108             Binary => 1,
109             }, {
110             Name => 'PreviewImage', # (written by HP R837 and Samsung S1060)
111             Condition => '$$valPt =~ /^\xff\xd8\xff\xdb/',
112             Notes => 'Samsung/HP preview image', # (Samsung, HP, BenQ)
113             }],
114             APP4 => [{
115             Name => 'Scalado',
116             Condition => '$$valPt =~ /^SCALADO\0/',
117             SubDirectory => { TagTable => 'Image::ExifTool::Scalado::Main' },
118             }, {
119             Name => 'FPXR', # (non-standard location written by some HP models)
120             Condition => '$$valPt =~ /^FPXR\0/',
121             SubDirectory => { TagTable => 'Image::ExifTool::FlashPix::Main' },
122             }, {
123             Name => 'ThermalParams', # (written by DJI FLIR models)
124             Condition => '$$self{Make} eq "DJI" and $$valPt =~ /^\xaa\x55\x12\x06/',
125             SubDirectory => { TagTable => 'Image::ExifTool::DJI::ThermalParams' },
126             }, {
127             Name => 'PreviewImage', # (eg. Samsung S1060)
128             Notes => 'continued from APP3',
129             }],
130             APP5 => [{
131             Name => 'RMETA',
132             Condition => '$$valPt =~ /^RMETA\0/',
133             SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::RMETA' },
134             }, {
135             Name => 'SamsungUniqueID',
136             Condition => '$$valPt =~ /ssuniqueid\0/',
137             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::APP5' },
138             }, {
139             Name => 'ThermalCalibration', # (written by DJI FLIR models)
140             Condition => '$$self{Make} eq "DJI"',
141             Notes => 'DJI thermal calibration data',
142             Groups => { 0 => 'APP5', 1 => 'DJI', 2 => 'Image' },
143             Binary => 1,
144             }, {
145             Name => 'PreviewImage', # (eg. BenQ DC E1050)
146             Notes => 'continued from APP4',
147             }],
148             APP6 => [{
149             Name => 'EPPIM',
150             Condition => '$$valPt =~ /^EPPIM\0/',
151             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::EPPIM' },
152             }, {
153             Name => 'NITF',
154             Condition => '$$valPt =~ /^NTIF\0/',
155             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::NITF' },
156             }, {
157             Name => 'HP_TDHD', # (written by R837)
158             Condition => '$$valPt =~ /^TDHD\x01\0\0\0/',
159             SubDirectory => { TagTable => 'Image::ExifTool::HP::TDHD' },
160             }, {
161             Name => 'GoPro',
162             Condition => '$$valPt =~ /^GoPro\0/',
163             SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
164             # also seen Motorola APP6 "MMIMETA\0", with sub-types: AL3A,ALED,MMI0,MOTD,QC3A
165             }, {
166             Name => 'DJI_DTAT', # (written by ZH20T)
167             Condition => '$$valPt =~ /^DTAT\0\0.\{/s',
168             Groups => { 0 => 'APP6', 1 => 'DJI' },
169             Notes => 'DJI Thermal Analysis Tool record',
170             ValueConv => 'substr($val,7)',
171             }],
172             APP7 => [{
173             Name => 'Pentax',
174             Condition => '$$valPt =~ /^PENTAX \0/',
175             SubDirectory => { TagTable => 'Image::ExifTool::Pentax::Main' },
176             }, {
177             Name => 'Huawei',
178             Condition => '$$valPt =~ /^HUAWEI\0\0/',
179             SubDirectory => { TagTable => 'Image::ExifTool::Unknown::Main' },
180             }, {
181             Name => 'Qualcomm',
182             Condition => '$$valPt =~ /^\x1aQualcomm Camera Attributes/',
183             SubDirectory => { TagTable => 'Image::ExifTool::Qualcomm::Main' },
184             }],
185             APP8 => {
186             Name => 'SPIFF',
187             Condition => '$$valPt =~ /^SPIFF\0/',
188             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::SPIFF' },
189             },
190             APP9 => {
191             Name => 'MediaJukebox',
192             Condition => '$$valPt =~ /^Media Jukebox\0/',
193             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::MediaJukebox' },
194             },
195             APP10 => {
196             Name => 'Comment',
197             Condition => '$$valPt =~ /^UNICODE\0/',
198             Notes => 'PhotoStudio Unicode comment',
199             },
200             APP11 => [{
201             Name => 'JPEG-HDR',
202             Condition => '$$valPt =~ /^HDR_RI /',
203             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::HDR' },
204             },{
205             Name => 'JUMBF',
206             Condition => '$$valPt =~ /^JP/',
207             SubDirectory => { TagTable => 'Image::ExifTool::Jpeg2000::Main' },
208             }],
209             APP12 => [{
210             Name => 'PictureInfo',
211             Condition => '$$valPt =~ /(\[picture info\]|Type=)/',
212             SubDirectory => { TagTable => 'Image::ExifTool::APP12::PictureInfo' },
213             }, {
214             Name => 'Ducky',
215             Condition => '$$valPt =~ /^Ducky/',
216             SubDirectory => { TagTable => 'Image::ExifTool::APP12::Ducky' },
217             }],
218             APP13 => [{
219             Name => 'Photoshop',
220             Condition => '$$valPt =~ /^(Photoshop 3.0\0|Adobe_Photoshop2.5)/',
221             SubDirectory => { TagTable => 'Image::ExifTool::Photoshop::Main' },
222             }, {
223             Name => 'Adobe_CM',
224             Condition => '$$valPt =~ /^Adobe_CM/',
225             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::AdobeCM' },
226             }],
227             APP14 => {
228             Name => 'Adobe',
229             Condition => '$$valPt =~ /^Adobe/',
230             Writable => 2, # (for docs only)
231             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::Adobe' },
232             },
233             APP15 => {
234             Name => 'GraphicConverter',
235             Condition => '$$valPt =~ /^Q\s*(\d+)/',
236             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::GraphConv' },
237             },
238             # APP15 - Also unknown "TEXT\0" segment stored by Casio/FujiFilm
239             COM => {
240             Name => 'Comment',
241             # note: flag as writable for documentation, but it won't show up
242             # in the TagLookup as writable because there is no WRITE_PROC
243             Writable => 2,
244             },
245             SOF => {
246             Name => 'StartOfFrame',
247             SubDirectory => { TagTable => 'Image::ExifTool::JPEG::SOF' },
248             },
249             DQT => {
250             Name => 'DefineQuantizationTable',
251             Notes => 'used to calculate the Extra JPEGDigest tag value',
252             },
253             Trailer => [{
254             Name => 'AFCP',
255             Condition => '$$valPt =~ /AXS(!|\*).{8}$/s',
256             SubDirectory => { TagTable => 'Image::ExifTool::AFCP::Main' },
257             }, {
258             Name => 'CanonVRD',
259             Condition => '$$valPt =~ /CANON OPTIONAL DATA\0.{44}$/s',
260             SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Main' },
261             }, {
262             Name => 'FotoStation',
263             Condition => '$$valPt =~ /\xa1\xb2\xc3\xd4$/',
264             SubDirectory => { TagTable => 'Image::ExifTool::FotoStation::Main' },
265             }, {
266             Name => 'PhotoMechanic',
267             Condition => '$$valPt =~ /cbipcbbl$/',
268             SubDirectory => { TagTable => 'Image::ExifTool::PhotoMechanic::Main' },
269             }, {
270             Name => 'MIE',
271             Condition => q{
272             $$valPt =~ /~\0\x04\0zmie~\0\0\x06.{4}[\x10\x18]\x04$/s or
273             $$valPt =~ /~\0\x04\0zmie~\0\0\x0a.{8}[\x10\x18]\x08$/s
274             },
275             SubDirectory => { TagTable => 'Image::ExifTool::MIE::Main' },
276             }, {
277             Name => 'Samsung',
278             Condition => '$$valPt =~ /QDIOBS$/',
279             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::Trailer' },
280             }, {
281             Name => 'EmbeddedVideo',
282             Notes => 'extracted only when ExtractEmbedded option is used',
283             Condition => '$$valPt =~ /^.{4}ftyp/s',
284             }, {
285             Name => 'Insta360',
286             Condition => '$$valPt =~ /8db42d694ccc418790edff439fe026bf$/',
287             }, {
288             Name => 'NikonApp',
289             Condition => '$$valPt =~ m(\0{6}/NIKON APP$)',
290             Notes => 'contains editing information in XMP format',
291             }, {
292             Name => 'PreviewImage',
293             Condition => '$$valPt =~ /^\xff\xd8\xff/',
294             Writable => 2, # (for docs only)
295             }],
296             );
297              
298             # JPS APP3 segment (ref http://paulbourke.net/stereographics/stereoimage/)
299             %Image::ExifTool::JPEG::JPS = (
300             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
301             GROUPS => { 0 => 'APP3', 1 => 'JPS', 2 => 'Image' },
302             NOTES => 'Tags found in JPEG Stereo (JPS) images.',
303             0x0a => {
304             Name => 'JPSSeparation',
305             Format => 'int32u', # (just so we can look ahead to MediaType);
306             Notes => 'stereo only',
307             RawConv => q{
308             $$self{MediaType} = $val & 0xff;
309             return undef unless $$self{MediaType} == 1;
310             return(($val >> 24) & 0xff);
311             },
312             },
313             0x08 => {
314             Name => 'HdrLength',
315             Format => 'int16u',
316             Hidden => 1,
317             RawConv => '$$self{HdrLength} = $val; undef',
318             },
319             0x0b => {
320             Name => 'JPSFlags',
321             PrintConv => { BITMASK => {
322             0 => 'Half height',
323             1 => 'Half width',
324             2 => 'Left field first',
325             }},
326             },
327             0x0c => [{
328             Name => 'JPSLayout',
329             Condition => '$$self{MediaType} == 0',
330             Notes => 'mono',
331             PrintConv => {
332             0 => 'Both Eyes',
333             1 => 'Left Eye',
334             2 => 'Right Eye',
335             },
336             },{
337             Name => 'JPSLayout',
338             Condition => '$$self{MediaType} == 1',
339             Notes => 'stereo',
340             PrintConv => {
341             1 => 'Interleaved',
342             2 => 'Side By Side',
343             3 => 'Over Under',
344             4 => 'Anaglyph',
345             },
346             }],
347             0x0d => {
348             Name => 'JPSType',
349             Hook => '$varSize += $$self{HdrLength} - 4', # comment starts after header block
350             PrintConv => { 0 => 'Mono', 1 => 'Stereo' },
351             },
352             # 0x0e - in16u comment length (ignored -- assume the remainder is all comment)
353             # (this is offset if we had a 4-byte JPS header block)
354             0x10 => {
355             Name => 'JPSComment',
356             Format => 'string',
357             },
358             );
359              
360             # EPPIM APP6 (Toshiba PrintIM) segment (ref PH, from PDR-M700 samples)
361             %Image::ExifTool::JPEG::EPPIM = (
362             GROUPS => { 0 => 'APP6', 1 => 'EPPIM', 2 => 'Image' },
363             NOTES => q{
364             APP6 is used in by the Toshiba PDR-M700 to store a TIFF structure containing
365             PrintIM information.
366             },
367             0xc4a5 => {
368             Name => 'PrintIM',
369             # must set Writable here so this tag will be saved with MakerNotes option
370             # (but it isn't actually writable because there is no WRITE_PROC)
371             Writable => 'undef',
372             Description => 'Print Image Matching',
373             SubDirectory => {
374             TagTable => 'Image::ExifTool::PrintIM::Main',
375             },
376             },
377             );
378              
379             # APP8 SPIFF segment. Refs:
380             # 1) http://www.fileformat.info/format/spiff/
381             # 2) http://www.jpeg.org/public/spiff.pdf
382             %Image::ExifTool::JPEG::SPIFF = (
383             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
384             GROUPS => { 0 => 'APP8', 1 => 'SPIFF', 2 => 'Image' },
385             NOTES => q{
386             This information is found in APP8 of SPIFF-style JPEG images (the "official"
387             yet rarely used JPEG file format standard: Still Picture Interchange File
388             Format). See L for the official
389             specification.
390             },
391             0 => {
392             Name => 'SPIFFVersion',
393             Format => 'int8u[2]',
394             PrintConv => '$val =~ tr/ /./; $val',
395             },
396             2 => {
397             Name => 'ProfileID',
398             PrintConv => {
399             0 => 'Not Specified',
400             1 => 'Continuous-tone Base',
401             2 => 'Continuous-tone Progressive',
402             3 => 'Bi-level Facsimile',
403             4 => 'Continuous-tone Facsimile',
404             },
405             },
406             3 => 'ColorComponents',
407             6 => {
408             Name => 'ImageHeight',
409             Notes => q{
410             at index 4 in specification, but there are 2 extra bytes here in my only
411             SPIFF sample, version 1.2
412             },
413             Format => 'int32u',
414             },
415             10 => {
416             Name => 'ImageWidth',
417             Format => 'int32u',
418             },
419             14 => {
420             Name => 'ColorSpace',
421             PrintConv => {
422             0 => 'Bi-level',
423             1 => 'YCbCr, ITU-R BT 709, video',
424             2 => 'No color space specified',
425             3 => 'YCbCr, ITU-R BT 601-1, RGB',
426             4 => 'YCbCr, ITU-R BT 601-1, video',
427             8 => 'Gray-scale',
428             9 => 'PhotoYCC',
429             10 => 'RGB',
430             11 => 'CMY',
431             12 => 'CMYK',
432             13 => 'YCCK',
433             14 => 'CIELab',
434             },
435             },
436             15 => 'BitsPerSample',
437             16 => {
438             Name => 'Compression',
439             PrintConv => {
440             0 => 'Uncompressed, interleaved, 8 bits per sample',
441             1 => 'Modified Huffman',
442             2 => 'Modified READ',
443             3 => 'Modified Modified READ',
444             4 => 'JBIG',
445             5 => 'JPEG',
446             },
447             },
448             17 => {
449             Name => 'ResolutionUnit',
450             PrintConv => {
451             0 => 'None',
452             1 => 'inches',
453             2 => 'cm',
454             },
455             },
456             18 => {
457             Name => 'YResolution',
458             Format => 'int32u',
459             },
460             22 => {
461             Name => 'XResolution',
462             Format => 'int32u',
463             },
464             );
465              
466             # APP9 Media Jukebox segment (ref PH)
467             %Image::ExifTool::JPEG::MediaJukebox = (
468             GROUPS => { 0 => 'XML', 1 => 'MediaJukebox', 2 => 'Image' },
469             VARS => { NO_ID => 1 },
470             NOTES => 'Tags found in the XML metadata of the APP9 "Media Jukebox" segment.',
471             Date => {
472             Groups => { 2 => 'Time' },
473             # convert from days since Dec 30, 1899 to seconds since Jan 1, 1970
474             ValueConv => 'ConvertUnixTime(($val - (70 * 365 + 17 + 2)) * 24 * 3600)',
475             PrintConv => '$self->ConvertDateTime($val)',
476             },
477             Album => { },
478             Caption => { },
479             Keywords => { },
480             Name => { },
481             People => { },
482             Places => { },
483             Tool_Name => { },
484             Tool_Version => { },
485             );
486              
487             # JPEG-HDR APP11 information (ref PH, guessed from http://anyhere.com/gward/papers/cic05.pdf)
488             %Image::ExifTool::JPEG::HDR = (
489             GROUPS => { 0 => 'APP11', 1 => 'JPEG-HDR', 2 => 'Image' },
490             PROCESS_PROC => \&ProcessJPEG_HDR,
491             TAG_PREFIX => '', # (no prefix for unknown tags)
492             NOTES => 'Information extracted from APP11 of a JPEG-HDR image.',
493             ver => 'JPEG-HDRVersion',
494             # (need names for the next 3 tags)
495             ln0 => { Description => 'Ln0' },
496             ln1 => { Description => 'Ln1' },
497             s2n => { Description => 'S2n' },
498             alp => { Name => 'Alpha' }, # (Alpha/Beta are saturation parameters)
499             bet => { Name => 'Beta' },
500             cor => { Name => 'CorrectionMethod' },
501             RatioImage => {
502             Groups => { 2 => 'Preview' },
503             Notes => 'the embedded JPEG-compressed ratio image',
504             Binary => 1,
505             },
506             );
507              
508             # AdobeCM APP13 (no references)
509             %Image::ExifTool::JPEG::AdobeCM = (
510             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
511             GROUPS => { 0 => 'APP13', 1 => 'AdobeCM', 2 => 'Image' },
512             NOTES => q{
513             The APP13 "Adobe_CM" segment presumably contains color management
514             information, but the meaning of the data is currently unknown. If anyone
515             has an idea about what this means, please let me know.
516             },
517             FORMAT => 'int16u',
518             0 => 'AdobeCMType',
519             );
520              
521             # Adobe APP14 refs:
522             # http://partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf
523             # http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html#color
524             %Image::ExifTool::JPEG::Adobe = (
525             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
526             GROUPS => { 0 => 'APP14', 1 => 'Adobe', 2 => 'Image' },
527             NOTES => q{
528             The APP14 "Adobe" segment stores image encoding information for DCT filters.
529             This segment may be copied or deleted as a block using the Extra "Adobe"
530             tag, but note that it is not deleted by default when deleting all metadata
531             because it may affect the appearance of the image.
532             },
533             FORMAT => 'int16u',
534             0 => 'DCTEncodeVersion',
535             1 => {
536             Name => 'APP14Flags0',
537             PrintConv => {
538             0 => '(none)',
539             BITMASK => {
540             15 => 'Encoded with Blend=1 downsampling'
541             },
542             },
543             },
544             2 => {
545             Name => 'APP14Flags1',
546             PrintConv => {
547             0 => '(none)',
548             BITMASK => { },
549             },
550             },
551             3 => {
552             Name => 'ColorTransform',
553             Format => 'int8u',
554             PrintConv => {
555             0 => 'Unknown (RGB or CMYK)',
556             1 => 'YCbCr',
557             2 => 'YCCK',
558             },
559             },
560             );
561              
562             # GraphicConverter APP15 (ref PH)
563             %Image::ExifTool::JPEG::GraphConv = (
564             GROUPS => { 0 => 'APP15', 1 => 'GraphConv', 2 => 'Image' },
565             NOTES => 'APP15 is used by GraphicConverter to store JPEG quality.',
566             'Q' => 'Quality',
567             );
568              
569             # APP0 AVI1 segment (ref http://www.schnarff.com/file-formats/bmp/BMPDIB.TXT)
570             %Image::ExifTool::JPEG::AVI1 = (
571             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
572             GROUPS => { 0 => 'APP0', 1 => 'AVI1', 2 => 'Image' },
573             NOTES => 'This information may be found in APP0 of JPEG image data from AVI videos.',
574             FIRST_ENTRY => 0,
575             0 => {
576             Name => 'InterleavedField',
577             PrintConv => {
578             0 => 'Not Interleaved',
579             1 => 'Odd',
580             2 => 'Even',
581             },
582             },
583             );
584              
585             # APP0 Ocad segment (ref PH)
586             %Image::ExifTool::JPEG::Ocad = (
587             PROCESS_PROC => \&ProcessOcad,
588             GROUPS => { 0 => 'APP0', 1 => 'Ocad', 2 => 'Image' },
589             TAG_PREFIX => 'Ocad',
590             FIRST_ENTRY => 0,
591             NOTES => q{
592             Tags extracted from the JPEG APP0 "Ocad" segment (found in Photobucket
593             images).
594             },
595             Rev => {
596             Name => 'OcadRevision',
597             Format => 'string[6]',
598             }
599             );
600              
601             # APP6 NITF segment (National Imagery Transmission Format)
602             # ref http://www.gwg.nga.mil/ntb/baseline/docs/n010697/bwcguide25aug98.pdf
603             %Image::ExifTool::JPEG::NITF = (
604             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
605             GROUPS => { 0 => 'APP6', 1 => 'NITF', 2 => 'Image' },
606             NOTES => q{
607             Information in APP6 used by the National Imagery Transmission Format. See
608             L for
609             the official specification.
610             },
611             0 => {
612             Name => 'NITFVersion',
613             Format => 'int8u[2]',
614             ValueConv => 'sprintf("%d.%.2d", split(" ",$val))',
615             },
616             2 => {
617             Name => 'ImageFormat',
618             ValueConv => 'chr($val & 0xff)',
619             PrintConv => { B => 'IMode B' },
620             },
621             3 => {
622             Name => 'BlocksPerRow',
623             Format => 'int16u',
624             },
625             5 => {
626             Name => 'BlocksPerColumn',
627             Format => 'int16u',
628             },
629             7 => {
630             Name => 'ImageColor',
631             PrintConv => { 0 => 'Monochrome' },
632             },
633             8 => 'BitDepth',
634             9 => {
635             Name => 'ImageClass',
636             PrintConv => {
637             0 => 'General Purpose',
638             4 => 'Tactical Imagery',
639             },
640             },
641             10 => {
642             Name => 'JPEGProcess',
643             PrintConv => {
644             1 => 'Baseline sequential DCT, Huffman coding, 8-bit samples',
645             4 => 'Extended sequential DCT, Huffman coding, 12-bit samples',
646             },
647             },
648             11 => 'Quality',
649             12 => {
650             Name => 'StreamColor',
651             PrintConv => { 0 => 'Monochrome' },
652             },
653             13 => 'StreamBitDepth',
654             14 => {
655             Name => 'Flags',
656             Format => 'int32u',
657             PrintConv => 'sprintf("0x%x", $val)',
658             },
659             );
660              
661             #------------------------------------------------------------------------------
662             # Extract information from the JPEG APP0 Ocad segment
663             # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
664             # Returns: 1 on success
665             sub ProcessOcad($$$)
666             {
667 0     0 0 0 my ($et, $dirInfo, $tagTablePtr) = @_;
668 0         0 my $dataPt = $$dirInfo{DataPt};
669 0         0 $et->VerboseDir('APP0 Ocad', undef, length $$dataPt);
670 0         0 for (;;) {
671 0 0       0 last unless $$dataPt =~ /\$(\w+):([^\0\$]+)/g;
672 0         0 my ($tag, $val) = ($1, $2);
673 0         0 $val =~ s/^\s+//; $val =~ s/\s+$//; # remove leading/trailing spaces
  0         0  
674 0 0       0 AddTagToTable($tagTablePtr, $tag) unless $$tagTablePtr{$tag};
675 0         0 $et->HandleTag($tagTablePtr, $tag, $val);
676             }
677 0         0 return 1;
678             }
679              
680             #------------------------------------------------------------------------------
681             # Extract information from the JPEG APP0 Ocad segment
682             # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
683             # Returns: 1 on success
684             sub ProcessJPEG_HDR($$$)
685             {
686 19     19 0 57 my ($et, $dirInfo, $tagTablePtr) = @_;
687 19         47 my $dataPt = $$dirInfo{DataPt};
688 19 50       110 $$dataPt =~ /~\0/g or $et->Warn('Unrecognized JPEG-HDR format'), return 0;
689 19         52 my $pos = pos $$dataPt;
690 19         66 my $meta = substr($$dataPt, 7, $pos-9);
691 19         103 $et->VerboseDir('APP11 JPEG-HDR', undef, length $$dataPt);
692 19         138 while ($meta =~ /(\w+)=([^,\s]*)/g) {
693 133         327 my ($tag, $val) = ($1, $2);
694 133 50       296 AddTagToTable($tagTablePtr, $tag) unless $$tagTablePtr{$tag};
695 133         326 $et->HandleTag($tagTablePtr, $tag, $val);
696             }
697 19         107 $et->HandleTag($tagTablePtr, 'RatioImage', substr($$dataPt, $pos));
698 19         69 return 1;
699             }
700              
701             1; # end
702              
703             __END__