327
Simple Photo Processing and Web Display with Perl Kent Cowgill

Simple Photo Processing and Web Display with Perl

Embed Size (px)

DESCRIPTION

I have a small photo gallery on my website and in this presentation, I sharesome steps I used in creating a nearly automatic workflow of gettingpictures from my camera to his gallery using Perl.

Citation preview

Page 1: Simple Photo Processing and Web Display with Perl

Simple Photo Processing

and

Web Displaywith

PerlKent Cowgill

Page 2: Simple Photo Processing and Web Display with Perl

Unfortunately, nothing super fancy.

Page 3: Simple Photo Processing and Web Display with Perl

The first camera I used

Page 4: Simple Photo Processing and Web Display with Perl

The pictures were ... ok

Page 5: Simple Photo Processing and Web Display with Perl

The phonestayed in my

pocket. Along with pocket lint. A lot

of pocket lint.

Page 6: Simple Photo Processing and Web Display with Perl

And a lot of lint got in the lens

Page 7: Simple Photo Processing and Web Display with Perl

And the pictures started getting blurryAnd a lot of lint got in the lens

Page 8: Simple Photo Processing and Web Display with Perl

Especiallywith allmy dailyactivities.

Page 9: Simple Photo Processing and Web Display with Perl

Especiallywith allmy dailyactivities.

Page 10: Simple Photo Processing and Web Display with Perl

And the pictures got blurrier

Page 11: Simple Photo Processing and Web Display with Perl

... and blurrier ...

Page 12: Simple Photo Processing and Web Display with Perl

And practically unrecognizable.

Page 13: Simple Photo Processing and Web Display with Perl

So I got a new phone.

Page 14: Simple Photo Processing and Web Display with Perl

This has been my camera

Page 15: Simple Photo Processing and Web Display with Perl

The pictures were better

Page 16: Simple Photo Processing and Web Display with Perl

No lint problem, even in harsh conditions

Page 17: Simple Photo Processing and Web Display with Perl

Until my phone dropped out of my pocket

and was picked up by Ricardo Signes at YAPC

Page 18: Simple Photo Processing and Web Display with Perl

But that blurrinesswas user error.

Page 19: Simple Photo Processing and Web Display with Perl

Thankfully, he returned my phone to me.

Page 20: Simple Photo Processing and Web Display with Perl

What a nice guy.

Page 21: Simple Photo Processing and Web Display with Perl

My RAZR hasserved me well.

Page 22: Simple Photo Processing and Web Display with Perl

Until Recently

Page 23: Simple Photo Processing and Web Display with Perl

More on that later.

Page 24: Simple Photo Processing and Web Display with Perl

Step 1:Get the picturefrom the phoneto the server.

Page 25: Simple Photo Processing and Web Display with Perl

This is what I looked like

Page 26: Simple Photo Processing and Web Display with Perl

Taking pictures with my RAZR

Page 27: Simple Photo Processing and Web Display with Perl

The obligatory

cat

Page 28: Simple Photo Processing and Web Display with Perl
Page 29: Simple Photo Processing and Web Display with Perl
Page 30: Simple Photo Processing and Web Display with Perl
Page 31: Simple Photo Processing and Web Display with Perl
Page 32: Simple Photo Processing and Web Display with Perl
Page 33: Simple Photo Processing and Web Display with Perl
Page 35: Simple Photo Processing and Web Display with Perl

Step 2:Get the picture

from the email to the filesystem.

Page 36: Simple Photo Processing and Web Display with Perl

1

strip image from mailcowgill

2/9/05

motorola v551

Page 37: Simple Photo Processing and Web Display with Perl

use MIME::Parser;use MIME::Entity;use MIME::Base64 qw(decode_base64);use Image::Magick::Thumbnail;

Page 38: Simple Photo Processing and Web Display with Perl

my $parser = MIME::Parser->new();$parser->output_dir( '/www/kentcowgill/photos/data' );

my $message = $parser->parse( \*STDIN ) };

Page 39: Simple Photo Processing and Web Display with Perl

for my $part( $message->parts_DFS ){ if( $part->bodyhandle ){ if( $part->mime_type eq 'image/jpeg' ){ $filename = $part->bodyhandle->path; $data .= $part->as_string; $data =~ s/.*\n\n(.*)/$1/ms; } $data = decode_base64($data);...

DFS?

Ew.

Page 40: Simple Photo Processing and Web Display with Perl

... open ARCHIVE, '>', $archive_image; binmode ARCHIVE; print ARCHIVE $data; close ARCHIVE;

my $src = new Image::Magick; $src->Read($archive_image);...

Error checkingis left as an exercise

for the reader.

Page 41: Simple Photo Processing and Web Display with Perl

... my( $thumb, $x, $y ) =Image::Magick::Thumbnail::create( $src, 64 ); $thumb->Write($archive_thumb); }}

Page 42: Simple Photo Processing and Web Display with Perl

Worked great.

Page 43: Simple Photo Processing and Web Display with Perl

Flawlessly.

Page 44: Simple Photo Processing and Web Display with Perl

For a while.

Page 45: Simple Photo Processing and Web Display with Perl

Until I upgraded...

PerlImage::Magick

God only knows what else.

And with all their dependencies...

Page 46: Simple Photo Processing and Web Display with Perl

WTF?

Page 47: Simple Photo Processing and Web Display with Perl

Then something broke.

WTF?

Page 48: Simple Photo Processing and Web Display with Perl

It didn't make this blurry.Then something broke.

WTF?

Page 49: Simple Photo Processing and Web Display with Perl

It didn't make this blurry.Then something broke.

WTF?

No, that was poor technique.

Page 50: Simple Photo Processing and Web Display with Perl

It didn't make this blurry.It started cutting off my photos.Then something broke.

WTF?

No, that was poor technique.

Page 51: Simple Photo Processing and Web Display with Perl

WTF?

It was really annoying.

Page 52: Simple Photo Processing and Web Display with Perl

WTF?

And inconsistent.

Page 53: Simple Photo Processing and Web Display with Perl

Cockroaches

Termites (Not to scale)

Bunnies (Also not to scale)

Page 54: Simple Photo Processing and Web Display with Perl

Tough to reliably reproduce.

Page 55: Simple Photo Processing and Web Display with Perl

So I spent my time and energy elsewhere.

Page 56: Simple Photo Processing and Web Display with Perl

Step 3:Get the picture

from the filesystem to the web browser.

Page 57: Simple Photo Processing and Web Display with Perl

This is the site that I made

Page 58: Simple Photo Processing and Web Display with Perl

To view the pictures that I took

Page 59: Simple Photo Processing and Web Display with Perl

Click on a thumbnail...

Page 60: Simple Photo Processing and Web Display with Perl

And see the full image.

Page 61: Simple Photo Processing and Web Display with Perl

But not that one. ;-)

Page 62: Simple Photo Processing and Web Display with Perl

<?php$start = $_GET["start"] ? $_GET["start"] : "0";

$filearray = array();

$dir = "/www/kentcowgill/photos/arch";$mydir = "/photos/arch";$thumbdir = "/photos/thumbs";

if( $handle = opendir( $dir ) ){ while( false !== ( $file = readdir( $handle ) ) ){ if( $file != "." && $file != ".."){ array_push( $filearray, $file ); } } closedir( $handle );}...

Page 63: Simple Photo Processing and Web Display with Perl

