Mail Index


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ApacheGallery] some contributions



Hi,

I've been using Apache::Gallery for a couple of weeks now and am very happy
with the results, thanks for producing this excellent software :-)

I've made some local changes along the way, so I thought I would give back.

1/ I've added a PerlSetVar GallerySortBy config option:

   Instead of the default filename ordering it allows you to optionally sort
   by any stat attribute. i.e. mtime or size.

   This is usefull if you don't stick to naming you files "img_XXXX.jpg"
   but still want some meaningfull ordering.

2/ I've added a PerlSetVar GalleryAutoRotate config option:

   I've found that when I grab images directly from the compact flash card
   my Canon IXUS v3 write to the images are not rotated at all, but contains
   an EXIF flag detailing the orientation used when capturing the image.

   I'm not a big fan of manually tagging all the rotation information, so
   I've added a tag which lets the module auto-build it's own .rotate 
   file based on the EXIF information.

   Of course this requires that the webserver have the ability to write to
   the file as needed, which is a bit poor.

3/ I've added a PerlSetVar GalleryMaintainThumbnailAspectRatio config option:

   When my girlfriend retrieves images from the DSC via her Windows computer
   it seems to automatically rotates the picture as required, and (sometimes)
   clears the Orientation flag. This results in thumbnails which are of
   different dimensions for those images, and breaks the alignment in the
   directory listing.

   On the other hand, when I use .rotate files it stretches the image
   horribly when making the thumbnail.

   This option maintains the aspect ratio on the stretched picture in the
   thumbnail only and fills in black bars where needed.

4/ I've added .wmv to "movie" suffix list -- windows media uses this.

5/ I've modified the module so that it passes thumbnail width and heights
   to picture.tpl where I've added:

      width="$WIDTH" height="$HEIGHT"

   This give hints on the dimensions of the thumbnails to the web browser
   and lets it allocate the image space before downloading which works
   better for me in Mozilla/Galeon.

6/ I've removed some unnecessary stat calls (minor)

I've made sure that all of the PerlSetVar options do not have a negative
performance impact if you choose not to use them, so they should be safe
to apply.

I didn't go so far as putting any of this information into perldoc ..

Regards,
--Iain
--- ./usr/lib/perl5/site_perl/5.6.1/Apache/Gallery.pm	Thu Oct 24 22:41:54 2002
+++ /usr/lib/perl5/site_perl/5.6.1/Apache/Gallery.pm	Thu Feb 20 16:54:55 2003
@@ -124,7 +124,12 @@
 	
 		# Read, sort, and filter files
 		my @files = grep { !/^\./ && -f "$filename/$_" } readdir (DIR);
-		@files = sort @files;
+
+		if (my $sortby = $r->dir_config('GallerySortBy')) {
+			@files = map(/^\d+ (.*)/, sort map(stat("$filename/$_")->$sortby." $_", @files));
+		} else {
+			@files = sort @files;
+		}
 
 		my @movies;
 
@@ -135,7 +140,7 @@
 
 				my $file = $topdir."/".$picture;
 
-				if ($file =~ m/\.(mpe?g|mov|avi|asf)$/i) {
+				if ($file =~ m/\.(mpe?g|mov|avi|wmv|asf)$/i) {
 					push (@movies, $picture);
 				}
 
@@ -179,7 +184,7 @@
 					$tpl->parse(FILES => '.directory');
 
 				}
-				elsif (-f $thumbfilename && $thumbfilename =~ m/\.(mpe?g|avi|mov|asf)$/i) {
+				elsif (-f $thumbfilename && $thumbfilename =~ m/\.(mpe?g|avi|mov|wmv|asf)$/i) {
 					my $type = lc($1);
 					my $stat = stat($thumbfilename);
 					my $size = $stat->size;
@@ -200,13 +205,15 @@
 
 					next unless (grep $type eq $_, @filetypes);
 					my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $width, $height);	
-					my $cached = scale_picture($r, $thumbfilename, $thumbnailwidth, $thumbnailheight);
+					my $cached = scale_picture($r, $thumbfilename, $thumbnailwidth, $thumbnailheight, 1);
 
 					my $imageinfo = get_imageinfo($r, $thumbfilename, $type, $width, $height);
 
 					$tpl->assign(FILEURL => uri_escape($fileurl, $escape_rule));
 					$tpl->assign(FILE    => $file);
 					$tpl->assign(DATE    => $imageinfo->{DateTimeOriginal} ? $imageinfo->{DateTimeOriginal} : ''); # should this really be a stat of the file instead of ''?
+					$tpl->assign(WIDTH   => $thumbnailwidth);
+					$tpl->assign(HEIGHT  => $thumbnailheight);
 					$tpl->assign(SRC     => uri_escape($uri."/.cache/$cached", $escape_rule));
 
 					$tpl->parse(FILES => '.picture');
@@ -327,7 +334,12 @@
 		}
 		my @pictures = grep { /^[^.].*\.(jpe?g|png|ppm|tiff?)$/i } readdir (DATADIR);
 		closedir(DATADIR);
