/usr/share/perl5/Image/MetaData/JPEG/parsers/app0.pl is in libimage-metadata-jpeg-perl 0.153-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ###########################################################
# A Perl package for showing/modifying JPEG (meta)data. #
# Copyright (C) 2004,2005,2006 Stefano Bettelli #
# See the COPYING and LICENSE files for license terms. #
###########################################################
use Image::MetaData::JPEG::data::Tables qw(:TagsAPP0);
no integer;
use strict;
use warnings;
###########################################################
# This method parses an APP0 segment. APP0 segments are #
# written by older cameras adopting the JFIF (JPEG File #
# Interchange Format) for storing images. JFIF uses the #
# APP0 application segment for inserting configuration #
# data and a thumbnail image. The format is as follows: #
#---------------------------------------------------------#
# 5 bytes identifier ('JFIF\000' = 0x4a46494600) #
# 1 byte major version (e.g. 0x01) #
# 1 byte minor version (e.g. 0x01 or 0x02) #
# 1 byte units (0: densities give aspect ratio #
# 1: density values are dots per inch #
# 2: density values are dots per cm) #
# 2 bytes Xdensity (Horizontal pixel density) #
# 2 bytes Ydensity (Vertical pixel density) #
# 1 byte Xthumbnail (Thumbnail horizontal pixel count) #
# 1 byte Ythumbnail (Thumbnail vertical pixel count) #
# 3n bytes (RGB)n, packed (24-bit) RGB values for the #
# thumbnail pixels, n = Xthumbnail * Ythumbnail #
#---------------------------------------------------------#
# There is also an "extended" version of JFIF (only pos- #
# sible for JFIF versions 1.02 and above). In this case #
# the identifier is not 'JFIF' but 'JFXX'. The syntax in #
# this case is modified as follows: #
#---------------------------------------------------------#
# 5 bytes identifier ('JFXX\000' = 0x4a46585800) #
# 1 byte extension (0x10 Thumbnail coded using JPEG #
# 0x11 Thumbnail using 1 byte/pixel #
# 0x13 Thumbnail using 3 bytes/pixel#
#---------------------------------------------------------#
# The remainder of the segment varies with the extension. #
#---------------------------------------------------------#
# Thumbnail coded using JPEG: the compressed thumbnail #
# immediately follows the extension code in the extension #
# data field and the length must be included in the JFIF #
# extension APP0 marker length field. The extension data #
# field conforms to the syntax for a JPEG file (SOI .... #
# SOF ... EOI); however, no 'JFIF' or 'JFXX' marker seg- #
# ments shall be present. #
#---------------------------------------------------------#
# Thumbnail stored using one byte per pixel: this must #
# include a thumbnail and a colour palette as follows: #
# 1 byte Xthumbnail (Thumbnail horizontal pixel count) #
# 1 byte Ythumbnail (Thumbnail vertical pixel count) #
# 768 bytes palette (24-bit RGB pixel values for the #
# colour palette. These values define #
# the colors represented by each value #
# of an 8-bit binary encoding (0-255)) #
# n bytes pixels (8-bit values for the thumbnail #
# pixels: n = Xthumbnail * Ythumbnail) #
#---------------------------------------------------------#
# Thumbnail stored using three bytes per pixel: in this #
# case there is no colour palette: #
# 1 byte Xthumbnail (Thumbnail horizontal pixel count) #
# 1 byte Ythumbnail (Thumbnail vertical pixel count) #
# 3n bytes pixels (24-bit RGB values for the thumbnail #
# pixels, n = Xthumbnail * Ythumbnail) #
#---------------------------------------------------------#
# Ref: http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/JPEG.txt #
###########################################################
sub parse_app0 {
my ($this) = @_;
my $offset = 0;
my $thumb_x_dim = 0; my $thumb_y_dim = 0;
# first, decode the identifier. It can be simple
# (JFIF), or extended (JFXX). We need five bytes
my $identifier = $this->store_record
('Identifier', $ASCII, $offset, length $APP0_JFIF_TAG)->get_value();
# go to the relevant decoding routine depending on it
goto APP0_simple if $identifier eq $APP0_JFIF_TAG;
goto APP0_extended if $identifier eq $APP0_JFXX_TAG;
# if we are still here, let us die of an unknown identifier
$this->die("Unknown identifier ($identifier)");
APP0_simple:
# as far as I know, in a JFIF APP0 there are always the following
# seven fields, even if the thumbnail is absent. This means that
# at least 14 bytes (including the initial identifier) must be there.
# Do a test size and then read the fields.
$this->test_size($offset + 9);
$this->store_record('MajorVersion', $BYTE , $offset);
$this->store_record('MinorVersion', $BYTE , $offset);
$this->store_record('Units' , $BYTE , $offset);
$this->store_record('XDensity' , $SHORT, $offset);
$this->store_record('YDensity' , $SHORT, $offset);
$thumb_x_dim =$this->store_record('XThumbnail',$BYTE,$offset)->get_value();
$thumb_y_dim =$this->store_record('YThumbnail',$BYTE,$offset)->get_value();
# now calculate the size of the thumbnail data area. This
# is three times the product of the two previous dimensions.
my $thumb_size = 3 * $thumb_x_dim * $thumb_y_dim;
# issue an error if the thumbnail data area is not there
$this->test_size($offset + $thumb_size, "corrupted thumbnail");
# if size is positive, get the packed thumbnail as unknown
$this->store_record('ThumbnailData', $UNDEF, $offset, $thumb_size)
if $thumb_size > 0;
goto APP0_END;
APP0_extended:
# so this is an extended JFIF (JFXX). Get the extension code
my $ext_code = $this->store_record
('ExtensionCode', $BYTE, $offset)->get_value();
# now, depending on it, go to another parsing segment
goto APP0_ext_jpeg if $ext_code == $APP0_JFXX_JPG;
goto APP0_ext_bytes if ($ext_code == $APP0_JFXX_1B ||
$ext_code == $APP0_JFXX_3B);
# if we are still here, die of unknown extension code
$this->die("Unknown extension code ($ext_code)");
APP0_ext_jpeg:
# in this case, the rest of the data area is a jpeg image
# which we save as undefined data in a single field. We don't
# dare to check the syntax of these data and go to the end.
$this->store_record('JPEGThumbnail',$UNDEF,$offset,$this->size()-$offset);
goto APP0_END;
APP0_ext_bytes:
# for the other two extensions, we first make sure that there
# are two other bytes, then we read the thumbnail size
$this->test_size($offset + 2, "no thumbnail dimensions");
$thumb_x_dim =$this->store_record('XThumbnail',$BYTE,$offset)->get_value();
$thumb_y_dim =$this->store_record('YThumbnail',$BYTE,$offset)->get_value();
# now calculate the number of pixels in the thumbnail data area.
# This is the product of the two previous dimensions.
my $thumb_pixels = $thumb_x_dim * $thumb_y_dim;
# now, the two extensions take different routes ...
goto APP0_ext_1byte if $ext_code eq $APP0_JFXX_1B;
goto APP0_ext_3bytes if $ext_code eq $APP0_JFXX_3B;
APP0_ext_1byte:
# in this case, there must be 768 bytes for the palette, followed
# by $thumb_pixels for the thumbnail. Issue an error otherwise
$this->test_size($offset + $APP0_JFXX_PAL + $thumb_pixels,
"Incorrect thumbnail data size in JFXX 0x10");
# store the colour palette and the thumbnail as
# undefined data and we have finished.
$this->store_record('ColorPalette' , $UNDEF, $offset, $APP0_JFXX_PAL);
$this->store_record('1ByteThumbnail', $UNDEF, $offset, $thumb_pixels);
goto APP0_END;
APP0_ext_3bytes:
# in this case, there must be 3 * $thumb_pixels
# for the thumbnail data. Issue an error otherwise
$this->test_size($offset + 3 * $thumb_pixels,
"Incorrect thumbnail data size in JFXX 0x13");
# store the thumbnail as undefined data and we have finished.
$this->store_record('3BytesThumbnail', $UNDEF, $offset, 3 * $thumb_pixels);
goto APP0_END;
APP0_END:
# check that there are no spurious data in the segment
$this->test_size(-$offset, "unknown data at segment end");
}
# successful load
1;
|