PHP?

Page 64: Simple Photo Processing and Web Display with Perl

Didn't I say Perlat the beginning?

Page 65: Simple Photo Processing and Web Display with Perl
Page 66: Simple Photo Processing and Web Display with Perl

$_ == 0 && do { $table .= "<tr><td align=center height=$CELLHEIGHT " . "width=$CELLWIDTH valign=bottom>"; last SWITCH;}

Page 67: Simple Photo Processing and Web Display with Perl

$_ == 0 && do { $table .= "<tr><td align=center height=$CELLHEIGHT " . "width=$CELLWIDTH valign=bottom>"; last SWITCH;}

My only excuse is that I wrote it a

really long time ago

Page 68: Simple Photo Processing and Web Display with Perl

:-p~

Page 69: Simple Photo Processing and Web Display with Perl
Page 70: Simple Photo Processing and Web Display with Perl
Page 71: Simple Photo Processing and Web Display with Perl
Page 72: Simple Photo Processing and Web Display with Perl
Page 73: Simple Photo Processing and Web Display with Perl

The picture viewerwas updated as well.

Page 74: Simple Photo Processing and Web Display with Perl

I also got a dog.

Cat

Dog

Page 75: Simple Photo Processing and Web Display with Perl

And I stored theusers' preferences...

Page 76: Simple Photo Processing and Web Display with Perl

UserPreferences

Page 77: Simple Photo Processing and Web Display with Perl

Step 4:Fix the imagestripping bug.

Page 78: Simple Photo Processing and Web Display with Perl

2

strip image from mailcowgill

7/25/06

motorola RAZR v3

Page 79: Simple Photo Processing and Web Display with Perl

Add module version requirements.

Page 80: Simple Photo Processing and Web Display with Perl

use MIME::Parser;use MIME::Entity;use MIME::Base64 qw(decode_base64);use Image::Magick::Thumbnail;

Page 81: Simple Photo Processing and Web Display with Perl

use MIME::Parser 5.415;use MIME::Entity 5.415;use MIME::Base64 3.07 qw(decode_base64);use Image::Magick::Thumbnail;

Page 82: Simple Photo Processing and Web Display with Perl

Add debugging and logging.

Page 83: Simple Photo Processing and Web Display with Perl

my $parser = MIME::Parser->new();$parser->output_dir( '/www/kentcowgill/photos/data' );

my $message = $parser->parse( \*STDIN ) };

Page 84: Simple Photo Processing and Web Display with Perl

my $parser = MIME::Parser->new();$parser->output_to_core(1);$parser->output_dir( '/www/kentcowgill/photos/data' );

my $message;

eval { $message = $parser->parse( \*STDIN ) };if( $@ ){ my $results = $parser->results; open ERR, '>', '/www/kentcowgill/photos/err.txt'; print ERR $results; close ERR;}

Additional error checking is leftas an exercisefor the reader.

Page 85: Simple Photo Processing and Web Display with Perl

for my $part( $message->parts_DFS ){ if( $part->bodyhandle ){ if( $part->mime_type eq 'image/jpeg' ){ $filename = $part->bodyhandle->path; $data .= $part->as_string; $data =~ s/.*\n\n(.*)/$1/ms; } $data = decode_base64($data);...

Page 86: Simple Photo Processing and Web Display with Perl

for my $part( $message->parts_DFS ){ if( $part->bodyhandle ){ if( $part->mime_type eq 'image/jpeg' ){ $filename = $part->bodyhandle->path; $data .= $part->as_string; print LOG2 $data; print LOG3 $filename; my @raw_part = split( /\n/, $data ); my @edited_part; for my $line( @raw_part ){ if( $line =~ m/^$/ ){ $found++; next; } next unless $found; push @edited_part, $line; } $data =~ s/.*\n\n(.*)/$1/ms; $data = join( "\n", @edited_part ); print LOG $data; } $data = decode_base64($data);

Page 87: Simple Photo Processing and Web Display with Perl

... my $src = new Image::Magick; $src->Read($archive_image);...

Page 88: Simple Photo Processing and Web Display with Perl

... my $src = new Image::Magick; my $debug = $src->Read($archive_image); print LOG "WARNING: ImageMagick::Read " . "had problem: $debug\n" if $debug;

...

Page 89: Simple Photo Processing and Web Display with Perl

... my( $thumb, $x, $y ) =Image::Magick::Thumbnail::create( $src, 64 ); $thumb->Write($archive_thumb); }}

Page 90: Simple Photo Processing and Web Display with Perl

... my( $thumb, $x, $y ) =Image::Magick::Thumbnail::create( $src, 64 ); $thumb->Write($archive_thumb); }}

No debugging here.

Page 91: Simple Photo Processing and Web Display with Perl

No problem with thumbnails.

The cut-off images scaled fine.

Page 92: Simple Photo Processing and Web Display with Perl

The result?

Page 93: Simple Photo Processing and Web Display with Perl

No hints.

Page 94: Simple Photo Processing and Web Display with Perl

No clues.

Page 95: Simple Photo Processing and Web Display with Perl

No fix.

Page 96: Simple Photo Processing and Web Display with Perl

:-(

Page 97: Simple Photo Processing and Web Display with Perl

Step 5:Replace the imagestripping program.

Page 98: Simple Photo Processing and Web Display with Perl

3

strip image from mailcowgill

1/5/07

motorola RAZR v3

Page 99: Simple Photo Processing and Web Display with Perl

Replace the modules used.

Page 100: Simple Photo Processing and Web Display with Perl

use MIME::Parser 5.415;use MIME::Entity 5.415;use MIME::Base64 3.07 qw(decode_base64);use Image::Magick::Thumbnail;

Page 101: Simple Photo Processing and Web Display with Perl

use Email::MIME;use Email::MIME::Attachment::Stripper;use MIME::Base64 qw(decode_base64);use Imager;

Still Used

Page 102: Simple Photo Processing and Web Display with Perl

my $parser = MIME::Parser->new();$parser->output_to_core(1);$parser->output_dir( '/www/kentcowgill/photos/data' );

my $message;

eval { $message = $parser->parse( \*STDIN ) };if( $@ ){ my $results = $parser->results; open ERR, '>', '/www/kentcowgill/photos/err.txt'; print ERR $results; close ERR;}

Page 103: Simple Photo Processing and Web Display with Perl

for my $part( $message->parts_DFS ){ if( $part->bodyhandle ){ if( $part->mime_type eq 'image/jpeg' ){ $filename = $part->bodyhandle->path; $data .= $part->as_string; print LOG2 $data; print LOG3 $filename; my @raw_part = split( /\n/, $data ); my @edited_part; for my $line( @raw_part ){ if( $line =~ m/^$/ ){ $found++; next; } next unless $found; push @edited_part, $line; } $data =~ s/.*\n\n(.*)/$1/ms; $data = join( "\n", @edited_part ); print LOG $data; } $data = decode_base64($data);

Page 104: Simple Photo Processing and Web Display with Perl

my $email = Email::MIME->new( $msg_text );

my $stripper = Email::MIME::Attachment::Stripper->new( $email );

my @files = $stripper->attachments;

@files = grep { $_->{content_type} eq 'image/jpeg'} @files;

my $image_data = @files ? $files[0]->{payload} : decode_base64( $email->{parts}[0]->{body} );

Page 105: Simple Photo Processing and Web Display with Perl

... my $src = new Image::Magick; my $debug = $src->Read($archive_image); print LOG "WARNING: ImageMagick::Read " . "had problem: $debug\n" if $debug;

...

Page 106: Simple Photo Processing and Web Display with Perl

my $src = Imager->new;

$src->read( file => $archive_image, type => 'jpeg' );

Page 107: Simple Photo Processing and Web Display with Perl

... my( $thumb, $x, $y ) =Image::Magick::Thumbnail::create( $src, 64 ); $thumb->Write($archive_thumb); }}

Page 108: Simple Photo Processing and Web Display with Perl

my $tmbimg = $src->copy();

my $thumb = $tmbimg->scale( xpixels => 64, ypixels => 48, type => 'min');

$thumb->write( file => $archive_thumb );

Page 109: Simple Photo Processing and Web Display with Perl
Page 110: Simple Photo Processing and Web Display with Perl

The result?

Page 111: Simple Photo Processing and Web Display with Perl

OMG!!

IT WORKS!@$!

Page 112: Simple Photo Processing and Web Display with Perl

No one was happier

than my dog.

Page 113: Simple Photo Processing and Web Display with Perl

Step 6:Add display options.

Page 114: Simple Photo Processing and Web Display with Perl

When was thepicture taken?

Page 115: Simple Photo Processing and Web Display with Perl

The pictures arrive at my server within

minutes.

Page 116: Simple Photo Processing and Web Display with Perl

[~]$ perldoc -f time

time Returns the number of non-leap seconds since whatever time the system considers to be the epoch, suitable for feeding to "gmtime" and "localtime".

Page 117: Simple Photo Processing and Web Display with Perl

my $archivedir = '/www/kentcowgill/photos/arch';my $thumbdir = '/www/kentcowgill/photos/thumbs';

my $pic_time = time;

my $archive_image = $archivedir . '/' . $pic_time . '.jpg';my $archive_thumb = $thumbdir . '/' . $pic_time .'_thumb.jpg';

Page 118: Simple Photo Processing and Web Display with Perl

return $date;}