-		@pictures = sort @pictures;
+
+		if (my $sortby = $r->dir_config('GallerySortBy')) {
+			@pictures = map(/^\d+ (.*)/, sort map(stat("$path/$_")->$sortby." $_", @pictures));
+		} else {
+			@pictures = sort @pictures;
+		}
 
 		$tpl->assign(TOTAL => scalar @pictures);
 
@@ -349,7 +361,7 @@
 				if ($prevpicture and $displayprev) {
 					my ($orig_width, $orig_height, $type) = imgsize($path.$prevpicture);
 					my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $orig_width, $orig_height);	
-					my $cached = scale_picture($r, $path.$prevpicture, $thumbnailwidth, $thumbnailheight);
+					my $cached = scale_picture($r, $path.$prevpicture, $thumbnailwidth, $thumbnailheight, 1);
 					$tpl->assign(URL       => uri_escape($prevpicture, $escape_rule));
 					$tpl->assign(FILENAME  => $prevpicture);
 					$tpl->assign(WIDTH     => $width);
@@ -369,7 +381,7 @@
 				if ($nextpicture) {
 					my ($orig_width, $orig_height, $type) = imgsize($path.$nextpicture);
 					my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $orig_width, $orig_height);	
-					my $cached = scale_picture($r, $path.$nextpicture, $thumbnailwidth, $thumbnailheight);
+					my $cached = scale_picture($r, $path.$nextpicture, $thumbnailwidth, $thumbnailheight, 1);
 					$tpl->assign(URL       => uri_escape($nextpicture, $escape_rule));
 					$tpl->assign(FILENAME  => $nextpicture);
 					$tpl->assign(WIDTH     => $width);
