Image-Info-1.28/0000755000175000017500000000000010773761473011200 5ustar teteImage-Info-1.28/t/0000755000175000017500000000000010773761473011443 5ustar teteImage-Info-1.28/t/bmp.t0000644000175000017500000000144310425372576012404 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; # test RLE encoded bitmaps BEGIN { plan tests => 10; chdir 't' if -d 't'; use lib '../lib'; use lib '../blib'; use_ok ("Image::Info") or die($@); }; use Image::Info qw(image_info dim); my $i = image_info("../img/test.rle") || die ("Couldn't read test.rle: $!"); #use Data::Dumper; print Dumper($i), "\n"; is ($i->{Compression}, 'RLE8', 'Compression'); is ($i->{BitsPerSample}, '8', 'BitsPerSample'); is ($i->{SamplesPerPixel}, 1, 'SamplesPerPixel'); is ($i->{file_media_type}, 'image/bmp', 'image/bmp'); is ($i->{BMP_ColorsImportant}, 255, '255 colors'); is ($i->{ColorTableSize}, 255, '255 colors'); is ($i->{BMP_Origin}, 1, 'BMP_Origin'); is ($i->{color_type}, 'Indexed-RGB', 'color_type'); is (dim($i), '64x64', 'dim()'); Image-Info-1.28/t/png.t0000644000175000017500000000271410456431647012413 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; # test PNG files BEGIN { plan tests => 18; chdir 't' if -d 't'; use lib '../lib'; use_ok ("Image::Info") or die($@); }; use Image::Info qw(image_info dim); my $i = image_info("../img/test.png") || die ("Couldn't read test.png: $!"); is ($i->{color_type}, 'Indexed-RGB', 'color_type'); is ($i->{LastModificationTime}, "2006-07-16 12:28:31", 'LastModificationTime'); is ($i->{file_ext}, 'png', 'png'); is ($i->{file_media_type}, 'image/png', 'media_type'); is ($i->{SampleFormat}, 'U4', 'SampleFormat'); is (dim($i), '150x113', 'dim()'); is_deeply ( $i->{ColorPalette}, [ '#171617', '#c8ced6', '#8d929b', '#75787f', '#565961', '#2f3033', '#fefefd', '#613e2f', '#a6acb6', '#e6ecf2', '#40464d', '#805d4b' ], 'ColorPalette' ); ############################################################################# # interlace test $i = image_info("../img/interlace.png") || die ("Couldn't read interlace.png: $!"); is ($i->{color_type}, 'RGB', 'color_type'); is ($i->{LastModificationTime}, "2006-07-16 12:32:43", 'LastModificationTime'); is ($i->{SampleFormat}, 'U8', 'SampleFormat'); is ($i->{Interlace}, 'Adam7', 'Interlace'); is ($i->{Compression}, 'Deflate', 'Compression'); is ($i->{PNG_Filter}, 'Adaptive', 'PNG_Filter'); is ($i->{file_ext}, 'png', 'png'); is ($i->{file_media_type}, 'image/png', 'media_type'); is ($i->{Comment}, 'Created with The GIMP', 'Comment'); is (dim($i), '200x100', 'dim()'); Image-Info-1.28/t/pod.t0000644000175000017500000000106610366650662012410 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; my $tests; BEGIN { $tests = 11; plan tests => $tests; chdir 't' if -d 't'; use lib '../lib'; }; SKIP: { skip( 'Test::Pod not installed on this system', $tests ) unless do { eval ("use Test::Pod;"); $@ ? 0 : 1; }; for my $m (qw[ Info.pm TIFF.pm Info/BMP.pm Info/GIF.pm Info/JPEG.pm Info/PNG.pm Info/PPM.pm Info/SVG.pm Info/TIFF.pm Info/XBM.pm Info/XPM.pm ]) { pod_file_ok( '../lib/Image/' . $m ); } } Image-Info-1.28/t/pod_cov.t0000644000175000017500000000111410402521463013234 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; my $tests; BEGIN { $tests = 7; plan tests => $tests; chdir 't' if -d 't'; use lib '../lib'; }; SKIP: { skip("Test::Pod::Coverage 1.00 required for testing POD coverage", $tests) unless do { eval "use Test::Pod::Coverage;"; $@ ? 0 : 1; }; for my $m (qw[ Info Info::BMP Info::PPM Info::SVG Info::XBM Info::XPM Info::TIFF ]) { pod_coverage_ok( 'Image::' . $m, "$m is covered" ); } # XXX TODO: # TIFF # Info::GIF # Info::PNG # Info::JPEG } Image-Info-1.28/t/svg.t0000644000175000017500000000232110456732752012421 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; # test SVG images BEGIN { chdir 't' if -d 't'; use lib '../lib'; plan skip_all => "Need XML::Simple for this test", unless do { eval "use XML::Simple;"; $@ ? 0 : 1; }; plan tests => 12; } use Image::Info qw(image_info dim); my $i = image_info("../img/test.svg") || die ("Couldn't read test.svg: $!"); #use Data::Dumper; print Dumper($i), "\n"; is ($i->{color_type}, 'sRGB', 'color_type'); is ($i->{file_media_type}, 'image/svg+xml', 'file_media_type'); is ($i->{SVG_StandAlone}, 'yes', 'SVG_StandAlone'); is ($i->{file_ext}, 'svg', 'file_ext'); is ($i->{SVG_Version}, 'unknown', 'SVG_Version unknown'); is (dim($i), '4inx3in', 'dim()'); ############################################################################# # second test file $i = image_info("../img/graph.svg") || die ("Couldn't read graph.svg: $!"); #use Data::Dumper; print Dumper($i), "\n"; is ($i->{SVG_StandAlone}, 'yes', 'SVG_StandAlone'); is ($i->{file_ext}, 'svg', 'file_ext'); is ($i->{file_media_type}, 'image/svg+xml', 'file_media_type'); is ($i->{SVG_Title}, 'Untitled graph', 'title'); is ($i->{SVG_Version}, '1.1', 'SVG_Version 1.1'); is (dim($i), '209x51', 'dim()'); Image-Info-1.28/t/tiny-pgm.t0000644000175000017500000000101410404253645013354 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; # test dim(), html_dim() and image_info() BEGIN { plan tests => 4; chdir 't' if -d 't'; use lib '../lib'; use_ok ("Image::Info") or die($@); }; use Image::Info qw(image_info); my $h = image_info("../img/tiny.pgm") || die ("Cannot read tiny.pgm: $!"); #use Data::Dumper; print STDERR "# ", Data::Dumper::Dumper($h), "\n"; is ($h->{file_media_type}, "image/pgm", 'file_media_type'); is ($h->{width}, 1, 'width=1'); is ($h->{height}, 1, 'height=1');; Image-Info-1.28/t/exif.t0000644000175000017500000000150110670753634012554 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; # Some basic tests for Exif extraction. Highly incomplete. BEGIN { plan tests => 7; chdir 't' if -d 't'; use lib '../lib'; use_ok ("Image::Info") or die($@); }; use Image::Info qw(image_info dim); my $i = image_info("../img/test.jpg") || die; #use Data::Dumper; print Dumper($i), "\n"; is ($i->{DateTimeDigitized}, "1999:12:06 16:38:40", 'DateTimeDigitized'); is ($i->{Make}, "OLYMPUS OPTICAL CO.,LTD", 'Make'); # test parsing of MakerNote (especially that there are no trailing \x00): # this is a "UNDEFINED" value with trailing zeros \x00: is ($i->{'Olympus-CameraID'}, 'OLYMPUS DIGITAL CAMERA', 'Olympus-CameraID'); isnt ($i->{UserComment}, "ASCII", 'UserComment'); like ($i->{UserComment}, qr/^\s+\z/, 'UserComment'); is (dim($i), '320x240', 'dim()'); Image-Info-1.28/t/00_basics.t0000644000175000017500000000273210424710361013356 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; use File::Spec; # test exporting of functions plus the basics BEGIN { plan tests => 11; chdir 't' if -d 't'; use lib '../lib'; use_ok ("Image::Info") or die($@); }; use Image::Info qw(image_info dim html_dim determine_file_format image_type); my $test = File::Spec->catfile( File::Spec->updir(), 'img', 'test.gif'); my $info = image_info($test); ############################################################################# # dim, html_dim my @dim = dim($info); is (join(" ", @dim), "200 150", 'dim()'); is (dim($info), '200x150', 'dim($info)'); is (html_dim($info), 'width="200" height="150"', 'html_dim()'); is (html_dim(image_info('README')), '', 'no README in info'); ############################################################################# # image_type my $type = image_type($test); if (is (ref($type), 'HASH', 'got hash from image_type')) { is ($type->{file_type}, 'GIF', 'image_type is GIF'); } else { fail ('image_type'); } $type = image_type($test.'non-existant'); if (is (ref($type), 'HASH', 'got hash from image_type')) { ok (exists $type->{error}, '{error} got set'); ok (exists $type->{Errno}, '{Errno} got set'); } else { fail ('image_type with error'); fail ('image_type with error'); } ############################################################################# # determine_file_format is (determine_file_format('GIF87a'), 'GIF', 'determine_file_format is GIF'); Image-Info-1.28/t/jpg_hang.t0000644000175000017500000000114710622150552013367 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; BEGIN { chdir 't' if -d 't'; use lib '../blib/'; use lib '../lib/'; plan tests => 2; } use Image::Info qw(image_info dim); # This image caused hangs in earlier versions (bug #26127/#26130) due to # a cycle in the IFDs: eval { local $SIG{ALRM} = sub { die "oops - did hang\n" }; alarm 5; my $i = image_info("../img/cynic_hang.jpg"); is (ref($i), 'HASH', 'image_info ran'); ok (!exists $i->{error}, 'image_info ran ok'); alarm 0; }; if ($@) { # propagate unexpected errors die unless $@ eq "oops - did hang\n"; # timed out } 1; Image-Info-1.28/t/tiff.t0000644000175000017500000000406410570300257012544 0ustar tete#!/usr/bin/perl -w use Test::More; use strict; BEGIN { chdir 't' if -d 't'; use lib '../blib/'; use lib '../lib/'; plan tests => 15; } use Image::Info qw(image_info dim); ## This TIFF file has 3 images, in 24-bit colour, 1-bit mono and 8-bit grey. my @i = image_info("../img/test.tif"); ok ( @i, 'image_info ran ok'); is ( @i, 3, 'Right number of images found' ); ## First image is ( scalar @{$i[0]->{BitsPerSample}}, 3 , 'Three lots of BitsPerSample for full-colour image' ); is ( $i[0]->{SamplesPerPixel}, 3, 'SamplesPerPixel is 3 for full-colour image' ); is ( $i[0]->{width}, 60, 'width is right for full-colour image'); is ( $i[0]->{height}, 50, 'height is right for full-colour image'); my $soft_text = "ImageMagick 6.0.6 01/25/06 Q16 http://www.imagemagick.org"; if ( $i[0]->{Software} eq $soft_text ) { ok (1, "Software text tag read correctly" ); } else { ok (0, "Software text tag read correctly" ); my @tagc = split //,$i[0]->{Software}; my @tstc = split //,$soft_text; printf "Tag string is %d characters, Test string is %d characters\n", scalar(@tagc), scalar(@tstc); for (my $i = 0; defined $tagc[$i] or defined $tstc[$i]; $i++) { $tagc[$i] = '[undef]' if ! defined $tagc[$i]; $tstc[$i] = '[undef]' if ! defined $tstc[$i]; if ($tagc[$i] ne $tstc[$i]) { warn sprintf("Strings differ at offset $i (expected: %s / found: %s)\n", $tagc[$i], $tstc[$i]); } } } ## Second image is ( $i[1]->{BitsPerSample}, 1, 'BitsPerSample right for 1-bit image' ); is ( $i[1]->{SamplesPerPixel}, 1, 'BitsPerSample right for 1-bit image' ); is ( $i[1]->{Compression}, 'CCITT T6', 'Compression right for 1-bit image' ); is ( $i[1]->{DocumentName}, "bb1bit.tif", "DocumentName text tag read correctly" ); ## Third image is ( $i[2]->{BitsPerSample}, 8, 'Bit depth right for greyscale image' ); is ( $i[2]->{SamplesPerPixel}, 1, 'Bit depth right for greyscale image' ); is ( dim($i[2]), '60x50' , 'dim() function is right for greyscale image' ); is ( $i[2]->{ImageDescription}, "Created with The GIMP", "ImageDescription text tag read correctly" ); 1; Image-Info-1.28/t/tiff_e.t0000644000175000017500000000162310425370752013054 0ustar tete#!/usr/bin/perl -w # Test the same TIFF file in little and big endian use Test::More; use strict; BEGIN { chdir 't' if -d 't'; use lib '../blib/'; use lib '../lib/'; plan tests => 10; } use Image::Info qw(image_info); ## ## TIFF Little Endian file ## my @le = image_info("../img/le.tif"); ok ( @le, 'TIFF Little Endian: image_info ran ok'); is ( @le, 1, 'One image found' ); is ( $le[0]->{SamplesPerPixel}, 4, 'SamplesPerPixel is 4' ); is ( $le[0]->{width}, 260, 'Width is right for the image'); is ( $le[0]->{height}, 6, 'Height is right for the image'); ## ## TIFF Big Endian file ## my @be = image_info("../img/be.tif"); ok ( @be, 'TIFF Big Endian: image_info ran ok'); is ( @be, 1, 'One image found' ); is ( $be[0]->{SamplesPerPixel}, 4, 'SamplesPerPixel is 4' ); is ( $be[0]->{width}, 260, 'Width is right for the image'); is ( $be[0]->{height}, 6, 'Height is right for the image'); 1; Image-Info-1.28/t/string.t0000644000175000017500000000301410425200163013106 0ustar tete#!/usr/bin/perl -w # Load file into a string into memory and then test it use strict; use Test::More; use File::Spec; my (@tests, $tests); BEGIN { @tests = glob("img/test*"); $tests = (scalar @tests) * 2; plan tests => $tests; chdir 't' if -d 't'; use lib '../lib'; }; my $requires = { xpm => 'Image::Xpm', xbm => 'Image::Xbm', svg => 'XML::Simple', }; SKIP: { skip( 'Need either Perl 5.008 or greater, or IO::String for these tests', $tests ) unless $] >= 5.008 || do { eval "use IO::String;"; $@ ? 0 : 1; }; use Image::Info qw(image_info); my $updir = File::Spec->updir(); for my $f (@tests) { # extract the extension of the image file $f =~ /\.([a-z]+)\z/i; my $x = lc($1 || ''); SKIP: { # test for loading the nec. library if (exists $requires->{$x}) { my $r = $requires->{$x}; skip( "Need $r for this test", 2 ) && next unless do { eval "use $r;"; $@ ? 0 : 1; }; } # 2 tests follow: my $file = File::Spec->catfile($updir,$f); my $h1 = image_info($file); is ($h1->{error}, undef, 'no error'); my $img = cat($file); my $h2 = image_info(\$img); is_deeply ($h1, $h2, $file); } # end inner SKIP } # end for each file } # end SKIP all block sub cat { my $file = shift; local(*F, $/); open(F, $file) || die "Can't open $file: $!"; binmode F; my $c = ; close(F); $c; } Image-Info-1.28/dev/0000755000175000017500000000000010773761473011756 5ustar teteImage-Info-1.28/dev/Info.pm.tmpl0000644000175000017500000002745610773753163014175 0ustar tete ############################################################################# # # ATTENTION! This file is autogenerated from dev/Info.pm.tmpl - DO NOT EDIT! # ############################################################################# package Image::Info; # Copyright 1999-2004, Gisle Aas. # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl v5.8.8 itself. # # Now maintained by Tels - (c) 2006 - 2008. use strict; use vars qw($VERSION @EXPORT_OK); $VERSION = '1.28'; require Exporter; *import = \&Exporter::import; @EXPORT_OK = qw(image_info dim html_dim image_type determine_file_format); # already required and failed sub-modules are remembered here my %mod_failure; sub image_info { my $source = _source(shift); return $source if ref $source eq 'HASH'; # Pass on errors # What sort of file is it? my $head = _head($source); return $head if ref($head) eq 'HASH'; # error? my $format = determine_file_format($head) or return { error => 'Unrecognized file format' }; no strict 'refs'; my $mod = "Image::Info::$format"; my $sub = "$mod\::process_file"; my $info = bless [], "Image::Info::Result"; eval { unless (defined &$sub) { # already required and failed? if (my $fail = $mod_failure{$mod}) { die $fail; } eval "require $mod"; if ($@) { $mod_failure{$mod} = $@; die $@; } die "$mod did not define &$sub" unless defined &$sub; } my %cnf = @_; # call process_file() &$sub($info, $source, \%cnf); $info->clean_up; }; return { error => $@ } if $@; return wantarray ? @$info : $info->[0]; } sub image_type { my $source = _source(shift); return $source if ref $source eq 'HASH'; # Pass on errors # What sort of file is it? my $head = _head($source) or return _os_err("Can't read head"); my $format = determine_file_format($head) or return { error => "Unrecognized file format" }; return { file_type => $format }; } sub _source { my $source = shift; if (!ref $source) { require Symbol; my $fh = Symbol::gensym(); open($fh, $source) || return _os_err("Can't open $source"); ${*$fh} = $source; # keep filename in case somebody wants to know binmode($fh); $source = $fh; } elsif (ref($source) eq "SCALAR") { if ($] >= 5.008) { open(my $s, "<", $source) or return _os_err("Can't open string"); $source = $s; } else { require IO::String; $source = IO::String->new($$source); } } else { seek($source, 0, 0) or return _os_err("Can't rewind"); } $source; } sub _head { my $source = shift; my $head; # tiny.pgm is 11 bytes my $to_read = 11; my $read = read($source, $head, $to_read); return _os_err("Couldn't read $to_read bytes") if $read != $to_read; if (ref($source) eq "IO::String") { # XXX workaround until we can trap seek() with a tied file handle $source->setpos(0); } else { seek($source, 0, 0) or return _os_err("Can't rewind"); } $head; } sub _os_err { return { error => "$_[0]: $!", Errno => $!+0, }; } %%DETERMINE_FILE_FORMAT%% sub dim { my $img = shift || return; my $x = $img->{width} || return; my $y = $img->{height} || return; wantarray ? ($x, $y) : "${x}x$y"; } sub html_dim { my($x, $y) = dim(@_); return "" unless $x; "width=\"$x\" height=\"$y\""; } ############################################################################# package Image::Info::Result; sub push_info { my($self, $n, $key) = splice(@_, 0, 3); push(@{$self->[$n]{$key}}, @_); } sub clean_up { my $self = shift; for (@$self) { for my $k (keys %$_) { my $a = $_->{$k}; $_->{$k} = $a->[0] if @$a <= 1; } } } sub get_info { my($self, $n, $key, $delete) = @_; my $v = $delete ? delete $self->[$n]{$key} : $self->[$n]{$key}; $v ||= []; @$v; } 1; __END__ =head1 NAME Image::Info - Extract meta information from image files (DEPRECATED) =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.jpg"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } my $color = $info->{color_type}; my $type = image_type("image.jpg"); if (my $error = $type->{error}) { die "Can't determine file type: $error\n"; } die "No gif files allowed!" if $type->{file_type} eq 'GIF'; my($w, $h) = dim($info); =head1 DESCRIPTION Please note that this module is B and should not be used. Alternatively, try one of the following modules: L, L. The code in this module is old, unreviewed, hackish, still has numerous bugs and is incomplete in quite a few cases. While this module is sort-of maintained (e.g. the most critical security-related bugs are fixed), no new features will be added and numerous minor bugs are very likely sprinkled through the entire code base. You have been warned. This module provide functions to extract various kind of meta information from image files. =head2 EXPORTS Exports nothing by default, but can export the following methods on request: image_info image_type dim html_dim determine_file_type =head2 METHODS The following functions are provided by the C module: =over =item image_info( $file ) =item image_info( \$imgdata ) =item image_info( $file, key => value,... ) This function takes the name of a file or a file handle as argument and will return one or more hashes (actually hash references) describing the images inside the file. If there is only one image in the file only one hash is returned. In scalar context, only the hash for the first image is returned. In case of error, and hash containing the "error" key will be returned. The corresponding value will be an appropriate error message. If a reference to a scalar is passed as argument to this function, then it is assumed that this scalar contains the raw image data directly. The image_info() function also take optional key/value style arguments that can influence what information is returned. =item image_type( \$imgdata ) Returns a hash with only one key, C<< file_type >>. The value will be the type of the file. On error, sets the two keys C<< error >> and C<< Errno >>. This function is a dramatically faster alternative to the image_info function for situations in which you B need to find the image type. It uses only the internal file-type detection to do this, and thus does not need to load any of the image type-specific driver modules, and does not access to entire file. It also only needs access to the first 11 bytes of the file. To maintain some level of compatibility with image_info, image_type returns in the same format, with the same error message style. That is, it returns a HASH reference, with the C<< $type->{error} >> key set if there was an error. On success, the HASH reference will contain the single key 'file_type', which represents the type of the file, expressed as the type code used for the various drivers ('GIF', 'JPEG', 'TIFF' and so on). If there are multiple images within the file they will be ignored, as this function provides only the type of the overall file, not of the various images within it. This function will not return multiple hashes if the file contains multiple images. Of course, in all (or at least effectively all) cases the type of the images inside the file is going to be the same as that of the file itself. =item dim( $info_hash ) Takes an hash as returned from image_info() and returns the dimensions ($width, $height) of the image. In scalar context returns the dimensions as a string. =item html_dim( $info_hash ) Returns the dimensions as a string suitable for embedding directly into HTML or SVG -tags. E.g.: print "\n"; =item determine_file_format( $filedata ) Determines the file format from the passed file data (a normal Perl scalar containing the first bytes of the file), and returns either undef for an unknown file format, or a string describing the format, like "BMP" or "JPEG". =back =head1 Image descriptions The image_info() function returns meta information about each image in the form of a reference to a hash. The hash keys used are in most cases based on the TIFF element names. All lower case keys are mandatory for all file formats and will always be there unless an error occured (in which case the "error" key will be present.) Mixed case keys will only be present when the corresponding information element is available in the image. The following key names are common for any image format: =over =item file_media_type This is the MIME type that is appropriate for the given file format. The corresponding value is a string like: "image/png" or "image/jpeg". =item file_ext The is the suggested file name extention for a file of the given file format. The value is a 3 letter, lowercase string like "png", "jpg". =item width This is the number of pixels horizontally in the image. =item height This is the number of pixels vertically in the image. (TIFF use the name ImageLength for this field.) =item color_type The value is a short string describing what kind of values the pixels encode. The value can be one of the following: Gray GrayA RGB RGBA CMYK YCbCr CIELab These names can also be prefixed by "Indexed-" if the image is composed of indexes into a palette. Of these, only "Indexed-RGB" is likely to occur. It is similar to the TIFF field PhotometricInterpretation, but this name was found to be too long, so we used the PNG inpired term instead. =item resolution The value of this field normally gives the physical size of the image on screen or paper. When the unit specifier is missing then this field denotes the squareness of pixels in the image. The syntax of this field is: "/" "/" The , and fields are numbers. The is a string like C, C or C (denoting "dots per inch/cm/meter). =item SamplesPerPixel This says how many channels there are in the image. For some image formats this number might be higher than the number implied from the C. =item BitsPerSample This says how many bits are used to encode each of samples. The value is a reference to an array containing numbers. The number of elements in the array should be the same as C. =item Comment Textual comments found in the file. The value is a reference to an array if there are multiple comments found. =item Interlace If the image is interlaced, then this tell which interlace method is used. =item Compression This tells you which compression algorithm is used. =item Gamma A number. =item LastModificationTime A ISO date string =back =head1 Supported Image Formats The following image file formats are supported: =over %%FORMAT_DESC%% =back =head1 CAVEATS Note that while the module is still maintained, no new features will be added and numerous bugs remain throughout the code base. Especially the EXIF parsing code is buggy, not tested at all, and quite incomplete (a lot of manufacturer's MakerNotes and tags are not parsed at all). If you want a stable, feature-complete, up-to-date and tested EXIF parsing library, please use L. Likewise, the image parsing code is quite hackish and seems to contain an endless supply of bugs that crash, or hang with malformed input. =head1 SEE ALSO L, L =head1 AUTHORS Copyright 1999-2004 Gisle Aas. See the CREDITS file for a list of contributors and authors. Now maintained by Tels - (c) 2006 - 2008. =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl v5.8.8 itself. =cut Image-Info-1.28/dev/build.pl0000755000175000017500000000376410424705730013412 0ustar tete#!/usr/bin/perl -w use strict; use File::Spec; ############################################################################# ############################################################################# # Write the Info.pm file with system specific code from Info.pm.tmpl: # This is run by the developer, and there is no need to rerun this at build # time. BEGIN { chdir 'dev' if -d 'dev'; } my $updir = File::Spec->updir(); my $tmpl = File::Spec->catfile("Info.pm.tmpl"); my $info_pm = File::Spec->catfile($updir,"lib", "Image", "Info.pm"); my $idir = File::Spec->catdir($updir,"lib", "Image", "Info"); opendir(DIR, $idir) || die "Can't opendir $idir: $!"; my (@code,@desc, $desc); for my $file (sort readdir(DIR)) { next unless $file =~ /^([a-zA-Z]\w*)\.pm$/; my $format = $1; open(F, File::Spec->catfile($idir, $file)) || die "Can't open '$idir/$file': $!"; my @magic; my @desc; while () { if (/^=begin\s+register\b/ ... /^=end\s+register\b/) { next if /^=(begin|end)/; if (/^MAGIC:\s+(.*)/) { push(@magic, $1); next; } push(@desc, $_); } } die "Missing magic for $format" unless @magic; for (@magic) { if (m:^/:) { push(@code, qq(return "$format" if $_;)); } else { push(@code, qq(return "$format" if \$_ eq $_;)); } } # trim shift(@desc) while @desc && $desc[0] =~ /^\s*$/; pop(@desc) while @desc && $desc[-1] =~ /^\s*$/; $desc .= "\n=item $format\n" unless @desc && $desc[0] =~ /^=item/; $desc .= "\n" . join("", @desc); } closedir(DIR); my $code = "sub determine_file_format { local(\$_) = \@_; " . join("\n ", @code) . " return undef; } "; # Copy template to top level module with substitutions open(TMPL, $tmpl) || die "Can't open $tmpl: $!"; open(INFO, ">$info_pm") || die "Can't create $info_pm: $!"; while () { if (/^%%DETERMINE_FILE_FORMAT%%/) { $_ = $code; } elsif (/^%%FORMAT_DESC%%/) { $_ = $desc; } print INFO $_; } close(INFO); close(TMPL); Image-Info-1.28/img/0000755000175000017500000000000010773761473011754 5ustar teteImage-Info-1.28/img/test.gif0000644000175000017500000007132010402022242013372 0ustar teteGIF89a 8Ho$Jhű>uO+̍hFD1~oWl %ɶDgBEJ`C,$H|`XqnwT(hx@0V( cst)%tlWY.FU8JeqqoHVd rUC̈́v;_߆ovV<.4!Stvf0\F/l6| 8@:8+ F#FG5^,+HZYe;W.VmDdӫɵ[9 @LWKctbPZtvz08IZVOQt` /pA0ί(2TLodo &+Թ))-?/3@|s+t@=<$yg6oI}0mL?{6Ԩ^&8OLaL`Z4qСaOTzecFA!iРL3+`aР_igA V2 ZQ s4ԢNLd!WM|e!2e|vF|\y7TnexM%d#8 lFRbURJfPa XX!G2Ԣ ~X)w,p~cg~Tfx@tFGERG{C>xDpOmmEvs fP(= 3O,cM'?b/^lC ?4ٖPC@aj! 2( E@:`*XA 85 j0C4<` 3ܣJ^@V(xa`Lt `4Q4PC <8 4 <5x0CП-]f@]:\W1 48ED1 hp i |< -n@ \A 7ծ  AnQ:/̰F#De&t#qOԀ!C= a >B4 QW(Џ ԣ>` (BD>A`& f yC4ad!E͐` ``-j2p]a t!p AE8c (1Phl`-@R4 > TE٤ծ9 [^a,Ԁ `C\!]GÍF@fPyy` c 9j (h-`{pM65t.E-ڥ+ri C@z7@ro,i=L   *r=P\@iv Gpp@ld+ui   -TkҀ4yGihPPwleIy!qǐ{ q@h=  zi.Eg \"-KVao态Wxpr n6"e H0gC8 034CFؐ۠BcVV6T .4"xyt y`Xf6Rc=p||L 2ph@rL`# L [4ra P '+fPQQAt@ٰ 4%`eI̦+ƊHgrqj Pvp ^3D;p pG^0J""t-`fn 2 ` W0g_` S{p # @l(P TP @ MP "Kfy o p-7ܠ0-^ce62]:XPW:MM6L  #ԧ:շ2tPԣ<<<0g:y V 10?m?pwc4ovg [| AT[(EdjE+Ȋ@[?uW Ukٝ6Pg xbn'MzGg*9'jhc%Z`0MPҒGL,#ʐ ,,-2.dm P ` Vנ`L`Rr âohv & p߰E${p CwC/M=cV}v`y0 <`9' \@)m@S`}bg0Ft~kii4W=(sihJ P [5pS@`# @Rg0PKQHf0 ¢02< P `@GWP7P)VͶ4@G`P d#Ou~P  pF 3 8f 0 +|HmqwRNz !E̐` R40K2= % g 3$ @*V0i.Ep p{ y U`6,=xppVtaE0y`e[z5b@+ 9OÏkL6 lP pW}kuOϯ , P>Gm8Z s!sbd;'y @Wiq I\iBB=\ bz謜=$03,_%9uD?@'K,Hc*x4Ƒ"- CKbXK4+݆9b:pxCa`ɑCĚ"ܶe @0"Nj^ +>;s=1™+w<{NhXeƊ40}!L#RäF-rY&u-jAGBRAg /Ö(2g&-sS$WlJ7,Ǣ۫20ʸ p(Œ 8t4ʠ0xxby WD.Lw@w(CnA{"A!`裌oI,Ҁ Hǂ"p1c+0E?`d QC0AC9Ցa.ASo>‹3ʸK2ĈPB0aC4 " ,ȁ V>x]3F9`@6J>8D x`A248΀4ha+J: ȣ N{@} 0olul`J7mm|j ;B|Pc =Qt.%# DZ!| P& XrZ@cߘR0\aq~|ѴA?W|mH1Z{#@~<;g,$x2paA~X@,0!h,:H  8GXLwpNj0h{}axiSwa<@/\;[8 84B)U'Tnpt E7!t5^%p+\G*%[0lK G?я2(YepzЏ! ?87px>pGx 1cq Jpo>G#.쩮0$`\G]3ԛil)xq0ֻޱcщp鏇<}^$.8v~o@\#V i᜺ s֞P6x7.qsW8Յ9nT@kT D_h|A_xAh2ll|k (4PB%%\B)9J 8(\)) ?`,90l9}*k)Ey?ػn!I4(Y;,Cop8z:pj7!s09Ch{skH<`9 A'4`<(*?!y bTȂM>( [R  bt)a*"1XF+8+tHf #8pk3(ܜ,<ltNqF (#cSzJj`L=8&`S|| |  SԈ `Cз  pTz3H"=8E>P)u5Ӹ̗ h2iPrHeڐv,ah4x,p8H38#p,h ]pk J JB|`W2xvM7X,8O -uȆ<& x<PBK>%P|Ѓ`' !6-=_m["`d >)P[`-HQS&-`m `O&ipi3pcȃˀ8Ev,3@JĂ< X[K<Co}xm܄ mW_=4`Z@ h#+؀t& =ЃՃpP|8U=Xɒ,C [FhJPڦ2]E ?ȇK88p؃L!Tw(_!PH ؇LhS3#xͣ2`^`Xc`+TуyوR8>@&@b e5M,',-؃<8![S# :I0x3P$N18膦LD;Ȁo`fh2tPPP?W)P*\nU, +L0+H7 =`j|p[\lP|xcazv&gbH'Pdb0)xg@&Ȃ-8=@t"1 Ѓ[)؃#@9V_p `Xx)vDeZ+؀4]$mȄ;@6ЉА Upw(XO- [w@qTpc))Q&Ȃl(|Hd)zXȑYgv5)mN>0\bx8Wh|(nH(8pk5S> %Yg~F8>*Ѐ^!P48 rR\yV|%v1O J^@h]~mHoa*5@Su؃X`4h9eS7Xh(KgТ~xS&&;H 9rZXX:X'@ ' "YSGĚ'">(wPDD XHgŊgVNh|,XgJRI?2H8?h RdHMii#vJ?,#550]V5-`i1 y&E{y*e̴$&APvIQ$Ұ$a:  > n}\Iy|'"^Hn tXiQehǢel1e}xrD̩=f2ٓDW %^js@ODoD|ӂy|@:$4Z4PFDQЂA; yxFE%guY8Z$55kChk 6l녜an L5@0p?/d hpha-~ xF2' (!%g׬!";F1 TP!pQznl0< h6 0L2(6z@[(oX`b $#'`ԂpE)X! WX*_ʃ(H) du L>jpe7Ą-<` g(7dȮ` r)9i"Ѕ:pgT<|[DZ.QzxE.Aє@0v`#pA @-|@yjJm0rPG т|Xb  >P Ol ,(E 6 zB |=0?,@ ! dXc0`iX )TG:ؘ3lg2x=6cMsva'@VqRl^Jy4r0 4h7B y0 |S/ Oo 0}( tC/3HEơWяoMmRgqC X8F4-!xi97Q4|# ޑ} ̀Ohڀ{0_aEhh0}`xMWa }p5h, "gH)fE+|<2p(H=P\) Dc@n3\BPpmc p4.AtH0zۆ8A3 hH$n CN<@z|Ё7p ,H,Zp @O A{x LЏh8Pɩd#0O=VBoE( @'B7@C\  QAAQ.ڀ7@@]oD/ޮN7\ mVѼ'6\8Cx=Adg^A@VpoR%t-jRx`7{CߜM `wg@0D$(*ؚҳTgL v.œ6 }zD_A6c1X@\*0*4@d>4^g&`^6b&(HcA XA Hv C,Htuh1d(@ 4L]@G1&4TsZĴK(nk%7 M06,V!X!á54A@4X\0d`\<*7$[v%9BhB|?$@XCvLЬ4KKй0H 9K anY@L8)X@IxI 5(J! h5m<+ӎı ]bP!~="mApƉ`=Nss|.s!PAx'swF(A-0Ww Þl2l)PGKovlI)X2)l7gw{X@GP:dݟ KHDg.; dus$(p RD@s噹HaUױ6 wInss=s~C@;}!˥N:?`,<,C[C;In̓A-Iw;H28lXvJX@w lL7Ё [v[Kޡ1hH,DB C>XXjx0y|ΈtCXX+6I䉮g`zFC7hD]r&cA0Cࣞ7,`,X81 Ȁ3lwoe[ p$1D?JGl7u,X<I d$& ,-0}C @Y- sLD|L4ha !hhey7/KP䝍w*AA> <ȣ4da/ Ĉ&8@B8X"҉fh&@Q(<8 ,b+i`h0CZc J)6g&#Hc+OԀr,Ր 5 У>xf lM6$5x=,ؠ&NӓpC?uG=PC`iȇ9=~I'/(F>I@]*|* f!_^;0ct(}vdSÚc)K jQ+h}91٣yI4 7ܠh<Óhz԰ē|T7J"D-MR=`&0 +`ȧ-PYDI'5jcXROp)ԓJ!{'TÂLz@) *hMeJL@e'׮$ZP,6?Ƈ |&\=ho{$,y; `&zأOZa|٣Qa8aNt9H-Ãi9©<>@nO@X?(mQ&0YyI)xF>FNoʃ<)N*gLe<kh@MLJ]Xcn&no|376[ e[`I [/jA #r*JcAR眔,ϱBʜC)X"`B~؂=x±YA H Geah(<'2o|  b#,0i`aXP@0 K3@A]5B R fȇef~aF 8a9RCjAL *<[@|G><E>x e3y.Ԡ? 6`B =HEC4(2 4VC <Lci(>'"H@g̸| XlٰF6xMtՓ`cY8-@2cj8p@A 7,ߘRuNX?lAQ@jdLȎ OA ˈ6H3E0A_]:Rt>u|RDzTG 0kX@AtFC;, )S e`H# c@z2Y c*n"`< ! f` a FM NnQZ ǚ e | 6[ 6,'8P pK怤j0l H n`N<<` z D.> b`@ dU6 . a Xv*bri%@-(`JP`K,`O@KHnA2h7J(.l,!H x Pp➏,ᛶ)7H ` R $0pa jN xjArP!KhAA`m Fv RQx͊` h@ 1Z7A J ! v mJ@T X  'Q `>$X׀x`  lGe* ".d ,@a#"aPŔ! <p5L>2e? ``< 27f& SX` 0KPԠ,  6@&+ Z6`7[ Rb3Mf ! %N  @ Pd:` 4A ^fA  o P@\ ڡ`x] za@ Gl`Ezdj0 ODd A@|I9P` &D J X`7".A0H ~@PBA> 5 4̀Aiޡ ֡ N@  z!^V M2QTT @XԘ3 D $n@ $ $' N2aA VZY@\e|^Ir7t7qS(#a. Ra6N($W N %_w3\ aSx`T6`3H@4l@E@,`^( ! 4 ,!@60 uG``ҁ% xЁE/! @9 ~x,`` vYn$ W<D`\ R!@x& (`P ᫰ KN` A ,!*ހ.MIF`  !fazAΈ Aa6>! !raH `$tCpbM> l]@#!&A">A\!`5a&DN Рp0" NZOr,¡ +5ě<60jf@ $/<$F7,~2zN` z! l %^ B ᢡ a F(`y(@   㚮 ޗ5 rm\@ YD`  D vw֠pa~$H$-R2 DUOx >u Ġ ЁB3KvCXԡn l i|ed dOH!Qa`n eOhl l pp='l rC  4[-n"r l4a@ ` ,Z`RAz@-,EAja9 jb>ahh :ϦzG_sԡՖ:o i&NaNtX`ՀO a Z@&lI5@!: @"I&F.M. `r`?k]/5/`\X ,D\`Ϣ rY,?6A J`AdV dHR !c nQ @AǏ y{7Ƞ N,N .` jjF%l V` @04 # (TE_w/N_ ΈO;-Z`bB* L%N"  <Ll h:7  JnhZ@ ā`v\8sˀHt| (6ONE?T @>@*, (K=3 uAHS-YNչ]AS:i<\PA$ ThVa d JľʓL x4K b R fٹ ĠʄH @&Fψ#0A d naE >ćZ B-/N2,pJ(x,Ā-,-GV!ȿ$ `7DɪdA |@ܹV-VhhB7?*@@-.q=j1ʏ| KF 9=H#԰{0(sJPrsҞ"GwYen{$ƛeX 1/h`"/ޝ)GXs k?T`ɑ@xo(IIٟ2>6#dڧe#WGw}S~^x^XM4BDsrFCC~7v0F [XR:pqjx H)=Ge%q7GH&Aq^SX!,VQd|;E>id-x=݀a|A|s1 FSa1<$x+Ow*-L`($PRx~ߔQ~JTQW a XBWauܱ27Fvh-H 0! ({ rӃj!%W̏B WQ0 fSeҍ|=}|S(A1<2qJ5@7^M7Sp"GD9< >JJ>DRyX0E VE @4!TRhXPFyA3X!k4±~R p15XLB {h[:rı rP {P@ݼ;pI\H0ȡκ6 `EO'AB Џ h@PB0}QK:Ng$q4+.E~q0'LKZKsqT~1G7bѪR@=G^A0 =Gb# ȁj/S ֶ! ?!Re0q8؀,=A#^ >0}@fv/ r@^1HFF`0$"6H!)%(0laj.ma\Ա"DanD)Z QzSh]OxXxޑʽ)^8A L 2cꡛc@{pL<$j;,?L}dx `%N# ^a 4Cx > @4:g4&Q= ?g"0l5,>Ѐ,F!sHZLjǀ tUlFBL6<Q Ohp>"ZJ), SP䡵"j:< Ru =>pi`hQCn-x`jBW-&h 7 a u-@?!nEX~CԡG!+b]L^CpQPa @ ,ѐ 9Ԡ 0X3AJ,A% L5vєXXL,h2;0Y%ԡJszц(YqP,` AR(>A8aHځ PبFC0i(0z  `n,B7'}7БtiB>0j$qjj ajH\ZaE~!q?8V>?a`0Xs!D`:`@!¡ݰ9?$%"0CjH,d<`3G%C8Πq[`ѹk~.$)`p#  hq4ș H&tV!}CiXN j, BKVdqXa:,a:@q`NDfS&6$R9kӯ^dnqcNV:& H`r P =$ KcvW00 5y\ p  +0 +@9ʀCg}BWv%F\p jp2< j PRn}L0leI hIQ#QuPVvpRt/77h-QwNb6`R`pCpP`nEunP6"Spz G@w NKs% %])w&e`Ђ`O@4(i% ,$SjP|mR0jpؐSG$P9, |j tL ߠV@,-m(!PhgGyP!xvT-l_trv PKX% h 6Ph0S@'( 2 x\B^t|0 CSp`](X7p} #KpqppGgPpg'PosL@{q$b } y`| hP`=#{B-j ||p [ z` sf@!YrV1, SP+ ' iKV (p@xB C<q GSgN A@X`ϐp1C0,$WUp` @,j 0-0{5'kp!p!`p 6 Eˀ#R` U- 5@p=fpU V%bH-? uI0%pzhp ߀D)A1yx (B`pg^pFJW<`$2`\9dd 9@DL0,*P\fmtP0