sub pretty_date { my( $stamp ) = shift; # $stamp = 1195004723; my @date = split /\s+/, scalar localtime $stamp; # @date = qw(Tue Nov 13 19:45:23 2007); my $date = join q{ }, splice @date, 1, 5; # $date = 'Nov 13 19:45:23 2007'; my ( $hr, $mn ) = ( split /:/, ( split /\s+/, $date)[2] )[0,1]; # $hr = 19; $mn = 45; my $merid = $hr > 12 ? do { $hr -= 12; 'pm' } : $hr == 12 ? 'pm' : 'am'; # $hr = 7; $merid = 'pm'; $date =~ s/(\w+) (\d+) .* (\d+)/$1 $2, $3: $hr:$mn$merid/; # $date = 'Nov 13, 2007: 7:45pm';

Page 119: Simple Photo Processing and Web Display with Perl

SIDE BAR

Concise and efficient?OR

Obfuscation?

my $merid = $hr > 12 ? do { $hr -= 12; 'pm' } : $hr == 12 ? 'pm' : 'am'; # $hr = 7; $merid = 'pm';

Page 120: Simple Photo Processing and Web Display with Perl

SIDE BAR<australian accent>

That's not an obfuscation...<australian accent>

Page 121: Simple Photo Processing and Web Display with Perl

$_='`$t` `.=lc for<>;u($_` )for` 3..``6;%t=qw ` `(a 82 b 15 c 28 d 43 e ` `127 f 22 ` g 20 h 61 i 70 ` `j 2 k 8 ```````l 40 m 24 n 67 ` o 75` ` p 19 q 1` ` r ` 60 s 63 t ` 91 ` u 28 v 1 `0 w ` 24 x 2 y ` `20 ` ` z 1);$k= k() ` ``;$d+=$t{$` `_}f o``r keys%t;$l =$d` /in` ``t(`length($t)/ $k)/100 ` ;map{%n=f(t($_));@g=b(1,\` `%n);$y.= i(\@g)}0..$k-1;@_=(a..z); map{@$_= @_;if($;++){for$"(2..$;){ pu ` sh` `` @$_,shift@$_} `` `` `}` }@_;map{$p=i` n` d`ex `((join\'\',` ` ` `@`{(sp `lit//,$y)[$c ` ]}),$_);` `$o```.=$p>=0?$`a` `` [ $p]: $_;$c+=$c<$k-1?1 ````: `-$` ``k+1}split//,$t;s ``ub \'b{my($e,$s `,@g)=@_;p ` ``ush@ `g`,[$_,(s pli` `` ``t//,\'#\' ``x in` `` `t($$s{`$_}*$e )`)]for ` `+sort+keys%$s;retur ```n@g}s` ub\'c{my$x=shift;$x=g($x,shift ```)while@_; return$x}sub\'f{my%d;$d{$_}++f` or grep/[a-z]/ ,split//,shift;$d{$_}||=0for a..z;return%d}su b\'g{my($x,$y)=@_;($x,$y)=($y,$x%$y)while$y;r eturn$x}sub\'i{my($g,@c)=@_;map{push@c,o(v($g),` `` ` $$g[0][0]);w($g)}0..25;return(map{$_->[1]}sort{$` b-`` >[0]<=>$a->[0]}@c)[0]} sub\'k{my@g;for(sort{$s{` `$b}`` <=>$s{$a}}keys%s){last ``if$s{$_}<3;next unless y `/a-``` z//>2;my@f ;push@f,(pos `($t)-3)while$t=~/$_/g;m` ````````y$g=c(n(@f) );`$g```` >2&&push@g,$g}return c(@` g)}sub\'n{my$o= shift;return map{$_-$o}@_ }sub\'o{my($g,$w) =@_;my$c=0;map{map{/\+/&&` $c++;/\-/&&$c--}@ $_}@$g;return[$c,$w]}sub\' `t{my($o)=@_;my$c= 0;my$r;map{$r.=$_ unless( `$k-$o+$c)%$k;$c++} split//,$t;$r=~s/[^a-z]/ /g;return$r}sub\'u{ my$l=$_[0];$s{substr($t` ,$_,$l)}++for 0..(le ngth($t)-$l)}sub\'v{my($ `m)=@_;my@g=b($l,\%t );$s=\@g;$z=0;map{$x=0;ma `p{$$s[$z][$x]=$$m` [$z][$x]eq\'#\'&&$$s[$z][ `$x]eq\'#\'?\'+` \':\'-\';$x++}@$_;$z++}@$m `;return$s}sub \'w{$R=shift;push@$R,shif` `t@$R}print" Key: $y\nPlaintext:\n$o\`` `n";';s-\s \s+--gmx;s&`&&gm;eval#;` #etur#`` `#my($x($v());$y=$z#`#` ##```` ``# charles #`` #`````` ````# babbage #`

Page 122: Simple Photo Processing and Web Display with Perl

$_='`$t` `.=lc for<>;u($_` )for` 3..``6;%t=qw ` `(a 82 b 15 c 28 d 43 e ` `127 f 22 ` g 20 h 61 i 70 ` `j 2 k 8 ```````l 40 m 24 n 67 ` o 75` ` p 19 q 1` ` r ` 60 s 63 t ` 91 ` u 28 v 1 `0 w ` 24 x 2 y ` `20 ` ` z 1);$k= k() ` ``;$d+=$t{$` `_}f o``r keys%t;$l =$d` /in` ``t(`length($t)/ $k)/100 ` ;map{%n=f(t($_));@g=b(1,\` `%n);$y.= i(\@g)}0..$k-1;@_=(a..z); map{@$_= @_;if($;++){for$"(2..$;){ pu ` sh` `` @$_,shift@$_} `` `` `}` }@_;map{$p=i` n` d`ex `((join\'\',` ` ` `@`{(sp `lit//,$y)[$c ` ]}),$_);` `$o```.=$p>=0?$`a` `` [ $p]: $_;$c+=$c<$k-1?1 ````: `-$` ``k+1}split//,$t;s ``ub \'b{my($e,$s `,@g)=@_;p ` ``ush@ `g`,[$_,(s pli` `` ``t//,\'#\' ``x in` `` `t($$s{`$_}*$e )`)]for ` `+sort+keys%$s;retur ```n@g}s` ub\'c{my$x=shift;$x=g($x,shift ```)while@_; return$x}sub\'f{my%d;$d{$_}++f` or grep/[a-z]/ ,split//,shift;$d{$_}||=0for a..z;return%d}su b\'g{my($x,$y)=@_;($x,$y)=($y,$x%$y)while$y;r eturn$x}sub\'i{my($g,@c)=@_;map{push@c,o(v($g),` `` ` $$g[0][0]);w($g)}0..25;return(map{$_->[1]}sort{$` b-`` >[0]<=>$a->[0]}@c)[0]} sub\'k{my@g;for(sort{$s{` `$b}`` <=>$s{$a}}keys%s){last ``if$s{$_}<3;next unless y `/a-``` z//>2;my@f ;push@f,(pos `($t)-3)while$t=~/$_/g;m` ````````y$g=c(n(@f) );`$g```` >2&&push@g,$g}return c(@` g)}sub\'n{my$o= shift;return map{$_-$o}@_ }sub\'o{my($g,$w) =@_;my$c=0;map{map{/\+/&&` $c++;/\-/&&$c--}@ $_}@$g;return[$c,$w]}sub\' `t{my($o)=@_;my$c= 0;my$r;map{$r.=$_ unless( `$k-$o+$c)%$k;$c++} split//,$t;$r=~s/[^a-z]/ /g;return$r}sub\'u{ my$l=$_[0];$s{substr($t` ,$_,$l)}++for 0..(le ngth($t)-$l)}sub\'v{my($ `m)=@_;my@g=b($l,\%t );$s=\@g;$z=0;map{$x=0;ma `p{$$s[$z][$x]=$$m` [$z][$x]eq\'#\'&&$$s[$z][ `$x]eq\'#\'?\'+` \':\'-\';$x++}@$_;$z++}@$m `;return$s}sub \'w{$R=shift;push@$R,shif` `t@$R}print" Key: $y\nPlaintext:\n$o\`` `n";';s-\s \s+--gmx;s&`&&gm;eval#;` #etur#`` `#my($x($v());$y=$z#`#` ##```` ``# charles #`` #`````` ````# babbage #`

Page 123: Simple Photo Processing and Web Display with Perl

Or with Date::Calc:use Date::Calc qw( Today Month_to_Text Localtime );

my $datestamp = shift;my( $year, $month, $day, $hour, $minute ) = ( Localtime( $datestamp ) )[ 0 .. 4 ];my $meridian = $hour > 12 ? do { $hour -= 12; 'pm' } : $hour == 12 ? 'pm' : 'am';my $date = sprintf( '%.3s %02d, %d: %d:%d%s', Month_to_Text( $month ), $day, $year, $hour, $minute, $meridian,);

# $date = 'Nov 13, 2007: 7:45pm';

Page 124: Simple Photo Processing and Web Display with Perl

Or with a regex:

my $date = scalar localtime $stamp;

$date =~ s{^\w{3}\s(\w{3} )(?{$^N})\s+(\d+)(?{$,=$^R.$". $^N})\s(\d+)(?{$.=$^N;$@=$.>12?do{$.-=12;'pm' }:$ .==12?'pm':'am'}):( \d+)(?{$ /="$ .:$ ^N$ @"}):\d+\s(\d{4})(?{$==$ ^N})}{$,$"$=:$"$/}x;

# $date = 'Nov 13, 2007: 7:45pm';

use strict;use warnings;

Believe it or not

Page 125: Simple Photo Processing and Web Display with Perl

Adding captionsto the photos.

Page 126: Simple Photo Processing and Web Display with Perl

Use a database.

Page 127: Simple Photo Processing and Web Display with Perl

create database photoblog;

use photoblog;

create table captions ( caption_id int( 11 ) not null auto_increment, caption_photo varchar( 32 ) not null, caption_text text, primary key( caption_id ), unique caption_id( caption_id ));

Page 128: Simple Photo Processing and Web Display with Perl

Create a row in the database when an

email arrives.

Page 129: Simple Photo Processing and Web Display with Perl

Why?

• Makes later CRUD implementation easier.

Page 130: Simple Photo Processing and Web Display with Perl

CRUDCreate RetrieveUpdate Delete

The four basic functions of persistent storage.

Page 131: Simple Photo Processing and Web Display with Perl

• Makes later CRUD implementation easier.

Why?

• In the editing interface, just implement:

• Retrieve and Update

• Don't worry about Create

• Delete is just updating a record to nothing.

Page 132: Simple Photo Processing and Web Display with Perl

CRUDWhat is CRUD without the Create and Delete?

Page 133: Simple Photo Processing and Web Display with Perl

RU

Page 134: Simple Photo Processing and Web Display with Perl

IN SOVIETRUSSIA

CRUDWRITES

YOU!

Page 135: Simple Photo Processing and Web Display with Perl

my $dbh = Mysql->connect( 'localhost', 'photoblog', $username, $password,);

my $sth = $dbh->query( qq{ insert into captions (caption_photo) values ('$new_filename')});

$sth->finish;

Binding input parameters is left

as an exercisefor the reader.

Page 136: Simple Photo Processing and Web Display with Perl

Create an interface to update captions.

Page 137: Simple Photo Processing and Web Display with Perl

my $caption = param( 'caption' ); my $url = param( 'url' ); $url =~ m/.*\/(.*)\.jpg/; my $picture = $1; $caption =~ s/'/''/g; $caption =~ s/<.*?>//g;

my $dbh = Mysql->connect( 'localhost', 'photoblog', $username, $password, );

my $query = qq{ update captions set caption_text='$caption' where caption_photo='$picture'};

my $sth = $dbh->query( $query );

Binding theinput parameter

would've helped here.

Just stripping out HTML tags.

Page 138: Simple Photo Processing and Web Display with Perl

Fetch the captionswhen showing the

thumbnails.

Page 139: Simple Photo Processing and Web Display with Perl

my $query = qq{ select caption_text from captions where caption_photo=$picbase};

my $dbh = Mysql->connect( 'localhost', 'photoblog', $username, $password, );

my $sth = $dbh->query( $query ); my $caption = $sth->fetchrow;

$caption = $caption || '';

Page 140: Simple Photo Processing and Web Display with Perl

Step 7:Redesign.

Page 141: Simple Photo Processing and Web Display with Perl

Fit into the design for the rest of the site

Page 142: Simple Photo Processing and Web Display with Perl
Page 143: Simple Photo Processing and Web Display with Perl

($header=<<" EOHEADER") =~ s/ //gm; <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head><title>$title</title> <style type="text/css"> EOHEADER... SWITCH: for( $counter ){ $_ == 0 && do { $table .= "<tr><td align=\"center\" " . "valign=\"bottom\">\n"; last SWITCH; }; $_ == ($cols) && do { $table .= "</tr>\n"; last SWITCH; }; $table .= qq(<td align="center" valign="bottom">\n); }

Page 144: Simple Photo Processing and Web Display with Perl

Templates++

Page 145: Simple Photo Processing and Web Display with Perl

use Template;

...

my %pic = ( picture => q{/photos/arch/} . $base . '.jpg', timestamp => pretty_date( $base ), thumb => q{/photos/thumbs/} . $base . q{_thumb.jpg}, caption => $caption, );

Page 146: Simple Photo Processing and Web Display with Perl

<table border="0" class="gallery"> [% FOREACH row IN pictures -%] <tr> [% FOREACH pic IN row -%]

<td align="center" valign="bottom" class="pic"> <a href="javascript:OpenWindow('[% pic.picture %]','700','540')"><img src ="[% pic.thumb %]" alt ="[% pic.caption %]" title ="[% pic.caption %]"/></a> <p class="timestamp">[% pic.timestamp %]</p></td>

[% END -%] </tr> [% END -%] </table>

Page 147: Simple Photo Processing and Web Display with Perl
Page 148: Simple Photo Processing and Web Display with Perl

Add a "current image".

i.e. most recently taken

Page 149: Simple Photo Processing and Web Display with Perl

my $src = Imager->new;$src->read( file => $archive_image, type => 'jpeg' );

my $newimg = $src->copy();

my $curimg = $newimg->scale( xpixels => 320, ypixels => 240, type => 'min',);

my $gryimg = $curimg->convert( preset => 'grey' );$gryimg->write( file => $current_image );

Page 150: Simple Photo Processing and Web Display with Perl

my ( $firstbase ) = $firstfile =~ m{^.+/(\d+)\.jpg$};

$vars->{ mostrecent } = get_caption( $firstbase );

$vars->{ randomizer } .= int rand 9 for 1 .. 8;

Page 151: Simple Photo Processing and Web Display with Perl

Why?• Browsers cache the image

• appending a random number

(i.e. "?12345678") prevents caching

• It's an actual image, but it could be a CGI

• It could be dynamically generated

• Your web browser and my server won't know the difference

• No caching, fresh request each time

Page 152: Simple Photo Processing and Web Display with Perl

[% IF mostrecent -%] <table border="0" class="mostrecent"> <tr><td class="mostrecent"> <img src="/photos/mostrecent.jpg?[% randomizer %]"/> </td></tr> </table>[% END -%]

Page 153: Simple Photo Processing and Web Display with Perl
Page 154: Simple Photo Processing and Web Display with Perl

Use it elsewhere.

Page 155: Simple Photo Processing and Web Display with Perl

Organize the photos.

Page 156: Simple Photo Processing and Web Display with Perl

Why?

• Having a chronological list is OK

• By assigning tags to photos, you won't have to remember which page of 60 has:

• that picture of the dog from 3 months ago

• the picture of the bed you bought last year

• or...

Page 157: Simple Photo Processing and Web Display with Perl

The picture of the video chat with your crazy in-laws.

Page 158: Simple Photo Processing and Web Display with Perl

Use the same database.

Page 159: Simple Photo Processing and Web Display with Perl

use photoblog;

create table tags ( tag_id int( 11 ) not null auto_increment, tag_photo varchar( 32 ) not null, tag_name text, primary key( tag_id ), unique tag_id( tag_id ));

Page 160: Simple Photo Processing and Web Display with Perl

Create an interface to add tags.

Page 161: Simple Photo Processing and Web Display with Perl

my $tags = param( 'tags' ); my @tags = split( /(?:\s+|,)/, $tags ); my $dbh = Mysql->connect( "localhost", "photoblog", $username, $password ); my $delete = qq{ delete from tags where tag_photo = '$picture'}; $sth = $dbh->query( $delete ); for my $tag( @tags ){ my $ins = qq{ insert into tags( tag_photo, tag_name ) values( '$picture', '$tag' )}; $sth = $dbh->query( $ins ); }

Page 162: Simple Photo Processing and Web Display with Perl

Fetch the tagswhen showing the

pictures.

Page 163: Simple Photo Processing and Web Display with Perl

my $query = q{ select tag_name from tags where tag_photo=$picbase};$sth = $dbh->query( $query );

my @tags;while( my $tag = $sth->fetchrow ){ push @tags, $tag;}

my $tags = join( ' ', @tags );$tags ||= '';

$vars->{ tags } = [ $tags ];

Page 164: Simple Photo Processing and Web Display with Perl

Create a "tag cloud".

Page 165: Simple Photo Processing and Web Display with Perl

$query = qq{ select count(*) as num, tag_name from tags group by tag_name having num > $MIN_TAGS};

$sth = $dbh->prepare( $query );$sth->execute;my @tags;while( my $hashrow = $sth->fetchrow_hashref ){ push @tags, $hashrow}

$vars->{ phototags } = [ @tags ];

Page 166: Simple Photo Processing and Web Display with Perl

<table style="background: #ccc; border: 1px solid #555"><tr><th align="left">Photos filed under...</th></tr><tr><td align="center">

[% FOREACH tag = phototags -%]

<span style="font-size: [% ( tag.num + 80 ) / 8 %]px"> <a href="/photos.cgi?tagged=[% tag.tag_name %]" title="[% tag.num %] photo[% IF tag.num > 1 %]s[% END %] filed under [% tag.tag_name %]">[% tag.tag_name %]</a></span>

[% END -%]

</td></tr></table>

Highly complicated and sophisticated

formula derived by minutes and minutes

of trial and error

Page 167: Simple Photo Processing and Web Display with Perl
Page 168: Simple Photo Processing and Web Display with Perl

Jazz it up with a little AJAX

Page 169: Simple Photo Processing and Web Display with Perl
Page 170: Simple Photo Processing and Web Display with Perl

AJAX (Asynchronous JavaScript and XML), or Ajax, is a group of inter-related web development techniques used for creating interactive web applications.

A primary characteristic is the increased responsiveness and interactiveness of web pages achieved by exchanging small amounts of data with the server "behind the scenes" so that the entire web page does not have to be reloaded each time the user performs an action.

This is intended to increase the web page's interactivity, speed, functionality, and usability.

http://en.wikipedia.org/wiki/Ajax_(programming)

Page 172: Simple Photo Processing and Web Display with Perl

AJ

Page 173: Simple Photo Processing and Web Display with Perl
Page 174: Simple Photo Processing and Web Display with Perl

AJ

Page 175: Simple Photo Processing and Web Display with Perl

http://jquery.com

Page 176: Simple Photo Processing and Web Display with Perl

Load JQuery in your template

<script type = "text/javascript" src = "/script/jquery.js"></script>

Right here

Page 177: Simple Photo Processing and Web Display with Perl

Create a Javascript Function

Callback

to switch the picturesfunction swapem( pic ){ $('#caption').fadeOut( 'slow' ); $('#display').fadeOut( 'slow', function(){ getData( pic ); $('#display').html( '<img src="' + pic + '" border="0">'); $('#display').show; $('#display').fadeIn( 1500 ); });}

Page 178: Simple Photo Processing and Web Display with Perl

Callback

A callback is executable code that is passed as an argument to other code.

Because of the asynchronous nature of calls in the JQuery library, using certain code as

callbacks helps ensure specific timing for events.

Page 179: Simple Photo Processing and Web Display with Perl

Create the AJAX request

Callback

Callback

function getData( pic ){ $.ajax( { url : '/caption.cgi', type : 'POST', dataType : 'html', data : 'pic=' + pic, success : function( retVal ){ $('#caption').html( retVal ); }, complete : function(){ $('#caption').fadeIn( 'slow' ); } });}

Page 180: Simple Photo Processing and Web Display with Perl

Call the AJAX code

<td align="center" valign="bottom" class="pic"> <a href="javascript:swapem('[% pic.picture %]');"><img src ="[% pic.thumb %]" alt ="[% pic.caption %]" title ="[% pic.caption %]"/></a> <p class="timestamp">[% pic.timestamp %]</p></td>

Right here

Page 181: Simple Photo Processing and Web Display with Perl

Create a CGI to handle the AJAX call

#!/usr/bin/perl

use strict;use warnings;

use DBI;use CGI qw/:standard/;use PhotoLib;

...

Saved a lot of copying and pasting

Page 182: Simple Photo Processing and Web Display with Perl

Damian said it best:

• Place original code inline.

• Place duplicated code in a subroutine.

• Place duplicated subroutines in a module.

- Perl Best Practices, page 401

Page 183: Simple Photo Processing and Web Display with Perl

Create a CGI to handle the AJAX call...

my $pic = param('pic') || exit;# $pic = '/photos/arch/1197770265.jpg';

$pic =~ s/[^\d]+(\d+)\..*/$1/;# $pic = '1197770265';

my $caption = get_caption( $pic );$caption =~ s/''/'/g; # stoopid mysql

my @tags = get_tags( $pic );

...

Page 184: Simple Photo Processing and Web Display with Perl

Create a CGI to handle the AJAX call

...

my $out = header();$out .= qq{<span style="font-family: tahoma; };$out .= qq{"><p>$caption</p><p>More pictures: };for my $tag( @tags ){ $out .= qq{<a href="photos.cgi?tagged=$tag">$tag</a> };}$out .= "</p>";print $out;

Should I have useda template?

Page 185: Simple Photo Processing and Web Display with Perl

Please visithttp://www.kentcowgill.org/photos

for the Ajax demonstration

Page 186: Simple Photo Processing and Web Display with Perl

Then something wonderful happened

Page 187: Simple Photo Processing and Web Display with Perl

8-D

Page 188: Simple Photo Processing and Web Display with Perl
Page 189: Simple Photo Processing and Web Display with Perl

The pictures arrive at my server within

minutes.

Page 191: Simple Photo Processing and Web Display with Perl
Page 192: Simple Photo Processing and Web Display with Perl
Page 193: Simple Photo Processing and Web Display with Perl

Why?

Page 194: Simple Photo Processing and Web Display with Perl

I got a real* camera

* For some values of real.

Page 195: Simple Photo Processing and Web Display with Perl
Page 196: Simple Photo Processing and Web Display with Perl

My new camera stores images on one of these...

Page 197: Simple Photo Processing and Web Display with Perl

www.kentcowgill.org

Happens much later, all at once

Also happens in batches

Page 198: Simple Photo Processing and Web Display with Perl
Page 199: Simple Photo Processing and Web Display with Perl

www.kentcowgill.org

They would all get the same timestamp:

Nov 13, 2007: 8:15pm

Page 200: Simple Photo Processing and Web Display with Perl

What to do?

Page 201: Simple Photo Processing and Web Display with Perl

ReadTheFine

Manual

Page 202: Simple Photo Processing and Web Display with Perl
Page 203: Simple Photo Processing and Web Display with Perl
Page 204: Simple Photo Processing and Web Display with Perl

I want to keep the filename standard

Page 205: Simple Photo Processing and Web Display with Perl

I want to keep the filename standard

I've already got over 700 images and their tags in my database

Page 206: Simple Photo Processing and Web Display with Perl

2007:10:28 18:03:54

exif_date_time_original

≠1193612634

Page 207: Simple Photo Processing and Web Display with Perl

Time::Local(3) User Contributed Perl Documentation Time::Local(3)

NAME Time::Local - efficiently compute time from local and GMT time

SYNOPSIS $time = timelocal($sec,$min,$hour,$mday,$mon,$year); $time = timegm($sec,$min,$hour,$mday,$mon,$year);

DESCRIPTION These routines are the inverse of built-in perl functions localtime() and gmtime(). They accept a date as a six-element array, and return the corresponding time(2) value in seconds since the system epoch (Mid- night, January 1, 1970 GMT on Unix, for example).

Page 208: Simple Photo Processing and Web Display with Perl

my $filebase = 'tempfilename';my $archive_image = qq($arch_dir/${filebase}.jpg);# ...my $date_time = $src->tags( name => 'exif_date_time_original');

my( $y, $mo, $d, $h, $m, $s ) = ( split /(?::| |T|-)/, $date_time )[ 0 .. 5 ];$y -= 1900;$mo -= 1;

Page 209: Simple Photo Processing and Web Display with Perl

my $filebase = 'tempfilename';my $archive_image = qq($arch_dir/${filebase}.jpg);# ...my $date_time = $src->tags( name => 'exif_date_time_original');

my( $y, $mo, $d, $h, $m, $s ) = ( split /(?::| |T|-)/, $date_time )[ 0 .. 5 ];$y -= 1900;$mo -= 1;

Page 210: Simple Photo Processing and Web Display with Perl

my $filebase = 'tempfilename';my $archive_image = qq($arch_dir/${filebase}.jpg);# ...my $date_time = $src->tags( name => 'exif_date_time_original');

my $new_filename = timelocal( $s, $m, $h, $d, $mo, $y );my $new_image = qq($arch_dir/${new_filename}.jpg);

rename $archive_image, $new_image;

my( $y, $mo, $d, $h, $m, $s ) = ( split /(?::| |T|-)/, $date_time )[ 0 .. 5 ];$y -= 1900;$mo -= 1;

Page 211: Simple Photo Processing and Web Display with Perl

my $filebase = 'tempfilename';my $archive_image = qq($arch_dir/${filebase}.jpg);# ...my $date_time = $src->tags( name => 'exif_date_time_original');

my $new_filename = timelocal( $s, $m, $h, $d, $mo, $y );my $new_image = qq($arch_dir/${new_filename}.jpg);

rename $archive_image, $new_image;

my( $y, $mo, $d, $h, $m, $s ) = ( split /(?::| |T|-)/, $date_time )[ 0 .. 5 ];$y -= 1900;$mo -= 1;

Page 212: Simple Photo Processing and Web Display with Perl

2007:10:28 18:03:54

exif_date_time_original

Page 213: Simple Photo Processing and Web Display with Perl

2007:10:28 18:03:54

exif_date_time_original

2007-10-28T18:03:54

Page 214: Simple Photo Processing and Web Display with Perl

=)

Page 215: Simple Photo Processing and Web Display with Perl

7.2 MEGA PIXELS

3,072px x 2,304px

Page 216: Simple Photo Processing and Web Display with Perl

3,072x 2,30412,288

2

921,600

1

+ 6,144,0007,077,888

1

pixelspixels

pixels

Page 217: Simple Photo Processing and Web Display with Perl

7,077,888x 1642,467,328

45544

+ 70,778,880113,246,208

pixelsbits per pixel

bits

Page 218: Simple Photo Processing and Web Display with Perl

113,246,208 bits14,155,776 bytes

13,824 kilobytes13.5 megabytes

Page 219: Simple Photo Processing and Web Display with Perl

TOO

Page 220: Simple Photo Processing and Web Display with Perl

BIG

Page 221: Simple Photo Processing and Web Display with Perl

Wouldn't it be great if I could get these 7 MP images automatically scaled to 640x480?

Page 222: Simple Photo Processing and Web Display with Perl
Page 223: Simple Photo Processing and Web Display with Perl

[Kent-Cowgills-Computer ~]$ locate Constrain

/Applications/Adobe ImageReady CS/Samples/Droplets/ImageReady Droplets/Constrain 350, Make JPG 30.exe

/Applications/Adobe ImageReady CS/Samples/Droplets/ImageReady Droplets/Constrain to 200x200 pixels.exe

/Applications/Adobe ImageReady CS/Samples/Droplets/ImageReady Droplets/Constrain to 64X64 pixels.exe

/Applications/Adobe ImageReady CS/Samples/Droplets/Photoshop Droplets/Constrain to 300 pixels.exe

Page 224: Simple Photo Processing and Web Display with Perl

Now for a tutorial on creating contextual menu droplets in...

Adobe ImageReady™

Page 225: Simple Photo Processing and Web Display with Perl

Just kidding.

Page 226: Simple Photo Processing and Web Display with Perl
Page 227: Simple Photo Processing and Web Display with Perl

But that's not Perl.

Page 228: Simple Photo Processing and Web Display with Perl

No Perl ≠ Fun

Page 229: Simple Photo Processing and Web Display with Perl

Perl === Fun

(wait - that's PHP)

Page 230: Simple Photo Processing and Web Display with Perl

Perl == Fun

Page 231: Simple Photo Processing and Web Display with Perl
Page 232: Simple Photo Processing and Web Display with Perl

Use Imager.pm to scale images to 640x480

Page 233: Simple Photo Processing and Web Display with Perl
Page 234: Simple Photo Processing and Web Display with Perl
Page 235: Simple Photo Processing and Web Display with Perl

my $src = Imager->new;$src->read( file => $archive_image, type => 'jpeg' );

my $newimg = $src->scale( xpixels => 640, ypixels => 480, type => 'min', qtype => 'mixing',);

$newimg->write( file => $new_name, type => 'jpeg', jpegquality => 85,);

Page 236: Simple Photo Processing and Web Display with Perl

What about when you rotate the camera?

Page 237: Simple Photo Processing and Web Display with Perl
Page 238: Simple Photo Processing and Web Display with Perl
Page 239: Simple Photo Processing and Web Display with Perl

Value 0th Row 0th Column1 top left side2 top right side3 bottom right side4 bottom left side5 left side top6 right side top7 right side bottom8 left side bottom

Exif Orientation Tag Values

Page 240: Simple Photo Processing and Web Display with Perl
Page 241: Simple Photo Processing and Web Display with Perl
Page 242: Simple Photo Processing and Web Display with Perl
Page 243: Simple Photo Processing and Web Display with Perl

From: http://sylvana.net/jpegcrop/exif_orientation.html

Here is what the letter F would look like if it were displayed by a program that

ignores the orientation tag:

1 2 3 4 888888 888888 88 88 88 88 88 88 8888 8888 8888 8888 88 88 88 8888 88 888888 888888

5 6 7 88888888888 88 88 888888888888 88 88 88 88 88 88 8888 8888888888 8888888888 88

Page 244: Simple Photo Processing and Web Display with Perl

8 8

8888

8888

8

8

8 8

8

8

8

Page 245: Simple Photo Processing and Web Display with Perl

8 8888888888 88 88 88

Page 246: Simple Photo Processing and Web Display with Perl

8

88888

8888

8 8

8 8

8

8

8

Page 247: Simple Photo Processing and Web Display with Perl

8 8888888888 88 88 88

Page 248: Simple Photo Processing and Web Display with Perl

my $src = Imager->new;$src->read( file => $archive_image, type => 'jpeg' );

my $orientation_tag = $src->tags( name => 'exif_orientation' );

my %degrees_for = ( 6 => 90, 8 => -90 );

my $newimg;if( exists $degrees_for{ $orientation_tag } ){ $src = $src->rotate( degrees => $degrees_for{ $orientation_tag } );}

Page 249: Simple Photo Processing and Web Display with Perl
Page 250: Simple Photo Processing and Web Display with Perl
Page 251: Simple Photo Processing and Web Display with Perl
Page 252: Simple Photo Processing and Web Display with Perl

Wouldn't it be great if I could get these scaled

photos automatically to my server?

Page 253: Simple Photo Processing and Web Display with Perl

Poker?

Page 254: Simple Photo Processing and Web Display with Perl
Page 255: Simple Photo Processing and Web Display with Perl

AWL MUH MUNNI ... DA POT HAZ IT

Page 256: Simple Photo Processing and Web Display with Perl

I've invested all that time with my image stripper for emails.

Page 257: Simple Photo Processing and Web Display with Perl

Plan A:

Automator

Page 258: Simple Photo Processing and Web Display with Perl
Page 259: Simple Photo Processing and Web Display with Perl

What's the problem?

Page 260: Simple Photo Processing and Web Display with Perl

1) Wasn't working right.

Page 261: Simple Photo Processing and Web Display with Perl

2) Wasn't Doing What I Mean (DWIM).

Page 262: Simple Photo Processing and Web Display with Perl

3) Wasn't Perl.

Page 263: Simple Photo Processing and Web Display with Perl

Automator ≠ Fun

Page 264: Simple Photo Processing and Web Display with Perl
Page 265: Simple Photo Processing and Web Display with Perl

Plan B:

AppleScript

Page 266: Simple Photo Processing and Web Display with Perl
Page 267: Simple Photo Processing and Web Display with Perl

WTF?

Page 268: Simple Photo Processing and Web Display with Perl

What's the problem?

Page 269: Simple Photo Processing and Web Display with Perl

1) Tell who what now?