@@ -542,8 +554,7 @@
 }
 
 sub scale_picture {
-
-	my ($r, $fullpath, $width, $height) = @_;
+	my ($r, $fullpath, $width, $height, $thumbnail) = @_;
 
 	my @dirs = split(/\//, $fullpath);
 	my $filename = pop(@dirs);
@@ -569,48 +580,71 @@
 		$newfilename = $width."x".$height."-".$filename;
 	}
 	
-	if (-f $cache."/".$newfilename) {	
+	my $filestat = stat($fullpath);
+	my $rotatestat = stat($fullpath.".rotate");
+
+	# Auto-build .rotate file if exif info available (and user requested).
+	my %orient_map = (
+		top_left  => 0,
+		right_top => 1,
+		bot_right => 2,
+		left_bot  => 3,
+	);
+
+	if ($r->dir_config('GalleryAutoRotate')) {
+		my $imageinfo = get_imageinfo($r, $fullpath, $type, $orig_width, $orig_height);
+
+		if ($orient_map{$imageinfo->{Orientation}} and (!$rotatestat or $rotatestat->mtime < $filestat->mtime)) {
+			open(OUT, ">$fullpath.rotate");
+			print OUT $orient_map{ $imageinfo->{Orientation} }."\n";
+			close(OUT);
+
+			$rotatestat = stat($fullpath . ".rotate");
+		}
+	}
+
+	if (my $cachestat = stat($cache."/".$newfilename) and -f _) {	
 		$scale = 0;
 
 		# Check to see if the image has changed
-		my $filestat = stat($fullpath);
-		my $cachestat = stat($cache."/".$newfilename);
 		if ($filestat->mtime > $cachestat->mtime) {
 			$scale = 1;
 		}	
 
 		# Check to see if the .rotate file has been added or changed
-		if (-f $fullpath . ".rotate") {
-			my $rotatestat = stat($fullpath . ".rotate");
-			if ($rotatestat->mtime > $cachestat->mtime) {
-				$scale = 1;
-			}	
+		if ($rotatestat and $rotatestat->mtime > $cachestat->mtime) {
+			$scale = 1;
 		}		
+
 		# Check to see if the copyrightimage has been added or changed
-		if ($r->dir_config('GalleryCopyrightImage') && -f $r->dir_config('GalleryCopyrightImage')) {
+		if ($r->dir_config('GalleryCopyrightImage') and my $copyrightstat = stat($r->dir_config('GalleryCopyrightImage')) and -f _) {
 			unless ($width == $thumbnailwidth or $width == $thumbnailheight) {
-				my $copyrightstat = stat($r->dir_config('GalleryCopyrightImage'));
 				if ($copyrightstat->mtime > $cachestat->mtime) {
 					$scale = 1;
 				}	
 			}
 		}	
-
 	}	
 
 	if ($scale) {
-
 		my $newpath = $cache."/".$newfilename;
-		my $rotate = 0;
 
-		if (-f $fullpath . ".rotate") {
-		    $rotate = readfile_getnum($fullpath . ".rotate");
+		my $rotate = readfile_getnum($fullpath . ".rotate");
+		my $rotate_src = 0;
+		my $rotate_dst = 0;
+		my $aspect = 0;
+
+		if ($thumbnail) {
+			$rotate_src = $rotate;
+			$aspect = $r->dir_config('GalleryMaintainThumbnailAspectRatio') || 0;
+		} else {
+			$rotate_dst = $rotate;
 		}
 
 		if ($width == $thumbnailwidth or $width == $thumbnailheight) {
-		    resizepicture($fullpath, $newpath, $width, $height, $rotate, '');
+		    resizepicture($fullpath, $newpath, $width, $height, $rotate_src, $rotate_dst, $aspect, '');
 		} else {
-		    resizepicture($fullpath, $newpath, $width, $height, $rotate, ($r->dir_config('GalleryCopyrightImage') ? $r->dir_config('GalleryCopyrightImage') : ''));
+		    resizepicture($fullpath, $newpath, $width, $height, $rotate_src, $rotate_dst, $aspect, ($r->dir_config('GalleryCopyrightImage') ? $r->dir_config('GalleryCopyrightImage') : ''));
 		}
 	}
 
@@ -648,7 +682,7 @@
 		my $tmpfilename = $file;
 		# We have a problem with Windows based file extensions here as they are often .THM
 		$tmpfilename =~ s/\.(\w+)$/.thm/;
-		if (-e $tmpfilename && -f $tmpfilename && -r $tmpfilename) {
+		if (-e $tmpfilename && -f _ && -r _) {
 			$imageinfo = image_info($tmpfilename);
 		}
 	} elsif (grep $type eq $_, qw(JPG)) {
@@ -807,7 +841,7 @@
 	}
 
 	if ($r->uri eq '/') {
-		return qq{ <a href="/">root:</a> };
+		return qq{ <a href="/">home:</a> };
 	}
 
 	my $menu;
@@ -817,14 +851,14 @@
 		$menuurl .= $link."/";
 		my $linktext = $link;
 		unless ($link) {
-			$linktext = "root: ";
+			$linktext = "home: ";
 		}
 
 		$menu .= "<a href=\"".uri_escape($menuurl, $escape_rule)."\">$linktext</a> / ";
 
 	}
 
-	if (-f $filename) {
+	if ($picturename) {
 		$menu .= $picturename;
 	}
 
@@ -840,35 +874,65 @@
 #include <Imlib2.h>
 #include <stdio.h>
 #include <string.h>
+#include <math.h>
 
-int resizepicture(char* infile, char* outfile, int x, int y, int rotate, char* copyrightfile) {
+int resizepicture(char* infile, char* outfile, int x, int y, int rotate_src, int rotate_dst, int aspect, char* copyrightfile) {
 
 	Imlib_Image image;
 	Imlib_Image buffer;
 	Imlib_Image logo;
+	double fx, fy;
 	int logo_x, logo_y;
-	int old_x;
-	int old_y;
+	int new_x, old_x, off_x = 0;
+	int new_y, old_y, off_y = 0;
 
 	image = imlib_load_image(infile);
 
+	if (rotate_src != 0) {
+		imlib_context_set_image(image);
+		imlib_image_orientate(rotate_src);
+	}
+
 	imlib_context_set_image(image);
 	imlib_context_set_blend(1);
 	imlib_context_set_anti_alias(1);
 	
+	new_x = x;
+	new_y = y;
+
 	old_x = imlib_image_get_width();
 	old_y = imlib_image_get_height();
-
-	buffer = imlib_create_image(x,y);
-	imlib_context_set_image(buffer);
 	
-	imlib_blend_image_onto_image(image, 0, 0, 0, old_x, old_y, 0, 0, x, y);
+	buffer = imlib_create_image(new_x, new_y);
+
+	fx = (double)new_x/old_x;
+	fy = (double)new_y/old_y;
+
+	if (aspect) {
+		imlib_context_set_image(buffer);
+		imlib_context_set_color(0, 0, 0, 255);
+		imlib_image_fill_rectangle(0, 0, new_x, new_y);
+
+		if (fx > fy) {
+			fx = fy;
+			new_x = ceil(old_x*fx);
+		} else {
+			fy = fx;
+			new_y = ceil(old_y*fy);
+		}
+
+		off_x = floor((x - new_x)/2);
+		off_y = floor((y - new_y)/2);
+	}
 
 	imlib_context_set_image(buffer);
-	
-	if (rotate != 0) {
-	    imlib_image_orientate(rotate);
+	imlib_blend_image_onto_image(image, 0, 0, 0, old_x, old_y, off_x, off_y, new_x, new_y);
+
+	if (rotate_dst != 0) {
+		imlib_context_set_image(buffer);
+		imlib_image_orientate(rotate_dst);
 	}
+
 	if (strcmp(copyrightfile, "") != 0) {
 	    logo = imlib_load_image(copyrightfile);