c5`x 4w`" Lp iA,w!,P\7oqa_j(`G%)/0V2D DP2%zV't0cF 4;( G Ёun@ E `f` !WpBg=ް @}w̽4% f PSJV`{ G@&;24pq`i0 {,x %C(){zl5}DQ90`‰(B$F.p1D^V:P#y Pp ܐx `{ Lp L`n`;x0|=hW{ x0YM2 p w`$p `$2y30RG:B ' eo]XPKpUp1EvVE _P'PGbVp {"0PsLep c]9(Ke?eYdOnp4dX K(G J,A*{cWyP iNS)m>zo .9 v-~H *gG=S&xc kZ<P:nBW4_R7hPJ3b~I`_PJr m<ʮx+)W[ݠE c;h(ظ䥏w'Ew(A LY2ez)s_?/2Ӑo$ f2$>)+s Riqꆝ}|˃'Nw b+P]txaw#/^7qYvi1Ĭ&|Qg\$\)Rݼ^+Б ‰Kq]w%!bn'AqeoZC y,[(ALm^ ."PSH@P?А`0 ;01Ɛw0ƺɣ+P/b)nZ@&8Ž$XnNC:A{ʘBwDh. g*̲&{No8 o[(Ê<@*<9!>0%o pc&7)6"%p:@ z  ""Ckmƺ3L@9e}SJZ\VQYCIÂ4N3!4ҸGXFǜn%R߹‚2a%D\<.@F/αh) >p4KN #,pccɤc]bwbia+4C3>˸m#P!1!/Cƀ.?ۮɲ0@"nf@ 8#~4!@8P`>n@9Fܽ81D$!(kaKxL8E7P\D J)*fRC(ĜP  2sy@>,a(D"IhvE?l=@B$8NA '850$H)aR8,q ,Ty-0!(zqgTZ;c1#@:(ȇ@Qq4' @9L I;Image-Info-1.28/img/test.jpg0000644000175000017500000007075510456430012013427 0ustar teteJFIFHH%ExifII*  (1 2iOLYMPUS DIGITAL CAMERA OLYMPUS OPTICAL CO.,LTDC2000ZHHv951p-801999:12:06 16:38:40&."'d02106J^ fn  v|~}0100 , 1999:12:06 16:38:401999:12:06 16:38:40  F OLYMP   (449  md d)|^GSR951[pictureInfo] Resolution=1 [Camera Info] Type=SR951OLYMPUS DIGITAL CAMERAyyry;mDZ ua  ) _daBOS2 PASCII R980100( HHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?;RKqxF O?h#^iMV 2|4vGR/z!Ԥk&`7c N3ϵxNfG<=2M jz|^hF'ZYk+o#s+zox-\^c+=sR}! kp XP;gG3_aQFkh5tAAr?%/lw52V$P*7#GL)ޫ,f8"1Z$Nϰ>/n<sWE#ffr*? ҵhJlé>WO;Er{=_v= K.nCjYv,\w_)F$+8aj.ˈ}OJ{+˩iF^e9c;Mђi|ڷ]A[v8GҖXƑO$\lcm#nq䴶9ɍC^!J3Z&TOx{LW/szh8}k2Y!/6e{-R0z" W]9z6lhO9BQcqО&.;!$OX0ўy6@mݼl,s" `2g ]$ ;TeUǚ 8؞"6d8 VaX\H'''A^LB@w!SJOcIwoƠeO+c˄cW=A犙cwU;OJC+Ioc-éłʾdg ִQ [x =jJ A+6XS'84T@Pht3,,$l!=^M1bmWFsPyk@dcz>kYs+9+oen7z$`Ib)2ȅ[UK/̏Eôp Eo-ı] yr{ɮ5eK۶ WLa(RܣSFj5EO[vȖȻrj=b+.NVvu2TLK;jblq)<~Ml\4p^6o fG>UKOEG#o({U5rl Xsɮg1ǧM<,s~s8kfDmEk/5-np2x³ U<6*pԥy(RFH횆8]mRMh*'۽tVcЫ$~?z)C}Y$ri@}?ZK=6,P{7ِĚhfٕwoPs ϿYYbcn~98_;Q̌=8~~Ub$rצ-|`ۻ!" 3C;n5g 4A D̎b.ҥ7UFo";MFJ$[_Jֺ}Uڇ@}j;Mky$}r>xmym7<^{Ja#Ic,6]!}ɦD+fmFN@;CMs /!ZT۝ S9nKy[Z]jYœkZɵDƹO)Yس$8CHy CLC 1~I =qIi}-H;cjmw;!_>'H̠(8{/"b̳Cz}MqײŕW!$A+ӭ,2S1=OХht,#9tWxtkSBw'ҽwKimHU@@=EuQ?W{_H5 G@>B)s[^M2gNxuח]saQ,+oRĖRC:YNׄ{e=֋y#b7=<TZҸͯk*r; {YR pv> ዳ\p3.|ii4 I6uEb4z*V4"Z)P$2;uǥ_m&.6^o$Sx&3V=ӥt7,@0N@t3ОYũAm] Ҧx8}A7Xǘ]v=~#,v- 뮋m&/Dң]=?GZꭼO[,KyXLDkשx{CMB%ikM3QT8h'&[.6;֐PJD`xi<29=N=>Ѧ/@OxKOm8r$$T]Xm{佦ʱ'v#^k;ybHLgd *)g=1T<:gIv*1ےRx.Ծ)iy 29zLGᐯ'(]+ 4Woe=fw9X~k Qwu$D'#vM,4řay= `$m횥>asy괐!e+_BQdA6o y9`8RLNOzjQ[](F^'vw6F1(8I=g*ycVvV:Cܘw߆$hyu;K|#7TܒWy? G_MzeɌ-1]IhQ{Z>,c{< 4է͎W7`OcJ[>H!r;?B"d{'n<ǓD\Nab%\7{ hj:e6|Ït kE7epsӑ?*ԕ=:Q\5I!gI:CbiτВ>O-Bsӭi [O1|ۉ9Nk6%Pݩ-57"F_`xq^#IꖇPWz~q]GpF]`벲fTd*`^jVRy$*@n:օƒ<EUlxS]{X+ St6HO *ލ-ďs={ZGܧ`qXL6lI%dGƵ4_L ]q֬iF$Њ"S} F2]y`qүA4-H̹9KkIg>m1 b'_!GRcadd!)9$h$Nw)Yj# .ӑes+,ԮluWV8$>NGju4HF.a1{W F0*&IbA$8u"FVI͊NOCV(sGs]Vm=*ewMûY'մ&!cOo$lW%̑dJ2LŦ\!'ZP0 )0gR2I ?7`p}{vv-r8VI:-3sUn.J@qңP 20/Lq@Ϳ';a3FUI~Oʟ0H <ˤ\[_ # sұIX['8+:?ݜzӽk%5ܩ$0@s݉±Rf`Đs93403/o~ W[yx9zQU~R3-Q]qZXbyr5Fzc-F0H)%Υ#䎋Jy.d+;q"5étѵyeb 6y9翧55~D#ʌu[U BG ~+\xlQK[ UYe@u:x5t%܄9:kYR5ܤJu:[x [Ё'xr<5WQ- 1JfY9W#z(5wL,˵Jg|&pzs&Fl٩\7D['k0:R [^}qN}:_1bX>r\ș d.|NHp~i5:/'28$xy4f$KXn1)luڽZOs[F 0 SP~R =k2~cfbr=EWϛcynPG3@$V*QErGgDcY4Q\Էf-xA㎵u)is2S/~[4+f%[Ae;[5]̮fGPW5`V+vL=aҫj&6DO(f ӽ9w9псʵ(N[E/ny^? Z `UzPZ v)'0E4aX:rGe&?Wu8ƹ|_ЍkTHowSO l9f:of]XWܿM2~3{ӜqKuk3oHwl|~0<^J1{I]'Lz}^=@I C5)ſob0xpxk|7F<DcsAamèMo+p]֞^F4@ՠÈ$G-X_긦5>rڪ˵d]~C-O'O=rh,auk5VrVqv%UJ+fjuVgUg';K\;Z٣lk!ņ=mwNe pzmBkC\w4g2tq_]ch`t==t'#';TAaFԓ.6 "n?c 9z٭Fea5mWA ,Yn^va@lUNGϋkV @$u.8a 1'F6LwAs)>[( *^+j;c;S=lݔxu5Gk&$M|\k*!"1 #2A$3B04[y?O"qڨaGV.-R*V iaCjګlSx[UiM+،sD:kބLej'QYEnO*'d%`3_K!hzU̖5`k 􀩖xu\xu=;ۮBD鼌'2ey&*QC3znC^ %80>/mmN 6͠V1NAoRq7 2zNgBQ_~ kwJV0V/FC jfa+$Q- e|c|38|6WEv*@1 9^5kbbW8g71p&s܏&.W6~#)»ߝ|s4Ze+ʪ+;51-h9'?y41kZR= clG#^O0frmZ_m1 :'\RC6n~S&݆[܌NBzqII-.p[KjAzG ȃ/\QˋTt 켮wGꝏfZ6}v3ۜKa8]9zga8,<8LjfѪ!zXA3ٰܪFnKEh !ݑs }&c&<,o0BVqX͛ C[#vD<k*g\8e(@+V`=TBn=dz "=U7R&b -ӟUSU,3 ^grճn+a 'S{}2SBǥh+l[ f=׎[ 5_\3JrA3o4_棟>PlI,8[w)}a,OQqIQƖ˴27Ld3Kt yk[nO[kVK~ֲN5T Bq6،䮞W>q4f&?=|rh4Y]ޭh\ۏ-o T;%qXϖ:GSU30ZMf>s&! 01A"2Qaq?\ [&Eb1]ybfL{'P !c0 J.:lfeу".qhcXw 3eS u<GkL|}*sjgu:ԵdJ V{ܩl˲\0} ,.@. KWN3|q*ܮ۷s"ANMW|6I*fGŏfecMXFkIfAN_ cוWruŋ MORNAa%r bVM%aKSt瑸VeꯉҚtθ$A]P{NOQh|Х ґz໚\qf]ȩgZQԩ6yk):E_ {S'.xink[EDbuʏO U+:4Ԝq!C=M4FgWde7's5XDui}0{?|,4;^pRS-:a.5O7U:b^:eW<?!^θAtB;5ؒ4PPiQp*)SaSNzT*iJfgVjū,hE\ElE: K\qe>Orx'$z*ߩ)Z?ԣ1m KByr^'b'\; edV$ SQL3E0zK-1nŶU5ti}t)^[ֈ: ݍ!xu3= Ƅ[SGƕϭOfKy52Q~+Qs-Kf9DE=a_~EEg*fZl^푌]Rz-oɜ]:fGJ̐[tKԏ,; M7™+h^ <l*iQ;\N=Uzk8ͿHG ԡZSt%|?a_mFG|t(d|اRd,ńT~>Dlf\}J;܊k3NꡚHrִ]jHR+JI3B&!WIzv\rariiBl'̤USi[VG8v>x[Ve\&%SZIݕaং갫{<]UER.%<[%#DZ$OQ' }2R1J݈hYcДyx?q.t{~E+6qRK5\(ߓl mmH(jk4ei35?D2~GW).TyiZp)-WFjT`ᒮHD'$f.ǡn=3o >Ҫd [NGTߧn[D2I&fX+m.2Nq{Uʶ3OVܨŒ8F^*ǚ%j_aMJ(6M ]EN-, ukԯ\д]zzIӽ6WUY$z y58 *U "L_Mӛ5Vt5 S6g[N1܈,Wo{NR{ .w$xHqTRQD{M.ZϮ~8G$a =]cv*tzeɭ}=;u\eўtO Q4Z{T_^̦W|SPyY8jDgVcu{Sc[ 9t#rYv_N}V/d˿.%GU-jNQeJV{ᡗR8Нq[v-t''!1AQaq ?! C4s*ic9PG#h*2y ؅u9&L2єqU#C 2r \JHXZ"j%iu0BRHuun"dj+*klnep_EbqFIp+ȶt5Pъb yO-lؖqMJr0m)G rK xWQS/8azԱD[t#䜰qh"x\Bgq1lGt KìGJh*40'iX2ڮ%i9fPl{[ay [*%pƂ\D|k^Qp b.~Q˓ Ks1_,*Q):E=`z&Lt+2 wK$\0YJ$-s:07f=ez}Pڶ jR0cRFj _j s?;a3- NFTOHYKᅾ,n Y߬$ze+~y%C%t=085\9{A(\AmA Xh,,~/V LgslUX,˂5lYP„/ܘ!>ef 9ATB"f%D59cwH7*S6~à"/=~EweP&HdWD|Cvk{PoM}p BT%Ł"ΐFj>D6YL</Q®eDt5,ܤu"5(fiW_䀷Afڟ}!Zz#[5[ \-p&At*T/hgDlg7EhKpaVyb;ЧGVLL/)~5JYj\̸넦QݦËZ讑@Bڢl}ctofaZ!ۧBFGmqhXEˏDbqŁHa'xQ/KSM*f)GSr)p6bߓ_D1Y ^[2ܼ( > e$sJNQee#Vs.rXOXEe}UGl_^fTV}& Xff%]Ⱥuny/lT"PkJLb^/,纕^c 6|*wf Cm)z"g$s [Kl,pCd'#\3>ciEœc7-Y3d]MKD*ufEf D ׇ~pmvŅf]FGo3DӺagEm[տ&t,Vow@Ǭ?2>0s)urg {H4":AU&5Z#rc‡rLeᦺHd)\aľڙzȈukPpֿKeJS59rDŽ:PvI1ŒႷY 3ms *_ꔄc TTWzA`I,*!~"wX.fO (K`@+pNX0m=(+DSZu\Xtb3#?t @Ekr"铥*ψZ.Peh9,5J r0 KU tW1Vy+ZxJ,fpE4K3-44^_.nf s_20J\ٯ%W,e;kqc 3v[ɕ8JS ?PufҢRd:= LNps.6<2JTSd^ҒiCƙQdWTٚֆ*ғݟ17 xh\(X>!w\ 53iBޱ+ELBµNΧ{@107rʢm*L;Jw9pc &֚wƴ˞iGC[YL]%>"(e9w~ _n(uMeWX<_(g;#s5oi!lJ8n^5\%>y*UP[IыT!hpB/^%[3\KT38,56dq@I'dx0slcf8v;T*q30#=.sfa;{Y ^-HlpеHc/&ZlcGI6IA1(f"HFk=A /A2V:E jޖq 闘yohU҄{#UCh5-rM/ Rh*鷴`7g!WvB;ژWOxd`52ra/OBQrZDc+͟W͓!q7hy{{C@U]`uB RSЅ03V xeO82,;FʔT=|ܰ_,d9&QbzDo .paYg38!H5f"a̩_Q_OIUh_S*̹QVsLG";`@5!Bp -p{17Ms=Nuy OǔO`-C%M>+NpBv0^&E luQGD"eg0$ǖP)V=YbP2Eq bQ=DB͗ qH;*Xq=) 鸚w97,R! W\#KK20ǫ-OwRBFo_I#RpJ\Zd7ڈG*P b+(4n:|9H,r9 }`V:ìb,Q K2& 2%0wek(S*[jmzv%^`T1 rP.dbB1ZP )rshf[39XՋes+J3=F^]EXf|)6a&FK3P[ u \[L#ksҹEX'HL%,n yv}]fq>#M6>g.ffA9ec <"]흢.рE"t1l\KD σܷ64cC G?4{c|S0w.؄UefJ]#9"ap[s{G-emap\DL`ٖ6AejRhP@7s&wu5@#Н8q&k sϣRD{{ UP{W7*F2̪.`/4F=RGr؆em[sJDs7*k .Дu}RR%9fPW*_e1ie(p2SCht#t镹(n7;J-9~Ga!P6|/vw9ǤlIN{ń;{a I!~5j27geE$ӬGrIʅ JCCslgYR _hs1~ u'1.#e:;To!?$Og!!1Aa Qq?~ o1crU$RAn% OiQ P¨"n:-/ ^< A7FbhpF gb[pٺ&ĺ4aexn6bFz(_oh鰢i2d_W:Eo%Kȸ ΊQ!6?3F?c.#UTO_HH8͎S1 'iyP%+@tɩ"N'F_*u Bmml*:Q󉭖^7^r l*SQԢv/ !;rnӦ3)BTWO=Ch3]8) k@G,"Jb4Q+t]~1):~%u)C^1 Ulh򚠠x`!xFz#4vD53:3 G\/|d Blz:"Ģ=O5 85#u;L i.'JYFVmu\P`LE'K;b+"t(z=]魊& ` }{ûQ7Ӭ5<ੂql_y2*I΂t PREC`t&7a$JW(4_˯"w_GF-c uُF MqM! xqxUoNgzoa:k_ 6 NGpro2\нƓolYrN]xPB즓(^9qf/-k HD/Рn: s}*@iZK"te SJ̔^&sE?,17B1F4t r/ғȞߌ ZT 8MqM9o* y&(>AA2$F'n~3_S"߳`SfgɄ'ְp4 (ȆQ) \YVKFSs"pT q2w:&X(u6wQ%f(G# E; jp^^U?9 M+q[YwqCГ2ы]=KAw/`)5?P m^\ֈ}_U=m>$.ߍR^^ɔ ?+H/(n=^v~pg@<͏iV/Oo8e*d?)SW ߮9BsB6W"-)! k{ 'xC`'-ykoI.w%E Cl1s9ST!:ӎB k/k ZO+'IGWNl:g/}^Fu×pEW>ivtDy" ?|J役RHk2R0c{Q,_8JVVw|Nr7S_ ( BA 4!?KAx|OjB^p{lCv~B ;=5;t2!P5K×@O:T FNBkA2茷xdR]IvP-e@{bVȅ<q|cPǎ(ޯ>ZdsxHCףu[O]I0;y=<;?n@\h0i݀PC_KEQ0 yW@~!Gg\@SbdtMN].l=|k}\C-Ӧqɑly{<~pB~>$F~ƛT;+Eʜ㾥Kd>c 4_9Ҋ԰N6ӻ ]?:|k%6l8MP\\x u}z)fR~1H<׼ePOY v8X^?͝QE^| z{d;eXR"`J֩y{D˾nF=,];]~ v6sޜ=2)EaV/xO0!CO$`=‰DR-\Td,t4][7g) W.zow:}ɉoS8'K۱Y[ʚ=!Ƽ?&/C-.8vuˊh^l頑p66{ ScBw)gwx𨅅0pHpt0GbYzJT-Hh3[FdtN3-4,4FqshfL/tҋ|9rmOߜ60 `w|umUqa|‹:"=*/Rq^t` 4^ʕ2GGC&hXD7v C^D\EP}m%&$BhLU2˹|Q`&LSLcil|̣M?~i:/U SN84:/_lF܋Q#TOLN's'42x6ZG7~@qj-zlHө}~:^HZ/W#3ҩ8ӕKJ_]PC vp('aדYQQ;r\y&mJL9RbQ2B:`X}>;ή:c((9~8nSi "As*?MA֠G허<)^sO;ޓDC?q뀪_zyNAa^ rF!�J6mC.[)7.0iTv_킇BSǣXw֡o1I7*DO8#*7NѬꐪWufoؒy6QvǜT/s\%G`{^Ū }!MlA᤹A[]N0~?0^#斞sXENfI~Pb^Y(jOtE88wCoS.ITj=pfB*o^GݬBQ Eu鯳(4 FeuTޢO}]A_$${au `l) N"`#g\PݓDsΊt2ԊclGկɦ.ʉQ4 pzc$Xr/Q1ӣwE]_^\"#qî|'n?iz}bEkp\(SU7+D^u1Wz8}>Sˊ(9} <&"'A~pC^$zҘ[7+A-5"”T{1CBaNqzɄ]t[ay:X7@%PEqbagrY"m(sdMY]m04m${r~nq#KqREj!4gɣi]W`5}5Viļ,LzФh;j`AKO 6w?zv{{ o8J6%j|1 TN>bKY>ir$ zehwצySX2=e]pp"ht(PU:8U/Zx.gL 3:ƫcS"#L[@]״(N2Nx^}xd05L9C5ns0=̪5B#Bk1Tjmվ}l]V=DްVX,jֿ(P2BZzƢvNzAQ> ߩK,#èzJvZ/n3+_&Q)AS6t@H|K@*2ao:%s5kWB|bBj9S޾rˡ oS9Ngmhj!5l Muz)OS?aVfDR qHTqJ'}^4k^ ~i?^i'{5Ԡe_p#O1Wu_5}òM @pvtw vO,n #΃3 pݡ,F/'8]Q7PB/ 4(B >$tK n:G&l b86X"}E/Yg% y;p&DR*r8% ħ%vK­LIqg<]p>@'3$A O>~xPRN{1% w( M8 DL[wc^&hDwH~2}"fUtN|aHQKߧ'J8@1Vt̕sM9&0p2PjSW&<|uȂ7:*Mkhv^b]^‘X2bb&0 MoD;:>[6שpA9dX@JvǾbAt<+'H`7.J*Pw?yTu󍆽_>=rPI G_!6#?F9!^2eyƷE5ra`lN jrz?e'N tg%Kj8rc9AѶ-dN0Usֺh5͈KfiO(u⮨JdHl.F#bmt~1Z'PZWX%jy{\!W@ݷ_X@ZT }wowx UUUQjH[_ݬjUVUTZoo{{ڠUZJ<onjVݮwUU+Bn}{i!UTR@UUUUUUT@o^UݮJH"@[U[ZU(ov[~5[]l@@A %TjUfoknz~o%%%P UU[kVVUJ^w_ZoRRR$PBmU͵UUUImwjjۿԉJR"UZڵjUj_޽_^*}T$Q*ڶVjI$]{")RHUIk]]UUUI^{wwݽj{@HRjnkUT޽ݵVڽvV"T*WkU]mUUUTݻ{m}o}Vi(UU%RUVnժUZUIwUkvڨ(RUT۪ZjRU.~vk{k}۷VJ$UKIUU[[VUUJ _U{ﵮmRjUVZRVmm{߮{zUV+UVVRҪZZ]ڕUZUUVֺUVw{ڿmu^Y6UjhVUUJRPݷo[w[~TJJUURmJj ڿmկUh֪JZ[ZUZU٪-m߿vu]Z*UU*ҪZZJ2?[~wU*UuJBEUZj]jJ}۾߯}jTZ֪ZUMZU*"vo_mZUEUUUU*UUU6UUVk߷w○}RUUUZ&UJRRJIMR_n]UڪUUjUUW~ڶVUUUVeVVUU*Bo?wUMVTںUUumVJYdu}エحRVkUՕUU]mSUUjۑBB"$_m}vmۿ[Vݺozjjꪬm$""uvwj[kURUUP l׀+w_[nJݶkSU$նJJZ&DB'}}{jU-jUmZ*"EnJ)!H\@7]ߵZ֪vnJյUUUU)*B61 @ ukUJJ*ժeUUj T$ S\!LyPU okoݶv % UZڢUUZYQUET ~ov P T Eڭ$UjhV"D 5 Hv޿!  *@%UMJZRD$$o(H"P`)A )!2@Q@A( [o]@@P$ "-URVDR%I U oڿ{_D (D@*UJA*A HJ( &! BI Rj$A BZIH]owm_sB@ B+ J,@ *I  }*H Ҡ) Q*%B!@H P *JQU H_Vw{ @" HXJDI%(( Ґ+CuM۵'T"D@Az "*PT [onޮoB@J@$I ȐUu_o+JPD(2E("@`@RR}wWUUQ*" A$@$H@HDBU*D-C)W^um[ 0EHDEH )PAA (=W߷m{!*"AJ(A  *JB"$T%ݷԚеu۴E{$T )R?}Q[_TP"BAPBD @ ]U"QR T"a$խb o[](@4J @+KJE@@(R oZm}_T H@5` nd$5@@($&Q *@MUm]J SU[Zo"  ){oJ{_}h$ ;vF ZտuUH,% ℀Iހ@$ %ڵUo֕Rr$ۻqwTO J JJVҿovݩTE f@ڸ7j(Ra I"оmJ @]/W}QX*gm!*p@IR^P $RJBڪYY%_)@m% o/MZV@~UAVhIb_$ `R)V$/Tɛ*_{$R!_ @nm;+B*v$}DBCP IUD [/MU@ P-QID@)"(^G()QP*bR$b?/UmMA2UH *"*KA$QmڪZ7Y RnMJ%{=FޯDM '\ӄ$JKE*E$ njӻt[JߛlS&hR*0U!~оIT J&۽iބn}JTޕwJ$J$EC_kB*"A?SRh)(%A!)IP (JEU]:j7 H ۔ҤR~T(DVD%[j-J$.}%DAA`P %w$ZǶ iVRJR$vNdI>EVodA&HTRT@5ZO"j|[P i fETEQ "E(M i ځ׈欯IjK$f ;6*R_oS6[)QP+T"(,a( E$hHP{ffrҪDlVR3Ћ6U}QD?/jhԩ$!R_0 $/-[gY^$ ubPQ (I RR2Ⱦ) +%@ j%$$"׿ Ѣ?"o)v̌* m+ xDJ%JoT JI]e UGEPДUh(YH!-_ŽI?$+UܜXWDT%*u *H*Jo} \ ( b B,2R{o$A_$UA% $JDUI@KFi?_yʨP'QD@\hF)oP$]TEw,VndRE%d1JBZdF+δdk_ۉ^JS]濵Z*ʂ*Q$_{~iyaXK~Uw*Rv dJ"6ǬVR!(6x_ZE_ߨ  &t ) !aM)]@UNT@+eE` GQQeKn+ԿwwR?2  (FBZTY U1ڷA~mJQ Ob I*kmt!VU[mЪTr&QT0֥lD S^FU%:VRաJ`%F"UUR̕Qou)}zU Z(kJڐ$TI_DDFVoKӿuQvmURd+CH;7HλSBZU•#@5o)oem_گ] vTI(YU}fjޭ߀M^EU@QFAZ g+Kovu? kFR QZ휲m_Uﺪ-@+"Q:`YLe.+_Ԡw}uZUARAi$tM+D ݷyoWU&L$HQ*a$սޫk@oڵm]u_ߵWߩ#e 4" jJ%RBvmw奪BUhZ$V:kovۭuR*(!N%_ZmwC*0 TS1渀&BVWjr[1T!*b!"ҕwY_nnmUUUm]ԓPPHi@CDA>EUo{oUj]U;5 (5 ֨@Yy嚯[m+U@UH o}(U׾eUm^~{*T_*ꂈ4B@Hh[۵Wo}uU_nUJJ"ʒnIe*SMy֪URUIzRj DbAQt^V}U_RRKƬФVVHN[w_TU+U[KBR"ӊR7ャtm{UUkUR*PTmMPW̾*O%J̻-Wv_xYUI{e}MJJMSk^o{[O]ݖU-H?v}-.EE@6JAJ߶ջ{{jVҢW*Ze"%ZkShH+mn}WkUVUT_šr^tM*V^UZk{{{~UVU%V/D%=+H&ֵB(+]}ުڪTJ;ڪ\BD2\߻.V׽{~}o֪UUJ"Pj%ejgM+]a-m~|'}ZUIETeu=H|n qO<ު}vUUTUew[%^*DVwJ^;WݷCڵVUU#jT}%H'ChRKyR]XUuUUUZXxU%IL(I-zT4*ФUUVnKJ*d%4"%u5M !]:V^jU%V]Hu"}R!*TZN'mU_~]TTQANUJV%Q TEڽVVnU+JʪPP(-&#$ )\%}v^omUVU%^H KF%\MRDJtmJkv_eknTԕDPEW/e)d)u[S[-Nu߻_UVR(G-] U5U.iYǎZֵwUUJJ_⪄HS'eUPuy]cejﮪUTԒQ!* "iuJױ `ǯv_n߿mrUJZJ }ujhԵO}~z꟟ݪ%(JP*jR/_mkW۶UR)A*(%N}JH׏m[[zmZU(HTZuJޮ]w?UUVV%T%TRԋ HfwH5ҫ{߶k;vݵUTB UK2N*K?]m׿5_nU_ RU"$RS=vUjխUU)IڋꪥݿW׽]/kUPRHU@=Jhwom_k_^eoUUMI4AM$BԖk߷뭻v"@ JSUwկ_oZ}jUADP;[ݻﺻ{wuT-(*@Cʁ8־zk[6AMHZ8hR~ou{Roݷ}tۿd*%ziBBh Wmvu]ۿwD! AXwBUmԪ׿zR]mmRR"Ъ(" u]I3w.گ}_X8?UZ׷Jm]JФ !֙m_tWY5mjڈ(-ZJPGm^¾"ZWޯojڵH. V~o[_wD r׷y'[mZT g**B$wW/[ʽW{)vOڴ@Q $~Zu^WeȊ)wOk{_HbVmtۊw߷{׉(֯ۼڶI.Y(zzTʵjֻnoM-#NQ[z'}P* PXWUm[oV4VjDg~@V ET$߿`ݮ۪տk^;T${]E)]Z!J3S!JAw־mڶBGjE(~vH&QTIZ@߻{k B`͈zh(VB J *}][T]ROm?H%*Dm}zBEJm*߯}v_X*蒦&(@\T Ud[j7&kmQ{=[rZB" ;z%}\¨[XUUۻ>huP(Lު+ڲQ*n%YwWij䂱ik))ADb"T}XibR}֭W{սUu^y.u@T@H dTTHBhmrP(eJ뷥jZֿy$y*(/ݻ_) 2R]UU 5\ճ1 jQPh%)(SԈB5vޫ5wv_-TBR&)H(ֿmp˥wխDUմY1ńH"!"!JД+߭ZMIVa[zw9Q"F Q %EPP_knkh)[oVYժB[WV@J%"J Swݗ5|/.fjq^KBJDTR E@(y\۪ԕdnw[{7 ;u]r(Q %7ov_z뛭R R.RJ3j{f $ U_5{rcWAXj;EkaPIjJK/_ﷷv o٥oWjTV$*UMU8մ!J%DDU{ړzseb@ΪJ&a${,H"nʷػ$JRSP imԈ*!mԒQ)Uo[oժz>BB R-dVE$B m!b @U۫^;?o֯V*!CK+ҥW4hAH"Tzϻ}ۿY;{r]龔-VR%j* T+w׭o= ;A5U֠OwDIUJ~ݛjڻUݯ (B]KO*Z!_˿ݷ_/ﲥ<{hWm)RHT )IVw[^ۥmVBں̝#E겥涵!Ul5_{۾DY~onr+Xl"Fu*ULVIk{WwwYjUړ}wwnI@jWnk[F#"Z̤/zvz"eJLuDW]}޷u-HDڕ-{ijҮժJR\)o^}oF^vmIH^սmkd\]UEksl׽jkn־.EKa]?UV;(&l]iv{{Յwb'UUmk2H}kWxAGQkWwݗcԨTԻ].kjTF( ~kjY~_KcY5zP w_UJETw?۟l޿j멖/گ*}oY/쭬)"ի;{vVD-zg0\eV$H/j5ުUUokz[kWm$Zߥ.TU-o[lnhm~tUS^WMu۷ou6tVU"?}'.Jۻ+]۾]UzvڰDMUZ~Uo9~MKɺۿ߿�d$5+5wJVoo(Okmnu+ڿjdll*{=ߖշSQ_o߿~~_}~kWT,Tz>o?{SO}nVnwꪭu咬-m*_V^{ԷoU]ԶVܪtzYջrʜO{o{Roj ϭ}U_m2nUYWt;m~rQz߻j+}ڻ}~-W.:n2LizjۿO]U$ۿwju%=߿mwZoeuUz&JJ[Iݶ_Z[IUm߾~}ݻJlRJ~eue}{ooT[5l%KUwj{^Jkw着ZXjJ߿oUoovJRTUjRU}/Wҭ_D^jnɿszj[__;T*iV%jko<߫[5Rݫ[uojҽyJʾ߿z~mojY'ޯv7uu}Z{mRWm_qN~nmI{]-n~vj~ݻ߾nվ߭_WhuM{v׻{[o$]_~Zww__﷿jo^{7}]o~u_tګWKm\VwwWwﶵj߻ߺVdkZ{ovޭU]~~TWm_kozw~U^k~V /i}W}{{vmo߷nWw{n^Uֿzګ+^rMwݫ[v}|ֿ?-S߷}UZ{vZۭ齾]wwn[o^uݿw}޶Y[VuڵԫU^{mk+!^ꪫZz^g[o}VݿU[+Z[e޺k]mj]޻_zUMZ"~~ۻ_}57_mYzWnݫoFuTwj_-Z6wmjݺ{z_U훭W׾}jjK߿A[k}kwݿzW~j覆߿V{j"{"߾wݽݶ?o-V~Zj[vJUjݷ__}om{߫UuKuu]_N߶Tۻֶ߽Tj_}ԥcf]߿[_|WjRubH~[uo[_TIZ]Qn[^m~EzURVjUlz{oImage-Info-1.28/img/test.pgm0000644000175000017500000002507607204034277013440 0ustar teteP5 120 90 255 EEME@MD:+-.ENMu}j;4+**/89O[h5<=60-5-&'&&%*AK3.+('''4ABD2447J4/,%""%)(" $1=EJMA(+%'*E@+29D@;2R5./!%%*."1LW=RD-U`&!!%)***3;H?=422G緵پ#""%*$9LLBQE>4GQ>.%$&(:?9MNL@>2037=ACJV\QMLRMOP[# #,$18EEDQ96EPUQ*##(,FIDMHDEDABNMKELJIIMNNROYǬ)0,2%#&-53,$$"%HM4  &%'.--)-3/.60/)6:,-()2?AF9=@@>HNMJMKM\⾷-3.4'"!(+&#($#):NP"$(+(*4.+)')+-31;;,"$!)39:>6B<>?NSFCFFJ\Տ{xut}ȱ+24,"# &'$'()-'.9<,-(%(*(2=*!!&&#&01)$+69<4==TijHN]WSCDEIQotonkihpqzrktv|yy{2-2.# $!!"'"&)#'&",=WQ+-(&'$""(,36@<7=6731/.,.6A,(*''%%*&&../3=85+%%'$&*'88)'!*& #$&(1,4@99),/*)=@E*+.),23=:>vx}~|yv{zy~xvz~~z{tzrzzrpgfmumn{}zjfnp~76.+,(" %&"&&&!./HF:3+/2/0+$""$)-&,$-@KRG2;306505>8/2+'(&&"#!"#$(>3.'2.8<1+*8/+/4DH_SKG\][cepcgpr|xxqu|qln{}xu~qnmi|hkbmxttxxzvvmyvԗA0')%;uaMJQQM3)&"$"698))#%')+(&*,#%04'-1GLnM$)LYWIH[qxYURRVutaj^U^[Wa[m|zmon{\eetv{~|zrxotuéO0PΟhO)3?H}û[2RamU?3+&(+.,1;JC)**,7;15=\ggWSS[koo~}ze]\_kkgx{fcxo{mipur{vwuplxǽ¾K),++.448<5,-+-20.5KYcig_{Ƶݱtxwv}vxurĽקīźϰm;.+0A:9=B@;;B=0-)&O=LNYmſĦӶyԍ÷s<22G?:?NVDF=192'(%#(),C))5JjzɔĸȿѰڤǦ¸ϭjCACE8A7A>&80FxG,'3*-EKE:4ȾΊџ~iqoŲ´ίͻͶM<.:NLQZs}mOFPF69<:I>MA5:@;>]t[azҫ}qzDz˾WGjnrTRöֶöi96F/4)C9DzdCKVEA4053(75495:87I<6Q4AЂ[VjƿªqfUvi 6W^XQronYnxp  %r8 68^[1<5AOTA@F[x^jccK[ĵ˳wh/FRRhmn~ƽľ¯{h# <=>;=QO:)KǾκ¸ĸV S?+ );VcIJKgeSu^uh}OM*a. !(DDLƽRn" +#  ##&= 1yºǔ¶\   ,=!dk\_WOYUtfdFyskʭܰN()e_|rj .  ! &Mjmͥ W- X^U[]dv[jzviA{yUm)#cO[IyqOn|ɿ ( (+V~ʷB a CxhpmYurfSG]aSupoI**zZnxdzг3 %$*$ -  +kКu}ɹptg  4 *\~X|o}qkXOjh;_hzvĩ>,## Hò̭'  UN PhwbvmF\VL¯|h|d[´ŧÕM D) '()#' UƯ{   >oS\O 2w{{eiHvoste~uQ{̵̺8 ) +((3 tŸ¥ʜ  $$ #7.uttscJorJrvu~ćvM- !ch^]   =@$/ (kbŚdc\x[ȻÙÛgoǾűƼĹ̲F0'%  ;nhvI_RdɛfuW.  "2B .O&|קkdmandhڣ_k}y~ȶn6"&&(, >YRunq7Qm:9TK>;  &/2y@+6a0aȴźʷưÖo|ÚĽpfNc^O+  DvrbSRinLvl7/ $a#  &gsG)!8A-rsfeeOb^̭ˬǮU÷tvpi^~iYYA   $JRMibHPli_f360>3  D_aaN½znWR7>l{Vtæe^d[wyv^NI\njz9Ca~^L-  0D6Ca]17FYqpwvf&D7G  #1*V|nKtU ̿rt»ǭ{ϸBHw~}ZNYLQNN7P.fðtX944&$8PRP\m*1<:ES&[Uye0()'GV6#>DRkTUp&!8E1==—֮yˮF^s^ϧzpIN)#&-,)6jF1:F`u<"2;aR-,EXUecZ^",<+045JURI *JnzY8ż\ŲЮ}Wc~kT͆[GwO20&&-Fj~u2CwqfM(1E=56AZXfruW-=#$",;HEG   *[K-Dv{}ycj©y~q\LaiΝvmVQpbAAD^jňwfX2/!,L.;SOP:4#72&#'HEHJ5 $5^systuwzPZy^_MYS.9I>5qy_[pu6Qlô~gUK|_vNA'5IjUrt`K..4CG69<]?>992*-0( 1.53RUpvo|V8Pvs;sL3z^ggnrgLągQO.7f]qixgMIKM=B.SJN5+770 ".((7'#'I0BcxnZ(4axkq›hglomû~5 GRyDYM_s_NKQ8?FQML60220-)+"#wg"-Sp@(32 P?MhrW0eZɿ~C,=|}mxvxgWmho8kcJ:$suqZUkTXnYK=Y:IQE;15BF;3/'%#[lh<3$H;.Roxy~4 1ѹšVŞ|pZ_YSWjDj\fnZ;2Y]Ur9Ljt\22vef<=7JB?>/48GQRI>/ DxHo`,  '&#+'$:HY^rl|}sF  -ȸʶrhmL0C3LK(==<%6FcT=_Ļftſ4=es2LeQ)-+/$sUN3VA[zMU[`U<% !$?^_Q8149iVfǚ5~aT}rAKcg]tUK;88;^y?Ǟ{`ʩͯ)#4A\N4c]A388mzzyo5=;?vPBwg}tnXKCCISv`ķγǗigdsv4)2IuqfV}v4GKZ~azmYB8Fn̤RSЎĴlµºqF5%@Zgy;(!7_dG~~ayz_kpSj|vk?@1(0mddM]88I}uj_qhhK>NwTOɮz˥ß}ʫg) *;dq6&/6DrT{d]nuRtnEEK#/owO72)/`O`bNE;=)]ufY?yYJo|`od̴Ѭ¨VөȻi2[&#+2dpEAL3K}SZStU:LNly^\U5PvSeB2V325OB2htZ|B%14U$+S*M>M=+KGCP&)<=B6j]S-*>rtW`^(.)O;PTwyspf[3WZ_o_R~jܶewp`VN[Ƚɓzh?B*%(+EHC04K7!#;$_M_D -6:TJ1$JP>>bF2 ,8E((/>]cJS3G'"! ,984):A-aU70R),I+%!Ls`pL?DOTtZnTJcH6!_RHyJ)#xmk8@fmZ]}HD=A|SdOhI*H_[&1=bii]0H H,$( &c^0+Z1XU;75Y)YI1-%9jk`FK^x`j~KjO`FQdUNrIyMaA=`/1Cx5DFQ7._hfVyb`RVfjrsRZMhV]|yB)67^ReV,*2'"&"AUgCFS==&027F)3J.F;5R\TuhuRLNU`>3_+:,ˢbPTGWED:681.Z=MjtIOrizk[[<4;]vE!6T|f6%#8SZa/u1HY;!/!)E-0D@R,( K/?C/EBG.FHIyIewsVX@kXlLJPD4 0or_=Q,-?74034)2?7EQiUA6oVv]tx7(6DVnK/9bA+5&Q9&+"&#-.,?!*AQ$NM0-0W1R@jJ:Qw0Di['vgeN^Y? 3./J&.;8+E;8B7*'*/I;?WpA;.CMg}{gG7$-.Xm@!553,!w8T&%!=Z%S0F:=PxrC?G^]dm?LrV2VmFFH^.'K^]&Pa-HHE?7*/8-(78_=A5P?)fmrcng|{}xUn%,y9}M1"2,'wL6:3@<-YzDdy.:6jsvdui<)6RD_vSNN>FSN;"QJG4:E;,1>)5n1??\oG1;)$#/:MG!2Vjn7VHtxfwo~lP&A07\]H.)2g]TG>E(41<)G@FE<5'/-Yf4UA@IBDVyonjKK""F&,!N681"/,*2+92<]BC3:15+\V)+&')?Sdsgj^nhac}erz=30QDi-'+> 6A>UR.D?,J^c[G06WR1v|eTX'->CKDm^>Twx_+/2(u:A1I4'$++#$ %==2A%!CV//5$(25Y\ttYMI,IeuZ~}stY`DAXj]=)"6$* S4HC0#N1D6EWBPY[x6BM^ZSPA;lYge3H[yV ;31K6=3&.$ $!=:AB912/78=7XMX?("&gnRzKTFNX6RG]P.:qUSOI)8^xa*=?9P0".ISb^vA>O8mO>n@0%B$#24>(!??>@E-071\dtjUF0XA[j;=XrhnSCifN>2.7($/L+%'*%"' ->##a+)<&69D5m*3CCnfd_|ZsGS.#!&# -&!:"I7., @5>F/D_RxwA0?=RXO83Wzd\`RF/E/1"% 8''IL":5##/[_/=aq@J~h_JD68 (HHNTfX[]oI;R(E*,%&%%7"+,)/*9""D86ECTY:0/75+I_a8pmYjRFC4,*'!HP?7,4*&0:&'6%.?0(;LlsK|hFZsPZbb&#"(-8huPSNb=>2((#/1,(F6) !0+.&7!!%3@;@9EI%'c]_JqxtTHVWI7%3,.,*:gfG;1* :?^$ 'A;<5:/x?MdCJa]9&(#"5&tP^Y@"6GgDIF+,/Z/ "++% 3+3+*T~`\vtqm}ZcM|FHbPX.">GR\G:8%DE1! %#9:B:N~soLIU6:lP8!!/#/D~i{E1/:L2+"#HdG:':&&}9')!$'+$0,"12'&$2?iQlyviVqlcsXrb]'1[eoA("Bab(()/0-TI ',""9TSÔTCKZpS=H*!!&4*K7mc2?163(&$0eYU85(x63"%(,A.*# ("';V*OwobHEFRD:+UpvWbtlvgJF)E^,%2#SpV8,&4#3:,. % C#.bL(>B4>Image-Info-1.28/img/test.png0000644000175000017500000001414010456430357013431 0ustar tetePNG  IHDRqnG$PLTE֍uxVYa/03a>/@FM]KI} pHYs  ~tIME wIDAThޝzs֖5Ɨ@y#d P$0b[bUjR/Vemz7vy %69R`L‡;90JJX1pU;P>Ǡ)kX4 CHi'I1?ĠeKsFS;/O'=AR!b-m$? N&'V˲LӺ4MU-Vf gb,t:֊e9Y@i\UUG bysn#0-e9Vٺ4/*zmn] qP e: jiV4/U|5ga@H@޸Yt:T<j)j\PP`inj9C"H gq#o󛹪4zL 7vӿ;[uI)WA4.r,15k7ss@E&pHE p@-hBCv`7!6e¼ЌTֵ0 Բ^FX~!i"z}*nbtzZ.V/b>kZBGf ArBiyf-fSeeCmvnn7K{zyy1ksdXe,?c9 ZPN?F:S/s6Mc|c`8ԟO|'Bg.lPOsӸjje|R7M5PKp~8?>UΪ LP~Tݣ{tn~Og3\\h(fjV|~Ox%OS&t_|&$SRL}."Oj"p f ٚfAW}]=l>X V&pM&pE۶zEeA~4G<*! &ùۊjO'ty!O^?)J/XG!L~<9 x|_?V7M," my`<L_I>wgɩYƮfnlaZاۋ8He~'iUpuXr)?dBtkh0{z+ dcor0W {&3uE״;/V}{Hw)pnwXn\= d2RK9sO;y29ƧO?^ﻯ7 /KYv  >y/NNS~dž&_^|~0bqQy""B<ϝ>O>6|ޟ^`߼b{rC :&z'nWOVkc9z,.eON]Y`-{9=ߐ>"d|_> d6rkN@hc-g+#e{`@QnumՔJqh ![?7(#wXW.ڿ̏f~c2 BG~L֋yXQ#m;q %"@cW=?4Gml m]f+ksvBFh-K08rgg}xoV{̟k' ޙ`{ㄐy%h\_}6:KߵGB"':vki4@m; +6jNّ4"TGhUAmf̃ r;$w77*EW 6Tɂ_:% ?`o٩+ &:^yl\Oa_8P*+h]MEl09loك[ݜyndu# Gކ8|:ܿñr[?˹{b&n6ND9\ڻ0a=lFK;39]&|By7qG[o3C}+[rL3[rײ7ᖜq 7o㽽gqo͟Uvk(P@QQoeߔöYҩtab2d'E1\K2·ktH}V2F>]ͫ?ͦBX9I{nOaG0  m"mN}02{6Cpj(59~Pj|l\cg`@ FiK}\P_JO\,Rl>Y5:;'Ξ+y݆ &.3V$$ZEKR2U0/ɠw4?ggܺ@"U9]@>7€-lgOQ+Q<2RZ$ov=8s{OK˥z!LZ&nX·WC t 12U )o-==$% yj-8#`x5ja)r*$IHk"XjRq,Fi¸&)z$YnrXn3zǍC -AB7>q{mmG:MBq\-Tj'^.! 꺇kF HIfDm-6:bP_!-Ϛz<_5JGg* jR9D Ty-SGNb5ϤZ[)k'rE;}6je:b@+JDf4#jI 2emyoZ GfQ~˲>jT((9@杤$}$ql':kI?ߧ(x٣tٗ^ӋϪ5: P'Q4"A=*P\t?|Q;Q\Ay=JFAu Rqo5Y$J3n@aLo{ .KDי$Fxu$+1~7 X{,@r ĉ*hzI-pCN$QK\WwgQe`aWfzFAl ErImh$,KTw~D$*4$7Eg:9 Gip<*%A=HvFam讇,7 2K&MThVG3 w oQ~O.YF4>I%ԒM$n 5^~LK:j/9I"1#0T0-! Z3jS'Zl !Ħגi ϢW)&jÅկ't։T-45=F2 HX2Cgjê'"$uHC$DM :5f+;M4\4rFDI+x5Q/e=bԈb@F^~>]n'ZzZ2'r Ռ鶬~sD{އQwbZo@Avb$ o%܅ }[i~73ȉ]4$=DT52g5홥|<*F54K^4E.5P~&%QBd&LgBЀBB4nuPJ(jZh0_&EU$X%l@SSR.E7*05SE90Pܷa4ӏ@LTbRji,eԛƬߣYfDTGBb $Uh/'?tc \\kTr~$B""[hS$La G\NԢ%3Ioo@[j&;F^&NlpooHQOr Rㆣ-V`g⏔?"bh8 T8Z[b&'.PFZf&Dʭg#DKFIwa-~eZ4⏢Y4s[<zQ,D0n5/!lLIބI4 srxR7©.EfC XmEjM{~&qԍ%S`ZNy.xKbxq@N"D>|h_IENDB`Image-Info-1.28/img/test.ppm0000644000175000017500000007723607204034133013445 0ustar teteP6 120 90 255 :IR>HSEO\;HU6CODP\;FR,@I".9#/?%0A9HRAS[BSSk|qlqZtd,D:+7?#.5!-5"-9&2<38G1H5?J/9>'3;'/9+9C 2=(1*4(3)2'3$+;=?V@N]+4D(0:"/4,2)1*5+2-5H9BV4FR8IN)4A,5D+7A/;R;GYCLZFMc;BU+5 06(0*3",9;FW5DI!/5-3B29I?DZ7BO3=I-4;LUVʽ,8B&1='1?%)&2'0!,@#2@$/)1OBMeMXq2>WEUi7HT$/CMUlNfs*1#0#/&1!+5",/%,5%+7-4A6O*4?,0=04=58;8@?6HD7IGDL\OWgU^iIT]FO^EM]JT_@SXBTZIQ_P_`$0!*!*!,%1#.<'1(2D/:MGY:FU;BT5>F9COAGM4:?*.2-34/67:AI:GQEN_GPfBM_FPdJVlGSeFRbGT`NWdYgg̼$/ )3#+"*8")8#-"$'64?S3FV;JdEWk'?LDHYCHU>LZ2?G+5@.8>7AP.:E0;G'1;*3;)18'/5(,7+/6*/43;?CHXBGYAO`MXnEQcFReFReGPg@L_CM[MUdSYdPZ[J`Yr{%.")3&5'-<".9!$ ($.'.=5BT:K\8NZ!)1$.15B-1$/9?QaM]t26 &$'()!*--47/:@,7B/7C)5@%-6,1?<@P-9E&19#-6'-8&/:$+2,0>*2=)/4$,3/458@G-6F+6>'.3$%%#%% "%!%4?I_CNd(7F$$!$"$#', ',#()*/1'/4*.7&)1'0:)7=)0<'/=17B)3=+0=%)626F5:J(-9&/7#*0"+1.49;>O8BS;H]/;L2@O6AV7AT6@PBIWJO_IM^EKZGN]ELZJMZV^a޺·(.:/4A+-?*6D)5%1$(!. *4&-6'%*!$&+'*#%+"#))(16;MCPeBTd"#* %+"*3'-/!,,(++34;,/3)+3$+2)-",+(.0).41590185HSEKYW_^Ҋw{uyst~rs|}ʿ)+7)4>+6C!0?%0,%3+#(!*$&1)')("),%&*'+/('1,0'(),.;0:L7;P'-9'.< *2&1$)/&+2")1037:>@$+1#$!#$"()#),%&"'),25/25%*3!'&.&,936B5:G9EV@EXDIYMQ[npoȾ͹Ϸڪqu{mn}jn{gkxciybhvlpnpvypqijxqusvz{yyvy{{Ѽ)5B&/=/1A&/=$5",%5#."2%5$(2""%)%'3&)&#"/$$,$&#!'++8:F58?:/5DQDHWTZ]{{xúºƸ͹ųɵԿ̶̹տԾ̸rt{ml|jlzeguehwgiwabyefzcg{ghwor~gjxcftjiumnxhisvtpoxsu}wv|xv{}{~~Ư25C,2@3;G17F-4B$-7&1#/"'3%)*$'-!!#)#$-%"'$!-&&*$"'&(2.10/39?E)0/$)*(-1)17%02*/7+07#(2'.6+.5,2<8:H#.2% "##)#(/,197-23(+*.23,01+-.(*-*+.'+,)35*,,.0.*-,132-24,24;>H7<=DILSY`z{^]hJJVDEU:?OADQGISXU\orqŲépronqpgixefyfgw_bv\`t]aoaeqbetgfsaaodenhiub`gkipprymmunmlnlpsqwups{xy}x|}~|{|{{:BK:?M6;F17=./4.1;*.6+**.*,+)*(&%0'&-& *$%*&%'$%.-29:;FFNHMQ@FP3;B'4;)/4"'$"$%+..5;5?L,3>,1<.;B&-.#!" !$$%%%$%**#*'#+(%$$(&(-*+--)+)+.,466-01(+.)*'/0-''%,.-688;9:<C/++-(#-)(+'"+'#'%"&%%0(&-%*&&/./1-///0624==<88?/7:$/)(&"''%)+&$!*'%,+$*)39C/;?!-/+,!"!#%$-.!))"! %""&$$(&'+&.33+.,554B?@::;7:7'+*'.+0/0)+))+%?=;D@=GEF==5)*4&*1(&1*)4/,0,+1*'/'"$!'(',-,*(%.(%,'!$&$% %%$*0-/46./4!)+*-045:'%#)*!,-!'( ##%%$"""! #%%%' $!##""'"&-+LKIdbdONL?>?%,/*,0./1')+)-+134441@<8;9;>>=|tl~wpy{y{{|vxyuv}z|~{ywz}wx~yu||zz~~{y~{{tswzz|trt{zz}zzxplspokeghgcnnqztxnlrpmq~zz|}|y}gju_khmmtpqqv?39B075++3)'5)%.'"$#"""+%)'"#''"('$%')#$,00,13FHPCHI=:=81/,**.01324*20,25*,/ &'%#"!"!##&(*$,.,%'&+-0"%#---=A@MKKQRRIFK0458AE034ACL?>E89<2/-52/*+(&)&%)(%'(#('$"&# #!%"% &!()%?>;063,/.&)&.55+1-7:67=C-36'.'*+%5:8/0.+-)/0-924JAEMFHg[aXQTKLEHGHZ\dZ]cW\cackcfmqnubclfihqpwqsuz|ux~uzxnpsv{~|~tpolmomotz|~}zxzvuv{vntqmnnlmjjfz|nffojccb`qllxzwyrsvtrxxz{xu{{z|vvtvvxqml|xuyvqݘL?7>,&*( +)'&$*?5Qvr`aiRJWOHNVN_YL\TJQ531+)$('# %"%$ %# "64C>7D77?((.'**%(#("#)*'**&./&*&$',(+/*-."#%%&$/1/355((&3,'8/-GIDPKMgqsMNR#%&(+'KNNYY_WV^IIOHHM[[`uot}uxXZ\SW\OSXPSWVV[wszvs{b_gmipa\bTUZ]_baYY[VVbad`YZlnn{}~zzyyjahLunf{{ya[\efgefhtusyuv||z}{}zzwvsrryxznqpzq{vs|΢ͱʝXLI7-.YHcՙmfmULS.'-915C=FLDSyϷǠ[Yf31;TN`g\ooiyYR\00=2-<73A;:936.,*-./-+,0-,42/5/-0/(652LLLcTYgbemhnnefc]a|{{˺ƶϺ͹DZɸ˹Ŭż~qiwwy}vw{uwzx~tuuxttsp}Ȼ枬ƪʗӶݫnlt;<>0.,0+$5/*G?>D70?85F:;DAAB@A8;@:;DDAF==KNINOM[ZXhqg˷ռű˾վȿȹƯѼѸμɶǷʶ˷Ĵ±̾wyÿָܒˢӾϲûƹ°ōƯɥvrw==961-611KFHG=9D77E>>SNJZUYDDHCFKB<;024;8;225('*')-$&'#%!(*&)*(,-,IB=-)&*+$:5.KKBll`~~dxԻìɱ˶dzïƶȱɾǼϷֿӽӽлŸζúĺ㠨Τë̴óܬ˺͐phjIA@I>BHADMCC>73G@=?54CAAA=;''$;773//IEKxuFFT,,.&(*42:**-..)EFJPJNKCDA87920F:0cYJf`TXLITF3/M=7PBB[PRIBA_`a`ZTUNBD?1úh|µȱʾǯͳθԾѻкιιϺϺ̸·ѢۂlmjboUlSȳƲƨխѾ׾Խѿջӷĩ[HEF885,*E70SMMOKOSPSYYcktqȳnlwRNVLDEZMMQB@>4/J5)I83D85OGC@@:NMRF@@<31?91I>4A:6C>4g\OutvaYWfaOv|eqDzȴͷѻҼԿսӽԽѼy}orwzwɬįʛկ|`cVBUD3}gMkOpsspWUQdLEzȧȶи˻ȯƭǼ෶˶ǽ}agG33A30MED5.&844+*)=EH87@CFCxxcdhEBCLKL[STMC?H@;A/,=,';3-<1+,'#86::46:30C60@2+B93=70B3.KIKB:;;7/SPU841DB8tįʶʶ̸˷ккӼӼӼԾϺZ]ZTWVih{ö˚ѷȹФƺǬ̫zo`ngRhQ>pVxsiY  G1"qP;xWAtQ9jJ5jLfLeGtR;slnrz~ ¶ylr"!   &'!sp{88< ?3-@6.a^]bZ[7/.I82<32BABPPMWTOL= <.,zuz˯x~z}kbklhjMH;uwzulymtkv[iv|~|~swvQQS}v¬ǨѰôڶƪŌ2<< .)   5(7$%1%!=0% %.ybzsqϘϡΟ      *# $$) $"#?6,9+)qrruzvtwssyfai{QGKopvrqxwIKLpsxsw{rttǿxvx­ȥʡƙLOG6+' *!!.V1ihjX_hy[]gì     /O7/B?E%$#~A)# 3% mjsg`b~Ɯ`eo`ej`Z`wxz^[]zշȻӓƙ\jyzpm~ռΰͼÿ͸ԱƪIF>8/'+'! 3 !  W3VvipwekkŹ̆qw~FISW`xJTa\euُ]jkuuzWWY0-.  -9H+D@I" "./3pC:.$x~ܨjksiadmmpȱg^dkpufdcajs妡[_oƶ¬`mx}txy~ڪvpnj=6,$$#%&+&''2&@& _4}UuKtR?RQYĬrudoeu49=HS`cp}8:B7:;OV`KKO?>>>9;    !>I&G+"xxB>J*+0778XG7.-b_ox̚ӯѽ¤۳ȟӬҔoo{u~ȯͲмؿњ˽±ɤ¦esz~`ipJN^`bw̋Z^qUOH+,+   %m8kEd;Q&D"mK3lijiov@Ocjxbn{29A,16!# "#$$`bg$"(       +9 fihqtyLFK,(-!!#=86]9$-.+to}gvyfekwdcv`hew|KN`\di]^d}٪֧ͮZRaխ̤mvnypn~`i|Xagwaj{VXj}\XTCA=      3!t= E"|>Y.P&4>`<`DUB^QF/!C1.-179?H148       $(O@@h\^b`gbaezlF3лʖwzgp{TViKT\:5:@@8dpoĪq}XT_ovx̴͢âdcx\]gcdm^[\ww{{{tzuwb]bMNKJJBcXbnlzlg~r|7<5JB=ɢx`bf{Ӹͱΐa^[MMK+.-  K'h9S.m7R*M$h n$ |4G!c[@6!?FL77=DHP       !- C+5'M{tuklQID}rmkNA ۽͞~spz{ozд̵Үzz߰ʤAD=OFIxw{y}|V^RVLI_V]KNLWNSIRLMPH:75JTO//&hdoԫuutZXS8;9!650;2./#0!P0mH/uI)sF%Q)a9Q c k,i*r* :|7:G%T+lC0.*(       PNIke^tpf|ylsm^oeXdO>;:/#/&,' <+$``bss|ƕڔ۹¨õȟtv~ּձ,+$L@8\RYyyz~|iot46)J>TָǏekg||EEA<>4@9(0-$@>9CGBVSM#)#Y\^TV\sydgc/2/!&)*(+))''IGGZVO<5/+!T8"a<"rJ-bDuL*zL(f@>= a+k:]# p,l-j.~;J!O%M+        653]]Z}~zwpaQbP@UI>^YMf^V^I:0 @>;ħ|ɻє婭wyݯHGCd]]xp}ϫǡ`^aݟszmsfJIMHRO++ #$&(4- .-!-("<45ijqDHE12*<:8EGCb_d}vvq>;7%!#125=;9db]XRI8+ :(\?'uP4sN.^B]@zS4T13'I#]2J!^" b%d'}:EBt<        ),,HMJnqg|zx}jSI986оٶτ}R_iԿիɑެ~w~VUfsѻacp~zϑlg}~ST\{S^eIEPszvMPR05-12)'',%2,"KF;nftvrxt44)EE=zt|o^oeWUMA$'841.HF=E=/F1M0W<%rT:mS;ybLnRpRsP3'#D'Z5;B B R f-x9r8t9    %,.W^]JLK|}}7*&CEJsw{zw}tx[cvǔ^lķ٤vxv~ɵopzY[j}?RUa\ydiyݘqx{knoTYWNQ]jryad_CA?DA;NB;b\]phjŲ̄xw~sscRfV@;0%//,!"0,&VK;7-!P6!Q6#W<&eQ8mV@jRhMlI0A'&J,O0)(? \(h0[,Z-S+-$ /1/-/,[_Y\^Xwyvxyu||lmcJA@-,0152~QYkNUdgo~jt`iz:6M.42S^bqsBG[L]pwekV_nkxkuŽШjkkt|v{KRZ{y7CBgct~}zںص˖twbfeX[\qsv~xxzORTUY]UUby~{|Ĺ˻ע~{rj`P_H3 ))%I>4OG85(I8,dTBM;+cP:aK7gK2W2N,+1 K1F-'!&+?:> ^A8Z>6JHGDLS25: ($ 95/[b]stsyzttukuuowwnwxq{|q|x~UOLX\\wx]^pSekNJ]QZjQQe,-35;=EJU<=L(:?y~dutyY`pȪȫťQ]net|rs|36?MPfcm֧ufhjTUZLIW|z[^rkzMNPBA?*'#:33MGLkhvSV[pq|vugh`S[H46-"2.$850KC2VC4@5%A7-F:-j[KP<(S:$Q2W0Q)>$<)B,9#*2)! 6/1,/1268443RSNTWSqsivwqqpgzz~r|bRO=74NQQvtfv=9KhvVE`,67vzzZ]u`hz`hveqyʑßymsbisys@O_~~ï~ggmSPRRNJ4.%B5/gdna\anq]ns{ynhhbTL>QH=NL?QNBC=3JA54.&ZREWH7^J8G0A%O0U.K($ - <*8%)$ +'+­57='(("$#'''HJK30-EB=bfZzxrooiz{~~|gUR,'(264[dmsx‡¤hkzgvwѓdf|_hz`pyİ̶҈ïkoËlj׳ȏ|~97*#!JFGRRXzxFCGYZ_GPT]]nxslh]PTNANLBTQK:9/C@9GGAVRHVK>^H3J0F*N*O*O'A'7&8), $'%"%swfgs""#+.2UQ\koMOEiidttg~zx}]UR9.,]huWYg˵սΕ|ʪu~~B@W),53ADt}oʥ{eo~~m|tsǨm|YmsUVemkhgv|qmv=78ng}|ZfnHLJ9<5(# yorwzuoxV[^WUUnlmMW\TYasnfgWGSK:A=6\ZO<;2MJDVQHPC6P6"H+P-]:!d>$[1S*F(2%1$!&"X]fembhz:=A237#%)"DHR !  8<=-00NTRppmwywz{rv>10 ".17⵺ƽգQVdםt~grɪƊP\oSbtQYpIUivyTX^bly@FEig~{W]cdglknLa`?:852.ZY^W^pMY\oq}8<3PLIjhxnvz]\a.41413svbflih[@=1D=/@6*QIAEC>B?7E>2<,I.P1Y4g@#pJ*kA"Z3H)%':9:r|ivJR_dmz:DP &)*#"   !%  #&(?@>WUQmnhw{xook~{twtgjZW  %%|ltĶΛ̽܌µѩ•ʷէə^c~BG^?GQj{vjxx]_lPTWWTjɋS^^VXXHPLtzGQM"!:49chtY_mGQLLHO=>:3/+<65ZW]fp{fjvfr{HPUMWU<36ie]DB@<:484-<81DB;11*#2(=-R:%]?&kH,uQ5lC#a:C' !$'INTDFIHKW_f{?DP14=  "-00  " #'&*,+JKG^`^llcjkctvovun}yywpK?<    auHRgܿڱѧƟӚԠhlԬȸՏsy^p{{nei{^hk@:ElvljlrR[^ffvSZ`497">B',)20+/)%##930\[e^bqopR`e*,+1*+vtlXYVW]Y/-+3/+?96+($*&>1"R9&`A)nJ/oJ-l?!`4D) ACPqyCJQmpzXao+,/  $(-&&)$%+,+%()$$";;8IIC[YV]`]ssnlnh|}}|~}vstNCB    &04ǨLJܶʀݫʧňmp_jyǯ̋ˮiosLJV?;=LIPjmxfZs}w{r~`jiFHGV[W454<1&WI&"  9>:=<5@KI18=#&(39>>@FMMSKQ_CL]G+29)*1'%&('('($SZXMLMcghLMO  -%W3;&(+,fstӶյցuòZYdbpyŴԽغot×PISji:CCMFV}vv;HI,02CFG.2+'%#"+(&"OQXVanFLP/0//2/-/(*,&943CFEVVaqu[hrbhy\biwk]`QCVJB=73'&%22/=<2<4(J7'Y;$\2Y/S.L+9$)  .-)4:9aktpfnirnwZbqV\jRW`+0<@KZ8=E;>J/16>EM/49DNZGMP%)*8@@=>C;=>&$' I0%d=&W0H(G:4WapȲԽڷԹױј̖ffodz{߼ںشҘ253?;ģjrVdv~hpado&(*78?6`Tbfk׶ֹؾܿ߱ї_gtru=BC~հЯ϶,+)',&$X]m+3-:99179@LH5;65@8MVS/>6D@LTX_4=:*/''%&/+/"IDI8;ELZlZhuKS]HWdP]kboMPQektcoajsBCL39E6:E+2:ydf}')3LYhU^o,6ABQ\/9A+47&)--12,+)1"F$I6&OH8cBvuB7*d_thu~jjxۜѱڷ͠&$!"'-).1.+/'*+(598GMVNQbxYcg@GJ37>5:>/44@HJKFSZ\hW]j6A@JOO241ZS`?AI[Yj|{sXL@eQFsU:1ejuQWd`fy|žאћ745y~a_lST]{|kt:DN@N\Xeyy_h|T`nyhxzSSbINHK7'U0L3 D:+U9rsE?3ٜo[akȫӫ٭-+ &%541W<(K,O2E4,kmuq|u|Ƶҝqzkn~860==B<:@B>@{txXNNBBFҵΫƯnx^gs}nsʟǴѯͣlm{YXUTHD_:+U?*OI:oK5rq`a\ӲܬƂȾٔqeqndkgchlu|xr13>+*'81/FJRmuxaw}_g|PVmͰѠ‡~|w}e~068>JNFKZU[iw}[clxf{jUkVCN?1C;0#"69Aul|rz~uk_mWB_D2iL4W5 M1S=4JINklЬ̈gde?EJ;E?69:DGGsltդQSTOUTɬі׿቎ɿ˱ĹqkfxγԭڹխɡºַհΦöslFEN<40)%!FSBM\$-,.?oort`]M9>6*44,)*))1;{W`{yPOQt[Kx^F^J9TB.H8'H;,.'&][lxƵkxcgn]YUJ=2tz]W_MJMpnsr^admpwceh۬̏υֿۧ۸ԡLYeħŸԻѵȡ⠪’Ļھ۱НҳӱұѴՠef)5=V\f*%# & )/%/5+\hfipBEXDH#' /3-259RU`6=KylgiSiN7<2##!**.&,7LRjcnkmyVC9PA31'9.%>62ѮǝДNMYͰwy|x{{}vyvzbgwgfrytƞ׼ڬ^gvgo{BFUOQZacomt{ܳͧ۬ʹռۭٙΠS\}EPd'-45;8+35(-*$ !'$*-*;JP17E?AZmYcmKKYghz:B8&$.**TST1(!KMS;?DFPQ;>?1(,KKLAJJADFLQX")$-)=>9:>A;EG866wiTqXDgN73-++%<>GgtkvQXdi_Qb^\.'3.#,*"NO\z{~ܶϧǡMRWSUZvvyxrrkpgfi_ZV93*`TPXYb``]ooya_bWQI}ngqᲷÞfekm{kp]bdYUUMNUW\eʸԪƞ߿۳ӿݐwxʟ`h;?MABB()8!(%#*, '.,:IW;NR8FY*46346IKT5:,##&" <<9%%"]_lMLSWbiAED",..8598<:SSeAOM03*$$!EMFITSE=4K<-w]FSC573'!,.%9;HQ\fWWXaUE96,.*!*'MPN<:BQX^ZYbtsz\enPPQQHMFKN|~|ehb4.!5/![UT{}ppoWWOD?3YSNt{{}XIJ`SNjkpԷw~QWas}^TZMCCGC>]YZZckҐҳԺ׾ۦŞop}}SOg<>F4:9?=S^tVgr=PRIVd.3@>LO&*$"#!#"!!0,';8:59:06<'+, 5BI~ȰШƦĠu{VOiaeo}|GNi|fcIHU**,@KQUbio\Xp,$#40-===[bw\k]nwSaj+33ALN !EJF(0$(%&*!!!*%(YfrQbp/1..*-P_\411TWiQUa7<>59382;^WR.*VY`DLJ32)//('&";99pfvcot[`nBGQKLOTamux^ahfj~|EMNdlvHP[__hBHKPQYddlXUPSMKvprQHAx{zNOEbaa:CI?>6^bc00'71(DD;vw73=?EMOCAVQMB5&9,]`_djneggPX^t|g`gc`_VQQMXcagrw~ªʯϘciksmsOS[ZXjEPT^iwURv !NciivwI=M.("96095?uTasEW`bc{F]\'/,&,%044"*&$$)&"#@@LNWf`f?EHHEIOTX<DKQ*2+BIH:<9269QP^S^lQSgruchtnuNS[KMQMM\WU[_adA?625+^a^/- <:7--)ښbddSOSVVJIJ7WXRCFG?EO:<9<7(C7'90 7-X]X?Z^`jzBD\ !'/;9NUaoecy;47-#(!992JTlN]qPig0-;ov*5-FF[P[i3@9""20-# .(+BDS*//./7FCHB?COR[*.,')(" #KLM/00=AA@EG+2/AGK@AOBIK/./GEHBKHHHSs{DI^acqujv{ĦOVjTXb@@Hkkn[XYmktNJSJJNKSOGE;65."!12'rnrsqya\i@5*+%!FVV6:A")%'..#$'&'&#--."#,/1*,05DE #-(-B>SEUZ!'$KOQHOS,22+.0*25SY_-35IWZ?AEcltHKQ4<5 NUf")$'& # <B68;-+'4/+7:<+/1')$8821;<[bd<=>>AR25?ISZ??E+*'cfkhnwnq\dvklee|us~s|qsvKVfjo|#&-&/+q}89@C;@30,4WWnxzDBPca{q{,/47:A66;hiylv~}lyf`xlwaku<=9%++389LTW@EQTayouMU^LM`JMa?=GGFKPS^JOV7A))*57/lpm02.=@C???Z]bonvLFH221=;7-()#%&##(00-9;8FOVCIN"$*5AL10349=V]d_W{IFX+1+**&227_gR_vEYj58<214#" 2./-,.'-&05/*.(:9;32/;=!! /+,LKG]^caeaV]_FGP,40865QYaJVV/1@mwu|`d~LWaQ\]"*(,.(9@E;EPIKUCDQ\^gkx|`Wv;==()) $#36>$$"(.$!!GYV,86?KQ5IJ(5.!""0?VO+4/CEC468IDH]T[BBKISWS\ZYYjn|.9=C39?RZ`IOTTY\9AH#)2!#)"(-[k{do5>NFT\iyfoxDFO<7;tqQWdlt|~[ivk{aiyxBGX:55133J\bDE_%*+$&)"#bwuYScI]a3;6DIYdo?UT#3-$ KK`CHZ3?<(..;FG03.1++F:=VO\s|GMQRTcx>JNKQUQ[_27?JU\DGTW^nIS]'1289IkqKWeNRgKNh=NV#,.49=Y^sozYcm)++9?A<@E4:CGR^(46 ##)/66>H?EJ" !#!" !*# E69G97IDISFG!%!(*$)/)(+&!$& %(9EE9=>/3735='*/QQX(+/(-1$*-1@E||hvSUXXfr}itgkl|~|zxel\g{CH\>HV;=?&()!&&%&*!($&-4 $ %(&',-36>HQgAMOFOXGL^BL\$1-#).01=DR_Thi%!!  A:FQOZNM`dls~aq{O`aALQ=DL:@H9CDDEH_alR\kIV_<>PWYr^hwLXhM^n_is|cq]kz=IOGP\@CUPYn18=17<&*124B.:F$21$+*-5@HPd/9Mx]q{GNn4BIdqxB>H,24*&=CL$$'#$%142/5<6AG#+( -7CG9@N8@J>@L?HN*./2/6:6=7-<]Xqc`}lv^oyLX]AGL.06TXdE?BYZgclu7>EM;AVOZSYiGQ`0;?32;TUmm~[f{O`nRfnKRfDET..5>FW(27+28#'',"&29F%(0%(-BKWGNQ%$!3=F+9< $# "%*23TZv\_q(1@5?HXfgjty=AI=O[|}~wbiwZ`lJJMHCD;556:: !!+($@LOAKPDPcGUmZh~K[pN]wR^whoFH`7;BJSc'). ;L?)+-&/4,! )'(- &*/;?&%&,7'.6&*.-11&-.59B$"## $ACY2;?65>?FW;ESMSoN\n/*--14C&+3$('+323>?%'&%'-27C'%)/9:>T..B(&74=K@Pafl~qsIJZqdg{CFQXXfkuNP_[Wed^qe`l$ &(#%#""#!)('---1<;ZkymvKOiRScHQRZel;><@>@.54#,) !!+*"&&5-*54,+3 !!,+:JO08?!.,! " "&'42%,3*0.&''29? "& !&#&)23;=@J2@D9@V5:G=FW?LX!'*&'';<@doqo}GS[S`rtixKUcO`m2=H,28!&-.7?/:@&,/"))-7#)-9DWKTe,09$'.!%)&(+#$#(+',FTY*2-,%,%$$+01"%//4:D*,5 $*)2SclvNT]>?B7>CHMXy|W[g5:=630633FEO(***)# !#6:Dtsu239e|ttwRbn"'2ATP&*<3=>6>:8@>(-0! %(&'73KadI[f#0'!+/7.6>$*3=&:9'1--.4")&!%!!*%#%#"%#15=4?JOZjGZkVlwJ]f2APVhrQahSdgGIViroykwHVm~{;L]KYkN[c>MW-<=(-.4>&/3(0;$0/&+34:K\i[h}BHQ8HX@I[UdvHR]K]d'08"!*8?JAHVGTfS]s?H]7:I!#0=8BHNO028".3%"!$'8MZSi~;J\1=F%'12>;$')#()i(C8$""*)$++#$ '$#(-',5&/'3>"02#"022032"*'")%%%!,56;?PcfEUdbnozgz^kOVqjqelYexktOYngu]auNau +-/0=T[sYhzbs}7DO&)-#):CSVbwTd{")7"+,!!!-**15-26(/2HYa@MR"#)-'.7!#,""#B7.WSR[QNĔSTaK?FSHKN_e^wKUf;'.'HMK199eo]b~uv/3@;AA/280:821:&)/!(/&+*1@RlyOXwFYh28M!369&)(h)=:")79%&! !"'$!#*.!&-;8EK&12%-( %# ')(!$#'(*9;DNYb**2JP_kycqYcx@JYM#-6LWjcrd|G\jTfufxcojy]i{ELX=JO",,>EWV_q(-4!'+-4<"%#ФA:=ld[[gn]flxVgw.3>(-.(04$/7$,,!*'(*0:HS%+3%/,RWaS`k02B%'-+>#+,/:GIT+-- !#"#4JE'-3+18;GXAHkI\m4BZ! %!?K]&$",01A@ .)'%((!$+)$" $;BT+36$-&-10/13*34169%,)CIJ:>B-./kfpzKXi1:MRauAPRGLV:<;52/&&%KL]FQaUmz=Oc1@UJepzPbk1:>iu^ny}&1>8ܿکUwVLhpNޫDx`rmZahbܹomv{   ˵˽    ˽ Ѷ͵ ± ˵ !±{_gή±aPggܽ Ȇld{_BJὢ  z{aE39J ˵wSFAHlbCg3Bg ήmSFFAl?X{EBJܽwqq}rqw mSFHA1d,3Jg ˽zzy\VyXXrqwwmSF 51*!3BJo xv\e/WWeMe`WW\\V\mSFFAA/*'BJoðukOZZOO`eD2& (WOThhmSFFA?5/'gg̼~~kZ`Oe2&&  2Gcffs imSFA5".BĴZZ=eD& &;;cf|mmF?1"9ĺk~e~&&  4;Ycn|iSFFA/" BJgļ~~kZZ2&  0;Gc|iSH?* $33gļkZZD& &(;;f||tiiS5"3g̼ĴkZeO2& &-G|F1*+)$3JJo߰~ekOMe& &4ffs|tX7bbN))%.3Bg vekO`O<=& (GYGhc[zzdbbRPE3B3JggŇy\``Me&--4GfnttilXddaNPP9B3Bgg ˦xV\MMO,=2# &-44Gffnntm?:1XddaRPB33BBJggҿxy\WWMMOM`M2& ! #-6Ys|nnpF?:1X7@aREB3JBJJo̲~kee`OOMO<=OW(&#6Tfn |t]A??>1>@NP83 9JIJ~e~`OOMMOM&WDI@7V6TTfnnfn[KA??:1>aCE93399gğZZ`MOO`M`OMW\[[hh[hh[]HAA?5>@",B..3g ĺ~ZkO``O``M e\Vlt[ KKFA??1*!%$.39Bg ~ZeZ`OOM`MO`OMWVtp][KLA??1*..3JJg,~uZZ`MOOZMMeZeWtp]]KUHA??/$39939JJgu~`~t]KUS?1"..3JJ]UHA^5>*..99.393JBgĺ  ^^>/)..393393BJBg ̼ļ ±z{R8939933.3B33BBJoļļ¶NP893993B9339BJg ļ ǹgoggJgJBB9BJ  ƹggo g   ƹ    C)  C    R  '     C  C     )j R)   +   @@@@Image-Info-1.28/img/test.tif0000644000175000017500000000542010402517335013421 0ustar teteII*J?@$ BaPd6DbQ8"cQv=R9$MRdQLfS8܆i7Nee6PhR:GQid*MSiUOj޷]K$eHdSmQ-uRn>}/}>  rT.N{Gjm6$,|>)(=;PieX8FKdBveS# ˱D9xwv  t0~@ A ?˜Ƽi{8;{#P?/%ۺ/}A]Gv]&ɲ~'0>x*=GlJR1~;~`*&Pty%3N2E`."9;< /vDd3K"\!.BXx9uχ(6q:n[t{&#;i5`C0 b]b {fY:J @ Kb mCEK)B( (0'i8A`"HG81Q8P0L` Np0ŴD`PH޹edH)<-+5,`K{X7Hx!MGzgdk@*:8NCv2Kka<S 6 . ughs< %Yy+ʂ'ང,@ tD5yqq2L$ v 9gaG8xUqjrđ53rY7Z[4ېK| A }Z+@pP ($>]"|xXA0 0:P 0!0 Y} =Eh*`'4( TsP(fS,%zmiҧ927 ޛvH@>#:+zRypFH)7R`<<6:k ?br̻V2 3@{a C}X{H9/Ŵ&cA38Mmٚ'th3yN=KL}O?g] ?@$ BaPd6DbQ8"cQv=R9$MRdQLfS8<24   :F\-dlt(1:|=bbcolor.tifCreated with The GIMP =HHImageMagick 6.0.6 01/25/06 Q16 http://www.imagemagick.org&Y<2   (2(1: bb1bit.tifDithered B&W version of /tmp/aa1bit.tifHHImageMagick 6.0.6 01/25/06 Q16 http://www.imagemagick.orgxQ0 F/?j AXx ƭw])Vq'~}緯_{?XvOLjkcJDl'737*2:Ov\MpppHpPp΅+L{YO}|47>3Qn^~/_ޟ8v4"v[Vzgzx;8sUq!mwv蒪D]y/???.vMz} Iͮ7|zss{өs_?\՟+!G_w#hHntx\ѤCjNkCq"0%78yL &N7Q0@( <2    &2  (1: bbgrey.tifCreated with The GIMPHHImageMagick 6.0.6 01/25/06 Q16 http://www.imagemagick.orgImage-Info-1.28/img/test.svg0000644000175000017500000000063107203410656013440 0ustar tete This is an example SVG file The global description uses markup from the mydoc namespace. Image-Info-1.28/img/test.xbm0000644000175000017500000000017007203410656013425 0ustar tete#define test_width 6 #define test_height 6 static unsigned char test_bits[] = { 0x1f, 0x07, 0x07, 0x09, 0x11, 0x20 } ; Image-Info-1.28/img/test.xpm0000644000175000017500000000337007203410656013450 0ustar tete/* XPM */ static char * test_xpm[] = { "127 13 2 1", " c None", ". c SkyBlue", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "...............................................................................................................................", "..............................................................................................................................."}; Image-Info-1.28/img/cynic_hang.jpg0000644000175000017500000003052410613745645014560 0ustar teteJFIFHHPhotoshop 3.08BIMExifMM*bj(1r2iHHAdobe Photoshop CS Windows2007:03:16 16:44:02C    $.' "+"(6(+/1343&8<82<.231C  1!!11111111111111111111111111111111111111111111111111" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ;KIfϗ m#d R^ FPơmm aMjiNrJ)$a9xH 3j2(aYt PڥәK!?jץUx UXE+g+kzoo$گ3dKv9#z+/I揣i|63HaCR)ʒ58N}QEQQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEG~Ak9X_W>5󞭨WrL)$,kx6kWVo?Oʰ0ᣧ%vz|3{㋿kH#ɤ\8Pu ?碎?QǦ>D56 +3Wu}+ꏅO{ۜƤw$ 3丂iWRSK:忇4KJ "z&5E//%2V1(^@j,Lӕ^w׌1\U9VN W=k >=LBZ^H~mݑ|=sj.d! ? H)M0`>'# fl7c( (\eAfJd|#5jnxEmu=ƊW)sG,R_&~ _G4WKAK?eGף0F~&xiMii]~vy\k,ZN/#ߨC~:"}SȮ)XH:0e9R5 ї,(1 ( ( ( ( ( ( +<]FmėjZL@EL{3|b=-*v=Xe8I-WƗ*tEh{ԟ@=+s&7-qF蠨wj~,!]P{~'GEx|Z֏ݞQ*6rgW/סzK#?>|?EH~*G}~+G-Oߘ—0^ė%ЮԤfh\zkZX՗*Mج^W#+B(((((((/|'ɣ+XEtG|{f>,1}yypKqgi@0ϏRrG+`xՕϨʪƮ/Egꆿ5I>J]F鸡X!bOj;O"kWDa >@8&qwlx\cMnwHFJꈣ,p&dEt`!#ָ:>`Zh $s(2ü!px=Gލ{f(; p]Mɫh|4#QNmw:O}+ _|+#/Oh/kvds,-u ; y]%g^ 3PofA_[^cO #hO!k]Rwedy泤h[[{Ҕ>$tQQNW![9 Jc v;MFAKr@O r+)#'V:pè:}Ŵr7Ԩ&׺ϥ8En"_;1%}%M5}2FhgR[GW]9{QwBE ( (lFMKEB.z ⦥{Mn|?J]WICJ]f:?B=cw\bКOo?_7w\bКOo?_B7}c$.|jXS"7[ $Q,{\' I_e};VZ֝-o()AGx vr~Xo.U?^> ,zwV=>XO?^=J*esfY'M;ytF\wLe9Su(5*j650c;W+~6MW H~ǧ#t붵Og<<UTF⦩VyH rxXٮDY#(x>i;!F8rB)/7n<]]&˫24kM#F ySҸ-)A62zTk}O:@V$ri(oݗEEl=kv\bm]' W:KZ1M]' WOϗz>wWsO#+z[ßXid@e t^?k _½8)$>BS%}WEy+K\ϰBir^ 1Ue);'3)EYy=E(v8W10#wHtQk5M:_;V ,P4wifcI5[qǧ#ȪVt^ u;<6BbuEV>⛻><nbp 1]o~'<5/dz}+ \י|cxd]c2۹{*~4ڥK#%ecWz懩èiҘ=wׇkf+ō^2B=^$0pW-b~| 6??G$گ\Ch|FZ {YO9^OX5ם*|jucV pٞOƒ^6)̶X'z|i^cIz^B>լ]V G?p^6/TZ4r/OmZ'*^Ov?u5^5;1e=O>fԓІ >?_]j&7 s1B.ZYղ8P H׵{}7OMAݏt O hi#e܏G=XtahsK<44ӿQEzƞ#@> N?WW~v5-6$4YV^BkïYem<]Ku_>#Lpx[_Ȳ|7.yL{J{0B9b!*Up͚ࡉݵ[gQX>׏+{'@OkGSli 9+nOۿm{\VUNMv;1N{9+_<$I#wc&SXi-ժe}A9>?χpC}& |gͯz~ku?R~fO_`ik (PF` .~U %(Ae |GJ_*/O-w ok 4jGf>W}E+k^EbA՚ffMn%%-RT։ 33M CAfc'ҽׁ꺬{5+ڱG`Z)]֭er)٣zwiEi{9&ån Z^upukJFkSPUԮu =ԍ+rz~+_iPI?`O |᚜\lTSv$Sz)sq3I+xy^)tzFP@TV\r{z\\tjWNV#Ed(HpExƯZQ.@@T' qXkGYoO  >!_jUΟw=ܱ\&ҮGoS3 WTSSV뾧},lUԂ}j:+ǼERoG 1dnv$~`nyIbܞ䜚mIxdf&rQ<*3_w8_Z[c2)onNuf|+4D@mǩ? )ky"thf٩m閰HcRWᮛi趑ju՟@'CB2VhjX׃h&]b1Go:ïJBjqR]OZ?%WeIvCֿ_ͫ$Ci8Xι744EnZx+׶]ZhsA2E WcRZ9z'F{Ů;2~$&@|[B?ƻ?YOtˈZ 27P;1Vy59qSd3Wצ<ܻci'{v 7Ko>v"(t;7`щKdտ> ##&ץF0Sq>YZ=_ t ^Ιn]I!B}:c^X\ZŅF+w)"zY]"6sUGXEGS*nykտgté^s7phμ0Q(toZZ,q ˖i6Bq}#jZu )Fz_1ju֑\imܣA+~2(ka4:䏨?]=iN+##O}#W?os,3+ٌTJ (~*xuCYV7>:̿|"c_aW|MXڄE!D!}fG„~]^mE캿?OD=KLyPp,ui3pWxpzدn5Ƿy>ڕhւvfRSж۷cҾmMF׍luSzbLw |d9w~URfrOҼ~8:-DY~*iV}Ls75k\RsdviB { nk~x]̖ſPyOs*RQnǣ*THoѱɯ6/GX>9tdac]R¨M~Sױ|dV0-Y3~4a=ziBU^;_Q\|Sk]kM)~z)IE])NB ?|NKRDrf}BJ$ұy$bǹ'$+œlq䂇ecg/ k_/|qyw]qj~9<b yx/XΔf4f}SDmEoV?A^>|oՅyI IHoW?B?+VtF'@=P?55W45ϓ >̵%*]BVE'Qg4uU!2Aw;;k}kEHSSA8t#ԁٯDjSWGW:p o g]kQس^ jAd|*ސP=kkzXx_@=+QYAn{96Nnh𒴞+zq}ʮڗ 4%-K\ 8NJJR}>2%}\H뛧SʩYZlgza}_PPii;]Rk[]xF bm/̫#n9)fl}-+^.~K9E,j0ºCCW9/ 뷞֭K'BxOU>[ѩ~; Tz(kV~!ѭ==C:7u>Z5'}Q2iQE1Q@u=Kնji֗> >Wĺ凅t7 Ļ!078U౳A!ws|>(ZLkV ?ˈGMd /Szֳ_^ɾysz`8RI94ɭU/ .#9vNpU"-??;+BkVhb翡wS\X]E{P6ӟ \27KȘtH1vboh4^ wΪ( {Mok{]o/ɊQƗ_5|6?]n?($5GSrEQ^f_4Ohw:]e\caX{_,kMޅ隂l}чfs_]ל|jWŝJ eQu+͈ήGb3tRzyէmO5},ϑZEЯz}>><ܾ5֜||g="xqT;\VysBnc׿FK'6KC0h$2Uw{G[ۯ{?>nZmY\$, ;xSXكWdL.nOCX%GN=6-62 Fߙp}]}Pwd}3IءSVRk[&/,W̮?co"z.-g%|}x7Mc+,hOs~G7<O{ pFbE0|Ï]l"F3[7cr? _ a[NG={玛W=5$nOcYүMBK Vc<U:z3#=z>Oʹja?x\nkO=ԲHrLYk:iZun72,h?S= F֗ܭEu_|*Ҭ nddB0=~UJ..)ԍHGfz!oEڻN?7p\m]O'w W|?9| ⒌ל}=Ϫȏה_">^1"ڇIzuWFG=s'g~)2ڿfUZVź;X_43Q;.;n|qb{^]z.cׂgIbOƫ| d kmٞVO\鵯ꖞKwo<]ҹJ` 3I>VB׺УIa/73ëx Y8=wokŭyEt{Io]ivթwy?.#W#%rQyUa=MrŘ4f{S݊Q[EguHԻ $ >=FzHg}NkW/ψmhmU/v/o{wiu>25:Om_cVGdu*He#LץuVx8o_ yrNgBkU#[Y-iW };o}C)GC_׸| -Zsg#:{{}+ Vф$ܙ2HƔQE"k_ /ji30inA8>)8ni c?xoRҬ.B$AO޺*U8-R4&ݽB(9Š(o&{[g.Trp; τ?z cb9y) jt].E)onP1=j#tQZrmA - I4N0"V#,~J[g!>cXaXr? /sHZRS V@?1ֽJSGE,Mj*Е- kJG5xw:?:5VMkQDi; UZrm|xX\a_*]nId') vOWC㊭o#-̚@ tddhx@.&yg[*r9J)՛o^–?GZR(PoG󲮓aZX(`dժ(VwaEP mແຆ9qE =h68=_i!OvYpO:qo뗊Ztidq؈+)/L p?#&/+!2(M? ߢi;"*bVW.޹OޥОv9ʮ}vUJ1Νjy) rOQ c_ݾTT(v6#Um+NEmn#AV9[mݔ5_gu(i0r=5—訔#-Z6IZiy _~֩u {7"I ~QKCojl( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?Image-Info-1.28/img/be.tif0000644000175000017500000000061210425235042013023 0ustar teteMM*FxԱ 1~a [$1zAxMQ#0  8=@H(1:P=Rbe.tifHHImageMagick 6.2.7 04/30/06 Q16 http://www.imagemagick.orgImage-Info-1.28/img/le.tif0000644000175000017500000000064010425236246013045 0ustar teteII*FxԱ 1~a [$1zAxMQ#0  8=@H(1PP=Rle.tifHHImageMagick 6.2.5 02/13/06 Q16 file:/usr/share/ImageMagick-6.2.5/doc/index.htmlImage-Info-1.28/img/graph.svg0000644000175000017500000000304010456422024013553 0ustar tete Untitled graph Image::Info Info Image-Info-1.28/img/gps.jpg0000644000175000017500000002011707740356572013250 0ustar tete(ExifMM* (i%"030524_2221~01KDDI-TSA5301THH022001002003:05:24 22:21:01 NE #$d)dNWGS-84ASCIIHYBRID-FIX2003:05:24C     C     }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzw!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz! ?)T}(ٓҿ:LpZwٟ.hcXH?Zq;cjʓUa :\z-RŻ{ 'OUeyi LpNFYȽӀBNEzMU" qJ'R3 j>.c?*K.3՞V?wں ?Fi:/Ojo3$dO A&]z5^04Gx8jX>"NH1~q8Ԫ7e)iez.L+o>;\WxG~{5v.7Z3> ISr{cj6bl=+ ()33'Wxnsӽ&|eK1;wZ^Yyy1W]hM1O5z {8ZWqGQ Fڒҕ5N<V>C;ߵ7xNtn_O7?b sό.~"kk;Ha#۸W 5if #NuJV*`1JuW>M)-lY%`Wʫ>[DSJB?aWzhX`ּKf_GfyzWeR2[9~}57UJwʖq}o5 ҕySXEXTv8 ϛϚZpe*Kݦ{[w LMZxrP#<Wq_ *#RSb}rxh7(k7gMfxYv)יpzpu*C q&|Ct˩;j߆5(M6*e%8ڜkLW#kw`KkpR9ۑb%>NX6gXtĉ[>oh\zsשth{5oc줞O [/̫{/?^XFY#}]+ tZdw}e5: \*J>ipF+ϠP(47ViZk>mu8|CɫZpy7V3@۹GO~{ ӎQ΢xwSWEysBNs_ m,K5k*t!9ux-ͤ[YTa֤^]1{p<$}xnREiWX5ǁQ6wh9Ffi-wq3]?!ӮdIg %wZG2f} qr'ܑCƜ;WޟՅ ixuK0:Wk I{R ޿|-*죫><ܱ`xTסEz`MK{zײuol4vuU>hFU;#];QZtglWg:Ѧz?Y s񎇯]8Q9~*>f)^{ c&Sgk-Q$Vm9zVIxKֱtV[ nB;ߵN'K{u^>o&ܘ˫H&!xNXt;?WYw+Uޗa+w[綊qp)P3b) mZUF5X;E+ۭ8^Os Dv]^J_-Z`2޶)]#KSY+td^;#6ucGO|3z~ϥf>B.S+?{<*v)6NMzGMoȒuwq].MNJG? ?lЬ,,5 ׷xg> ^}M1"qױ)~Z3eh-Q> ^YrE,cԭšgվKCѓgkGS|+m<\x ߝ!15Q}knd?J:tb}žoVUm%ZOڹ[)hʞ]7񏙫͢}Nv]eIߚ歪3!E=}jmE񷝵}/2BxJ+I♥}_++!K_2jΥNM󯴍,2OU+Ė:to>U^ҴcH6gW6)bcͰa=_Cꎶֿ87Ye_˦0I[#dfl85c,Cv_1)_ln~GZ~wOj`W 7Q-7W%Q#ҹ~3]OR.c7Gz8zti޹Z3<IJy㏗>.m--(df#+1).c*GsXIpnDh6\W%-ǎ|]Ai<}ծ 8 rk#ԭꤷG'| ?J+˙S|]ݿ uAFÜ}k%0'#-˜x5hCΰ~_?h!k{GZ> nZ,r௨5|Y1elM{HG| inLk-5OM͗kFbL|b {x^ƅS"O7WsLtU ZxUFWW9vfX8sIA`c,xL4G"nǖ^7 vr^B 89޾_ N2QVN1wG+3Y9ҡٰިLv]U"EkB9,R^<Rj._yß#ӭSD4C~PG_S]\,-@j^iSW#e!^;Ck,{bgm^w;.';'TZkQ{[ߜ?-"C\߇<x`6>'k;vchSstϮUZ fIV[}=u~vgAt>?x5ku>dW0-,m /m+-m:kVkXcڿfo?xU;Z_"=V>*|p֊~lTh|wؾ$y j6D1Ý»^ŎPCo/[kAe3\DI#/r<4[V5wh$|_~XB5ozDž o*>wKvP+0=N*׮T_%ؘvV58+;e c\sS> ⯨ O"woqR+nZEsC/|6OW7~!p<1L]{n~;qrԡ ' #pgmZk;UͶ4};N# =%uML]/2*^zUWZ< H=ENSl4e _3ZuxY򯦬5kxQfqRI3MI'5;;Vl%!O|0ԒjZ$?G]&cFl3V&jeQ5**Rb8{XxC$ W {Mkxt7C3s m< AD+ΈJ:V('IژW=tR=&zzUX{Wq Wx{z0ӒǫK=o4]ަe~ {e%lRC6~^ZgJ=xmB:t &r椴rR{QQ=>VYfm+ҵ7^o.f)%-N:ܹpn.|"| 8{\ڱeҰ8[q@7J1[ON=OqHp.×>kĖ'Gz¥5QZF*OC +@Vr^\(p+玘Ӽ۾)t5mm9%u1\t~Qp\T>w. lV4I- nHdOS]a'5$qb%dImage-Info-1.28/img/tiny.pgm0000644000175000017500000000001307740310602013416 0ustar teteP2 1 1 1 1 Image-Info-1.28/img/interlace.png0000644000175000017500000001134010456430753014417 0ustar tetePNG  IHDRd; pHYs  tIME +ڨtEXtCommentCreated with The GIMPd%nVIDATx]ixU%IgCBB. "\."\|D8L3:::3þ zȾ LسKz_8N:NөGΩS_|9_a4MA]ue.@E!:MKJJMNk)*mgX'Ϟ]aA_WwR[5թ];kWDsɇmAoO~1:8,zvi:sD&E䞺CxQ| <] ݺg٣o%/2jP_2.|TA\H_qFѹmnsIe@=kچ 0# xw)>m~ofb̗F/hև3A`!*}Y;7tLOiQ1nXLWPS|Փۛ.d>X*Hn'4BF dЬnաpvTBS{l1MCJ=rMbbՋڊXBꙶ 5Sfe܉h>5+ھڳڿy f՗PiIyzjo2{3+65.^-Va{bK1* ;[u6Nm3H笈ޏ܈F3Z&U:B f#_{Ёk] 9P@L- *t*J2iäU#i8#u!vϬ2Ce5w`S vAܦSm hד k>h6pm1/jۜyPQBѬ2fEb@4k4.E"uw4xG]gc|.i{(dPIƉy-ͭEE>?g)`b wVz>E3 ^w) ~ڈ_#{v:^|SZWKe177i C9vY7;ֵN_ڑ!.~HtaMë 1'%,*m蒬.힋`>]<|T@Iei8'HV.BV>2KvgHm1Q<n?sjʂH:0tŵ?&;k|(m=xr+߾S˾}$L!ڧG);ö㽃W~V m 7hlN]>D]?C-ZeXCS/\ZZzN6b{C^D&q ac0pf$}ʋrSwC4"+~v:I[ҭY_w =m?,gWK*ik_%bRMϣ},Cvf{brxǐ7Zȳqq2AfrHo 3 Y%ɛsOK9|4E1لda",,6bbbbŒŒrFxY}܍=$N_dt != 'PyIg:,tKvy.;lmުd.$PzCv"S Rf=MaF_/P>Lֽf>$hdž}u@Ez(},!ȱd YEǒ.,w!3 |og kB;6}χ^#kdODc~ݛu@o )%c|`_{l85br/W-~$8LqFi;z tGkm<  S'7t7[>Ο\ x"]eW]HMS'NYrSm҉YҡFp]ƒ"8&X`ł VX,Xb +,,xpQ`恡QH!zls6~g;˻_8R$%f30L29P6nߡ3 }_[>Ӆ#c}pvb3 Qvڨ#$!,Y|bKRInU#/la6PV3$w$|555 i}Ʋf2esN%>\8﹪|*,GJ酼^cCos ,cyJS_nRY-&J^dS|gߊz޹b *Tmkmk0ximnҠ?cO0\tyls} wgoӬQBXU _-/{ a=Sv'[㰆ʶU>󃊚bST"oҜhnIF]3ª7Ok7.R 6 Tاd86/?n7b:CCOVUO)(2*ɭ~ʚk-B r{:A` [TC欈owG Wu6+!8;;Y,w10 <3iڻZ0/Y:R> ԆnҎ1mMQ܅ /c` +,NIu&BaQ*,J 4>" EcpG"x*Xz@ >U8c5̔gW5<`T\it?h0wZ?-ҞTm(" 2qǯ}IX57 Łog#mi$- p+U^l(4ɀ31D $]NB%0u8PXB Jd!r0.Nk.Q a&ͧ͘/|@܊i JU1oQM w)=+,2.0ՋPCi++,gTIYaKz,Ĩ#,2.%qab`[AXa!/qKDž|MAX np 36E1Npcޞ@Msc. l"t`‘?/]L\'bL?bC6ftS ksf9 8c)? qgD=Ae_1H\W]:ekVERSION($ver || 0); 1 }; } # check if we can run some command sub can_run { my ($self, $cmd) = @_; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { my $abs = File::Spec->catfile($dir, $_[1]); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } # can we locate a (the) C compiler sub can_cc { my $self = shift; my @chunks = split(/ /, $Config::Config{cc}) or return; # $Config{cc} may contain args; try to find out the program part while (@chunks) { return $self->can_run("@chunks") || (pop(@chunks), next); } return; } # Fix Cygwin bug on maybe_command(); if ( $^O eq 'cygwin' ) { require ExtUtils::MM_Cygwin; require ExtUtils::MM_Win32; if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) { *ExtUtils::MM_Cygwin::maybe_command = sub { my ($self, $file) = @_; if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) { ExtUtils::MM_Win32->maybe_command($file); } else { ExtUtils::MM_Unix->maybe_command($file); } } } } 1; __END__ #line 157 Image-Info-1.28/inc/Module/Install/Base.pm0000644000175000017500000000203510773761462016012 0ustar tete#line 1 package Module::Install::Base; $VERSION = '0.71'; # Suspend handler for "redefined" warnings BEGIN { my $w = $SIG{__WARN__}; $SIG{__WARN__} = sub { $w }; } ### This is the ONLY module that shouldn't have strict on # use strict; #line 41 sub new { my ($class, %args) = @_; foreach my $method ( qw(call load) ) { *{"$class\::$method"} = sub { shift()->_top->$method(@_); } unless defined &{"$class\::$method"}; } bless( \%args, $class ); } #line 61 sub AUTOLOAD { my $self = shift; local $@; my $autoload = eval { $self->_top->autoload } or return; goto &$autoload; } #line 76 sub _top { $_[0]->{_top} } #line 89 sub admin { $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new; } sub is_admin { $_[0]->admin->VERSION; } sub DESTROY {} package Module::Install::Base::FakeAdmin; my $Fake; sub new { $Fake ||= bless(\@_, $_[0]) } sub AUTOLOAD {} sub DESTROY {} # Restore warning handler BEGIN { $SIG{__WARN__} = $SIG{__WARN__}->(); } 1; #line 138 Image-Info-1.28/inc/Module/Install/Win32.pm0000644000175000017500000000340210773761463016042 0ustar tete#line 1 package Module::Install::Win32; use strict; use Module::Install::Base; use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '0.71'; @ISA = qw{Module::Install::Base}; $ISCORE = 1; } # determine if the user needs nmake, and download it if needed sub check_nmake { my $self = shift; $self->load('can_run'); $self->load('get_file'); require Config; return unless ( $^O eq 'MSWin32' and $Config::Config{make} and $Config::Config{make} =~ /^nmake\b/i and ! $self->can_run('nmake') ); print "The required 'nmake' executable not found, fetching it...\n"; require File::Basename; my $rv = $self->get_file( url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe', ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe', local_dir => File::Basename::dirname($^X), size => 51928, run => 'Nmake15.exe /o > nul', check_for => 'Nmake.exe', remove => 1, ); die <<'END_MESSAGE' unless $rv; ------------------------------------------------------------------------------- Since you are using Microsoft Windows, you will need the 'nmake' utility before installation. It's available at: http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe or ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe Please download the file manually, save it to a directory in %PATH% (e.g. C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to that directory, and run "Nmake15.exe" from there; that will create the 'nmake.exe' file needed by this module. You may then resume the installation process described in README. ------------------------------------------------------------------------------- END_MESSAGE } 1; Image-Info-1.28/inc/Module/Install/WriteAll.pm0000644000175000017500000000132110773761463016661 0ustar tete#line 1 package Module::Install::WriteAll; use strict; use Module::Install::Base; use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '0.71'; @ISA = qw{Module::Install::Base}; $ISCORE = 1; } sub WriteAll { my $self = shift; my %args = ( meta => 1, sign => 0, inline => 0, check_nmake => 1, @_, ); $self->sign(1) if $args{sign}; $self->Meta->write if $args{meta}; $self->admin->WriteAll(%args) if $self->is_admin; $self->check_nmake if $args{check_nmake}; unless ( $self->makemaker_args->{PL_FILES} ) { $self->makemaker_args( PL_FILES => {} ); } if ( $args{inline} ) { $self->Inline->write; } else { $self->Makefile->write; } } 1; Image-Info-1.28/inc/Module/Install/AutoInstall.pm0000644000175000017500000000227210773761462017402 0ustar tete#line 1 package Module::Install::AutoInstall; use strict; use Module::Install::Base; use vars qw{$VERSION $ISCORE @ISA}; BEGIN { $VERSION = '0.71'; $ISCORE = 1; @ISA = qw{Module::Install::Base}; } sub AutoInstall { $_[0] } sub run { my $self = shift; $self->auto_install_now(@_); } sub write { my $self = shift; $self->auto_install(@_); } sub auto_install { my $self = shift; return if $self->{done}++; # Flatten array of arrays into a single array my @core = map @$_, map @$_, grep ref, $self->build_requires, $self->requires; my @config = @_; # We'll need Module::AutoInstall $self->include('Module::AutoInstall'); require Module::AutoInstall; Module::AutoInstall->import( (@config ? (-config => \@config) : ()), (@core ? (-core => \@core) : ()), $self->features, ); $self->makemaker_args( Module::AutoInstall::_make_args() ); my $class = ref($self); $self->postamble( "# --- $class section:\n" . Module::AutoInstall::postamble() ); } sub auto_install_now { my $self = shift; $self->auto_install(@_); Module::AutoInstall::do_install(); } 1; Image-Info-1.28/inc/Module/Install/Makefile.pm0000644000175000017500000001412110773761463016655 0ustar tete#line 1 package Module::Install::Makefile; use strict 'vars'; use Module::Install::Base; use ExtUtils::MakeMaker (); use vars qw{$VERSION $ISCORE @ISA}; BEGIN { $VERSION = '0.71'; $ISCORE = 1; @ISA = qw{Module::Install::Base}; } sub Makefile { $_[0] } my %seen = (); sub prompt { shift; # Infinite loop protection my @c = caller(); if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) { die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])"; } # In automated testing, always use defaults if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) { local $ENV{PERL_MM_USE_DEFAULT} = 1; goto &ExtUtils::MakeMaker::prompt; } else { goto &ExtUtils::MakeMaker::prompt; } } sub makemaker_args { my $self = shift; my $args = ($self->{makemaker_args} ||= {}); %$args = ( %$args, @_ ) if @_; $args; } # For mm args that take multiple space-seperated args, # append an argument to the current list. sub makemaker_append { my $self = sShift; my $name = shift; my $args = $self->makemaker_args; $args->{name} = defined $args->{$name} ? join( ' ', $args->{name}, @_ ) : join( ' ', @_ ); } sub build_subdirs { my $self = shift; my $subdirs = $self->makemaker_args->{DIR} ||= []; for my $subdir (@_) { push @$subdirs, $subdir; } } sub clean_files { my $self = shift; my $clean = $self->makemaker_args->{clean} ||= {}; %$clean = ( %$clean, FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_), ); } sub realclean_files { my $self = shift; my $realclean = $self->makemaker_args->{realclean} ||= {}; %$realclean = ( %$realclean, FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_), ); } sub libs { my $self = shift; my $libs = ref $_[0] ? shift : [ shift ]; $self->makemaker_args( LIBS => $libs ); } sub inc { my $self = shift; $self->makemaker_args( INC => shift ); } my %test_dir = (); sub _wanted_t { /\.t$/ and -f $_ and $test_dir{$File::Find::dir} = 1; } sub tests_recursive { my $self = shift; if ( $self->tests ) { die "tests_recursive will not work if tests are already defined"; } my $dir = shift || 't'; unless ( -d $dir ) { die "tests_recursive dir '$dir' does not exist"; } %test_dir = (); require File::Find; File::Find::find( \&_wanted_t, $dir ); $self->tests( join ' ', map { "$_/*.t" } sort keys %test_dir ); } sub write { my $self = shift; die "&Makefile->write() takes no arguments\n" if @_; # Make sure we have a new enough require ExtUtils::MakeMaker; $self->configure_requires( 'ExtUtils::MakeMaker' => $ExtUtils::MakeMaker::VERSION ); # Generate the my $args = $self->makemaker_args; $args->{DISTNAME} = $self->name; $args->{NAME} = $self->module_name || $self->name; $args->{VERSION} = $self->version; $args->{NAME} =~ s/-/::/g; if ( $self->tests ) { $args->{test} = { TESTS => $self->tests }; } if ($] >= 5.005) { $args->{ABSTRACT} = $self->abstract; $args->{AUTHOR} = $self->author; } if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) { $args->{NO_META} = 1; } if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 and $self->sign ) { $args->{SIGN} = 1; } unless ( $self->is_admin ) { delete $args->{SIGN}; } # merge both kinds of requires into prereq_pm my $prereq = ($args->{PREREQ_PM} ||= {}); %$prereq = ( %$prereq, map { @$_ } map { @$_ } grep $_, ($self->configure_requires, $self->build_requires, $self->requires) ); # Remove any reference to perl, PREREQ_PM doesn't support it delete $args->{PREREQ_PM}->{perl}; # merge both kinds of requires into prereq_pm my $subdirs = ($args->{DIR} ||= []); if ($self->bundles) { foreach my $bundle (@{ $self->bundles }) { my ($file, $dir) = @$bundle; push @$subdirs, $dir if -d $dir; delete $prereq->{$file}; } } if ( my $perl_version = $self->perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; } $args->{INSTALLDIRS} = $self->installdirs; my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_})} keys %$args; my $user_preop = delete $args{dist}->{PREOP}; if (my $preop = $self->admin->preop($user_preop)) { $args{dist} = $preop; } my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile'); } sub fix_up_makefile { my $self = shift; my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; my $preamble = $self->preamble ? "# Preamble by $top_class $top_version\n" . $self->preamble : ''; my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); local *MAKEFILE; open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; my $makefile = do { local $/; }; close MAKEFILE or die $!; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; # Module::Install will never be used to build the Core Perl # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m; #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m; # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well. $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g; # XXX - This is currently unused; not sure if it breaks other MM-users # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg; open MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; print MAKEFILE "$preamble$makefile$postamble" or die $!; close MAKEFILE or die $!; 1; } sub preamble { my ($self, $text) = @_; $self->{preamble} = $text . $self->{preamble} if defined $text; $self->{preamble}; } sub postamble { my ($self, $text) = @_; $self->{postamble} ||= $self->admin->postamble; $self->{postamble} .= $text if defined $text; $self->{postamble} } 1; __END__ #line 371 Image-Info-1.28/inc/Module/Install/Fetch.pm0000644000175000017500000000463010773761463016175 0ustar tete#line 1 package Module::Install::Fetch; use strict; use Module::Install::Base; use vars qw{$VERSION $ISCORE @ISA}; BEGIN { $VERSION = '0.71'; $ISCORE = 1; @ISA = qw{Module::Install::Base}; } sub get_file { my ($self, %args) = @_; my ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) { $args{url} = $args{ftp_url} or (warn("LWP support unavailable!\n"), return); ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; } $|++; print "Fetching '$file' from $host... "; unless (eval { require Socket; Socket::inet_aton($host) }) { warn "'$host' resolve failed!\n"; return; } return unless $scheme eq 'ftp' or $scheme eq 'http'; require Cwd; my $dir = Cwd::getcwd(); chdir $args{local_dir} or return if exists $args{local_dir}; if (eval { require LWP::Simple; 1 }) { LWP::Simple::mirror($args{url}, $file); } elsif (eval { require Net::FTP; 1 }) { eval { # use Net::FTP to get past firewall my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); $ftp->login("anonymous", 'anonymous@example.com'); $ftp->cwd($path); $ftp->binary; $ftp->get($file) or (warn("$!\n"), return); $ftp->quit; } } elsif (my $ftp = $self->can_run('ftp')) { eval { # no Net::FTP, fallback to ftp.exe require FileHandle; my $fh = FileHandle->new; local $SIG{CHLD} = 'IGNORE'; unless ($fh->open("|$ftp -n")) { warn "Couldn't open ftp: $!\n"; chdir $dir; return; } my @dialog = split(/\n/, <<"END_FTP"); open $host user anonymous anonymous\@example.com cd $path binary get $file $file quit END_FTP foreach (@dialog) { $fh->print("$_\n") } $fh->close; } } else { warn "No working 'ftp' program available!\n"; chdir $dir; return; } unless (-f $file) { warn "Fetching failed: $@\n"; chdir $dir; return; } return if exists $args{size} and -s $file != $args{size}; system($args{run}) if exists $args{run}; unlink($file) if $args{remove}; print(((!exists $args{check_for} or -e $args{check_for}) ? "done!" : "failed! ($!)"), "\n"); chdir $dir; return !$?; } 1; Image-Info-1.28/inc/Module/Install/Include.pm0000644000175000017500000000101410773761463016520 0ustar tete#line 1 package Module::Install::Include; use strict; use Module::Install::Base; use vars qw{$VERSION $ISCORE @ISA}; BEGIN { $VERSION = '0.71'; $ISCORE = 1; @ISA = qw{Module::Install::Base}; } sub include { shift()->admin->include(@_); } sub include_deps { shift()->admin->include_deps(@_); } sub auto_include { shift()->admin->auto_include(@_); } sub auto_include_deps { shift()->admin->auto_include_deps(@_); } sub auto_include_dependent_dists { shift()->admin->auto_include_dependent_dists(@_); } 1; Image-Info-1.28/inc/Module/Install/Metadata.pm0000644000175000017500000002073010773761462016662 0ustar tete#line 1 package Module::Install::Metadata; use strict 'vars'; use Module::Install::Base; use vars qw{$VERSION $ISCORE @ISA}; BEGIN { $VERSION = '0.71'; $ISCORE = 1; @ISA = qw{Module::Install::Base}; } my @scalar_keys = qw{ name module_name abstract author version license distribution_type perl_version tests installdirs }; my @tuple_keys = qw{ configure_requires build_requires requires recommends bundles }; sub Meta { shift } sub Meta_ScalarKeys { @scalar_keys } sub Meta_TupleKeys { @tuple_keys } foreach my $key (@scalar_keys) { *$key = sub { my $self = shift; return $self->{values}{$key} if defined wantarray and !@_; $self->{values}{$key} = shift; return $self; }; } sub requires { my $self = shift; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @{ $self->{values}->{requires} }, [ $module, $version ]; } $self->{values}{requires}; } sub build_requires { my $self = shift; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @{ $self->{values}->{build_requires} }, [ $module, $version ]; } $self->{values}{build_requires}; } sub configure_requires { my $self = shift; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @{ $self->{values}->{configure_requires} }, [ $module, $version ]; } $self->{values}{configure_requires}; } sub recommends { my $self = shift; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @{ $self->{values}->{recommends} }, [ $module, $version ]; } $self->{values}{recommends}; } sub bundles { my $self = shift; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @{ $self->{values}->{bundles} }, [ $module, $version ]; } $self->{values}{bundles}; } # Aliases for build_requires that will have alternative # meanings in some future version of META.yml. sub test_requires { shift->build_requires(@_) } sub install_requires { shift->build_requires(@_) } # Aliases for installdirs options sub install_as_core { $_[0]->installdirs('perl') } sub install_as_cpan { $_[0]->installdirs('site') } sub install_as_site { $_[0]->installdirs('site') } sub install_as_vendor { $_[0]->installdirs('vendor') } sub sign { my $self = shift; return $self->{'values'}{'sign'} if defined wantarray and ! @_; $self->{'values'}{'sign'} = ( @_ ? $_[0] : 1 ); return $self; } sub dynamic_config { my $self = shift; unless ( @_ ) { warn "You MUST provide an explicit true/false value to dynamic_config, skipping\n"; return $self; } $self->{values}{dynamic_config} = $_[0] ? 1 : 0; return $self; } sub all_from { my ( $self, $file ) = @_; unless ( defined($file) ) { my $name = $self->name or die "all_from called with no args without setting name() first"; $file = join('/', 'lib', split(/-/, $name)) . '.pm'; $file =~ s{.*/}{} unless -e $file; die "all_from: cannot find $file from $name" unless -e $file; } # Some methods pull from POD instead of code. # If there is a matching .pod, use that instead my $pod = $file; $pod =~ s/\.pm$/.pod/i; $pod = $file unless -e $pod; # Pull the different values $self->name_from($file) unless $self->name; $self->version_from($file) unless $self->version; $self->perl_version_from($file) unless $self->perl_version; $self->author_from($pod) unless $self->author; $self->license_from($pod) unless $self->license; $self->abstract_from($pod) unless $self->abstract; return 1; } sub provides { my $self = shift; my $provides = ( $self->{values}{provides} ||= {} ); %$provides = (%$provides, @_) if @_; return $provides; } sub auto_provides { my $self = shift; return $self unless $self->is_admin; unless (-e 'MANIFEST') { warn "Cannot deduce auto_provides without a MANIFEST, skipping\n"; return $self; } # Avoid spurious warnings as we are not checking manifest here. local $SIG{__WARN__} = sub {1}; require ExtUtils::Manifest; local *ExtUtils::Manifest::manicheck = sub { return }; require Module::Build; my $build = Module::Build->new( dist_name => $self->name, dist_version => $self->version, license => $self->license, ); $self->provides( %{ $build->find_dist_packages || {} } ); } sub feature { my $self = shift; my $name = shift; my $features = ( $self->{values}{features} ||= [] ); my $mods; if ( @_ == 1 and ref( $_[0] ) ) { # The user used ->feature like ->features by passing in the second # argument as a reference. Accomodate for that. $mods = $_[0]; } else { $mods = \@_; } my $count = 0; push @$features, ( $name => [ map { ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_ } @$mods ] ); return @$features; } sub features { my $self = shift; while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) { $self->feature( $name, @$mods ); } return $self->{values}->{features} ? @{ $self->{values}->{features} } : (); } sub no_index { my $self = shift; my $type = shift; push @{ $self->{values}{no_index}{$type} }, @_ if $type; return $self->{values}{no_index}; } sub read { my $self = shift; $self->include_deps( 'YAML::Tiny', 0 ); require YAML::Tiny; my $data = YAML::Tiny::LoadFile('META.yml'); # Call methods explicitly in case user has already set some values. while ( my ( $key, $value ) = each %$data ) { next unless $self->can($key); if ( ref $value eq 'HASH' ) { while ( my ( $module, $version ) = each %$value ) { $self->can($key)->($self, $module => $version ); } } else { $self->can($key)->($self, $value); } } return $self; } sub write { my $self = shift; return $self unless $self->is_admin; $self->admin->write_meta; return $self; } sub version_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->version( ExtUtils::MM_Unix->parse_version($file) ); } sub abstract_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->abstract( bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix' )->parse_abstract($file) ); } sub name_from { my $self = shift; if ( Module::Install::_read($_[0]) =~ m/ ^ \s package \s* ([\w:]+) \s* ; /ixms ) { my $name = $1; $name =~ s{::}{-}g; $self->name($name); } else { die "Cannot determine name from $_[0]\n"; return; } } sub perl_version_from { my $self = shift; if ( Module::Install::_read($_[0]) =~ m/ ^ use \s* v? ([\d_\.]+) \s* ; /ixms ) { my $perl_version = $1; $perl_version =~ s{_}{}g; $self->perl_version($perl_version); } else { warn "Cannot determine perl version info from $_[0]\n"; return; } } sub author_from { my $self = shift; my $content = Module::Install::_read($_[0]); if ($content =~ m/ =head \d \s+ (?:authors?)\b \s* ([^\n]*) | =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s* .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s* ([^\n]*) /ixms) { my $author = $1 || $2; $author =~ s{E}{<}g; $author =~ s{E}{>}g; $self->author($author); } else { warn "Cannot determine author info from $_[0]\n"; } } sub license_from { my $self = shift; if ( Module::Install::_read($_[0]) =~ m/ ( =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b .*? ) (=head\\d.*|=cut.*|) \z /ixms ) { my $license_text = $1; my @phrases = ( 'under the same (?:terms|license) as perl itself' => 'perl', 1, 'GNU public license' => 'gpl', 1, 'GNU lesser public license' => 'lgpl', 1, 'BSD license' => 'bsd', 1, 'Artistic license' => 'artistic', 1, 'GPL' => 'gpl', 1, 'LGPL' => 'lgpl', 1, 'BSD' => 'bsd', 1, 'Artistic' => 'artistic', 1, 'MIT' => 'mit', 1, 'proprietary' => 'proprietary', 0, ); while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) { $pattern =~ s{\s+}{\\s+}g; if ( $license_text =~ /\b$pattern\b/i ) { if ( $osi and $license_text =~ /All rights reserved/i ) { warn "LEGAL WARNING: 'All rights reserved' may invalidate Open Source licenses. Consider removing it."; } $self->license($license); return 1; } } } warn "Cannot determine license info from $_[0]\n"; return 'unknown'; } 1; Image-Info-1.28/inc/Module/Install.pm0000644000175000017500000002027510773761462015146 0ustar tete#line 1 package Module::Install; # For any maintainers: # The load order for Module::Install is a bit magic. # It goes something like this... # # IF ( host has Module::Install installed, creating author mode ) { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install # 3. The installed version of inc::Module::Install loads # 4. inc::Module::Install calls "require Module::Install" # 5. The ./inc/ version of Module::Install loads # } ELSE { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install # 3. The ./inc/ version of Module::Install loads # } BEGIN { require 5.004; } use strict 'vars'; use vars qw{$VERSION}; BEGIN { # All Module::Install core packages now require synchronised versions. # This will be used to ensure we don't accidentally load old or # different versions of modules. # This is not enforced yet, but will be some time in the next few # releases once we can make sure it won't clash with custom # Module::Install extensions. $VERSION = '0.71'; } # Whether or not inc::Module::Install is actually loaded, the # $INC{inc/Module/Install.pm} is what will still get set as long as # the caller loaded module this in the documented manner. # If not set, the caller may NOT have loaded the bundled version, and thus # they may not have a MI version that works with the Makefile.PL. This would # result in false errors or unexpected behaviour. And we don't want that. my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm'; unless ( $INC{$file} ) { die <<"END_DIE" } Please invoke ${\__PACKAGE__} with: use inc::${\__PACKAGE__}; not: use ${\__PACKAGE__}; END_DIE # If the script that is loading Module::Install is from the future, # then make will detect this and cause it to re-run over and over # again. This is bad. Rather than taking action to touch it (which # is unreliable on some platforms and requires write permissions) # for now we should catch this and refuse to run. if ( -f $0 and (stat($0))[9] > time ) { die <<"END_DIE" } Your installer $0 has a modification time in the future. This is known to create infinite loops in make. Please correct this, then run $0 again. END_DIE # Build.PL was formerly supported, but no longer is due to excessive # difficulty in implementing every single feature twice. if ( $0 =~ /Build.PL$/i or -f 'Build.PL' ) { die <<"END_DIE" } Module::Install no longer supports Build.PL. It was impossible to maintain duel backends, and has been deprecated. Please remove all Build.PL files and only use the Makefile.PL installer. END_DIE use Cwd (); use File::Find (); use File::Path (); use FindBin; *inc::Module::Install::VERSION = *VERSION; @inc::Module::Install::ISA = __PACKAGE__; sub autoload { my $self = shift; my $who = $self->_caller; my $cwd = Cwd::cwd(); my $sym = "${who}::AUTOLOAD"; $sym->{$cwd} = sub { my $pwd = Cwd::cwd(); if ( my $code = $sym->{$pwd} ) { # delegate back to parent dirs goto &$code unless $cwd eq $pwd; } $$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym"; unshift @_, ( $self, $1 ); goto &{$self->can('call')} unless uc($1) eq $1; }; } sub import { my $class = shift; my $self = $class->new(@_); my $who = $self->_caller; unless ( -f $self->{file} ) { require "$self->{path}/$self->{dispatch}.pm"; File::Path::mkpath("$self->{prefix}/$self->{author}"); $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self ); $self->{admin}->init; @_ = ($class, _self => $self); goto &{"$self->{name}::import"}; } *{"${who}::AUTOLOAD"} = $self->autoload; $self->preload; # Unregister loader and worker packages so subdirs can use them again delete $INC{"$self->{file}"}; delete $INC{"$self->{path}.pm"}; return 1; } sub preload { my $self = shift; unless ( $self->{extensions} ) { $self->load_extensions( "$self->{prefix}/$self->{path}", $self ); } my @exts = @{$self->{extensions}}; unless ( @exts ) { my $admin = $self->{admin}; @exts = $admin->load_all_extensions; } my %seen; foreach my $obj ( @exts ) { while (my ($method, $glob) = each %{ref($obj) . '::'}) { next unless $obj->can($method); next if $method =~ /^_/; next if $method eq uc($method); $seen{$method}++; } } my $who = $self->_caller; foreach my $name ( sort keys %seen ) { *{"${who}::$name"} = sub { ${"${who}::AUTOLOAD"} = "${who}::$name"; goto &{"${who}::AUTOLOAD"}; }; } } sub new { my ($class, %args) = @_; # ignore the prefix on extension modules built from top level. my $base_path = Cwd::abs_path($FindBin::Bin); unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) { delete $args{prefix}; } return $args{_self} if $args{_self}; $args{dispatch} ||= 'Admin'; $args{prefix} ||= 'inc'; $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author'); $args{bundle} ||= 'inc/BUNDLES'; $args{base} ||= $base_path; $class =~ s/^\Q$args{prefix}\E:://; $args{name} ||= $class; $args{version} ||= $class->VERSION; unless ( $args{path} ) { $args{path} = $args{name}; $args{path} =~ s!::!/!g; } $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm"; $args{wrote} = 0; bless( \%args, $class ); } sub call { my ($self, $method) = @_; my $obj = $self->load($method) or return; splice(@_, 0, 2, $obj); goto &{$obj->can($method)}; } sub load { my ($self, $method) = @_; $self->load_extensions( "$self->{prefix}/$self->{path}", $self ) unless $self->{extensions}; foreach my $obj (@{$self->{extensions}}) { return $obj if $obj->can($method); } my $admin = $self->{admin} or die <<"END_DIE"; The '$method' method does not exist in the '$self->{prefix}' path! Please remove the '$self->{prefix}' directory and run $0 again to load it. END_DIE my $obj = $admin->load($method, 1); push @{$self->{extensions}}, $obj; $obj; } sub load_extensions { my ($self, $path, $top) = @_; unless ( grep { lc $_ eq lc $self->{prefix} } @INC ) { unshift @INC, $self->{prefix}; } foreach my $rv ( $self->find_extensions($path) ) { my ($file, $pkg) = @{$rv}; next if $self->{pathnames}{$pkg}; local $@; my $new = eval { require $file; $pkg->can('new') }; unless ( $new ) { warn $@ if $@; next; } $self->{pathnames}{$pkg} = delete $INC{$file}; push @{$self->{extensions}}, &{$new}($pkg, _top => $top ); } $self->{extensions} ||= []; } sub find_extensions { my ($self, $path) = @_; my @found; File::Find::find( sub { my $file = $File::Find::name; return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is; my $subpath = $1; return if lc($subpath) eq lc($self->{dispatch}); $file = "$self->{path}/$subpath.pm"; my $pkg = "$self->{name}::$subpath"; $pkg =~ s!/!::!g; # If we have a mixed-case package name, assume case has been preserved # correctly. Otherwise, root through the file to locate the case-preserved # version of the package name. if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) { my $content = Module::Install::_read($subpath . '.pm'); my $in_pod = 0; foreach ( split //, $content ) { $in_pod = 1 if /^=\w/; $in_pod = 0 if /^=cut/; next if ($in_pod || /^=cut/); # skip pod text next if /^\s*#/; # and comments if ( m/^\s*package\s+($pkg)\s*;/i ) { $pkg = $1; last; } } } push @found, [ $file, $pkg ]; }, $path ) if -d $path; @found; } ##################################################################### # Utility Functions sub _caller { my $depth = 0; my $call = caller($depth); while ( $call eq __PACKAGE__ ) { $depth++; $call = caller($depth); } return $call; } sub _read { local *FH; open FH, "< $_[0]" or die "open($_[0]): $!"; my $str = do { local $/; }; close FH or die "close($_[0]): $!"; return $str; } sub _write { local *FH; open FH, "> $_[0]" or die "open($_[0]): $!"; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!" } close FH or die "close($_[0]): $!"; } sub _version { my $s = shift || 0; $s =~ s/^(\d+)\.?//; my $l = $1 || 0; my @v = map { $_ . '0' x (3 - length $_) } $s =~ /(\d{1,3})\D?/g; $l = $l . '.' . join '', @v if @v; return $l + 0; } 1; # Copyright 2008 Adam Kennedy. Image-Info-1.28/inc/Module/AutoInstall.pm0000644000175000017500000005077210773761463016005 0ustar tete#line 1 package Module::AutoInstall; use strict; use Cwd (); use ExtUtils::MakeMaker (); use vars qw{$VERSION}; BEGIN { $VERSION = '1.03'; } # special map on pre-defined feature sets my %FeatureMap = ( '' => 'Core Features', # XXX: deprecated '-core' => 'Core Features', ); # various lexical flags my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $HasCPANPLUS ); my ( $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly ); my ( $PostambleActions, $PostambleUsed ); # See if it's a testing or non-interactive session _accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN ); _init(); sub _accept_default { $AcceptDefault = shift; } sub missing_modules { return @Missing; } sub do_install { __PACKAGE__->install( [ $Config ? ( UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) : () ], @Missing, ); } # initialize various flags, and/or perform install sub _init { foreach my $arg ( @ARGV, split( /[\s\t]+/, $ENV{PERL_AUTOINSTALL} || $ENV{PERL_EXTUTILS_AUTOINSTALL} || '' ) ) { if ( $arg =~ /^--config=(.*)$/ ) { $Config = [ split( ',', $1 ) ]; } elsif ( $arg =~ /^--installdeps=(.*)$/ ) { __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) ); exit 0; } elsif ( $arg =~ /^--default(?:deps)?$/ ) { $AcceptDefault = 1; } elsif ( $arg =~ /^--check(?:deps)?$/ ) { $CheckOnly = 1; } elsif ( $arg =~ /^--skip(?:deps)?$/ ) { $SkipInstall = 1; } elsif ( $arg =~ /^--test(?:only)?$/ ) { $TestOnly = 1; } } } # overrides MakeMaker's prompt() to automatically accept the default choice sub _prompt { goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault; my ( $prompt, $default ) = @_; my $y = ( $default =~ /^[Yy]/ ); print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] '; print "$default\n"; return $default; } # the workhorse sub import { my $class = shift; my @args = @_ or return; my $core_all; print "*** $class version " . $class->VERSION . "\n"; print "*** Checking for Perl dependencies...\n"; my $cwd = Cwd::cwd(); $Config = []; my $maxlen = length( ( sort { length($b) <=> length($a) } grep { /^[^\-]/ } map { ref($_) ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} ) : '' } map { +{@args}->{$_} } grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} } )[0] ); while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) { my ( @required, @tests, @skiptests ); my $default = 1; my $conflict = 0; if ( $feature =~ m/^-(\w+)$/ ) { my $option = lc($1); # check for a newer version of myself _update_to( $modules, @_ ) and return if $option eq 'version'; # sets CPAN configuration options $Config = $modules if $option eq 'config'; # promote every features to core status $core_all = ( $modules =~ /^all$/i ) and next if $option eq 'core'; next unless $option eq 'core'; } print "[" . ( $FeatureMap{ lc($feature) } || $feature ) . "]\n"; $modules = [ %{$modules} ] if UNIVERSAL::isa( $modules, 'HASH' ); unshift @$modules, -default => &{ shift(@$modules) } if ( ref( $modules->[0] ) eq 'CODE' ); # XXX: bugward combatability while ( my ( $mod, $arg ) = splice( @$modules, 0, 2 ) ) { if ( $mod =~ m/^-(\w+)$/ ) { my $option = lc($1); $default = $arg if ( $option eq 'default' ); $conflict = $arg if ( $option eq 'conflict' ); @tests = @{$arg} if ( $option eq 'tests' ); @skiptests = @{$arg} if ( $option eq 'skiptests' ); next; } printf( "- %-${maxlen}s ...", $mod ); if ( $arg and $arg =~ /^\D/ ) { unshift @$modules, $arg; $arg = 0; } # XXX: check for conflicts and uninstalls(!) them. if ( defined( my $cur = _version_check( _load($mod), $arg ||= 0 ) ) ) { print "loaded. ($cur" . ( $arg ? " >= $arg" : '' ) . ")\n"; push @Existing, $mod => $arg; $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { print "missing." . ( $arg ? " (would need $arg)" : '' ) . "\n"; push @required, $mod => $arg; } } next unless @required; my $mandatory = ( $feature eq '-core' or $core_all ); if ( !$SkipInstall and ( $CheckOnly or _prompt( qq{==> Auto-install the } . ( @required / 2 ) . ( $mandatory ? ' mandatory' : ' optional' ) . qq{ module(s) from CPAN?}, $default ? 'y' : 'n', ) =~ /^[Yy]/ ) ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } elsif ( !$SkipInstall and $default and $mandatory and _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', ) =~ /^[Nn]/ ) { push( @Missing, @required ); $DisabledTests{$_} = 1 for map { glob($_) } @skiptests; } else { $DisabledTests{$_} = 1 for map { glob($_) } @tests; } } $UnderCPAN = _check_lock(); # check for $UnderCPAN if ( @Missing and not( $CheckOnly or $UnderCPAN ) ) { require Config; print "*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n"; # make an educated guess of whether we'll need root permission. print " (You may need to do that as the 'root' user.)\n" if eval '$>'; } print "*** $class configuration finished.\n"; chdir $cwd; # import to main:: no strict 'refs'; *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main'; } # Check to see if we are currently running under CPAN.pm and/or CPANPLUS; # if we are, then we simply let it taking care of our dependencies sub _check_lock { return unless @Missing; if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) { print <<'END_MESSAGE'; *** Since we're running under CPANPLUS, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } _load_cpan(); # Find the CPAN lock-file my $lock = MM->catfile( $CPAN::Config->{cpan_home}, ".lock" ); return unless -f $lock; # Check the lock local *LOCK; return unless open(LOCK, $lock); if ( ( $^O eq 'MSWin32' ? _under_cpan() : == getppid() ) and ( $CPAN::Config->{prerequisites_policy} || '' ) ne 'ignore' ) { print <<'END_MESSAGE'; *** Since we're running under CPAN, I'll just let it take care of the dependency's installation later. END_MESSAGE return 1; } close LOCK; return; } sub install { my $class = shift; my $i; # used below to strip leading '-' from config keys my @config = ( map { s/^-// if ++$i; $_ } @{ +shift } ); my ( @modules, @installed ); while ( my ( $pkg, $ver ) = splice( @_, 0, 2 ) ) { # grep out those already installed if ( defined( _version_check( _load($pkg), $ver ) ) ) { push @installed, $pkg; } else { push @modules, $pkg, $ver; } } return @installed unless @modules; # nothing to do return @installed if _check_lock(); # defer to the CPAN shell print "*** Installing dependencies...\n"; return unless _connected_to('cpan.org'); my %args = @config; my %failed; local *FAILED; if ( $args{do_once} and open( FAILED, '.#autoinstall.failed' ) ) { while () { chomp; $failed{$_}++ } close FAILED; my @newmod; while ( my ( $k, $v ) = splice( @modules, 0, 2 ) ) { push @newmod, ( $k => $v ) unless $failed{$k}; } @modules = @newmod; } if ( _has_cpanplus() ) { _install_cpanplus( \@modules, \@config ); } else { _install_cpan( \@modules, \@config ); } print "*** $class installation finished.\n"; # see if we have successfully installed them while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { if ( defined( _version_check( _load($pkg), $ver ) ) ) { push @installed, $pkg; } elsif ( $args{do_once} and open( FAILED, '>> .#autoinstall.failed' ) ) { print FAILED "$pkg\n"; } } close FAILED if $args{do_once}; return @installed; } sub _install_cpanplus { my @modules = @{ +shift }; my @config = _cpanplus_config( @{ +shift } ); my $installed = 0; require CPANPLUS::Backend; my $cp = CPANPLUS::Backend->new; my $conf = $cp->configure_object; return unless $conf->can('conf') # 0.05x+ with "sudo" support or _can_write($conf->_get_build('base')); # 0.04x # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $conf->get_conf('makeflags') || ''; if ( UNIVERSAL::isa( $makeflags, 'HASH' ) ) { # 0.03+ uses a hashref here $makeflags->{UNINST} = 1 unless exists $makeflags->{UNINST}; } else { # 0.02 and below uses a scalar $makeflags = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); } $conf->set_conf( makeflags => $makeflags ); $conf->set_conf( prereqs => 1 ); while ( my ( $key, $val ) = splice( @config, 0, 2 ) ) { $conf->set_conf( $key, $val ); } my $modtree = $cp->module_tree; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { print "*** Installing $pkg...\n"; MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; my $success; my $obj = $modtree->{$pkg}; if ( $obj and defined( _version_check( $obj->{version}, $ver ) ) ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = $cp->install( modules => [ $obj->{module} ] ); if ( $rv and ( $rv->{ $obj->{module} } or $rv->{ok} ) ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation cancelled.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _cpanplus_config { my @config = (); while ( @_ ) { my ($key, $value) = (shift(), shift()); if ( $key eq 'prerequisites_policy' ) { if ( $value eq 'follow' ) { $value = CPANPLUS::Internals::Constants::PREREQ_INSTALL(); } elsif ( $value eq 'ask' ) { $value = CPANPLUS::Internals::Constants::PREREQ_ASK(); } elsif ( $value eq 'ignore' ) { $value = CPANPLUS::Internals::Constants::PREREQ_IGNORE(); } else { die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n"; } } else { die "*** Cannot convert option $key to CPANPLUS version.\n"; } } return @config; } sub _install_cpan { my @modules = @{ +shift }; my @config = @{ +shift }; my $installed = 0; my %args; _load_cpan(); require Config; if (CPAN->VERSION < 1.80) { # no "sudo" support, probe for writableness return unless _can_write( MM->catfile( $CPAN::Config->{cpan_home}, 'sources' ) ) and _can_write( $Config::Config{sitelib} ); } # if we're root, set UNINST=1 to avoid trouble unless user asked for it. my $makeflags = $CPAN::Config->{make_install_arg} || ''; $CPAN::Config->{make_install_arg} = join( ' ', split( ' ', $makeflags ), 'UNINST=1' ) if ( $makeflags !~ /\bUNINST\b/ and eval qq{ $> eq '0' } ); # don't show start-up info $CPAN::Config->{inhibit_startup_message} = 1; # set additional options while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) { ( $args{$opt} = $arg, next ) if $opt =~ /^force$/; # pseudo-option $CPAN::Config->{$opt} = $arg; } local $CPAN::Config->{prerequisites_policy} = 'follow'; while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) { MY::preinstall( $pkg, $ver ) or next if defined &MY::preinstall; print "*** Installing $pkg...\n"; my $obj = CPAN::Shell->expand( Module => $pkg ); my $success = 0; if ( $obj and defined( _version_check( $obj->cpan_version, $ver ) ) ) { my $pathname = $pkg; $pathname =~ s/::/\\W/; foreach my $inc ( grep { m/$pathname.pm/i } keys(%INC) ) { delete $INC{$inc}; } my $rv = $args{force} ? CPAN::Shell->force( install => $pkg ) : CPAN::Shell->install($pkg); $rv ||= eval { $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, ) ->{install} if $CPAN::META; }; if ( $rv eq 'YES' ) { print "*** $pkg successfully installed.\n"; $success = 1; } else { print "*** $pkg installation failed.\n"; $success = 0; } $installed += $success; } else { print << "."; *** Could not find a version $ver or above for $pkg; skipping. . } MY::postinstall( $pkg, $ver, $success ) if defined &MY::postinstall; } return $installed; } sub _has_cpanplus { return ( $HasCPANPLUS = ( $INC{'CPANPLUS/Config.pm'} or _load('CPANPLUS::Shell::Default') ) ); } # make guesses on whether we're under the CPAN installation directory sub _under_cpan { require Cwd; require File::Spec; my $cwd = File::Spec->canonpath( Cwd::cwd() ); my $cpan = File::Spec->canonpath( $CPAN::Config->{cpan_home} ); return ( index( $cwd, $cpan ) > -1 ); } sub _update_to { my $class = __PACKAGE__; my $ver = shift; return if defined( _version_check( _load($class), $ver ) ); # no need to upgrade if ( _prompt( "==> A newer version of $class ($ver) is required. Install?", 'y' ) =~ /^[Nn]/ ) { die "*** Please install $class $ver manually.\n"; } print << "."; *** Trying to fetch it from CPAN... . # install ourselves _load($class) and return $class->import(@_) if $class->install( [], $class, $ver ); print << '.'; exit 1; *** Cannot bootstrap myself. :-( Installation terminated. . } # check if we're connected to some host, using inet_aton sub _connected_to { my $site = shift; return ( ( _load('Socket') and Socket::inet_aton($site) ) or _prompt( qq( *** Your host cannot resolve the domain name '$site', which probably means the Internet connections are unavailable. ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/ ); } # check if a directory is writable; may create it on demand sub _can_write { my $path = shift; mkdir( $path, 0755 ) unless -e $path; return 1 if -w $path; print << "."; *** You are not allowed to write to the directory '$path'; the installation may fail due to insufficient permissions. . if ( eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt( qq( ==> Should we try to re-execute the autoinstall process with 'sudo'?), ((-t STDIN) ? 'y' : 'n') ) =~ /^[Yy]/ ) { # try to bootstrap ourselves from sudo print << "."; *** Trying to re-execute the autoinstall process with 'sudo'... . my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; return unless system( 'sudo', $^X, $0, "--config=$config", "--installdeps=$missing" ); print << "."; *** The 'sudo' command exited with error! Resuming... . } return _prompt( qq( ==> Should we try to install the required module(s) anyway?), 'n' ) =~ /^[Yy]/; } # load a module and return the version it reports sub _load { my $mod = pop; # class/instance doesn't matter my $file = $mod; $file =~ s|::|/|g; $file .= '.pm'; local $@; return eval { require $file; $mod->VERSION } || ( $@ ? undef: 0 ); } # Load CPAN.pm and it's configuration sub _load_cpan { return if $CPAN::VERSION; require CPAN; if ( $CPAN::HandleConfig::VERSION ) { # Newer versions of CPAN have a HandleConfig module CPAN::HandleConfig->load; } else { # Older versions had the load method in Config directly CPAN::Config->load; } } # compare two versions, either use Sort::Versions or plain comparison sub _version_check { my ( $cur, $min ) = @_; return unless defined $cur; $cur =~ s/\s+$//; # check for version numbers that are not in decimal format if ( ref($cur) or ref($min) or $cur =~ /v|\..*\./ or $min =~ /v|\..*\./ ) { if ( ( $version::VERSION or defined( _load('version') )) and version->can('new') ) { # use version.pm if it is installed. return ( ( version->new($cur) >= version->new($min) ) ? $cur : undef ); } elsif ( $Sort::Versions::VERSION or defined( _load('Sort::Versions') ) ) { # use Sort::Versions as the sorting algorithm for a.b.c versions return ( ( Sort::Versions::versioncmp( $cur, $min ) != -1 ) ? $cur : undef ); } warn "Cannot reliably compare non-decimal formatted versions.\n" . "Please install version.pm or Sort::Versions.\n"; } # plain comparison local $^W = 0; # shuts off 'not numeric' bugs return ( $cur >= $min ? $cur : undef ); } # nothing; this usage is deprecated. sub main::PREREQ_PM { return {}; } sub _make_args { my %args = @_; $args{PREREQ_PM} = { %{ $args{PREREQ_PM} || {} }, @Existing, @Missing } if $UnderCPAN or $TestOnly; if ( $args{EXE_FILES} and -e 'MANIFEST' ) { require ExtUtils::Manifest; my $manifest = ExtUtils::Manifest::maniread('MANIFEST'); $args{EXE_FILES} = [ grep { exists $manifest->{$_} } @{ $args{EXE_FILES} } ]; } $args{test}{TESTS} ||= 't/*.t'; $args{test}{TESTS} = join( ' ', grep { !exists( $DisabledTests{$_} ) } map { glob($_) } split( /\s+/, $args{test}{TESTS} ) ); my $missing = join( ',', @Missing ); my $config = join( ',', UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config} ) if $Config; $PostambleActions = ( $missing ? "\$(PERL) $0 --config=$config --installdeps=$missing" : "\$(NOECHO) \$(NOOP)" ); return %args; } # a wrapper to ExtUtils::MakeMaker::WriteMakefile sub Write { require Carp; Carp::croak "WriteMakefile: Need even number of args" if @_ % 2; if ($CheckOnly) { print << "."; *** Makefile not written in check-only mode. . return; } my %args = _make_args(@_); no strict 'refs'; $PostambleUsed = 0; local *MY::postamble = \&postamble unless defined &MY::postamble; ExtUtils::MakeMaker::WriteMakefile(%args); print << "." unless $PostambleUsed; *** WARNING: Makefile written with customized MY::postamble() without including contents from Module::AutoInstall::postamble() -- auto installation features disabled. Please contact the author. . return 1; } sub postamble { $PostambleUsed = 1; return << "."; config :: installdeps \t\$(NOECHO) \$(NOOP) checkdeps :: \t\$(PERL) $0 --checkdeps installdeps :: \t$PostambleActions . } 1; __END__ #line 1003 Image-Info-1.28/lib/0000755000175000017500000000000010773761473011746 5ustar teteImage-Info-1.28/lib/Image/0000755000175000017500000000000010773761473012770 5ustar teteImage-Info-1.28/lib/Image/Info/0000755000175000017500000000000010773761473013663 5ustar teteImage-Info-1.28/lib/Image/Info/GIF.pm0000644000175000017500000001245307341513274014622 0ustar tetepackage Image::Info::GIF; # Copyright 1999-2000, Gisle Aas. # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. =begin register MAGIC: /^GIF8[79]a/ Both GIF87a and GIF89a are supported and the version number is found as C for the first image. GIF files can contain multiple images, and information for all images will be returned if image_info() is called in list context. The Netscape-2.0 extention to loop animation sequences is represented by the C key for the first image. The value is either "forever" or a number indicating loop count. =end register =cut use strict; sub my_read { my($source, $len) = @_; my $buf; my $n = read($source, $buf, $len); die "read failed: $!" unless defined $n; die "short read ($len/$n)" unless $n == $len; $buf; } sub read_data_blocks { my $source = shift; my @data; while (my $len = ord(my_read($source, 1))) { push(@data, my_read($source, $len)); } join("", @data); } sub process_file { my($info, $fh) = @_; my $header = my_read($fh, 13); die "Bad GIF signature" unless $header =~ s/^GIF(8[79]a)//; my $version = $1; $info->push_info(0, "GIF_Version" => $version); # process logical screen descriptor my($sw, $sh, $packed, $bg, $aspect) = unpack("vvCCC", $header); $info->push_info(0, "ScreenWidth" => $sw); $info->push_info(0, "ScreenHeight" => $sh); my $color_table_size = 1 << (($packed & 0x07) + 1); $info->push_info(0, "ColorTableSize" => $color_table_size); $info->push_info(0, "SortedColors" => ($packed & 0x08) ? 1 : 0) if $version eq "89a"; $info->push_info(0, "ColorResolution", (($packed & 0x70) >> 4) + 1); my $global_color_table = $packed & 0x80; $info->push_info(0, "GlobalColorTableFlag" => $global_color_table ? 1 : 0); if ($global_color_table) { $info->push_info(0, "BackgroundColor", $bg); } if ($aspect) { $aspect = ($aspect + 15) / 64; $info->push_info(0, "PixelAspectRatio" => $aspect); # XXX is this correct???? $info->push_info(0, "resolution", "1/$aspect"); } else { $info->push_info(0, "resolution", "1/1"); } $info->push_info(0, "file_media_type" => "image/gif"); $info->push_info(0, "file_ext" => "gif"); # more?? if ($global_color_table) { my $color_table = my_read($fh, $color_table_size * 3); #$info->push_info(0, "GlobalColorTable", color_table($color_table)); } my $img_no = 0; my @comments; my @warnings; while (1) { my $intro = ord(my_read($fh, 1)); if ($intro == 0x3B) { # trailer (end of image) last; } elsif ($intro == 0x2C) { # new image if (@comments) { for (@comments) { $info->push_info(0, "Comment", $_); } @comments = (); } $info->push_info($img_no, "color_type" => "Indexed-RGB"); my($x_pos, $y_pos, $w, $h, $packed) = unpack("vvvvC", my_read($fh, 9)); $info->push_info($img_no, "XPosition", $x_pos); $info->push_info($img_no, "YPosition", $y_pos); $info->push_info($img_no, "width", $w); $info->push_info($img_no, "height", $h); if ($packed & 0x80) { # yes, we have a local color table my $ct_size = 1 << (($packed & 0x07) + 1); $info->push_info($img_no, "LColorTableSize" => $ct_size); my $color_table = my_read($fh, $ct_size * 3); } $info->push_info($img_no, "Interlace" => "GIF") if $packed & 0x40; my $lzw_code_size = ord(my_read($fh, 1)); #$info->push_info($img_no, "LZW_MininmCodeSize", $lzw_code_size); read_data_blocks($fh); # skip image data $img_no++; } elsif ($intro == 0x21) { # GIF89a extension push(@warnings, "GIF 89a extensions in 87a") if $version eq "87a"; my $label = ord(my_read($fh, 1)); my $data = read_data_blocks($fh); if ($label == 0xF9 && length($data) == 4) { # Graphic Control my($packed, $delay, $trans_color) = unpack("CvC", $data); my $disposal_method = ($packed >> 2) & 0x07; $info->push_info($img_no, "DisposalMethod", $disposal_method) if $disposal_method; $info->push_info($img_no, "UserInput", 1) if $packed & 0x02; $info->push_info($img_no, "Delay" => $delay/100) if $delay; $info->push_info($img_no, "TransparencyIndex" => $trans_color) if $packed & 0x01; } elsif ($label == 0xFE) { # Comment $data =~ s/\0+$//; # is often NUL-terminated push(@comments, $data); } elsif ($label == 0xFF) { # Application my $app = substr($data, 0, 11, ""); my $auth = substr($app, -3, 3, ""); if ($app eq "NETSCAPE" && $auth eq "2.0" && $data =~ /^\01/) { my $loop = unpack("xv", $data); $loop = "forever" unless $loop; $info->push_info($img_no, "GIF_Loop" => $loop); } else { $info->push_info($img_no, "APP-$app-$auth" => $data); } } else { $info->push_info($img_no, "GIF_Extension-$label" => $data); } } else { die "Unknown introduced code $intro, bad GIF"; } } for (@comments) { $info->push_info(0, "Comment", $_); } for (@warnings) { $info->push_info(0, "Warn", $_); } } sub color_table { my @n = unpack("C*", shift); die "Color table not a multiple of 3" if @n % 3; my @table; while (@n) { my @triple = splice(@n, -3); push(@table, sprintf("#%02x%02x%02x", @triple)); } [reverse @table]; } 1; Image-Info-1.28/lib/Image/Info/PNG.pm0000644000175000017500000000777507341511051014643 0ustar tetepackage Image::Info::PNG; # Copyright 1999-2000, Gisle Aas. # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. =begin register MAGIC: /^\x89PNG\x0d\x0a\x1a\x0a/ Information from IHDR, PLTE, gAMA, pHYs, tEXt, tIME chunks are extracted. The sequence of chunks are also given by the C key. =end register =cut use strict; # Test for Compress::Zlib (for reading zTXt chunks) my $have_zlib = 0; eval { require Compress::Zlib; $have_zlib++; }; sub my_read { my($source, $len) = @_; my $buf; my $n = read($source, $buf, $len); die "read failed: $!" unless defined $n; die "short read ($len/$n)" unless $n == $len; $buf; } sub process_file { my($info, $fh) = @_; my $signature = my_read($fh, 8); die "Bad PNG signature" unless $signature eq "\x89PNG\x0d\x0a\x1a\x0a"; $info->push_info(0, "file_media_type" => "image/png"); $info->push_info(0, "file_ext" => "png"); my @chunks; while (1) { my($len, $type) = unpack("Na4", my_read($fh, 8)); if (@chunks) { my $last = $chunks[-1]; $last =~ s/\s(\d+)$//; my $count = $1 || 1; if ($last eq $type) { $count++; $chunks[-1] = "$type $count"; } else { push(@chunks, $type); } } else { push(@chunks, $type); } last if $type eq "IEND"; my $data = my_read($fh, $len + 4); my $crc = unpack("N", substr($data, -4, 4, "")); if ($type eq "IHDR" && $len == 13) { my($w, $h, $depth, $ctype, $compression, $filter, $interlace) = unpack("NNCCCCC", $data); $ctype = { 0 => "Gray", 2 => "RGB", 3 => "Indexed-RGB", 4 => "GrayA", 6 => "RGBA", }->{$ctype} || "PNG-$ctype"; $compression = "Deflate" if $compression == 0; $filter = "Adaptive" if $filter == 0; $interlace = "Adam7" if $interlace == 1; $info->push_info(0, "width", $w); $info->push_info(0, "height", $h); $info->push_info(0, "SampleFormat", "U$depth"); $info->push_info(0, "color_type", $ctype); $info->push_info(0, "Compression", $compression); $info->push_info(0, "PNG_Filter", $filter); $info->push_info(0, "Interlace", $interlace) if $interlace; } elsif ($type eq "PLTE") { my @table; while (length $data) { push(@table, sprintf("#%02x%02x%02x", unpack("C3", substr($data, 0, 3, "")))); } $info->push_info(0, "ColorPalette" => \@table); } elsif ($type eq "gAMA" && $len == 4) { $info->push_info(0, "Gamma", unpack("N", $data)/100_000); } elsif ($type eq "pHYs" && $len == 9) { my $res; my($res_x, $res_y, $unit) = unpack("NNC", $data); if (0 && $unit == 1) { # convert to dpi $unit = "dpi"; for ($res_x, $res_y) { $_ *= 0.0254; } } $res = ($res_x == $res_y) ? $res_x : "$res_x/$res_y"; if ($unit) { if ($unit == 1) { $res .= " dpm"; } else { $res .= " png-unit-$unit"; } } $info->push_info(0, "resolution" => $res) } elsif ($type eq "tEXt") { my($key, $val) = split(/\0/, $data, 2); # XXX should make sure $key is not in conflict with any # other key we might generate $info->push_info(0, $key, $val); } elsif ($type eq "zTXt" && $have_zlib) { my($key, $val) = split(/\0/, $data, 2); my($method,$ctext) = split(//, $val, 2); if ($method == 0) { $info->push_info(0, $key, Compress::Zlib::uncompress($ctext)); } else { $info->push_info(0, "Chunk-$type" => $data); } } elsif ($type eq "tIME" && $len == 7) { $info->push_info(0, "LastModificationTime", sprintf("%04d-%02d-%02d %02d:%02d:%02d", unpack("nC5", $data))); } elsif ($type eq "sBIT") { $info->push_info(0, "SignificantBits" => unpack("C*", $data)); } elsif ($type eq "IDAT") { # ignore } else { $info->push_info(0, "Chunk-$type" => $data); } } $info->push_info(0, "PNG_Chunks", @chunks); unless ($info->get_info(0, "resolution")) { $info->push_info(0, "resolution", "1/1"); } } 1; Image-Info-1.28/lib/Image/Info/PPM.pm0000644000175000017500000000503010402057015014626 0ustar tetepackage Image::Info::PPM; # Copyright 2000, Gisle Aas. # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. =begin register MAGIC: /^P[1-6]/; =item PBM/PGM/PPM All information available is extracted. =end register =cut use strict; use vars qw/$VERSION/; $VERSION = 0.02; sub process_file { my($info, $fh) = @_; my @header; my $type; my $num_wanted = 3; my $binary; local($/, $_) = ("\n"); while (<$fh>) { if (s/#\s*(.*)//) { $info->push_info(0, "Comment", $1); } push(@header, split(' ')); if (!$type && @header) { $type = shift(@header); $type =~ s/^P// || die; $binary++ if $type > 3; $type = "p" . qw/p b g/[$type % 3] . "m"; $num_wanted = 2 if $type eq "pbm"; } for (@header) { unless (/^\d+$/) { die "Badly formatted $type file"; } } next unless @header >= $num_wanted; # Now we know everything there is to know... $info->push_info(0, "file_media_type" => "image/$type"); $info->push_info(0, "file_ext" => "$type"); $info->push_info(0, "width", shift @header); $info->push_info(0, "height", shift @header); $info->push_info(0, "resolution", "1/1"); if ($type eq "ppm") { my $MSV = shift @header; $info->push_info(0, "MaxSampleValue", $MSV); $info->push_info(0, "color_type", "RGB"); my $double = 1; $double = 2 if $MSV > 256; $info->push_info(0, "SamplesPerPixel", $double * 3); if ($binary) { for (1..3) { $info->push_info(0, "BitsPerSample", int(log($MSV + 1) / log(2) ) ); } } } else { $info->push_info(0, "color_type", "Gray"); $info->push_info(0, "SamplesPerPixel", 1); $info->push_info(0, "BitsPerSample", ($type eq "pbm") ? 1 : 8) if $binary; $info->push_info(0, "MaxSampleValue", shift @header) if $type ne 'pbm'; } last; } } 1; =pod =head1 NAME Image::Info:PPM - PPM support Image::Info =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.ppm"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } my($w, $h) = dim($info); =head1 DESCRIPTION This modules adds ppm support to Image::Info. It is loaded and used automatically. =head1 METHODS =head2 process_file() $info->process_file($source, $options); Processes one file and sets the found info fields in the C<$info> object. =head1 AUTHOR Gisle Aas. =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Image-Info-1.28/lib/Image/Info/SVG.pm0000644000175000017500000000755510456426771014671 0ustar tetepackage Image::Info::SVG; $VERSION = '1.04'; use strict; no strict 'refs'; use XML::Simple; sub process_file { my($info, $source) = @_; my(@comments, @warnings, %info, $comment, $img, $imgdata, $xs); local($_); while(<$source>){ if( ! exists($info{standalone}) && /standalone="(.+?)"/ ){ $info{standalone} = $1; } if( // ){ $comment .= $_; } if( /-->/ ){ $comment =~ s///; chomp($comment); push @comments, $comment; $comment = ''; } $imgdata .= $_; } if( $imgdata !~ /push_info(0, "error", "Not a valid SVG image"); } local $SIG{__WARN__} = sub { push(@warnings, @_); }; $xs = XML::Simple->new; $img = $xs->XMLin($imgdata); # use Data::Dumper; print Dumper($img); $info->push_info(0, "color_type" => "sRGB"); $info->push_info(0, "file_ext" => "svg"); # "image/svg+xml" is the official MIME type $info->push_info(0, "file_media_type" => "image/svg+xml"); $info->push_info(0, "height", $img->{height}); $info->push_info(0, "width", $img->{width}); $info->push_info(0, "SVG_StandAlone", $info{standalone}); $info->push_info(0, "SVG_Version", $img->{version} || 'unknown'); # XXX Description, title etc. could be tucked away in a :-( $info->push_info(0, "ImageDescription", $img->{desc}) if $img->{desc}; $info->push_info(0, "SVG_Title", $img->{title}) if $img->{title}; # $info->push_info(0, "SamplesPerPixel", -1); # $info->push_info(0, "resolution", "1/1"); # $info->push_info(0, "BitsPerSample", 8); if( $img->{image} ){ if( ref($img->{image}) eq 'ARRAY' ){ foreach my $img (@{$img->{image}}){ $info->push_info(0, "SVG_Image", $img->{'xlink:href'}); } } else{ $info->push_info(0, "SVG_Image", $img->{image}->{'xlink:href'}); } } for (@comments) { $info->push_info(0, "Comment", $_); } for (@warnings) { $info->push_info(0, "Warn", $_); } } 1; __END__ =pod =head1 NAME Image::Info::SVG - SVG support for Image::Info =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.svg"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } my $title = $info->{SVG_Title}; my($w, $h) = dim($info); =head1 DESCRIPTION This modules supplies the standard key names except for BitsPerSample, Compression, Gamma, Interlace, LastModificationTime, as well as: =over =item ImageDescription The image description, corresponds to . =item SVG_Image A scalar or reference to an array of scalars containing the URI's of embedded images (JPG or PNG) that are embedded in the image. =item SVG_StandAlone Whether or not the image is standalone. =item SVG_Title The image title, corresponds to =item SVG_Version The URI of the DTD the image conforms to. =back =head1 METHODS =head2 process_file() $info->process_file($source, $options); Processes one file and sets the found info fields in the C<$info> object. =head1 FILES This module requires L<XML::Simple>. =head1 SEE ALSO L<Image::Info>, L<XML::Simple>, L<expat> =head1 NOTES For more information about SVG see: http://www.w3.org/Graphics/SVG/ Random notes: Colors # iterate over polygon,rect,circle,ellipse,line,polyline,text for style->stroke: style->fill:? # and iterate over each of these within <g> too?! and recurse?! # append <color>'s # perhaps even deep recursion through <svg>'s? ColorProfile <color-profile> RenderingIntent ? requiredFeatures requiredExtensions systemLanguage =head1 AUTHOR Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org> This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =begin register MAGIC: /^<\?xml/ Provides a plethora of attributes and metadata of an SVG vector grafic. =end register =cut ���������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/lib/Image/Info/XBM.pm���������������������������������������������������������������0000644�0001750�0001750�00000005241�10402433176�014632� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Image::Info::XBM; $VERSION = '1.06'; use strict; use Image::Xbm 1.07; sub process_file { my($info, $source, $opts) = @_; $SIG{__WARN__} = sub { $info->push_info(0, "Warn", shift); }; my $i = Image::Xbm->new(-width => 0, -height => 0); # loading the file as a seperate step avoids a "-r" test, this would # file with in-memory strings (aka fake files) $i->load($source); $info->push_info(0, "color_type" => "Grey"); $info->push_info(0, "file_ext" => "xbm"); $info->push_info(0, "file_media_type" => "image/x-xbitmap"); $info->push_info(0, "height", $i->get(-height)); $info->push_info(0, "resolution", "1/1"); $info->push_info(0, "width", $i->get(-width)); $info->push_info(0, "BitsPerSample" => 1); $info->push_info(0, "SamplesPerPixel", 1); $info->push_info(0, "ColorTableSize" => 2 ); if( $opts->{L1D_Histogram} ){ #Do Histogram my $imgdata = $i->as_binstring(); $info->push_info(0, "L1D_Histogram", [$imgdata =~ tr/0//d, $imgdata =~ tr/1//d ]); } $info->push_info(0, "HotSpotX" => $i->get(-hotx) ); $info->push_info(0, "HotSpotY" => $i->get(-hoty) ); } 1; __END__ =head1 NAME Image::Info::XBM - XBM support for Image::Info =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.xbm"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } my $color = $info->{color_type}; my($w, $h) = dim($info); =head1 DESCRIPTION This modules supplies the standard key names except for Compression, Gamma, Interlace, LastModificationTime, as well as: =over =item HotSpotX The x-coord of the image's hotspot. Set to -1 if there is no hotspot. =item HotSpotY The y-coord of the image's hotspot. Set to -1 if there is no hotspot. =item L1D_Histogram Reference to an array representing a one dimensioanl luminance histogram. This key is only present if C<image_info> is invoked as C<image_info($file, L1D_Histogram=E<gt>1)>. The range is from 0 to 1. =back =head1 METHODS =head2 process_file() $info->process_file($source, $options); Processes one file and sets the found info fields in the C<$info> object. =head1 AUTHOR =head1 FILES This module requires L<Image::Xbm> =head1 SEE ALSO L<Image::Info>, L<Image::Xbm> =head1 NOTES For more information about XBM see: http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/XBM.txt =head1 AUTHOR Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org> Now maintained by Tels - (c) 2006. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut =begin register MAGIC: /^#define\s+/ See L<Image::Info::XBM> for details. =end register =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/lib/Image/Info/XPM.pm���������������������������������������������������������������0000644�0001750�0001750�00000011554�10402433204�014644� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Image::Info::XPM; $VERSION = '1.06'; #Path to X11 RGB database $RGBLIB ||= "/usr/X11R6/lib/X11/rgb.txt"; use strict; use Image::Xpm 1.08; sub process_file{ my($info, $source, $opts) = @_; $SIG{__WARN__} = sub { $info->push_info(0, "Warn", shift); }; my $i = Image::Xpm->new(-width => 0, -height => 0); # loading the file as a seperate step avoids a "-r" test, this would # file with in-memory strings (aka fake files) $i->load($source); $info->push_info(0, "color_type" => "Indexed-RGB"); $info->push_info(0, "file_ext" => "xpm"); $info->push_info(0, "file_media_type" => "image/x-xpixmap"); $info->push_info(0, "height", $i->get(-height)); $info->push_info(0, "resolution", "1/1"); $info->push_info(0, "width", $i->get(-width)); $info->push_info(0, "BitsPerSample" => 8); $info->push_info(0, "SamplesPerPixel", 1); $info->push_info(0, "XPM_CharactersPerPixel" => $i->get(-cpp) ); # XXX is this always? $info->push_info(0, "ColorResolution", 8); $info->push_info(0, "ColorTableSize" => $i->get(-ncolours) ); if( $opts->{ColorPalette} ){ $info->push_info(0, "ColorPalette" => [keys %{$i->get(-cindex)}] ); } if( $opts->{L1D_Histogram} ){ #Do Histograms my(%RGB, @l1dhist, $R, $G, $B, $color); for(my $y=0; $y<$i->get(-height); $y++){ for(my $x=0; $x<$i->get(-width); $x++){ $color = $i->xy($x, $y); if( $color !~ /^#/ ){ unless( exists($RGB{white}) ){ local $_; if( open(RGB, $Image::Info::XPM::RGBLIB) ){ while(<RGB>){ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)/; $RGB{$4}=[$1,$2,$3]; } } else{ $RGB{white} = "0 but true"; $info->push_info(0, "Warn", "Unable to open RGB database, you may need to set \$Image::Info::XPM::RGBLIB or define \$RGBLIB in ". __FILE__); } } $R = $RGB{$color}->[0]; $G = $RGB{$color}->[1]; $B = $RGB{$color}->[2]; } else{ $R = hex(substr($color,1,2)); $G = hex(substr($color,3,2)); $B = hex(substr($color,5,2)); } if( $opts->{L1D_Histogram} ){ $l1dhist[(.3*$R + .59*$G + .11*$B)]++; } } } if( $opts->{L1D_Histogram} ){ $info->push_info(0, "L1D_Histogram", [@l1dhist]); } } $info->push_info(0, "HotSpotX" => $i->get(-hotx) ); $info->push_info(0, "HotSpotY" => $i->get(-hoty) ); $info->push_info(0, 'XPM_Extension-'.ucfirst($i->get(-extname)) => $i->get(-extlines)) if $i->get(-extname); for (@{$i->get(-comments)}) { $info->push_info(0, "Comment", $_); } } 1; __END__ =head1 NAME Image::Info::XPM - XPM support for Image::Info =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.xpm"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } my $color = $info->{color_type}; my($w, $h) = dim($info); =head1 DESCRIPTION This modules supplies the standard key names except for Compression, Gamma, Interlace, LastModificationTime, as well as: =over =item ColorPalette Reference to an array of all colors used. This key is only present if C<image_info> is invoked as C<image_info({ColorPaletteE<gt>=1})>. =item ColorTableSize The number of colors the image uses. =item HotSpotX The x-coord of the image's hotspot. Set to -1 if there is no hotspot. =item HotSpotY The y-coord of the image's hotspot. Set to -1 if there is no hotspot. =item L1D_Histogram Reference to an array representing a one dimensioanl luminance histogram. This key is only present if C<image_info> is invoked as C<image_info($file, L1D_Histogram=E<gt>1)>. The range is from 0 to 255, however auto-vivification is used so a null field is also 0, and the array may not actually contain 255 fields. =item XPM_CharactersPerPixel This is typically 1 or 2. See L<Image::Xpm>. =item XPM_Extension-.* XPM Extensions (the most common is XPMEXT) if present. =back =head1 METHODS =head2 process_file() $info->process_file($source, $options); Processes one file and sets the found info fields in the C<$info> object. =head1 AUTHOR =head1 FILES This module requires L<Image::Xpm> I<$Image::Info::XPM::RGBLIB> is set to F</usr/X11R6/lib/X11/rgb.txt> by default, this is used to resolve textual color names to their RGB counterparts. =head1 SEE ALSO L<Image::Info>, L<Image::Xpm> =head1 NOTES For more information about XPM see: ftp://ftp.x.org/contrib/libraries/xpm-README.html =head1 CAVEATS While the module attempts to be as robust as possible, it may not recognize older XBMs (Versions 1-3), if this is the case try inserting S</* XPM */> as the first line. =head1 AUTHOR Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org> Now maintained by Tels - (c) 2006. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut =begin register MAGIC: /(^\/\* XPM \*\/)|(static\s+char\s+\*\w+\[\]\s*=\s*{\s*"\d+)/ See L<Image::Info::XPM> for details. =end register =cut ����������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/lib/Image/Info/TIFF.pm��������������������������������������������������������������0000644�0001750�0001750�00000015316�10570300257�014737� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Image::Info::TIFF; $VERSION = 0.02; use strict; use Config; use Carp qw(confess); use Image::TIFF; my @types = ( [ "ERROR INVALID TYPE", "?", 0], [ "BYTE", "C", 1], [ "ASCII", "A", 1], [ "SHORT", "S", 2], [ "LONG", "L", 4], [ "RATIONAL", "N2", 8], [ "SBYTE", "c", 1], [ "UNDEFINED", "a", 1], [ "SSHORT", "s", 2], [ "SLONG", "l", 4], [ "SRATIONAL", "N2", 8], [ "FLOAT", "f", 4], [ "DOUBLE", "d", 8], ); sub _hostbyteorder { my $hbo = $Config{byteorder}; # we only care about the order, not the length (for 64 bit, it might # be 12345678) if ($hbo =~ /^1234/) { return '1234' } if ($hbo =~ /4321$/) { return '4321' } die "Unexpected host byteorder: $hbo"; } sub _read { # read bytes, and move the file pointer forward my($source, $len) = @_; my $buf; my $n = read($source, $buf, $len); die "read failed: $!" unless defined $n; die "short read ($len/$n)" unless $n == $len; $buf; } sub _readbytes { # read bytes, but make the file pointer stand still my ($fh,$offset,$len) = @_; my $curoffset = tell($fh); my $buf; seek($fh,$offset,0); my $n = read($fh,$buf,$len); confess("short read($n/$len)") unless $n == $len; # back to before. seek($fh,$curoffset,0); return $buf; } sub _readrational { my ($fh,$offset,$byteorder,$count,$ar,$signed) = @_; my $curoffset = tell($fh); my $buf; seek($fh,$offset,0); while ($count > 0) { my $num; my $denom; if ($signed) { $num = unpack("l",_read_order($fh,4,$byteorder)); $denom = unpack("l",_read_order($fh,4,$byteorder)); } else { $num = unpack("L",_read_order($fh,4,$byteorder)); $denom = unpack("L",_read_order($fh,4,$byteorder)); } push(@{$ar},new Image::TIFF::Rational($num,$denom)); $count--; } # back to before. seek($fh,$curoffset,0); } sub _read_order { my($source, $len,$byteorder) = @_; my $buf = _read($source,$len); # maybe reverse the read data? if ($byteorder ne _hostbyteorder()) { my @bytes = unpack("C$len",$buf); my @newbytes; # swap bytes for (my $i = $len-1; $i >= 0; $i--) { push(@newbytes,$bytes[$i]); } $buf = pack("C$len",@newbytes); } $buf; } my %order = ( "MM\x00\x2a" => '4321', "II\x2a\x00" => '1234', ); sub process_file { my($info, $fh) = @_; my $soi = _read($fh, 4); die "TIFF: SOI missing" unless (defined($order{$soi})); # XXX: should put this info in all pages? $info->push_info(0, "file_media_type" => "image/tiff"); $info->push_info(0, "file_ext" => "tif"); my $byteorder = $order{$soi}; my $ifdoff = unpack("L",_read_order($fh,4,$byteorder)); my $page = 0; do { # print "TIFF Directory at $ifdoff\n"; $ifdoff = _process_ifds($info,$fh,$page,0,$byteorder,$ifdoff); $page++; } while ($ifdoff); } sub _process_ifds { my($info, $fh, $page, $tagsseen, $byteorder, $ifdoffset) = @_; my $curpos = tell($fh); seek($fh,$ifdoffset,0); my $n = unpack("S",_read_order($fh, 2, $byteorder)); ## Number of entries my $i = 1; while ($n > 0) { # process one IFD entry my $tag = unpack("S",_read_order($fh,2,$byteorder)); my $fieldtype = unpack("S",_read_order($fh,2,$byteorder)); unless ($types[$fieldtype]) { warn "Unrecognised fieldtype $fieldtype, skipping\n"; next; } my ($typename, $typepack, $typelen) = @{$types[$fieldtype]}; my $count = unpack("L",_read_order($fh,4,$byteorder)); my $value_offset_orig = _read_order($fh,4,$byteorder); my $value_offset = unpack("L", $value_offset_orig); my $val; ## The 4 bytes of $value_offset may actually contains the value itself, ## if it fits into 4 bytes. my $len = $typelen * $count; if ($len <= 4) { if (($byteorder ne _hostbyteorder()) && ($len != 4)) { my @bytes = unpack("C4", $value_offset_orig); for (my $i=0; $i < 4 - $len; $i++) { shift @bytes; } $value_offset_orig = pack("C$len", @bytes); } @$val = unpack($typepack x $count, $value_offset_orig); } elsif ($fieldtype == 2) { ## ASCII text. The last byte is a NUL, which we don't need ## to include in the Perl string, so read one less than the count. @$val = _readbytes($fh, $value_offset, $count - 1); } elsif ($fieldtype == 5) { ## Unsigned Rational _readrational($fh,$value_offset,$byteorder,$count,$val,0); } elsif ($fieldtype == 10) { ## Signed Rational _readrational($fh,$value_offset,$byteorder,$count,$val,1); } else { ## Just read $count thingies from the offset @$val = unpack($typepack x $count, _readbytes($fh, $value_offset, $typelen * $count)); } #look up tag my $tn = Image::TIFF->exif_tagname($tag); foreach my $v (@$val) { if (ref($tn)) { $v = $$tn{$v}; $tn = $$tn{__TAG__}; } } if ($tn eq "NewSubfileType") { # start new page if necessary if ($tagsseen) { $page++; $tagsseen = 0; } } else { $tagsseen = 1; } my $vval; ## If only one value, use direct if (@$val <= 1) { $val = $val->[0] || ''; $vval = $val; } else { $vval = '(' . join(',',@$val) . ')'; } # print "$page/$i:$value_offset:$tag ($tn), fieldtype: $fieldtype, count: $count = $vval\n"; if ($tn eq "ExifOffset") { # parse ExifSubIFD # print "ExifSubIFD at $value_offset\n"; _process_ifds($info,$fh,$page,$tagsseen,$byteorder,$value_offset); } $info->push_info($page, $tn => $val); $n--; $i++; } my $ifdoff = unpack("L",_read_order($fh,4,$byteorder)); #print "next dir at $ifdoff\n"; seek($fh,$curpos,0); return $ifdoff if $ifdoff; 0; } 1; __END__ =pod =head1 NAME Image::Info::TIFF - TIFF support for Image::Info =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.tif"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } print $info->{BitPerSample}; my($w, $h) = dim($info); =head1 DESCRIPTION This module adds TIFF support for Image::Info. =head1 METHODS =head2 process_file() $info->process_file($source, $options); Processes one file and sets the found info fields in the C<$info> object. =head1 SEE ALSO L<Image::Info> =head1 AUTHOR Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org> Patches and fixes by Ben Wheeler. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =begin register MAGIC: /^MM\x00\x2a/ MAGIC: /^II\x2a\x00/ The C<TIFF> spec can be found at: L<http://partners.adobe.com/public/developer/tiff/> The EXIF spec can be found at: L<http://www.exif.org/> =end register =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/lib/Image/Info/JPEG.pm��������������������������������������������������������������0000644�0001750�0001750�00000020404�10773761332�014740� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Image::Info::JPEG; # Copyright 1999-2000, Gisle Aas. # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. # maintained by Tels 2007 - 2008 $VERSION = 0.02; =begin register MAGIC: /^\xFF\xD8/ For JPEG files we extract information both from C<JFIF> and C<Exif> application chunks. C<Exif> is the file format written by most digital cameras. This encode things like timestamp, camera model, focal length, exposure time, aperture, flash usage, GPS position, etc. The following web page contain description of the fields that can be present: http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html The C<Exif> spec can be found at: http://www.exif.org/specifications.html =end register =cut use strict; my %sof = ( 0xC0 => "Baseline", 0xC1 => "Extended sequential", 0xC2 => "Progressive", 0xC3 => "Lossless", 0xC5 => "Differential sequential", 0xC6 => "Differential progressive", 0xC7 => "Differential lossless", 0xC9 => "Extended sequential, arithmetic coding", 0xCA => "Progressive, arithmetic coding", 0xCB => "Lossless, arithmetic coding", 0xCD => "Differential sequential, arithmetic coding", 0xCE => "Differential progressive, arithmetic coding", 0xCF => "Differential lossless, arithmetic coding", ); sub my_read { my($source, $len) = @_; my $buf; my $n = read($source, $buf, $len); die "read failed: $!" unless defined $n; die "short read ($len/$n)" unless $n == $len; $buf; } BEGIN { my $f = ($] >= 5.008) ? <<'EOT' : <<'EOT'; sub with_io_string (&$) { open(my $fh, "<", \$_[1]); local $_ = $fh; &{$_[0]}; } EOT sub with_io_string (&$) { require IO::String; local $_ = IO::String->new($_[1]); &{$_[0]}; $_->close; } EOT #print $f; eval $f; die $@ if $@; } sub process_file { my($info, $fh, $cnf) = @_; _process_file($info, $fh, 0); } sub _process_file { my($info, $fh, $img_no) = @_; my $soi = my_read($fh, 2); my $ofs = tell() - 2; die "SOI missing in JPEG file at offset $ofs" unless $soi eq "\xFF\xD8"; $info->push_info($img_no, "file_media_type" => "image/jpeg"); $info->push_info($img_no, "file_ext" => "jpg"); while (1) { my($ff, $mark, $len) = unpack("CCn", my_read($fh, 4)); last if $ff != 0xFF; last if $mark == 0xDA || $mark == 0xD9; # SOS/EOI last if $len < 2; process_chunk($info, $img_no, $mark, my_read($fh, $len - 2)); } } sub process_chunk { my($info, $img_no, $mark, $data) = @_; #printf "MARK 0x%02X, len=%d\n", $mark, length($data); if ($mark == 0xFE) { $info->push_info($img_no, Comment => $data); } elsif ($mark >= 0xE0 && $mark <= 0xEF) { process_app($info, $mark, $data) if $img_no == 0; } elsif ($sof{$mark}) { my($precision, $height, $width, $num_comp) = unpack("CnnC", substr($data, 0, 6, "")); $info->push_info($img_no, "JPEG_Type", $sof{$mark}); # fix bug #15167 by keeping the highest values my $old_w = $info->get_info($img_no, "width") || -1; my $old_h = $info->get_info($img_no, "height") || -1; $info->replace_info($img_no, "width", $width) if $old_w < $width; $info->replace_info($img_no, "height", $height) if $old_h < $height; for (1..$num_comp) { $info->push_info($img_no, "BitsPerSample", $precision); } $info->push_info($img_no, "SamplesPerPixel" => $num_comp); # XXX need to consider JFIF/Adobe markers to determine this... if ($num_comp == 1) { $info->push_info($img_no, "color_type" => "Gray"); } elsif ($num_comp == 3) { $info->push_info($img_no, "color_type" => "YCbCr"); # or RGB ? } elsif ($num_comp == 4) { $info->push_info($img_no, "color_type" => "CMYK"); # or YCCK ? } if (1) { my %comp_id_lookup = ( 1 => "Y", 2 => "Cb", 3 => "Cr", 82 => "R", 71 => "G", 66 => "B" ); while (length($data)) { my($comp_id, $hv, $qtable) = unpack("CCC", substr($data, 0, 3, "")); my $horiz_sf = $hv >> 4 & 0x0f; my $vert_sf = $hv & 0x0f; $comp_id = $comp_id_lookup{$comp_id} || $comp_id; $info->push_info($img_no, "ColorComponents", [$comp_id, $hv, $qtable]); $info->push_info($img_no, "ColorComponentsDecoded", { ComponentIdentifier => $comp_id, HorizontalSamplingFactor => $horiz_sf, VerticalSamplingFactor => $vert_sf, QuantizationTableDesignator => $qtable } ); } } } } sub process_app { my($info, $mark, $data) = @_; my $app = $mark - 0xE0; my $id = substr($data, 0, 5, ""); #$info->push_info(0, "Debug", "APP$app $id"); $id = "$app-$id"; if ($id eq "0-JFIF\0") { process_app0_jfif($info, $data); } elsif ($id eq "0-JFXX\0") { process_app0_jfxx($info, $data); } elsif ($id eq "1-Exif\0") { process_app1_exif($info, $data); } elsif ($id eq "14-Adobe") { process_app14_adobe($info, $data); } else { $info->push_info(0, "App$id", $data); #printf " %s\n", Data::Dump::dump($data); } } sub process_app0_jfif { my($info, $data) = @_; if (length $data < 9) { $info->push_info(0, "Debug", "Short JFIF chunk"); return; } my($ver_hi, $ver_lo, $unit, $x_density, $y_density, $x_thumb, $y_thumb) = unpack("CC C nn CC", substr($data, 0, 9, "")); $info->push_info(0, "JFIF_Version", sprintf("%d.%02d", $ver_hi, $ver_lo)); my $res = $x_density != $y_density || !$unit ? "$x_density/$y_density" : $x_density; if ($unit) { $unit = { 0 => "pixels", 1 => "dpi", 2 => "dpcm" }->{$unit} || "jfif-unit-$unit"; $res .= " $unit"; } $info->push_info(0, "resolution", $res); if ($x_thumb || $y_thumb) { $info->push_info(1, "width", $x_thumb); $info->push_info(1, "height", $y_thumb); $info->push_info(1, "ByteCount", length($data)); } } sub process_app0_jfxx { my($info, $data) = @_; my($code) = ord(substr($data, 0, 1, "")); $info->push_info(1, "JFXX_ImageType", { 0x10 => "JPEG thumbnail", 0x11 => "Bitmap thumbnail", 0x13 => "RGB thumbnail", }->{$code} || "Unknown extention code $code"); if ($code == 0x10) { eval { with_io_string { _process_file($info, $_, 1); } $data; }; $info->push_info(1, "error" => $@) if $@; } } sub process_app1_exif { my($info, $data) = @_; my $null = substr($data, 0, 1, ""); if ($null ne "\0") { $info->push_info(0, "Debug", "Exif chunk does not start with \\0"); return; } require Image::TIFF; my $t = Image::TIFF->new(\$data); for my $i (0 .. $t->num_ifds - 1) { my $ifd = $t->ifd($i); # use Data::Dumper; # print STDERR Dumper($ifd); for (@$ifd) { # use Devel::Peek; # print STDERR "# pushing info $i $_->[0] $_->[3]\n"; # print STDERR Devel::Peek::Dump($_->[3]),"\n" if $_->[0] =~ /Olympus-/; $info->push_info($i, $_->[0], $_->[3]); } # If we find JPEGInterchangeFormat/JPEGInterchangeFormatLngth, # then we should apply process_file kind of recusively to extract # information of this (thumbnail) image file... if (my($ipos) = $info->get_info($i, "JPEGInterchangeFormat", 1)) { my($ilen) = $info->get_info($i, "JPEGInterchangeFormatLength", 1); if ($ilen) { my $jdata = substr($data, $ipos, $ilen); #$info->push_info($i, "JPEGImage" => $jdata); with_io_string { _process_file($info, $_, $i); } $jdata; } } # Turn XResolution/YResolution into 'resolution' my($xres) = $info->get_info($i, "XResolution", 1); my($yres) = $info->get_info($i, "YResolution", 1); # Samsung Digimax 200 is a totally confused camera that # puts rational numbers with 0 as denominator and they # also seem to not understand what resolution means. for ($xres, $yres) { $_ += 0 if ref($_) eq "Image::TIFF::Rational"; } my($unit) = $info->get_info($i, "ResolutionUnit", 1); my $res = "1/1"; # default; if ($xres && $yres) { $res = ($xres == $yres) ? $xres : "$xres/$yres"; } $res .= " $unit" if $unit && $unit ne "pixels"; $info->push_info($i, "resolution", $res); } } sub process_app14_adobe { my($info, $data) = @_; my($version, $flags0, $flags1, $transform) = unpack("nnnC", $data); $info->push_info(0, "AdobeTransformVersion" => $version); $info->push_info(0, "AdobeTransformFlags" => [$flags0, $flags1]); $info->push_info(0, "AdobeTransform" => $transform); } 1; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/lib/Image/Info/BMP.pm���������������������������������������������������������������0000644�0001750�0001750�00000012506�10402056104�014614� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Image::Info::BMP; $VERSION = '1.01'; use strict; sub process_file { my($info, $source, $opts) = @_; my(@comments, @warnings, @header, %info, $buf, $total); read($source, $buf, 54) == 54 or die "Can't reread BMP header: $!"; @header = unpack("vVv2V2V2v2V2V2V2", $buf); $total += length($buf); if( $header[9] && $header[9] < 24 ){ $info->push_info(0, "color_type" => "Indexed-RGB"); } else{ $info->push_info(0, "color_type" => "RGB"); } $info->push_info(0, "file_media_type" => "image/bmp"); if( $header[10] == 1 || $header[10] == 2){ $info->push_info(0, "file_ext" => "rle"); } else{ $info->push_info(0, "file_ext" => "bmp"); # || dib } $info->push_info(0, "height", abs($header[7])); $info->push_info(0, "resolution", "$header[12]/$header[13]"); $info->push_info(0, "width", $header[6]); $info->push_info(0, "BitsPerSample" => $header[9]); $info->push_info(0, "SamplesPerPixel", $header[8]); $info->push_info(0, "BMP_ColorsImportant", $header[15]); $info->push_info(0, "BMP_Origin", $header[7]>1 ? 1 : 0 ); $info->push_info(0, "ColorTableSize", $header[14]); $info->push_info(0, "Compression", [ 'none', 'RLE8', 'RLE4', 'BITFIELDS', #V4 'JPEG', #V5 'PNG', #V5 ]->[$header[10]]); #Version 5 Header ammendements # XXX Discard for now, need a test image if( $header[5] > 40 ){ read($source, $buf, $header[5]-40); # XXX test $total += length($buf); my @v5 = unpack("V38", $buf); splice(@v5, 5, 27); $info->push_info(0, "BMP_MaskRed", $v5[0]); $info->push_info(0, "BMP_MaskGreen", $v5[1]); $info->push_info(0, "BMP_MaskBlue", $v5[2]); $info->push_info(0, "BMP_MaskAlpha", $v5[3]); # $info->push_info(0, "BMP_color_type", $v5[4]); $info->push_info(0, "BMP_GammaRed", $v5[5]); $info->push_info(0, "BMP_GammaGreen", $v5[6]); $info->push_info(0, "BMP_GammaBlue", $v5[7]); } if( $header[9] < 24 && $opts->{ColorPalette} ){ my(@color, @palette); for(my $i=0; $i<$header[14]; $i++){ read($source, $buf, 4) == 4 or die "Can't read: $!"; $total += length($buf); @color = unpack("C3", $buf); # Damn M$, BGR instead of RGB push @palette, sprintf("#%02x%02x%02x", $color[2], $color[1], $color[0]); } $info->push_info(0, "ColorPalette", @palette); } #Verify size # XXX Cheat and do -s if it's an actual file? while( read($source, $buf, 1024) ){ $total += length($buf); } if( $header[1] != $total ){ push @warnings, "Size mismatch." } for (@comments) { $info->push_info(0, "Comment", $_); } for (@warnings) { $info->push_info(0, "Warn", $_); } } 1; __END__ =pod =head1 NAME Image::Info:BMP - Windows Device Indepdent Bitmap support for Image::Info =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.bmp"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } my $color = $info->{color_type}; my($w, $h) = dim($info); =head1 DESCRIPTION This modules supplies the standard key names except for Gamma, Interlace, LastModificationTime, as well as: =over =item BMP_ColorsImportant Specifies the number of color indexes that are required for displaying the bitmap. If this value is zero, all colors are required. =item BMP_Origin If true the bitmap is a bottom-up DIB and its origin is the lower-left corner. Otherwise, the bitmap is a top-down DIB and its origin is the upper-left corner. =item ColorPalette Reference to an array of all colors used. This key is only present if C<image_info> is invoked as C<image_info($file, ColorPalette=E<gt>1)>. =item ColorTableSize The number of colors the image uses. If 0 then this is a true color image. The number of color I<available> is 2 ^ B<BitsPerSample>. =back =head1 METHODS =head2 process_file() $info->process_file($source, $options); Processes one file and sets the found info fields in the C<$info> object. =head1 SEE ALSO L<Image::Info> =head1 NOTES For more information about BMP see: http://msdn.microsoft.com Random notes: warn if height is negative and compress is not RGB or BITFILEDS (0 or 3) ICO and CUR support? ### v5 If bit depth is 0, it relies upon underlying JPG/PNG :-( Extra Information DWORD bV5RedMask; DWORD bV5GreenMask; DWORD bV5BlueMask; DWORD bV5AlphaMask; DWORD bV5CSType; CIEXYZTRIPLE bV5EndPoints; #3*CIEXYZ #CIEXYZ = 3*FXPT2DOT30#FXPT2DOT30 = long DWORD bV5GammaRed; DWORD bV5GammaGreen; DWORD bV5GammaBlue; DWORD bV5Intent; DWORD bV5ProfileData; DWORD bV5ProfileSize; =head1 DIAGNOSTICS =over =item Size mismatch The image may be correct, the filesize does not match the internally stored value. =back =head1 BUGS The current implementation only function on little-endian architectures. Consequently erroneous data concerning compression (including B<file_ext> and B<file_mime_type>) may be reported. =head1 AUTHOR Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org> This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =begin register MAGIC: /^BM/ This module supports the Microsoft Device Independent Bitmap format (BMP, DIB, RLE). For more information see L<Image::Info::BMP>. =end register =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/lib/Image/Info.pm�������������������������������������������������������������������0000644�0001750�0001750�00000033612�10773760561�014223� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ############################################################################# # # ATTENTION! This file is autogenerated from dev/Info.pm.tmpl - DO NOT EDIT! # ############################################################################# package Image::Info; # Copyright 1999-2004, Gisle Aas. # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl v5.8.8 itself. # # Now maintained by Tels - (c) 2006 - 2008. use strict; use vars qw($VERSION @EXPORT_OK); $VERSION = '1.28'; require Exporter; *import = \&Exporter::import; @EXPORT_OK = qw(image_info dim html_dim image_type determine_file_format); # already required and failed sub-modules are remembered here my %mod_failure; sub image_info { my $source = _source(shift); return $source if ref $source eq 'HASH'; # Pass on errors # What sort of file is it? my $head = _head($source); return $head if ref($head) eq 'HASH'; # error? my $format = determine_file_format($head) or return { error => 'Unrecognized file format' }; no strict 'refs'; my $mod = "Image::Info::$format"; my $sub = "$mod\::process_file"; my $info = bless [], "Image::Info::Result"; eval { unless (defined &$sub) { # already required and failed? if (my $fail = $mod_failure{$mod}) { die $fail; } eval "require $mod"; if ($@) { $mod_failure{$mod} = $@; die $@; } die "$mod did not define &$sub" unless defined &$sub; } my %cnf = @_; # call process_file() &$sub($info, $source, \%cnf); $info->clean_up; }; return { error => $@ } if $@; return wantarray ? @$info : $info->[0]; } sub image_type { my $source = _source(shift); return $source if ref $source eq 'HASH'; # Pass on errors # What sort of file is it? my $head = _head($source) or return _os_err("Can't read head"); my $format = determine_file_format($head) or return { error => "Unrecognized file format" }; return { file_type => $format }; } sub _source { my $source = shift; if (!ref $source) { require Symbol; my $fh = Symbol::gensym(); open($fh, $source) || return _os_err("Can't open $source"); ${*$fh} = $source; # keep filename in case somebody wants to know binmode($fh); $source = $fh; } elsif (ref($source) eq "SCALAR") { if ($] >= 5.008) { open(my $s, "<", $source) or return _os_err("Can't open string"); $source = $s; } else { require IO::String; $source = IO::String->new($$source); } } else { seek($source, 0, 0) or return _os_err("Can't rewind"); } $source; } sub _head { my $source = shift; my $head; # tiny.pgm is 11 bytes my $to_read = 11; my $read = read($source, $head, $to_read); return _os_err("Couldn't read $to_read bytes") if $read != $to_read; if (ref($source) eq "IO::String") { # XXX workaround until we can trap seek() with a tied file handle $source->setpos(0); } else { seek($source, 0, 0) or return _os_err("Can't rewind"); } $head; } sub _os_err { return { error => "$_[0]: $!", Errno => $!+0, }; } sub determine_file_format { local($_) = @_; return "BMP" if /^BM/; return "GIF" if /^GIF8[79]a/; return "JPEG" if /^\xFF\xD8/; return "PNG" if /^\x89PNG\x0d\x0a\x1a\x0a/; return "PPM" if /^P[1-6]/;; return "SVG" if /^<\?xml/; return "TIFF" if /^MM\x00\x2a/; return "TIFF" if /^II\x2a\x00/; return "XBM" if /^#define\s+/; return "XPM" if /(^\/\* XPM \*\/)|(static\s+char\s+\*\w+\[\]\s*=\s*{\s*"\d+)/; return undef; } sub dim { my $img = shift || return; my $x = $img->{width} || return; my $y = $img->{height} || return; wantarray ? ($x, $y) : "${x}x$y"; } sub html_dim { my($x, $y) = dim(@_); return "" unless $x; "width=\"$x\" height=\"$y\""; } ############################################################################# package Image::Info::Result; sub push_info { my($self, $n, $key) = splice(@_, 0, 3); push(@{$self->[$n]{$key}}, @_); } sub replace_info { my($self, $n, $key) = splice(@_, 0, 3); $self->[$n]{$key}[0] = $_[0]; } sub clean_up { my $self = shift; for (@$self) { for my $k (keys %$_) { my $a = $_->{$k}; $_->{$k} = $a->[0] if @$a <= 1; } } } sub get_info { my($self, $n, $key, $delete) = @_; my $v = $delete ? delete $self->[$n]{$key} : $self->[$n]{$key}; $v ||= []; @$v; } 1; __END__ =head1 NAME Image::Info - Extract meta information from image files (DEPRECATED) =head1 SYNOPSIS use Image::Info qw(image_info dim); my $info = image_info("image.jpg"); if (my $error = $info->{error}) { die "Can't parse image info: $error\n"; } my $color = $info->{color_type}; my $type = image_type("image.jpg"); if (my $error = $type->{error}) { die "Can't determine file type: $error\n"; } die "No gif files allowed!" if $type->{file_type} eq 'GIF'; my($w, $h) = dim($info); =head1 DESCRIPTION Please note that this module is B<deprecated> and should not be used. Alternatively, try one of the following modules: L<Image::Size>, L<Image::ExifTool>. The code in this module is old, unreviewed, hackish, still has numerous bugs and is incomplete in quite a few cases. While this module is sort-of maintained (e.g. the most critical security-related bugs are fixed), no new features will be added and numerous minor bugs are very likely sprinkled through the entire code base. You have been warned. This module provide functions to extract various kind of meta information from image files. =head2 EXPORTS Exports nothing by default, but can export the following methods on request: image_info image_type dim html_dim determine_file_type =head2 METHODS The following functions are provided by the C<Image::Info> module: =over =item image_info( $file ) =item image_info( \$imgdata ) =item image_info( $file, key => value,... ) This function takes the name of a file or a file handle as argument and will return one or more hashes (actually hash references) describing the images inside the file. If there is only one image in the file only one hash is returned. In scalar context, only the hash for the first image is returned. In case of error, and hash containing the "error" key will be returned. The corresponding value will be an appropriate error message. If a reference to a scalar is passed as argument to this function, then it is assumed that this scalar contains the raw image data directly. The image_info() function also take optional key/value style arguments that can influence what information is returned. =item image_type( \$imgdata ) Returns a hash with only one key, C<< file_type >>. The value will be the type of the file. On error, sets the two keys C<< error >> and C<< Errno >>. This function is a dramatically faster alternative to the image_info function for situations in which you B<only> need to find the image type. It uses only the internal file-type detection to do this, and thus does not need to load any of the image type-specific driver modules, and does not access to entire file. It also only needs access to the first 11 bytes of the file. To maintain some level of compatibility with image_info, image_type returns in the same format, with the same error message style. That is, it returns a HASH reference, with the C<< $type->{error} >> key set if there was an error. On success, the HASH reference will contain the single key 'file_type', which represents the type of the file, expressed as the type code used for the various drivers ('GIF', 'JPEG', 'TIFF' and so on). If there are multiple images within the file they will be ignored, as this function provides only the type of the overall file, not of the various images within it. This function will not return multiple hashes if the file contains multiple images. Of course, in all (or at least effectively all) cases the type of the images inside the file is going to be the same as that of the file itself. =item dim( $info_hash ) Takes an hash as returned from image_info() and returns the dimensions ($width, $height) of the image. In scalar context returns the dimensions as a string. =item html_dim( $info_hash ) Returns the dimensions as a string suitable for embedding directly into HTML or SVG <img>-tags. E.g.: print "<img src="..." @{[html_dim($info)]}>\n"; =item determine_file_format( $filedata ) Determines the file format from the passed file data (a normal Perl scalar containing the first bytes of the file), and returns either undef for an unknown file format, or a string describing the format, like "BMP" or "JPEG". =back =head1 Image descriptions The image_info() function returns meta information about each image in the form of a reference to a hash. The hash keys used are in most cases based on the TIFF element names. All lower case keys are mandatory for all file formats and will always be there unless an error occured (in which case the "error" key will be present.) Mixed case keys will only be present when the corresponding information element is available in the image. The following key names are common for any image format: =over =item file_media_type This is the MIME type that is appropriate for the given file format. The corresponding value is a string like: "image/png" or "image/jpeg". =item file_ext The is the suggested file name extention for a file of the given file format. The value is a 3 letter, lowercase string like "png", "jpg". =item width This is the number of pixels horizontally in the image. =item height This is the number of pixels vertically in the image. (TIFF use the name ImageLength for this field.) =item color_type The value is a short string describing what kind of values the pixels encode. The value can be one of the following: Gray GrayA RGB RGBA CMYK YCbCr CIELab These names can also be prefixed by "Indexed-" if the image is composed of indexes into a palette. Of these, only "Indexed-RGB" is likely to occur. It is similar to the TIFF field PhotometricInterpretation, but this name was found to be too long, so we used the PNG inpired term instead. =item resolution The value of this field normally gives the physical size of the image on screen or paper. When the unit specifier is missing then this field denotes the squareness of pixels in the image. The syntax of this field is: <res> <unit> <xres> "/" <yres> <unit> <xres> "/" <yres> The <res>, <xres> and <yres> fields are numbers. The <unit> is a string like C<dpi>, C<dpm> or C<dpcm> (denoting "dots per inch/cm/meter). =item SamplesPerPixel This says how many channels there are in the image. For some image formats this number might be higher than the number implied from the C<color_type>. =item BitsPerSample This says how many bits are used to encode each of samples. The value is a reference to an array containing numbers. The number of elements in the array should be the same as C<SamplesPerPixel>. =item Comment Textual comments found in the file. The value is a reference to an array if there are multiple comments found. =item Interlace If the image is interlaced, then this tell which interlace method is used. =item Compression This tells you which compression algorithm is used. =item Gamma A number. =item LastModificationTime A ISO date string =back =head1 Supported Image Formats The following image file formats are supported: =over =item BMP This module supports the Microsoft Device Independent Bitmap format (BMP, DIB, RLE). For more information see L<Image::Info::BMP>. =item GIF Both GIF87a and GIF89a are supported and the version number is found as C<GIF_Version> for the first image. GIF files can contain multiple images, and information for all images will be returned if image_info() is called in list context. The Netscape-2.0 extention to loop animation sequences is represented by the C<GIF_Loop> key for the first image. The value is either "forever" or a number indicating loop count. =item JPEG For JPEG files we extract information both from C<JFIF> and C<Exif> application chunks. C<Exif> is the file format written by most digital cameras. This encode things like timestamp, camera model, focal length, exposure time, aperture, flash usage, GPS position, etc. The following web page contain description of the fields that can be present: http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html The C<Exif> spec can be found at: http://www.exif.org/specifications.html =item PNG Information from IHDR, PLTE, gAMA, pHYs, tEXt, tIME chunks are extracted. The sequence of chunks are also given by the C<PNG_Chunks> key. =item PBM/PGM/PPM All information available is extracted. =item SVG Provides a plethora of attributes and metadata of an SVG vector grafic. =item TIFF The C<TIFF> spec can be found at: L<http://partners.adobe.com/public/developer/tiff/> The EXIF spec can be found at: L<http://www.exif.org/> =item XBM See L<Image::Info::XBM> for details. =item XPM See L<Image::Info::XPM> for details. =back =head1 CAVEATS Note that while the module is still maintained, no new features will be added and numerous bugs remain throughout the code base. Especially the EXIF parsing code is buggy, not tested at all, and quite incomplete (a lot of manufacturer's MakerNotes and tags are not parsed at all). If you want a stable, feature-complete, up-to-date and tested EXIF parsing library, please use L<Image::ExifTool>. Likewise, the image parsing code is quite hackish and seems to contain an endless supply of bugs that crash, or hang with malformed input. =head1 SEE ALSO L<Image::Size>, L<Image::ExifTool> =head1 AUTHORS Copyright 1999-2004 Gisle Aas. See the CREDITS file for a list of contributors and authors. Now maintained by Tels - (c) 2006 - 2008. =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl v5.8.8 itself. =cut ����������������������������������������������������������������������������������������������������������������������Image-Info-1.28/lib/Image/TIFF.pm�������������������������������������������������������������������0000644�0001750�0001750�00000077471�10724767523�014074� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Image::TIFF; # Copyright 1999-2001, Gisle Aas. # Copyright 2006, 2007 Tels # # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl v5.8.8 itself. use strict; use vars qw($VERSION); $VERSION = '1.06'; my @types = ( [ "BYTE", "C1", 1], [ "ASCII", "A1", 1], [ "SHORT", "n1", 2], [ "LONG", "N1", 4], [ "RATIONAL", "N2", 8], [ "SBYTE", "c1", 1], [ "UNDEFINED", "a1", 1], [ "BINARY", "a1", 1], # treat binary data as UNDEFINED [ "SSHORT", "n1", 2], [ "SLONG", "N1", 4], [ "SRATIONAL", "N2", 8], [ "FLOAT", "f1", 4], # XXX 4-byte IEEE format [ "DOUBLE", "d1", 8], # XXX 8-byte IEEE format # XXX TODO: # [ "IFD", "??", ?], # See ExifTool ); my %nikon1_tags = ( 0x0003 => "Quality", 0x0004 => "ColorMode", 0x0005 => "ImageAdjustment", 0x0006 => "CCDSensitivity", 0x0007 => "Whitebalance", 0x0008 => "Focus", 0x000A => "DigitalZoom", 0x000B => "Converter", ); my %nikon2_tags = ( 0x0001 => "NikonVersion", 0x0002 => "ISOSetting", 0x0003 => "ColorMode", 0x0004 => "Quality", 0x0005 => "Whitebalance", 0x0006 => "ImageSharpening", 0x0007 => "FocusMode", 0x0008 => "FlashSetting", 0x0009 => "FlashMetering", 0x000B => "WBAdjustment", 0x000F => "ISOSelection", 0x0080 => "ImageAdjustment", 0x0082 => "AuxiliaryLens", 0x0084 => "Lens", 0x0085 => "ManualFocusDistance", 0x0086 => "DigitalZoom", 0x0088 => { __TAG__ => "AFFocusPosition", pack("xCxx",0) => "Center", pack("xCxx",1) => "Top", pack("xCxx",2) => "Bottom", pack("xCxx",3) => "Left", pack("xCxx",4) => "Right", }, 0x008d => "ColorMode", 0x0090 => "FlashType", 0x0095 => "NoiseReduction", 0x0010 => "DataDump", ); my %olympus_tags = ( 0x0200 => "SpecialMode", 0x0201 => { __TAG__ => "JpegQual", 0 => "SQ", 1 => "HQ", 2 => "SHQ" }, 0x0202 => { __TAG__ => "Macro", 0 => "Normal", 1 => "Macro" }, 0x0204 => "DigiZoom", 0x0207 => "SoftwareRelease", 0x0208 => "PictInfo", 0x0209 => "CameraID", 0x0f00 => "DataDump", ); my %fujifilm_tags = ( 0x0000 => "Version", 0x1000 => "Quality", 0x1001 => { __TAG__ => "Sharpness", 1 => "Very Soft", 2 => "Soft", 3 => "Normal", 4 => "Hard", 5 => "Very Hard", }, 0x1002 => { __TAG__ => "WhiteBalance", 0 => "Auto", 256 => "Daylight", 512 => "Cloudy", 768 => "DaylightColor-fluorescence", 769 => "DaywhiteColor-fluorescence", 770 => "White-fluorescence", 1024 => "Incandenscense", 3840 => "Custom white balance", }, 0x1003 => { __TAG__ => "Color", 0 => "Normal", 256 => "High", 512 => "Low" }, 0x1004 => { __TAG__ => "Tone" , 0 => "Normal", 256 => "High", 512 => "Low" }, 0x1010 => { __TAG__ => "FlashMode", 0 => "Auto", 1 => "On", 2 => "Off", 3 => "Red-eye reduction" }, 0x1011 => "FlashStrength", 0x1020 => { __TAG__ => "Macro", 0 => "Off", 1 => "On"}, 0x1021 => { __TAG__ => "FocusMode", 0 => "Auto", 1 => "Manual" }, 0x1030 => { __TAG__ => "SlowSync", 0 => "Off", 1 => "On"}, 0x1031 => { __TAG__ => "PictureMode", 0 => "Auto", 1 => "Portrait", 2 => "Landscape", 4 => "Sports", 5 => "Night", 6 => "Program AE", 256 => "Aperture priority", 512 => "Shutter priority", 768 => "Manual", }, 0x1100 => { __TAG__ => "AutoBracketing", 0 => "Off", 1 => "On"}, 0x1300 => { __TAG__ => "BlurWarning", 0 => "No", 1 => "Yes"}, 0x1301 => { __TAG__ => "FocusWarning", 0 => "No", 1 => "Yes"}, 0x1302 => { __TAG__ => "AEWarning", 0 => "No", 1 => "Yes"}, ); my %casio_tags = ( 0x0001 => { __TAG__ => "RecordingMode", 1 => "SingleShutter", 2 => "Panorama", 3 => "Night scene", 4 => "Portrait", 5 => "Landscape", }, 0x0002 => { __TAG__ => "Quality", 1 => "Economy", 2 => "Normal", 3 => "Fine" }, 0x0003 => { __TAG__ => "FocusingMode", 2 => "Macro", 3 => "Auto", 4 => "Manual", 5 => "Infinity", }, 0x0004 => { __TAG__ => "FlashMode", 1 => "Auto", 2 => "On", 3 => "Off", 4 => "Red-eye reduction" }, 0x0005 => { __TAG__ => "FlashIntensity", 11 => "Weak", 13 => "Normal", 15 => "Strong" }, 0x0006 => "ObjectDistance", 0x0007 => { __TAG__ => "WhiteBalance", 1 => "Auto", 2 => "Tungsten", 3 => "Daylight", 4 => "Fluorescent", 5 => "Shade", 129 => "Manual", }, 0x000a => { __TAG__ => "DigitalZoom", 65536 => "Off", 65537 => "2X" }, 0x000b => { __TAG__ => "Sharpness", 0 => "Normal", 1 => "Soft", 2 => "Hard" }, 0x000c => { __TAG__ => "Contrast" , 0 => "Normal", 1 => "Low", 2 => "High" }, 0x000d => { __TAG__ => "Saturation", 0 => "Normal", 1 => "Low", 2 => "High" }, 0x0014 => { __TAG__ => "CCDSensitivity", 64 => "Normal", 125 => "+1.0", 250 => "+2.0", 244 => "+3.0", 80 => "Normal", 100 => "High", }, ); my %canon_0x0001_tags = ( 0 => { __TAG__ => "MacroMode", 1 => "Macro", 2 => "Normal" }, 1 => "SelfTimer", 2 => { __TAG__ => "Quality", 2 => "Normal", 3 => "Fine", 5 => "SuperFine" }, 3 => 'Tag-0x0001-03', 4 => { __TAG__ => 'FlashMode', 0 => 'Flash Not Fired', 1 => 'Auto', 2 => 'On', 3 => 'Red-Eye Reduction', 4 => 'Slow Synchro', 5 => 'Auto + Red-Eye Reduction', 6 => 'On + Red-Eye Reduction', 16 => 'External Flash' }, 5 => { __TAG__ => 'ContinuousDriveMode', 0 => 'Single Or Timer', 1 => 'Continuous' }, 6 => 'Tag-0x0001-06', 7 => { __TAG__ => 'FocusMode', 0 => 'One-Shot', 1 => 'AI Servo', 2 => 'AI Focus', 3 => 'MF', 4 => 'Single', 5 => 'Continuous', 6 => 'MF' }, 8 => 'Tag-0x0001-08', 9 => 'Tag-0x0001-09', 10 => { __TAG__ => 'ImageSize', 0 => 'Large', 1 => 'Medium', 2 => 'Small' }, 11 => { __TAG__ => 'EasyShootingMode', 0 => 'Full Auto', 1 => 'Manual', 2 => 'Landscape', 3 => 'Fast Shutter', 4 => 'Slow Shutter', 5 => 'Night', 6 => 'B&W', 7 => 'Sepia', 8 => 'Portrait', 9 => 'Sports', 10 => 'Macro/Close-Up', 11 => 'Pan Focus' }, 12 => { __TAG__ => 'DigitalZoom', 0 => 'None', 1 => '2x', 2 => '4x' }, 13 => { __TAG__ => 'Contrast', 0xFFFF => 'Low', 0 => 'Normal', 1 => 'High' }, 14 => { __TAG__ => 'Saturation', 0xFFFF => 'Low', 0 => 'Normal', 1 => 'High' }, 15 => { __TAG__ => 'Sharpness', 0xFFFF => 'Low', 0 => 'Normal', 1 => 'High' }, 16 => { __TAG__ => 'ISO', 0 => 'See ISOSpeedRatings Tag', 15 => 'Auto', 16 => '50', 17 => '100', 18 => '200', 19 => '400' }, 17 => { __TAG__ => 'MeteringMode', 3 => 'Evaluative', 4 => 'Partial', 5 => 'Center-Weighted' }, 18 => { __TAG__ => 'FocusType', 0 => 'Manual', 1 => 'Auto', 3 => 'Close-Up (Macro)', 8 => 'Locked (Pan Mode)' }, 19 => { __TAG__ => 'AFPointSelected', 0x3000 => 'None { __TAG__ => MF)', 0x3001 => 'Auto-Selected', 0x3002 => 'Right', 0x3003 => 'Center', 0x3004 => 'Left' }, 20 => { __TAG__ => 'ExposureMode', 0 => 'Easy Shooting', 1 => 'Program', 2 => 'Tv-priority', 3 => 'Av-priority', 4 => 'Manual', 5 => 'A-DEP' }, 21 => 'Tag-0x0001-21', 22 => 'Tag-0x0001-22', 23 => 'LongFocalLengthOfLensInFocalUnits', 24 => 'ShortFocalLengthOfLensInFocalUnits', 25 => 'FocalUnitsPerMM', 26 => 'Tag-0x0001-26', 27 => 'Tag-0x0001-27', 28 => { __TAG__ => 'FlashActivity', 0 => 'Did Not Fire', 1 => 'Fired' }, 29 => { __TAG__ => 'FlashDetails', 14 => 'External E-TTL', 13 => 'Internal Flash', 11 => 'FP Sync Used', 7 => '2nd ("Rear")-Curtain Sync Used', 4 => 'FP Sync Enabled' }, 30 => 'Tag-0x0001-30', 31 => 'Tag-0x0001-31', 32 => { __TAG__ => 'FocusMode', 0 => 'Single', 1 => 'Continuous' }, ); my %canon_0x0004_tags = ( 7 => { __TAG__ => 'WhiteBalance', 0 => 'Auto', 1 => 'Sunny', 2 => 'Cloudy', 3 => 'Tungsten', 4 => 'Fluorescent', 5 => 'Flash', 6 => 'Custom' }, 9 => 'SequenceNumber', 14 => 'AFPointUsed', 15 => { __TAG__ => 'FlashBias', 0xFFC0 => '-2 EV', 0xFFCC => '-1.67 EV', 0xFFD0 => '-1.50 EV', 0xFFD4 => '-1.33 EV', 0xFFE0 => '-1 EV', 0xFFEC => '-0.67 EV', 0xFFF0 => '-0.50 EV', 0xFFF4 => '-0.33 EV', 0x0000 => '0 EV', 0x000C => '0.33 EV', 0x0010 => '0.50 EV', 0x0014 => '0.67 EV', 0x0020 => '1 EV', 0x002C => '1.33 EV', 0x0030 => '1.50 EV', 0x0034 => '1.67 EV', 0x0040 => '2 EV', }, 19 => 'SubjectDistance' ); my %canon_tags = ( 0x0001 => { __TAG__ => "Custom_0x0001", __ARRAYOFFSET__ => \%canon_0x0001_tags }, 0x0004 => { __TAG__ => "Custom_0x0004", __ARRAYOFFSET__ => \%canon_0x0004_tags }, 0x0006 => "ImageType", 0x0007 => "FirmwareVersion", 0x0008 => "ImageNumber", 0x0009 => "OwnerName", 0x000c => "SerialNumber", ); # see http://www.compton.nu/panasonic.html my %panasonic_tags = ( 0x0001 => { __TAG__ => "ImageQuality", 2 => 'High', 3 => 'Normal', 6 => 'Very High', #3 (Leica) 7 => 'Raw', #3 (Leica) }, 0x0002 => "FirmwareVersion", 0x0003 => { __TAG__ => "WhiteBalance", 1 => 'Auto', 2 => 'Daylight', 3 => 'Cloudy', 4 => 'Halogen', 5 => 'Manual', 8 => 'Flash', 10 => 'Black & White', #3 (Leica) }, 0x0007 => { __TAG__ => "FocusMode", 1 => 'Auto', 2 => 'Manual', 5 => 'Auto, Continuous', 4 => 'Auto, Focus button', }, 0x000f => { __TAG__ => "SpotMode", # XXX TODO: does not decode properly "0,1" => 'On', "0,16" => 'Off', }, 0x001a => { __TAG__ => "ImageStabilizer", 2 => 'On, Mode 1', 3 => 'Off', 4 => 'On, Mode 2', }, 0x001c => { __TAG__ => "MacroMode", 1 => 'On', 2 => 'Off', }, 0x001f => { __TAG__ => "ShootingMode", 1 => 'Normal', 2 => 'Portrait', 3 => 'Scenery', 4 => 'Sports', 5 => 'Night Portrait', 6 => 'Program', 7 => 'Aperture Priority', 8 => 'Shutter Priority', 9 => 'Macro', 11 => 'Manual', 13 => 'Panning', 18 => 'Fireworks', 19 => 'Party', 20 => 'Snow', 21 => 'Night Scenery', }, 0x0020 => { __TAG__ => "Audio", 1 => 'Yes', 2 => 'No', }, 0x0021 => "DataDump", 0x0022 => "Panasonic 0x0022", 0x0023 => "WhiteBalanceBias", 0x0024 => "FlashBias", 0x0025 => "SerialNumber", 0x0026 => "Panasonic 0x0026", 0x0027 => "Panasonic 0x0027", 0x0028 => { __TAG__ => "ColorEffect", 1 => 'Off', 2 => 'Warm', 3 => 'Cool', 4 => 'Black & White', 5 => 'Sepia', }, 0x0029 => "Panasonic 0x0029", 0x002a => { __TAG__ => "BurstMode", 0 => 'Off', 1 => 'Low/High Quality', 2 => 'Infinite', }, 0x002b => "ImageSequenceNumber", 0x002c => { __TAG__ => "Contrast", 0 => 'Normal', 1 => 'Low', 2 => 'High', 0x100 => 'Low', # Leica 0x110 => 'Normal', # Leica 0x120 => 'High', # Leica }, 0x002d => { __TAG__ => "NoiseReduction", 0 => 'Standard', 1 => 'Low', 2 => 'High', }, 0x002e => { __TAG__ => "SelfTimer", 1 => 'Off', 2 => '10s', 3 => '2s', }, 0x002f => "Panasonic 0x002f", 0x0030 => "Panasonic 0x0030", 0x0031 => "Panasonic 0x0031", 0x0032 => "Panasonic 0x0032", ); # format: # "Make Model" => [ Offset, 'Tag_prefix', ptr to tags ] # Offset is either 0, or a positive number of Bytes. # Offset -1 or -2 means a kludge for Fuji or Nikon my %makernotes = ( "NIKON CORPORATION NIKON D1" => [0, 'NikonD1', \%nikon2_tags], "NIKON CORPORATION NIKON D70" => [-2, 'NikonD1', \%nikon2_tags], "NIKON CORPORATION NIKON D100" => [-2, 'NikonD1', \%nikon2_tags], # For the following manufacturers we simple discard the model and always # decode the MakerNote in the same manner. This makes it work with all # models, even yet unreleased ones. (That's better than the very limited # list of models we previously had) "CANON" => [0, 'Canon', \%canon_tags], 'PANASONIC' => [12, 'Panasonic', \%panasonic_tags], "FUJIFILM" => [-1, 'FinePix', \%fujifilm_tags], "CASIO" => [0, 'Casio', \%casio_tags], "OLYMPUS" => [8, 'Olympus', \%olympus_tags], ); BEGIN { # add some Nikon cameras for my $model (qw/E700 E800 E900 E900S E910 E950/) { $makernotes{'NIKON ' . $model} = [8, 'CoolPix', \%nikon1_tags]; } for my $model (qw/E880 E990 E995/) { $makernotes{'NIKON ' . $model} = [0, 'CoolPix', \%nikon2_tags]; } } my %exif_intr_tags = ( 0x1 => "InteroperabilityIndex", 0x2 => "InteroperabilityVersion", 0x1000 => "RelatedImageFileFormat", 0x1001 => "RelatedImageWidth", 0x1002 => "RelatedImageLength", ); # Tag decode helpers sub components_configuration_decoder; sub file_source_decoder; sub scene_type_decoder; my %exif_tags = ( 0x828D => "CFARepeatPatternDim", 0x828E => "CFAPattern", 0x828F => "BatteryLevel", 0x8298 => "Copyright", 0x829A => "ExposureTime", 0x829D => "FNumber", 0x83BB => "IPTC/NAA", 0x8769 => "ExifOffset", 0x8773 => "InterColorProfile", 0x8822 => { __TAG__ => "ExposureProgram", 0 => "unknown", 1 => "Manual", 2 => "Program", 3 => "Aperture priority", 4 => "Shutter priority", 5 => "Program creative", 6 => "Program action", 7 => "Portrait", 8 => "Landscape", # 9 .. 255 reserved }, 0x8824 => "SpectralSensitivity", 0x8827 => "ISOSpeedRatings", 0x8828 => "OECF", 0x9000 => "ExifVersion", 0x9003 => "DateTimeOriginal", 0x9004 => "DateTimeDigitized", 0x9101 => { __TAG__ => "ComponentsConfiguration", DECODER => \&components_configuration_decoder, }, 0x9102 => "CompressedBitsPerPixel", 0x9201 => "ShutterSpeedValue", 0x9202 => "ApertureValue", 0x9203 => "BrightnessValue", 0x9204 => "ExposureBiasValue", 0x9205 => "MaxApertureValue", 0x9206 => "SubjectDistance", 0x9207 => { __TAG__ => "MeteringMode", 0 => "unknown", 1 => "Average", 2 => "CenterWeightedAverage", 3 => "Spot", 4 => "MultiSpot", 5 => "Pattern", 6 => "Partial", # 7 .. 254 reserved in EXIF 1.2 255 => "other", }, 0x9208 => { __TAG__ => "LightSource", 0 => "unknown", 1 => "Daylight", 2 => "Fluorescent", 3 => "Tungsten", 4 => "Flash", # 5 .. 8 reserveed in EXIF 2.2 9 => "Fine weather", 10 => "Cloudy weather", 11 => "Shade", 12 => "Daylight fluorescent (D 5700-7100K)", 13 => "Day white fluorescent (N 4600-5400K)", 14 => "Cool white fluorescent (W 3900-4500K)", 15 => "White fluorescent (WW 3200-3700K)", 17 => "Standard light A", 18 => "Standard light B", 19 => "Standard light C", 20 => "D55", 21 => "D65", 22 => "D75", 23 => "D50", 24 => "ISO studio tungesten", # 25 .. 254 reserved in EXIF 2.2 255 => "other light source", }, 0x9209 => { __TAG__ => "Flash", 0x0000 => "Flash did not fire", 0x0001 => "Flash fired", 0x0005 => "Strobe return light not detected", 0x0007 => "Strobe return light detected", 0x0009 => "Flash fired, compulsory flash mode", 0x000D => "Flash fired, compulsory flash mode, return light not detected", 0x000F => "Flash fired, compulsory flash mode, return light detected", 0x0010 => "Flash did not fire, compulsory flash mode", 0x0018 => "Flash did not fire, auto mode", 0x0019 => "Flash fired, auto mode", 0x001D => "Flash fired, auto mode, return light not detected", 0x001F => "Flash fired, auto mode, return light detected", 0x0020 => "No flash function", 0x0041 => "Flash fired, red-eye reduction mode", 0x0045 => "Flash fired, red-eye reduction mode, return light not detected", 0x0047 => "Flash fired, red-eye reduction mode, return light detected", 0x0049 => "Flash fired, compulsory flash mode, red-eye reduction mode", 0x004D => "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected", 0x004F => "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected", 0x0059 => "Flash fired, auto mode, red-eye reduction mode", 0x005D => "Flash fired, auto mode, return light not detected, red-eye reduction mode", 0x005F => "Flash fired, auto mode, return light detected, red-eye reduction mode" }, 0x920A => "FocalLength", 0x9214 => "SubjectArea", 0x927C => "MakerNote", 0x9286 => "UserComment", 0x9290 => "SubSecTime", 0x9291 => "SubSecTimeOriginal", 0x9292 => "SubSecTimeDigitized", 0xA000 => "FlashPixVersion", 0xA001 => "ColorSpace", 0xA002 => "ExifImageWidth", 0xA003 => "ExifImageLength", 0xA004 => "RelatedAudioFile", 0xA005 => {__TAG__ => "InteroperabilityOffset", __SUBIFD__ => \%exif_intr_tags, }, 0xA20B => "FlashEnergy", # 0x920B in TIFF/EP 0xA20C => "SpatialFrequencyResponse", # 0x920C - - 0xA20E => "FocalPlaneXResolution", # 0x920E - - 0xA20F => "FocalPlaneYResolution", # 0x920F - - 0xA210 => { __TAG__ => "FocalPlaneResolutionUnit", # 0x9210 - - 1 => "pixels", 2 => "dpi", 3 => "dpcm", }, 0xA214 => "SubjectLocation", # 0x9214 - - 0xA215 => "ExposureIndex", # 0x9215 - - 0xA217 => {__TAG__ => "SensingMethod", 1 => "Not defined", 2 => "One-chip color area sensor", 3 => "Two-chip color area sensor", 4 => "Three-chip color area sensor", 5 => "Color sequential area sensor", 7 => "Trilinear sensor", 8 => "Color sequential linear sensor" }, 0xA300 => {__TAG__ => "FileSource", DECODER => \&file_source_decoder, }, 0xA301 => {__TAG__ => "SceneType", DECODER => \&scene_type_decoder, }, 0xA302 => "CFAPattern", 0xA401 => {__TAG__ => "CustomRendered", 0 => "Normal process", 1 => "Custom process" }, 0xA402 => {__TAG__ => "ExposureMode", 0 => "Auto exposure", 1 => "Manual exposure", 2 => "Auto bracket" }, 0xA403 => {__TAG__ => "WhiteBalance", 0 => "Auto white balance", 1 => "Manual white balance" }, 0xA404 => "DigitalZoomRatio", 0xA405 => "FocalLengthIn35mmFilm", 0xA406 => {__TAG__ => "SceneCaptureType", 0 => "Standard", 1 => "Landscape", 2 => "Portrait", 3 => "Night Scene" }, 0xA407 => {__TAG__ => "GainControl", 0 => "None", 1 => "Low gain up", 2 => "High gain up", 3 => "Low gain down", 4 => "High gain down" }, 0xA408 => {__TAG__ => "Contrast", 0 => "Normal", 1 => "Soft", 2 => "Hard" }, 0xA409 => {__TAG__ => "Saturation", 0 => "Normal", 1 => "Low saturation", 2 => "High saturation" }, 0xA40A => {__TAG__ => "Sharpness", 0 => "Normal", 1 => "Soft", 2 => "Hard" }, 0xA40B => "DeviceSettingDescription", 0xA40C => {__TAG__ => "SubjectDistanceRange", 0 => "Unknown", 1 => "Macro", 2 => "Close view", 3 => "Distant view" }, 0xA420 => "ImageUniqueID", ); my %gps_tags = ( 0x0000 => 'GPSVersionID', 0x0001 => 'GPSLatitudeRef', 0x0002 => 'GPSLatitude', 0x0003 => 'GPSLongitudeRef', 0x0004 => 'GPSLongitude', 0x0005 => 'GPSAltitudeRef', 0x0006 => 'GPSAltitude', 0x0007 => 'GPSTimeStamp', 0x0008 => 'GPSSatellites', 0x0009 => 'GPSStatus', 0x000A => 'GPSMeasureMode', 0x000B => 'GPSDOP', 0x000C => 'GPSSpeedRef', 0x000D => 'GPSSpeed', 0x000E => 'GPSTrackRef', 0x000F => 'GPSTrack', 0x0010 => 'GPSImgDirectionRef', 0x0011 => 'GPSImgDirection', 0x0012 => 'GPSMapDatum', 0x0013 => 'GPSDestLatitudeRef', 0x0014 => 'GPSDestLatitude', 0x0015 => 'GPSDestLongitudeRef', 0x0016 => 'GPSDestLongitude', 0x0017 => 'GPSDestBearingRef', 0x0018 => 'GPSDestBearing', 0x0019 => 'GPSDestDistanceRef', 0x001A => 'GPSDestDistance', 0x001B => 'GPSProcessingMethod', 0x001C => 'GPSAreaInformation', 0x001D => 'GPSDateStamp', 0x001E => 'GPSDifferential', ); my %tiff_tags = ( 254 => { __TAG__ => "NewSubfileType", 1 => "ReducedResolution", 2 => "SinglePage", 4 => "TransparencyMask", }, 255 => { __TAG__ => "SubfileType", 1 => "FullResolution", 2 => "ReducedResolution", 3 => "SinglePage", }, 256 => "width", 257 => "height", 258 => "BitsPerSample", 259 => { __TAG__ => "Compression", 1 => "PackBytes", 2 => "CCITT Group3", 3 => "CCITT T4", 4 => "CCITT T6", 5 => "LZW", 6 => "JPEG", 7 => "JPEG DCT", 8 => "Deflate (Adobe)", 32766 => "NeXT 2-bit RLE", 32771 => "#1 w/ word alignment", 32773 => "PackBits (Macintosh RLE)", 32809 => "ThunderScan RLE", 32895 => "IT8 CT w/padding", 32896 => "IT8 Linework RLE", 32897 => "IT8 Monochrome picture", 32898 => "IT8 Binary line art", 32908 => "Pixar companded 10bit LZW", 32909 => "Pixar companded 11bit ZIP", 32946 => "Deflate", }, 262 => { __TAG__ => "PhotometricInterpretation", 0 => "WhiteIsZero", 1 => "BlackIsZero", 2 => "RGB", 3 => "RGB Palette", 4 => "Transparency Mask", 5 => "CMYK", 6 => "YCbCr", 8 => "CIELab", }, 263 => { __TAG__ => "Threshholding", 1 => "NoDithering", 2 => "OrderedDither", 3 => "Randomized", }, 266 => { __TAG__ => "FillOrder", 1 => "LowInHigh", 2 => "HighInLow", }, 269 => "DocumentName", 270 => "ImageDescription", 271 => "Make", 272 => "Model", 273 => "StripOffsets", 274 => { __TAG__ => "Orientation", 1 => "top_left", 2 => "top_right", 3 => "bot_right", 4 => "bot_left", 5 => "left_top", 6 => "right_top", 7 => "right_bot", 8 => "left_bot", }, 277 => "SamplesPerPixel", 278 => "RowsPerStrip", 279 => "StripByteCounts", 282 => "XResolution", 283 => "YResolution", 284 => {__TAG__ => "PlanarConfiguration", 1 => "Chunky", 2 => "Planar", }, 296 => {__TAG__ => "ResolutionUnit", 1 => "pixels", 2 => "dpi", 3 => "dpcm", }, 297 => "PageNumber", 301 => "TransferFunction", 305 => "Software", 306 => "DateTime", 315 => "Artist", 316 => "Host", 318 => "WhitePoint", 319 => "PrimaryChromaticities", 320 => "ColorMap", 513 => "JPEGInterchangeFormat", 514 => "JPEGInterchangeFormatLength", 529 => "YCbCrCoefficients", 530 => "YCbCrSubSampling", 531 => "YCbCrPositioning", 532 => "ReferenceBlackWhite", 33432 => "Copyright", 34665 => { __TAG__ => "ExifOffset", __SUBIFD__ => \%exif_tags, }, 34853 => { __TAG__ => "GPSInfo", __SUBIFD__ => \%gps_tags, }, ); sub new { my $class = shift; my $source = shift; if (!ref($source)) { local(*F); open(F, $source) || return; binmode(F); $source = \*F; } if (ref($source) ne "SCALAR") { # XXX should really only read the file on demand local($/); # slurp mode my $data = <$source>; $source = \$data; } my $self = bless { source => $source }, $class; for ($$source) { my $byte_order = substr($_, 0, 2); $self->{little_endian} = ($byte_order eq "II"); $self->{version} = $self->unpack("n", substr($_, 2, 2)); my $ifd = $self->unpack("N", substr($_, 4, 4)); while ($ifd) { push(@{$self->{ifd}}, $ifd); my($num_fields) = $self->unpack("x$ifd n", $_); my $next_ifd = $self->unpack("N", substr($_, $ifd + 2 + $num_fields*12, 4)); # guard against (bug #26127) $next_ifd = 0 if $next_ifd > length($_); # guard against looping ifd (bug #26130) if ($next_ifd <= $ifd) { # bad TIFF header - would cause a loop or strange results last; } $ifd = $next_ifd; } } $self; } sub unpack { my $self = shift; my $template = shift; if ($self->{little_endian}) { $template =~ tr/nN/vV/; } #print "UNPACK $template\n"; CORE::unpack($template, $_[0]); } sub num_ifds { my $self = shift; scalar @{$self->{ifd}}; } sub ifd { my $self = shift; my $num = shift || 0; my @ifd; $self->add_fields($self->{ifd}[$num], \@ifd); } sub tagname { $tiff_tags{$_[1]} || sprintf "Tag-0x%04x",$_[1]; } sub exif_tagname { $tiff_tags{$_[1]} || $exif_tags{$_[1]} || sprintf "Tag-0x%04x",$_[1]; } sub add_fields { my($self, $offset, $ifds, $tags, $voff_plus) = @_; return unless $offset; # guard against finding the same offset twice (bug #29088) return if $self->{seen_offset}{$offset}++; $tags ||= \%tiff_tags; for (${$self->{source}}) { # alias as $_ last if $offset > length($_) - 2; # bad offset my $entries = $self->unpack("x$offset n", $_); my $max_entries = int((length($_) - $offset - 2) / 12); # print "ENTRIES $entries $max_entries\n"; if ($entries > $max_entries) { # Hmmm, something smells bad here... parsing garbage $entries = $max_entries; last; } FIELD: for my $i (0 .. $entries-1) { my $entry_offset = 2 + $offset + $i*12; my($tag, $type, $count, $voff) = $self->unpack("nnNN", substr($_, $entry_offset, 12)); #print STDERR "TAG $tag $type $count $voff\n"; if ($type == 0 || $type > @types) { # unknown type code might indicate that we are parsing garbage print STDERR "# Ignoring unknown type code $type\n"; next; } # extract type information my($tmpl, $vlen); ($type, $tmpl, $vlen) = @{$types[$type-1]}; die "Undefined type while parsing" unless $type; if ($count * $vlen <= 4) { $voff = $entry_offset + 8; } elsif ($voff + $count * $vlen > length($_)) { # offset points outside of string, corrupt entry ignore print STDERR "# ignoring offset pointer outside of string\n"; next; } else { $voff += $voff_plus || 0; } $tmpl =~ s/(\d+)$/$count*$1/e; my @v = $self->unpack("x$voff $tmpl", $_); if ($type =~ /^S(SHORT|LONG|RATIONAL)/) { my $max = 2 ** ($1 eq "SHORT" ? 15 : 31); $v[0] -= ($max * 2) if $v[0] >= $max; } my $val = (@v > 1) ? \@v : $v[0]; bless $val, "Image::TIFF::Rational" if $type =~ /^S?RATIONAL$/; if ($type eq 'ASCII' || $type eq 'UNDEFINED') { if ($val =~ /\0[^\0]+\z/) { # cut out the first "ASCII\0" and take the remaining text # (fix bug #29243 parsing of UserComment) # XXX TODO: this needs to handle UNICODE, too: $val =~ /\0([^\0]+)/; $val = '' . ($1 || ''); } else { # avoid things like "Foo\x00\x00\x00" by removing trailing nulls # this needs to handle UNICODE, too: $val =~ /^([^\0]*)/; $val = '' . ($1 || ''); } } $tag = $tags->{$tag} || $self->tagname($tag); if ($tag eq 'MakerNote') { my $maker = uc($self->{Make} || ''); $maker =~ /^([A-Z]+)/; $maker = $1 || ''; # "OLYMPUS ..." > "OLYMPUS" # if 'Panasonic' doesn't exist, try 'Panasonic DMC-FZ5' $maker = $self->{Make}.' '.$self->{Model} unless exists $makernotes{$maker}; if (exists $makernotes{$maker}) { my ($ifd_off, $tag_prefix, $sub) = @{$makernotes{$maker}}; #print STDERR "# Decoding Makernotes from $maker\n"; $self->{tag_prefix} = $tag_prefix; if ($ifd_off == -1) { # fuji kludge - http://www.butaman.ne.jp/~tsuruzoh/Computer/Digicams/exif-e.html#APP4 my $save_endian = $self->{little_endian}; $self->{little_endian} = 1; $ifd_off = $self->unpack("N", substr($val, 8, 4)); $self->add_fields($voff+$ifd_off, $ifds, $sub, $voff); $self->{little_endian} = $save_endian; } elsif ($ifd_off == -2) { # Nikon D70/D100 kludge -- word "Nikon" and 5 # bytes of data is tacked to the front of MakerNote; # all EXIF offsets are relative to MakerNote section my ($nikon_voff); $nikon_voff = 0; if (substr($val, 0, 5) eq 'Nikon') { $nikon_voff = $voff+10; } #print "IFD_OFF $ifd_off NIKON_VOFF $nikon_voff\n"; $self->add_fields($voff+18, $ifds, $sub, $nikon_voff); } else { $self->add_fields($voff+$ifd_off, $ifds, $sub) } delete $self->{tag_prefix}; next FIELD; } } if (ref($tag)) { die "Assert" unless ref($tag) eq "HASH"; if (my $sub = $tag->{__SUBIFD__}) { next if $val < 0 || $val > length($_); #print "SUBIFD $tag->{__TAG__} $val ", length($_), "\n"; $self->add_fields($val, $ifds, $sub); next FIELD; } if (my $sub = $tag->{__ARRAYOFFSET__}) { my $prefix = $tag = $self->{tag_prefix} . '-' if $self->{tag_prefix}; for (my $i=0; $i < @$val; $i++) { if ( exists($sub->{$i}) ) { if ( ref($sub->{$i}) eq "HASH" && exists($sub->{$i}->{__TAG__}) ) { if ( exists($sub->{$i}->{$val->[$i]}) ) { push @$ifds, [ $prefix . $sub->{$i}->{__TAG__}, $type, $count, $sub->{$i}->{$val->[$i]} ]; } else { push @$ifds, [ $prefix . $sub->{$i}->{__TAG__}, $type, $count, "Unknown (" . $val->[$i] . ")" ]; } } else { push @$ifds, [ $prefix . $sub->{$i}, $type, $count, $val->[$i] ]; } } } next FIELD; } #hack for UNDEFINED values, they all have different #meanings depending on tag $val = &{$tag->{DECODER}}($self,$val) if defined($tag->{DECODER}); $val = $tag->{$val} if exists $tag->{$val}; $tag = $tag->{__TAG__}; } $tag = $self->{tag_prefix} . '-' . $tag if $self->{tag_prefix}; #if ( $val =~ m/ARRAY/ ) { $val = join(', ',@$val); } push @$ifds, [ $tag, $type, $count, $val ]; $self->{$tag} = $val if ($tag eq 'Make' or $tag eq 'Model'); } } $ifds; } sub components_configuration_decoder { my $self = shift; my $val = shift; my $rv = ""; my %v = ( 0 => undef, 1 => 'Y', 2 => 'Cb', 3 => 'Cr', 4 => 'R', 5 => 'G', 6 => 'B', ); return join ( '', map { $v{$_} if defined($v{$_}) } $self->unpack('c4',$val) ); } sub file_source_decoder { my $self = shift; my $val = shift; my %v = ( 3 => "(DSC) Digital Still Camera", ); $val = $self->unpack('c',$val); return $v{$val} if $v{$val}; "Other"; } sub scene_type_decoder { my $self = shift; my $val = shift; my %v = ( 1 => "Directly Photographed Image", ); $val = $self->unpack('c',$val); return $v{$val} if $v{$val}; "Other"; } package Image::TIFF::Rational; use overload '""' => \&as_string, '0+' => \&as_float, fallback => 1; sub new { my($class, $a, $b) = @_; bless [$a, $b], $class; } sub as_string { my $self = shift; #warn "@$self"; "$self->[0]/$self->[1]"; } sub as_float { my $self = shift; # We check here because some stupid cameras (Samsung Digimax 200) # use rationals with 0 denominator (found in thumbnail resolution spec). if ($self->[1]) { return $self->[0] / $self->[1]; } else { return $self->[0]; } } 1; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/TODO��������������������������������������������������������������������������������0000644�0001750�0001750�00000000601�10456427520�011653� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� * Image::TIFF should not need to slurp * convert the EXIF parsing code to just use something like Image::Exiftool - our code is way to complicated, outdated, and it's double work to maintain it * get rid of the need for XML::Simple for SVG parsing - half of the parsing is done via custom regexps, anyway. * get rid of the comment parsing for SVG, it's whacky and undocumented �������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/SIGNATURE���������������������������������������������������������������������������0000644�0001750�0001750�00000011601�10773761473�012463� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.55. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 04a304eede20a1fe525519aa4def534a51c6b972 CHANGES SHA1 b0965787df2efb2004af6e1bc896e03d8e16a60a CREDITS SHA1 4312b53c14d9f9f932b0561aaed534de59480fe4 MANIFEST SHA1 78443312eec2a05f1f80b8a9cb6ca9fae85fbfe9 MANIFEST.SKIP SHA1 f0a5bd2ee5137d29de37ef47deb6cf322bb4f237 META.yml SHA1 6c9061573637a44b0eb4e620b1bc7d3adb906e82 Makefile.PL SHA1 3410cb1f8c806ee87e044b774bd4b0f7ee9dd6fa README SHA1 61d95b3f38d12cc08817e518d1cc863fccf08208 TODO SHA1 1417b90564a55762c70e6a9238efc2c678962037 dev/Info.pm.tmpl SHA1 d3d01a60781b852da7df22ebcad2db57979b6d4e dev/build.pl SHA1 38b386e67725abff64ea00abb8e92c46f38e2f59 exifdump SHA1 c11f86df48ca57d0364c9afd1449683ebf1979f4 img/be.tif SHA1 951a303482fb78bc02c65e8310854a7be975bfca img/cynic_hang.jpg SHA1 49a6dcd04263d15377be6e7ced44f4e3ce01437c img/gps.jpg SHA1 4243d003552c27c110b75ca121294d5edddc62a8 img/graph.svg SHA1 07f4778b513d5c951c1878c376fba49ff0ecd644 img/interlace.png SHA1 979ea4a5afe76a6532fe21a2724c3dfc8405bb2a img/le.tif SHA1 5d3db653df616830a6a135d862e30e355464a43a img/test.gif SHA1 6299f38bf7c592409362601fe34a5b0baafdcf47 img/test.jpg SHA1 3ffdf0d8f92b3548aefe19e88ba7365b98315377 img/test.pbm SHA1 ded4506e3a536c422794966d685141cd868b4f08 img/test.pgm SHA1 9edfc7ab4cb4808f70d1fea5aa7cc74694c36d6e img/test.png SHA1 cc4e7c8487ba03b141b24983650549e3bed22abf img/test.ppm SHA1 1e4af5ca289c895e0499d40b04781afc3e748ca4 img/test.rle SHA1 b51c0ee17e88970b032f96026119d16ab667b686 img/test.svg SHA1 f345165b605868be0b843fe6f98e5243a449b7d4 img/test.tif SHA1 8a8f9bfb0a791f01f5aeecb29d095bdb94b16d43 img/test.xbm SHA1 d7ead6bd7acf3aa703424697913c5a0e9c2e9244 img/test.xpm SHA1 d33e338aa7a45dc6fa4cefcdd376916e2267f3f9 img/tiny.pgm SHA1 376cc1bd8424b1123f0073df81ce5433be4df58e imgdump SHA1 603bb9de29fb8cba7f13409c546750972eff645d inc/Module/AutoInstall.pm SHA1 d8f6d2df4e75cb9e6e77a8377457f0ececd00e31 inc/Module/Install.pm SHA1 af0833ed8863138d63c446ab756b868d9ec1a8da inc/Module/Install/AutoInstall.pm SHA1 03590cde5c3de0d0d8a84d2b96917ed1a2cf9a30 inc/Module/Install/Base.pm SHA1 8ef3c70e905be7d1007b446f21d4eb3ff6ae24cb inc/Module/Install/Can.pm SHA1 79054604a1cd4e99443b05cbb62832568a204a33 inc/Module/Install/Fetch.pm SHA1 160e1fc7baca4f31c50fe498df10280c9a218ada inc/Module/Install/Include.pm SHA1 dfa433f2f41d990946f1b3d68a29299539f2dea6 inc/Module/Install/Makefile.pm SHA1 72cab336b6be5716aae0a1cb6d9add6c98a7a1f5 inc/Module/Install/Metadata.pm SHA1 35a62725a7eade0fa617ef2ba4cf2f4d4a69a3fe inc/Module/Install/Win32.pm SHA1 19dcc6d1e9f02c56d3f6d184642f4cd68aa371e6 inc/Module/Install/WriteAll.pm SHA1 5e01e2c2a3ab78f04c32034907fc8893a44ebc40 lib/Image/Info.pm SHA1 9f0dd1235685ad2efb78ccb70f824eb5ecbb9add lib/Image/Info/BMP.pm SHA1 b47fa780d8a4b1012c60ac58b9f36ea024637bc8 lib/Image/Info/GIF.pm SHA1 094adf51611a8fb8213b33839ec8f24d0f2ed46d lib/Image/Info/JPEG.pm SHA1 24a4d91c9d86469a2017119847e83451a1056e9a lib/Image/Info/PNG.pm SHA1 dffb9c70bdc96fc0e8649e5a205aad5a38f7ee89 lib/Image/Info/PPM.pm SHA1 5d79a2a37b15024fdf0ed23424ba169369eac94f lib/Image/Info/SVG.pm SHA1 5651f6354dbf10fd6638800d24e1b85f973da6e7 lib/Image/Info/TIFF.pm SHA1 64fd553234970072b2d3e482c2669ed2bb300569 lib/Image/Info/XBM.pm SHA1 69f6ac1388bb51ef1993bc73cd5740fe70892900 lib/Image/Info/XPM.pm SHA1 f6b9e43f87a4985252a1156322bf6d583ef296b4 lib/Image/TIFF.pm SHA1 34e6def40374dc924ea7ef58c5aa04e04a783295 t/00_basics.t SHA1 4c1a8d80c57bec3631d5ede6f02bfcf219f5a9cf t/bmp.t SHA1 7cddff7d8bccd9b2e303554d31ad6f8891b7705b t/exif.t SHA1 3443c36fd2dbc7f58599cf175e0793c5e8601ea9 t/jpg_hang.t SHA1 3b005676e1fba556f2ba18fea2bfeebc7742e23e t/png.t SHA1 cc217a37ee14356bb57e4ea32c1eda94d1a2d8c9 t/pod.t SHA1 a8867b6d1a97c51e22eb650cc26e80178f4264e5 t/pod_cov.t SHA1 90032ccc1d7c8bdf65097fe077d9da3b380f558d t/string.t SHA1 838f5cbb41e41a2bec24944c2199b6b3f72f9dcf t/svg.t SHA1 4946d0695d7b48a04723b790ba70815ba42ef385 t/tiff.t SHA1 76e7e08522799dc0f39896c8925aff1d42b09da4 t/tiff_e.t SHA1 21c60748e74cd08f3e8cb12a5e652d225c39f108 t/tiny-pgm.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iQEVAwUBR+/jO3cLPEOTuEwVAQJB8Qf+N+vNDX1p0oynfU1BYzSEivqcvrJYTsEp AKfYEiN40ZbY3O7/UtZZBLEjt8ABbLU2W2QZnfr8xXTSmRAiOqoKdHMJruuZQsw4 DOyOru9HOLSW0KmEMln9SagVTxZZYlJGkjcoZnUcyuDBUuGusLUQCQGBplKWI9yC 5tA05UXL9uJvi9f2sS4AVwlSGEToJoD3lNnTAJA1Y7hIel1ZXoNqq/vIWocdZaRS EnW5vWrNSRkkpMEeHGbO2km4IV/h+lohMkb11Xu7R3D0OKl201tz9B+2BJUIHePo +wjl4O8NIejl9ps2epMJYhdbUS4xKyT3rsUOrxQJWQsOhWg5oxI3aw== =S+++ -----END PGP SIGNATURE----- �������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/README������������������������������������������������������������������������������0000644�0001750�0001750�00000001721�10670555777�012065� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������This Perl extention allows you to extract meta information from various types of image files. The following file formats are supported: JPEG (plain JFIF and Exif) PNG GIF PBM/PGM/PPM SVG XBM/XPM BMP/DIB/RLE Usage is something like this: use Image::Info qw(image_info); @info = image_info("filename"); $refto_hash_describing_1st_image = $info[0]; $refto_hash_describing_2nd_image = $info[1]; Copyright 1999-2004 Gisle Aas. Now maintained by Tels <nospam-abuse@bloodgate.com> Note that while the module is still maintained, no new features will be added. Especially the EXIF parsing code is buggy, not tested at all, and quite incomplete (a lot of manufacturer's MakerNotes and tags are not parsed at all). If you want a stable, feature-complete, up-to-date and tested EXIF parsing library, please use Image::ExifTool. This library is free software; you can redistribute it and/or modify it under the same terms as Perl v5.8.8 itself. �����������������������������������������������Image-Info-1.28/MANIFEST.SKIP�����������������������������������������������������������������������0000644�0001750�0001750�00000000145�10622147547�013067� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.*\.tar\.gz ^blib.* ^\w+\.(html|txt|dot|pl|old|bak|org) ^Makefile\z ^Makefile.(old|bak)\z pm_to_blib ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/Makefile.PL�������������������������������������������������������������������������0000644�0001750�0001750�00000001244�10773761441�013146� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ############################################################################# require 5.006002; use strict; # Load the Module::Install bundled in ./inc/ use inc::Module::Install; # Get most of the details from the primary module all_from 'lib/Image/Info.pm'; requires 'IO::String' => '1.03' if $] < 5.008; recommends 'Image::Xpm' => 1.0, 'Image::Xbm' => 1.0, 'XML::Simple' => 0; test_requires 'Test::More' => '0.62'; license 'perl'; author 'Tels <nospam-abuse@bloodgate.com>', 'Gisle Aas'; # Do not index these no_index directory => 'img', 'dev'; # Auto-install all dependencies from CPAN auto_install; # Generate the Makefile WriteAll; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/META.yml����������������������������������������������������������������������������0000644�0001750�0001750�00000000765�10731303002�012427� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������--- abstract: Extract meta information from image files (DEPRECATED) author: - 'Tels <nospam-abuse@bloodgate.com>' build_requires: Test::More: 0.62 distribution_type: module generated_by: Module::Install version 0.68 license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.3.html version: 1.3 name: Image-Info no_index: directory: - img - dev - inc - t recommends: Image::Xbm: 1 Image::Xpm: 1 XML::Simple: 0 requires: perl: 5.6.2 version: 1.28 �����������Image-Info-1.28/CHANGES�����������������������������������������������������������������������������0000644�0001750�0001750�00000034415�10773761124�012173� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Revision history for Image::Info 2008-03-30 v1.28 Tels 128 tests * raise minimum required Perl version to v5.6.2 (it doesn't work on 5.005 anyway, open() with three arguments is not supported there and I don't have time to rewrite the code for outdated Perl versions. If you need it to run on 5.005, write a patch and file a bug report please.) * fix bug #15167: Incorrect width and height for JPG files (the fix now keeps the highest value for width/height, instead of creating an array ref with all the values) * remove Build.PL (bundle Module::Install 0.71) 2007-12-15 v1.27 Tels 128 tests * add both main authors to META.yml (does not work yet due to bug in Module::Install) * fix bug #30890: [PATCH] Transposed lines in documentation * fix bug #31165: Add attribute for parsing TIFF images (Thanx Adam Witney!) 2007-09-09 v1.26 Tels 128 tests * clarify the license by adding "v5.8.8" (otherwise it is quite unclear which Perl version, release or product the license text refers to) * fix bug #29088 - Another hanging image * fix bug #29243 - Exiftext fields (like UserComment) not parsed correctly 2007-05-25 v1.25 Tels 127 tests * fix bug #26130 - hang in parsing JPG/TIFF images with repeating block numbers 2007-02-24 v1.24 Tels 125 tests * fix bug #22507: add missing compression modes for TIFF * fix bug #25032: fix TIFF ASCII text field handling (Thanx BJWHEELER!) (This enables, among other things the ImageDescription tag for TIFF files) 2006-09-30 v1.23 Tels 122 tests * regenerate the stale META.yml file * fix svg.t failing if no XML::Simple was installed (bug #21166) * fix _process_ifds call (missing underscore) (Thanx to Dermot Paikkos!) 2006-07-16 v1.22 Tels 123 tests * fix bug #19071: byteorder for TIFF on 64-bit systems broken * better error message in case SOI is missing in a JPEG (still no fix for #20183) * SVG: + use the correct MIME type "image/svg+xml" + version extraction was broken + comments had too much whitespace at front/end (these should be ignored and not extracted anyway) * add svg.t * resize test.jpg and test.png to make dist smaller * add interlace.png and beef up t/png.t 2006-05-01 v1.21 Tels 96 tests * move the code to build Info.pm to dev/build.pl * include a pre-generated Info.pm into MANIFEST (fixes the indexing issue with CPAN) * dont use Symbol(), it is required before its usage anyway * allow exporting of determine_file_type and image_type * remove a needless diag message in string.t (Thanx jpo!) * add two test TIFFs (little/big endian) and a test file (Thanx jpo!) * create a new, much smaller test.rle file * more tests in t/bmp.t 2006-03-13 v1.20 Tels 74 tests * a few additions to Panasonic MakerNote in EXIF parsing * use Module::Install 0.60 to fix breakage from 0.58 * fix bug #8193: Adds direct access to the determine_file_format logic With the following changes: + read only 11 bytes to determine file format (tiny.pgm is 11 bytes long) + fix provided patch to really work * fix bug #18147: + new TIFF code failed if the system endianness didn't match the TIFF image endianness - thanx jpo! * replace the link to the TIFF spec with a public link - thanx jpo! 2006-03-05 v1.19 Tels 74 tests * finally fix bug #6558: (Thanx jpo!) + fix typos: Image::X(B|P)M must be Image::X(p|b)m (Thanx jpo!) + fix missing semicolon in Image/Info/XPM.pm + Image::Info::XPM and Image::Info::XBM: add -width and -height to new() * add POD for process_file() into SVG, Xbm and Xpm * a few additions to Panasonic MakerNote in EXIF parsing * add doc about EXIF being wholly incomplete and using Image::ExifTool * apply patch, tests and add test.tif from Ben Wheeler, Thanx!: + fix bug #7442 Infinite loop of errors in Image::Info::TIFF + fix bug #3698 Broken BitsPerSample handling in TIFFs 2006-03-03 v1.18 Tels 61 tests * fix bug #6558: Image::Info 1.16 -> fails two tests (Thanx jpo!) + make string.t use strict, Test::More and simplify it + let string.t skip tests if Image::Xpm, Image::Xbm or XML::Simple are not installed (these would formerly silently fail) + Image::Info::XPM and Image::Info::XBM now handle in-memory files better + fix also pod_cov.t warnings (was "Image::Info.pm" vs "Image::Info") * reduce img/test.gif in size, it did eat up 1/3 of the entire dist size * reducing test.jpg with GIMP reveals a bug in EXIF parsing (not yet fixed) * MakerNote parsing: + add support for Panasonic cameras + for the following manufacturers we do not check the camera model, this gets all cameras, even yet unreleased ones to work: + Canon + Panasonic + Casio + Olympus + Fujifilm + UNDEFINED/ASCII strings from MakeNotes might have wrong length due to trailing \x00 chars, so we remove them and set the correct length * update one more URL for EXIF specs * imgdump uses Data::Dumper (not Data::Dump) * Install/build: + use Module::Install and bundle it, clean Makefile.PL up + add a compat Build.PL file * add a CREDITS file * PPM.pm: add VERSION, and POD * various POD fixes and additions * various small code cleanups 2006-01-28 v1.17 Tels 48 tests * new maintainer: TELS * signed with my key * convert tests to Test::More * add pod.t and pod_cover.t * fix all POD errors * use strict in Makefile.PL and generate custom META.yml * don't include lib/Image/Info.pm - it is autogenerated anyway * html_dim() returns lowercase and properly quoted, for SVG/XHTML etc., e.g. you get now 'width="900" height="800"' * fix bug #8136: update URL for EXIF standard * fix bug #8522 - dies at JPEGInterchangeFormatLngth (Thanx srezic@cpan.org) * fix also: EXIF says it is "JPEGInterchangeFormatLength", and not "...Lngth" * fix bug #5165: (duplicate of #8522) * fix bug #6018: FocalPlaneResolutionUnit decoded wrongly * fix bug #6083: add support for MakerNote for Nikon D70/D100 * fix bug #16161: netpbm images may have more than 8bit/channel 2004-01-07 Gisle Aas <gisle@ActiveState.com> Release 1.16 Support for Canon 300D/Digital Rebel. Patch contributed by Karl Palsson <kpalsson@cisco.com>. Cleaned up SVG/XPM/XBM implementations so that they don't try to override carp/croak in other modules. 2003-10-06 Gisle Aas <gisle@ActiveState.com> Release 1.15 Avoid IO::String dependency for perl-5.8. It was supposed to work but did not. 2003-10-06 Gisle Aas <gisle@ActiveState.com> Release 1.14 Support TIFF/Exif GPS tags. 2003-10-06 Gisle Aas <gisle@ActiveState.com> Release 1.13 The module reported the SamplesPerPixel field as SamlesPerPixel for PPM files. Patch contributed by Geoff Richards <qef@ungwe.org>. Image::Info was not able to handle files smaller than 32 bytes. Support for Olympus C-700UZ and fix for the Olympus-JpegQual attribute contributed by Nick Hibma <n_hibma@van-laarhoven.org>. Support for Canon makernote. Contributed by John Cavanaugh <john-cavanaugh@attbi.com>. IO::String v1.02 core dumps fixed by depending on v1.03. 2002-12-30 Gisle Aas <gisle@ActiveState.com> Release 1.12 Don't require IO::String for perl-5.8 as it has that feature built in. Based on patch by Slaven Rezic <slaven.rezic@berlin.de>. Looks like the TIFF support that was really functional because I forgot to add lib/Image/Info/TIFF.pm to the MANIFEST :-( Support for Exif 2.2 tags contributed by Stephane Bailliez <sbailliez@apache.org>. Support Olympus C4000Z MakerNote also from Stephane Bailliez. 2002-07-04 Gisle Aas <gisle@ActiveState.com> Release 1.11 More robust TIFF parser that keeps on going if some of the fields appears to be garbage. Workaround for "Samsung Digimax 200"'s brain-dead resolution values. Updated some tags based on the Exif 1.2 spec. Minor fix to exifdump example program so that it can actually dump the test.jpg 2002-05-28 Gisle Aas <gisle@ActiveState.com> Release 1.10 Support for "FUJIFILM FinePix6900ZOOM" and "Canon Canon EOS D60". The Fuji support was contributed by Cyril L. Pertsev <kika@kika.ru> and also included infrastructure for decoding of EXIF tags with UNKNOWN value types. Deal with signed TIFF values. 2001-12-14 Gisle Aas <gisle@ActiveState.com> Release 1.09 Use File::Spec in Makefile.PL to improve portability. Patch by Chris Nandor <pudge@pobox.com>. Extended support for decoding of maker specific tags for Nikon E995 and Olympus 3040Z. TIFF support contributed by <clarsen@emf.net>. Decoding of JPEG color components by <tkil@scrye.com>. 2001-08-24 Gisle Aas <gisle@ActiveState.com> Release 1.08 The html_dim() function did not work at all. Patch by Hans-Georg <hgf@berlin.snafu.de>. Removed ASCII image support. TIFF rational numbers are now blessed and use overloading to convert themselves to strings and numbers in a more sensible way. They are still references to arrays containing 2 numbers. GIF global color table reading fix. Patch by Tom Hargreaves <admin@traderwebs.co.uk>. Support for zTXt chunks in PNG. This only works when the Compress::Zlib module is available. Contributed by Chip Marshall <chip@setzer.chocobo.cx> Updated Exif URIs in documentation 2001-04-10 Gisle Aas <gisle@ActiveState.com> Release 1.07 Image::Info::BMP should not use architecture-dependent unpack descriptors. Fix by <Jost.Krieger@ruhr-uni-bochum.de>. 2001-03-26 Gisle Aas <gisle@ActiveState.com> Release 1.06 Avoid using sysread in Image::Info::BMP. Avoids failures because of mixing of hi- and low-level file reading operations. 2001-03-24 Gisle Aas <gisle@ActiveState.com> Release 1.05 Exif MakerNote decoding implemented by Jay Soffian <jay@loudcloud.com>. His patch support the following camera models: NIKON E700 NIKON E800 NIKON E900 NIKON E900S NIKON E910 NIKON E950 NIKON E880 NIKON E990 NIKON CORPORATION NIKON D1 OLYMPUS OPTICAL CO.,LTD C2000Z OLYMPUS OPTICAL CO.,LTD C2100UZ OLYMPUS OPTICAL CO.,LTD C2500L OLYMPUS OPTICAL CO.,LTD C3030Z OLYMPUS OPTICAL CO.,LTD E-10 FUJIFILM FinePix4900ZOOM FUJIFILM FinePix40i FUJIFILM FinePix4700 ZOOM FUJIFILM FinePixS1Pro CASIO QV-3000EX Canon Canon EOS D30 Canon Canon DIGITAL IXUS Canon Canon DIGITAL IXUS 300 Canon Canon PowerShot G1 Canon Canon PowerShot Pro90 IS Canon Canon PowerShot S10 Canon Canon PowerShot S20 Jay's exifdump program included. 2000-11-30 Gisle Aas <gisle@ActiveState.com> Release 1.04 Allow extra image_info() arguments to pass through to the image format handlers. This make the histogram and color palette returns functional again. Distribute a copy of lib/Image/Info.pm so that search.cpan.org finds it. 2000-11-13 Gisle Aas <gisle@ActiveState.com> Release 1.03 Support for even more image formats added by Jerrad Pierce: - Added support for ASCII and BMP/DIB/RLE - Palettes are only returned if requested (see documentation) - Added Luminance Histogram for ASCII, XBM, XPM 2000-11-10 Gisle Aas <gisle@ActiveState.com> Release 1.02 Avoid direct hardcoding of image file magic and doc by generating lib/Image/Info.pm in Makefile.PL XBM/XPM/SVG support contributed by Jerrad Pierce <belg4mit@mit.edu>/<webmaster@pthbb.org> 2000-10-31 Gisle Aas <gisle@ActiveState.com> Release 1.01 GIF parsing fixes from Ralf Steines <metamonk@yahoo.com>: - GIF 'DisposalMethod' and 'UserInput' now show proper values. - GIF 'TransparencyIndex' now appears in the info hash. - GIF anims with local color tables don't fail anymore (table size calculation bug). - Added: GIFs marked as 87a which contain graphics control extension blocks don't fail anymore, GIF is parsed anyway but $info->{warn} contains 'GIF 89a extensions in 87a'. 2000-10-18 Gisle Aas <gisle@ActiveState.com> Release 1.00 IO::String is now a PREREQ module. Added PPM/PGM/PBM support Improved documentation. Standardized on how "resolution" is expressed. The field in now mandatory. All comments are now found as "Comment" tag. Pick up data about thumbnails embedded in JPEG Exif files. 2000-08-24 Gisle Aas <gisle@ActiveState.com> Release 0.05 Passing a reference to a scalar as argument to img_info() indicates that this scalar contains raw image data. If you want to use this feature, you need to install the IO::String module first. 2000-01-04 Gisle Aas <gisle@aas.no> Release 0.04 Renaming of keys for things that are common across file formats. Common things now use lowercase keys. Better support for JPEG JFXX chunks Better determination of color_type for JPEG Partial support for App14-Adobe chunks in JPEG Support sBIT chunks for PNG 1999-12-25 Gisle Aas <gisle@aas.no> Release 0.03 Eliminated Image::TIFF::Exif. The TIFF module now knows about the Exif tags by itself. Errors are returned as a hash too. Start on Image::Info POD Various tweaks to the reported info keys for JPEG/PNG/GIF. Support Netscape's Loop extention to GIF. Support ColorTable dump for GIF and PNG. Support FileMediaType/FileExt for all image formats. Report number of repeated chunks in PNG_Chunks values. 1999-12-22 Gisle Aas <gisle@aas.no> Release 0.02 Removed external OO interface. The main interface is now an plain function called image_info() that returns one or more hashes. One hash per image found in the file. Exif/TIFF integer that are codes representing something else are now expaned. TIFF Rational values are reduced to plain integers when possible. Added GIF support Added some test scripts 1999-12-19 Gisle Aas <gisle@aas.no> Release 0.01 (now Image-Info) New common framwork that can support many image formats. Added JPEG support Added PNG support 1999-12-14 Gisle Aas <gisle@aas.no> First try, released as Image-Exif-0.01 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/imgdump�����������������������������������������������������������������������������0000755�0001750�0001750�00000000262�10402520117�012541� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/perl -w use lib "./lib"; use strict; use Image::Info qw(image_info); use Data::Dumper; while (@ARGV) { print Data::Dumper::Dumper(image_info(shift)), "\n"; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/exifdump����������������������������������������������������������������������������0000755�0001750�0001750�00000001471�10402027330�012722� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/perl -w use lib 'lib'; use strict; use Image::Info qw(image_info); my $i=image_info($ARGV[0]); foreach (sort keys %$i) { if ($i->{$_} =~ /[\001-\037\177-\377]/ && !/error/) { printf "%s ->\n" ,$_; hex_print($i->{$_}); next; } $i->{$_} =~ s/\000//g; printf "%s -> %s\n" ,$_, ref($i->{$_}) ? deref(@{$i->{$_}}) : $i->{$_} }; sub deref { my @args; if (ref($_[0]) eq 'ARRAY') { foreach my $ref (@_) { push(@args, deref(@{$ref})) } } else { @args = @_; } '[' . join(',',@args) . ']'; } sub hex_print { for (my $i=0; $i<length $_[0];$i+=16) { my $ss = substr($_[0],$i,16); printf " %04x: %s ", $i, join(' ',grep !/^$/,split(/(..)/,unpack("H*",$ss))); $ss =~ tr /\000-\037\177-\377/./; print $ss,"\n"; } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/CREDITS�����������������������������������������������������������������������������0000644�0001750�0001750�00000002433�10730754063�012210� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Special thanx go to Gisle Aas, the main author and contributor. The Exif code is written based on TsuruZoh Tachibanaya's "Description of Exif file format" and Thierry Bousch's Python module 'exifdump.py' http://www.butaman.ne.jp/~tsuruzoh/Computer/Digicams/exif-e.html http://topo.math.u-psud.fr/~bousch/exifdump.py The following list is in alphabetical order. If you contributed to Image::Info and miss your name on the list, please file a bug report at https://rt.cpan.org or send email to the current maintainer: Adam Kennedy <cpan@ali.as> image_type() Ben Wheeler <b.wheeler@ulcc.ac.uk> TIFF bugfixes and patches <clarsen@emf.net> TIFF support Doug Larrick <doug@ties.org> Nikon D70/D100 MakerNote patch Gisle Aas Main author and contributor H.Merijn Brand <h.m.brand@xs4all.nl> 64 bit patches, tests & feedback Jay Soffian <jay@loudcloud.com> Exif MakerNote decoding Jerrad Pierce <belg4mit@mit.edu> ASCII, BMP SVG, XPM and XBM support José Pedro Oliveira <jpo@di.uminho.pt> XBM/XPM/TIFF bug reports and patches TIFF endian tests Testing on Mac and PPC Phil Harvey <phil@owl.phy.queensu.ca> Panasonic Exif MakerNotes Ralf Steines <metamonk@yahoo.com> GIF fixes Slaven Rezic <srezic@cpan.org> various bug reports Tels <http://www.bloodgate.com> Maintainer from 2006 on �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Image-Info-1.28/MANIFEST����������������������������������������������������������������������������0000644�0001750�0001750�00000002420�10773753235�012324� 0����������������������������������������������������������������������������������������������������ustar �te������������������������������te���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������CHANGES CREDITS dev/build.pl dev/Info.pm.tmpl Will become lib/Image/Info.pm exifdump Test driver script img/be.tif img/cynic_hang.jpg cycle in IFD's causing hangs in older than v1.25 img/gps.jpg img/graph.svg img/interlace.png Interlaced PNG example img/le.tif img/test.gif An GIF example img/test.jpg An Exif example from my Digicam img/test.pbm img/test.pgm img/test.png An PNG example img/test.ppm img/test.rle img/test.svg img/test.tif img/test.xbm img/test.xpm img/tiny.pgm imgdump Test driver script inc/Module/AutoInstall.pm inc/Module/Install.pm inc/Module/Install/AutoInstall.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Include.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm lib/Image/Info.pm lib/Image/Info/BMP.pm lib/Image/Info/GIF.pm lib/Image/Info/JPEG.pm lib/Image/Info/PNG.pm lib/Image/Info/PPM.pm lib/Image/Info/SVG.pm lib/Image/Info/TIFF.pm lib/Image/Info/XBM.pm lib/Image/Info/XPM.pm lib/Image/TIFF.pm Parse TIFF tags Makefile.PL MANIFEST MANIFEST.SKIP META.yml Module meta-data README SIGNATURE t/00_basics.t t/bmp.t t/exif.t t/jpg_hang.t t/png.t t/pod.t t/pod_cov.t t/string.t t/svg.t t/tiff.t t/tiff_e.t t/tiny-pgm.t TODO ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������