Page 270: Simple Photo Processing and Web Display with Perl

2) Repeat what with which in the where?

Page 271: Simple Photo Processing and Web Display with Perl

3) Dear God why can't I find an example.

Page 272: Simple Photo Processing and Web Display with Perl

4) Wasn't Perl.

Page 273: Simple Photo Processing and Web Display with Perl

AppleScript ≠ Fun

Page 274: Simple Photo Processing and Web Display with Perl
Page 275: Simple Photo Processing and Web Display with Perl

Plan C:

AppleScript

From Perl

Page 276: Simple Photo Processing and Web Display with Perl

Yes! Perl!

Page 277: Simple Photo Processing and Web Display with Perl

Perl == Fun!

Page 278: Simple Photo Processing and Web Display with Perl

use Mac::AppleScript qw(RunAppleScript);...sub send_email { my $scr; my $msg = shift; DEBUG "Attempting to send email"; ($scr = <<" EOS") =~ s/^\s+//gm; set fromAcct to "$FROM_ACCOUNT" set toAcct to "$TO_ACCOUNT" tell application "Mail" repeat with acc in accounts if display name of acc is fromAcct then connect acc repeat with ctc in contacts of acc if display name of ctc is toAcct then send ctc message "$msg" on account acc end if end repeat disconnect acc end if end repeat end tell EOS RunAppleScript($scr) or DEBUG "couldn't run applescript";}

Page 279: Simple Photo Processing and Web Display with Perl

What's the problem?

Page 280: Simple Photo Processing and Web Display with Perl

1) I'm sorry, AppleScriptis just a pain.

Page 281: Simple Photo Processing and Web Display with Perl

2) It's just a hunk of AppleScript crammed

into Perl.

Page 282: Simple Photo Processing and Web Display with Perl

3) So basically,it wasn't Perl.

Page 283: Simple Photo Processing and Web Display with Perl

AppleScript, even when used from within Perl

≠Fun

Page 284: Simple Photo Processing and Web Display with Perl

Are you thinkingwhat I'm thinking?

Page 285: Simple Photo Processing and Web Display with Perl

Too bad I didn'tthink of it earlier.

( I really didn't! =:-o )

Page 286: Simple Photo Processing and Web Display with Perl

Plan D:

MIME::LiteIt's

Perl!

Page 287: Simple Photo Processing and Web Display with Perl

opendir my $indir, $picdir or die "Can't open directory - $!";

send_img( $_ ) for grep { ! /^\./ } readdir $indir;

sub send_img { my $image = shift; my $file = "$picdir/$image"; my $msg = MIME::Lite->new( From => '[email protected]', To => '[email protected]', Subject => 'Here is my image', Type => 'multipart/mixed' );

$msg->attach( Type => 'image/jpeg', Encoding => 'base64', Path => $file, Filename => $image, Disposition => 'attachment' );

$msg->send( 'smtp', 'localhost:2025' ); my $new_loc = $file; $new_loc =~ s/send/sent/; rename $file, $new_loc;}

Use your own SMTP server, not the SSH tunnel

on my computer :)

Page 288: Simple Photo Processing and Web Display with Perl

Perl == Fun!

Page 289: Simple Photo Processing and Web Display with Perl
Page 290: Simple Photo Processing and Web Display with Perl

:-D

Page 291: Simple Photo Processing and Web Display with Perl

But now there'sa new problem...

Page 292: Simple Photo Processing and Web Display with Perl

WTF?

Page 293: Simple Photo Processing and Web Display with Perl

8-[

Page 294: Simple Photo Processing and Web Display with Perl

The problem:

No image (exif) tags

Page 295: Simple Photo Processing and Web Display with Perl

In the process of creating the scaled image, Imager didn't keep the exif tags.

Page 296: Simple Photo Processing and Web Display with Perl

It's a known limitation.

Page 297: Simple Photo Processing and Web Display with Perl

Some might call it a design decision.

Page 298: Simple Photo Processing and Web Display with Perl

I've invested all that time with my image stripper for emails.

Page 299: Simple Photo Processing and Web Display with Perl

(sound familiar?)

Page 300: Simple Photo Processing and Web Display with Perl

Tony Cook suggests:

Image::ExifTool

Page 301: Simple Photo Processing and Web Display with Perl
Page 302: Simple Photo Processing and Web Display with Perl
Page 303: Simple Photo Processing and Web Display with Perl
Page 304: Simple Photo Processing and Web Display with Perl

use strict;use warnings;use Imager;use Image::ExifTool;

my $src = Imager->new;$src->read( file => $file );

my $exif = new Image::ExifTool;

my $info = $exif->SetNewValuesFromFile( $file );

$exif->SetNewValue( 'orientation' => 1, Type => 'ValueConv');...

$exif->WriteInfo( $new_file );

Page 305: Simple Photo Processing and Web Display with Perl

"So, that's great and all.

But I use flickr."

Page 306: Simple Photo Processing and Web Display with Perl
Page 307: Simple Photo Processing and Web Display with Perl
Page 308: Simple Photo Processing and Web Display with Perl

Need I say more?

Page 309: Simple Photo Processing and Web Display with Perl

=o]

Page 310: Simple Photo Processing and Web Display with Perl

So, in review, the process is...

Page 311: Simple Photo Processing and Web Display with Perl

Take the picture

Page 312: Simple Photo Processing and Web Display with Perl

Get the picture to the computer

Page 313: Simple Photo Processing and Web Display with Perl

Reorient and scale

Page 314: Simple Photo Processing and Web Display with Perl

Send it

Page 315: Simple Photo Processing and Web Display with Perl

Through the internet

www.kentcowgill.org

Page 316: Simple Photo Processing and Web Display with Perl

my $email = Email::MIME->new( $msg_text );

my $stripper = Email::MIME::Attachment::Stripper->new( $email );

my @files = $stripper->attachments;

@files = grep { $_->{content_type} eq 'image/jpeg'} @files;

my $image_data = @files ? $files[0]->{payload} : decode_base64( $email->{parts}[0]->{body} );

Strip it from the email

Page 317: Simple Photo Processing and Web Display with Perl

my $src = Imager->new;

$src->read( file => $archive_image, type => 'jpeg' );

my $tmbimg = $src->copy();

my $thumb = $tmbimg->scale( xpixels => 64, ypixels => 48, type => 'min');

$thumb->write( file => $archive_thumb );

Make a thumbnail

Page 318: Simple Photo Processing and Web Display with Perl

my $curimg = $newimg->scale( xpixels => 320, ypixels => 240, type => 'min',);

my $gryimg = $curimg->convert( preset => 'grey' );$gryimg->write( file => $current_image );

Make a greyscale image

Page 319: Simple Photo Processing and Web Display with Perl

my $dbh = Mysql->connect( 'localhost', 'photoblog', $username, $password,);

my $query = qq{ update captions set caption_text='$caption' where caption_photo='$picture'};

my $sth = $dbh->query( $query );

Add a caption

Page 320: Simple Photo Processing and Web Display with Perl

Add tags

my $tags = param( 'tags' );my @tags = split( /(?:\s+|,)/, $tags );

for my $tag( @tags ){ my $ins = qq{ insert into tags( tag_photo, tag_name ) values( '$picture', '$tag' )";}; $sth = $dbh->query( $ins );}

Page 321: Simple Photo Processing and Web Display with Perl

Fetch the tags

Page 322: Simple Photo Processing and Web Display with Perl

Display the thumbnails

Page 323: Simple Photo Processing and Web Display with Perl

Show the picture

Page 324: Simple Photo Processing and Web Display with Perl

And that's it.

Page 325: Simple Photo Processing and Web Display with Perl

Thank you.

Page 326: Simple Photo Processing and Web Display with Perl

Any questions?

Page 327: Simple Photo Processing and Web Display with Perl

References•Chuck Norris' Action Jeans:http://www.denimology.co.uk/2006/09/chuck_norris_action_jeans.php

•AJAX on Wikipedia:http://en.wikipedia.org/wiki/Ajax_(programming)

•JQuery:http://jquery.com/

•Great "visual" jquery documentation:http://visualjquery.com/

•Exif Orientation information:http://sylvana.net/jpegcrop/exif_orientation.html

•My photo gallery:http://www.kentcowgill.org/photos

•My Flickr page:http://flickr.com/photos/kcowgill