Mail Index


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

Re: [ApacheGallery] Patch to replace inline C code with native Perl



On Wed, Mar 12, 2003 at 09:00:58PM -0800, Jon McClintock wrote:
> This is a good point. I tried it out just now: on a directory with 117 
> 1600x1200 images, the load spiked up to 4.25. It only took a couple of
> minutes to produce the thumbnails for the whole directory, though. And, 
> the client didn't time out while loading the page (in the current
> version, the client times out several times while waiting for the HTML
> to unblock on the resize).
> 
> Keep in mind, you'll only experience that load while it populates the
> cache.
> 
> I'll test it a little more and send a patch out.

Ok, as promised, here is an updated version of my patch. In addition to
my previous changes, it modifies Apache::Gallery to not resize the
images until the image fetch. To appease those who objected, I added 
a configuration variable "GalleryResizeOnPageFetch". If it's set, the
original behavior is retained, and images are resized when the index
page is generated. If it's not set, images aren't resized until they are
requested specifically.

-Jon
diff -Nur Apache-Gallery-0.5.1/INSTALL apache-gallery/INSTALL
--- Apache-Gallery-0.5.1/INSTALL	Fri Nov  8 02:56:43 2002
+++ apache-gallery/INSTALL	Sat Mar 22 09:03:49 2003
@@ -1,7 +1,7 @@
 Apache/Gallery version 0.5
 ===========================
 
-$Id: INSTALL,v 1.4 2002/06/06 19:41:30 mil Exp $
+$Id: INSTALL,v 1.2 2003/03/22 17:03:49 jammer Exp $
 
 INSTALLATION
 
@@ -14,16 +14,9 @@
 - URI::Escape
 - Image::Info
 - Image::Size
+- Image::Magick
 - CGI::FastTemplate
-- Inline::C
 - X11 libraries (ie, XFree86)
-- Imlib2 (http://prdownloads.sourceforge.net/enlightenment/imlib2-1.0.3.tar.gz)
-
-When installing Imlib2 from rpm, deb or other packages formats, remember
-that you need the imlib2-dev package too. On Debian this can be installed
-with:
-
-apt-get install libimlib2-dev
 
 Then, to install Apache::Gallery run the following commands:
 
@@ -53,10 +46,6 @@
 Copy the files from templates/ to where you pointed GalleryTemplateDir to,
 copy htdocs/folder.png and htdocs/video-*.png to your Apache icons 
 directory and copy htdocs/gallery.css to the DocumentRoot of your gallery.
-
-Make sure your httpd can write to the temporary directory (usually /tmp).
-This will be used by the Inline module to compile the c-code used to
-access functions in Imlib2.
 
 It is possible to include a graphical copyright notice on each picture now.
 By setting the GalleryCopyrightImage PerlSetVar you can define the path
diff -Nur Apache-Gallery-0.5.1/Makefile.PL apache-gallery/Makefile.PL
--- Apache-Gallery-0.5.1/Makefile.PL	Fri Sep 20 01:42:51 2002
+++ apache-gallery/Makefile.PL	Sat Mar 22 09:03:49 2003
@@ -1,5 +1,5 @@
 use ExtUtils::MakeMaker;
-# $Id: Makefile.PL,v 1.7 2002/02/09 06:32:03 thomas Exp $
+# $Id: Makefile.PL,v 1.2 2003/03/22 17:03:49 jammer Exp $
 # See lib/ExtUtils/MakeMaker.pm for details of how to influence
 # the contents of the Makefile that is written.
 WriteMakefile(
@@ -8,8 +8,8 @@
     'PREREQ_PM'		=> { 
  				Image::Info  => 0,
 				Image::Size => 0,
+				Image::Magick => 0,
 				CGI::FastTemplate => 0, 
-				Inline => 0, 
 				mod_perl => 0,
 				URI::Escape => 0,
 				Apache::Request => 0,
diff -Nur Apache-Gallery-0.5.1/README apache-gallery/README
--- Apache-Gallery-0.5.1/README	Tue Oct 22 13:42:08 2002
+++ apache-gallery/README	Sat Mar 22 10:43:12 2003
@@ -80,6 +80,21 @@
 
         Set to 1 or 0, default is 0
 
+    GalleryResizeOnPageFetch
+        Resize the images when generating the HTML for a page,
+	instead of waiting until the browser requests the
+	individual images. Setting this has both advantages
+	and disadvantages.
+
+	On the plus side, your server's load will be limited,
+	because at most one image resize operation will take
+	place at any one time, per client. On the minus side,
+	since the page will not be returned until all of the
+	images have been resized, the client browser may time
+	out with an error on directories with many images.
+
+	Set to 1 or 0, default is 0
+
     GallerySlideshowIntervals
         With this option you can configure which intervals can be selected
         for a slideshow. The default is '3 5 10 15 30'
@@ -120,8 +135,8 @@
     URI::Escape
     Image::Info
     Image::Size
+    Image::Magick
     CGI::FastTemplate
-    Inline::C
     X11 libraries (ie, XFree86)
     Imlib2 Remember the -dev package when using rpm, deb or other package
     formats!
diff -Nur Apache-Gallery-0.5.1/lib/Apache/Gallery.pm apache-gallery/lib/Apache/Gallery.pm
--- Apache-Gallery-0.5.1/lib/Apache/Gallery.pm	Wed Mar 12 19:48:00 2003
+++ apache-gallery/lib/Apache/Gallery.pm	Sat Mar 22 10:43:43 2003
@@ -1,7 +1,7 @@
 package Apache::Gallery;
 
-# $Author: mil $ $Rev: 88 $
-# $Date: 2002-10-24 14:41:49 +0200 (Thu, 24 Oct 2002) $
+# $Author: jammer $ $Rev: 88 $
+# $Date: 2003/03/22 18:43:43 $
 
 use strict;
 
@@ -15,6 +15,7 @@
 
 use Image::Info qw(image_info);
 use Image::Size qw(imgsize);
+use Image::Magick;
 use CGI::FastTemplate;
 use File::stat;
 use File::Spec;
@@ -24,20 +25,12 @@
 # Regexp for escaping URI's
 my $escape_rule = "^A-Za-z0-9\-_.!~*'()\/";
 
-use Inline C => Config => 
-				LIBS => '-L/usr/X11R6/lib -lImlib2 -lm -ldl -lXext -lXext',
-				DIRECTORY => File::Spec->tmpdir(),
-				INC => '-I/usr/X11R6/include';
-
-use Inline 'C';
-Inline->init;
-
 sub handler {
 
 	my $r = shift or Apache->request();
 
 	$r->header_out("X-Powered-By","apachegallery.dk $VERSION - Hest design!");
-	$r->header_out("X-Gallery-Version", '$Rev: 88 $ $Date: 2002-10-24 14:41:49 +0200 (Thu, 24 Oct 2002) $');
+	$r->header_out("X-Gallery-Version", '$Rev: 88 $ $Date: 2003/03/22 18:43:43 $');
 
 	# Just return the http headers if the client requested that
 	if ($r->header_only) {
@@ -53,6 +46,9 @@
 		my $cached = cache_dir($r, 0);
 
 		$cached =~ s/\/\.cache//;
+		
+		update_cache_entry($r, $cached);
+		    
 		unless (open(FILE, "$cached")) {
 			$r->log_error("Error opening $cached: $!\n");
 			return SERVER_ERROR;
@@ -200,7 +196,7 @@
 
 					next unless (grep $type eq $_, @filetypes);
 					my ($thumbnailwidth, $thumbnailheight) = get_thumbnailsize($r, $width, $height);	
-					my $cached = scale_picture($r, $thumbfilename, $thumbnailwidth, $thumbnailheight);
+					my $cached = get_cache_filename($r, $thumbfilename, $thumbnailwidth, $thumbnailheight);
 
 					my $imageinfo = get_imageinfo($r, $thumbfilename, $type, $width, $height);
 
@@ -208,6 +204,8 @@
 					$tpl->assign(FILE    => $file);
 					$tpl->assign(DATE    => $imageinfo->{DateTimeOriginal} ? $imageinfo->{DateTimeOriginal} : ''); # should this really be a stat of the file instead of ''?
 					$tpl->assign(SRC     => uri_escape($uri."/.cache/$cached", $escape_rule));
+					$tpl->assign(WIDTH   => $thumbnailwidth);
+					$tpl->assign(HEIGHT  => $thumbnailheight);
 
 					$tpl->parse(FILES => '.picture');
 
@@ -293,7 +291,7 @@
 		$width       = floor($width);
 		$height      = floor($height);
 
-		my $cached = scale_picture($r, $filename, $image_width, $height);
+		my $cached = get_cache_filename($r, $filename, $image_width, $height);
 		
 		my $tpl = new CGI::FastTemplate($r->dir_config('GalleryTemplateDir'));
 
@@ -320,6 +318,8 @@
 		$tpl->assign(MENU => generate_menu($r));
 		$tpl->assign(SRC => ".cache/".$cached);
 		$tpl->assign(URI => $r->uri());
+		$tpl->assign(PICTURE_WIDTH => $image_width);
+		$tpl->assign(PICTURE_HEIGHT => $height);
 
 		unless (opendir(DATADIR, $path)) {
 			show_error($r, "Unable to access directory", "Unable to access directory $path");
@@ -349,10 +349,12 @@
 				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 = get_cache_filename($r, $path.$prevpicture, $thumbnailwidth, $thumbnailheight);
 					$tpl->assign(URL       => uri_escape($prevpicture, $escape_rule));
 					$tpl->assign(FILENAME  => $prevpicture);
 					$tpl->assign(WIDTH     => $width);
+					$tpl->assign(THUMB_WIDTH   => $thumbnailwidth);
+					$tpl->assign(THUMB_HEIGHT  => $thumbnailheight);
 					$tpl->assign(PICTURE   => uri_escape(".cache/$cached", $escape_rule));
 					$tpl->assign(DIRECTION => "Prev");
 					$tpl->parse(BACK => "navpicture");
@@ -369,10 +371,12 @@
 				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 = get_cache_filename($r, $path.$nextpicture, $thumbnailwidth, $thumbnailheight);
 					$tpl->assign(URL       => uri_escape($nextpicture, $escape_rule));
 					$tpl->assign(FILENAME  => $nextpicture);
 					$tpl->assign(WIDTH     => $width);
+					$tpl->assign(THUMB_WIDTH   => $thumbnailwidth);
+					$tpl->assign(THUMB_HEIGHT  => $thumbnailheight);
 					$tpl->assign(PICTURE   => uri_escape(".cache/$cached", $escape_rule));
 					$tpl->assign(DIRECTION => "Next");
 					$tpl->parse(NEXT => "navpicture");
@@ -481,6 +485,7 @@
 	return OK;
 }
 
+
 sub get_cache_root {
 
 	my ($r) = @_;
@@ -505,6 +510,8 @@
 	return $cache_root;
 }
 
+
+
 sub cache_dir {
 
 	my ($r, $strip_filename) = @_;
@@ -550,17 +557,63 @@
 	}
 }
 
-sub scale_picture {
+sub get_cache_filename {
 
 	my ($r, $fullpath, $width, $height) = @_;
 
 	my @dirs = split(/\//, $fullpath);
 	my $filename = pop(@dirs);
+	my ($orig_width, $orig_height, $type) = imgsize($fullpath);
+
+	my $newfilename;
+	if (grep $type eq $_, qw(PPM TIF)) {
+		$newfilename = $width."x".$height."-".$filename;
+		# needs to be configurable
+		$newfilename =~ s/\.(\w+)$/-$1\.jpg/;
+	} else {
+		$newfilename = $width."x".$height."-".$filename;
+	}
+	
+	if ($r->dir_config('GalleryResizeOnPageFetch')) {
+		my $relpath = substr($fullpath, length($r->document_root));
+		generate_cache_image($r, $relpath, $width, $height);
+	}
+	
+	return $newfilename;
+
+}
+
+sub update_cache_entry {
+
+	my ($r, $cachefilepath) = @_;
+
+	my $relpath = substr($cachefilepath, length(get_cache_root($r)));
+        my @dirs = split(/\//, $relpath);
+	my $filename = pop(@dirs);
+
+	$filename =~ s/^(\d+)x(\d+)-(.*)$/$3/g;
+	my $width = $1;
+	my $height = $2;
 
+	$relpath = join("/", @dirs) . "/$filename";
+
+	generate_cache_image($r, $relpath, $width, $height);
+
+}
+
+sub generate_cache_image {
+
+	my ($r, $relpath, $width, $height) = @_;
+
+	my $fullpath = $r->document_root . "/" . $relpath;
 	my ($orig_width, $orig_height, $type) = imgsize($fullpath);
 
-	my @cachedir = split("/", cache_dir($r, 0));
-	pop(@cachedir) unless (-d join("/", @cachedir));
+        my @dirs = split(/\//, $fullpath);
+	my $filename = pop(@dirs);
+
+	my @cachedir = split("/", get_cache_root($r));
+	push(@cachedir, split(/\//, $relpath));
+	pop(@cachedir);
 
 	my $cache = join("/", @cachedir);
 
@@ -604,7 +657,6 @@
 				}	
 			}
 		}	
-
 	}	
 
 	if ($scale) {
@@ -623,11 +675,10 @@
 		}
 	}
 
-	return $newfilename;
-
 }
 
 sub get_thumbnailsize {
+
 	my ($r, $orig_width, $orig_height) = @_;
 
 	my ($thumbnailwidth, $thumbnailheight) = split(/x/, ($r->dir_config('GalleryThumbnailSize') ?  $r->dir_config('GalleryThumbnailSize') : "100x75"));
@@ -841,76 +892,46 @@
 }
 
 
-1;
-__DATA__
-__C__
+sub resizepicture {
 
-#include <X11/Xlib.h>
-#include <Imlib2.h>
-#include <stdio.h>
-#include <string.h>
-
-int resizepicture(char* infile, char* outfile, int x, int y, int rotate, char* copyrightfile) {
-
-	Imlib_Image image;
-	Imlib_Image buffer;
-	Imlib_Image logo;
-	int logo_x, logo_y;
-	int old_x;
-	int old_y;
-
-	image = imlib_load_image(infile);
-
-	imlib_context_set_image(image);
-	imlib_context_set_blend(1);
-	imlib_context_set_anti_alias(1);
-	
-	old_x = imlib_image_get_width();
-	old_y = imlib_image_get_height();
+	my ($infile, $outfile, $width, $height, $rotate, $copyrightfile) = @_;
+	my $x;
 
-	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);
+	my $image = new Image::Magick;
+	$x = $image->Read($infile);
+	warn "$x" if "$x";
 
-	imlib_context_set_image(buffer);
-	
-	if (rotate != 0) {
-	    imlib_image_orientate(rotate);
-	}
-	if (strcmp(copyrightfile, "") != 0) {
-	    logo = imlib_load_image(copyrightfile);
+	$x = $image->Resize(geometry => "$width" . "x" . "$height", 
+			    filter => "Box",
+			    blur => 0.5);
+	warn "$x" if "$x";
 
-	    imlib_context_set_image(buffer);
+	if ($rotate != 0) {
+		$x = $image->Rotate($rotate * 90);
+		warn "$x" if "$x";
+	}
 
-	    x = imlib_image_get_width();
-	    y = imlib_image_get_height();
-	    
-	    imlib_context_set_image(logo);
-	    
-	    logo_x = imlib_image_get_width();
-	    logo_y = imlib_image_get_height();
+	if ($copyrightfile ne "") {
+		my $copyrightimage = Image::Magick->new;
+		$x = $copyrightimage->Read("png:$copyrightfile");
+		warn "$x" if "$x";
 
-	    imlib_context_set_image(buffer);
-	    imlib_blend_image_onto_image(logo, 0, 0, 0, logo_x, logo_y, x-logo_x, y-logo_y, logo_x, logo_y);
+		$x = $image->Composite(image => $copyrightimage, 
+				compose => "Over",
+				gravity => "SouthEast");
+		warn "$x" if "$x";
 
-	    imlib_context_set_image(logo);
-	    imlib_free_image();
-	    imlib_context_set_image(buffer);
+		undef $copyrightimage;
 	}
 
-	imlib_save_image(outfile);
-
-	imlib_context_set_image(image);
-	imlib_free_image();
-
-	imlib_context_set_image(buffer);
-	imlib_free_image();
+	$x = $image->Write(filename => $outfile);
+	warn "$x" if "$x";
 
 	return 1;
 }
 
-__END__
+
+1;
 
 =head1 NAME
 
@@ -1007,6 +1028,20 @@
 
 Set to 1 or 0, default is 0
 
+=item B<GalleryResizeOnPageFetch>
+
+Resize the images when generating the HTML for a page, instead of
+waiting until the browser requests the individual images. Setting this
+has both advantages and disadvantages.
+
+On the plus side, your server's load will be limited, because at most one
+image resize operation will take place at any one time, per client. On
+the minus side, since the page will not be returned until all of the images
+have been resized, the client browser may time out with an error on directories
+with many images.
+
+Set to 1 or 0, default is 0
+
 =item B<GallerySlideshowIntervals>
 
 With this option you can configure which intervals can be selected for
@@ -1067,8 +1102,6 @@
 
 =item B<CGI::FastTemplate>
 
-=item B<Inline::C>
-
 =item B<X11 libraries>
 (ie, XFree86)
 
@@ -1106,7 +1139,7 @@
 
 =head1 SEE ALSO
 
-L<perl>, L<mod_perl>, L<Apache::Request>, L<Inline::C>, L<CGI::FastTemplate>,
-L<Image::Info>, and L<Image::Size>.
+L<perl>, L<mod_perl>, L<Apache::Request>, L<CGI::FastTemplate>,
+L<Image::Info>, L<Image::Magick>, and L<Image::Size>.
 
 =cut
diff -Nur Apache-Gallery-0.5.1/templates/directory.tpl apache-gallery/templates/directory.tpl
--- Apache-Gallery-0.5.1/templates/directory.tpl	Sun Jul 28 13:11:10 2002
+++ apache-gallery/templates/directory.tpl	Sat Mar 22 09:02:50 2003
@@ -1 +1 @@
-    <div id="folder"><a href="$FILEURL"><img border="0" src="/icons/folder.png"><br>$FILE</a></div>
+    <div id="folder"><a href="$FILEURL"><img border="0" src="/icons/folder.png" width="48" height="48"><br>$FILE</a></div>
diff -Nur Apache-Gallery-0.5.1/templates/movie.tpl apache-gallery/templates/movie.tpl
--- Apache-Gallery-0.5.1/templates/movie.tpl	Sun Jul 28 13:11:10 2002
+++ apache-gallery/templates/movie.tpl	Sat Mar 22 09:02:50 2003
@@ -1 +1 @@
-    <div id="folder"><a href="$FILEURL"><img border="0" alt="$ALT" src="/icons/video-$TYPE.png"><br>$FILE</a></div>
+    <div id="folder"><a href="$FILEURL"><img border="0" alt="$ALT" src="/icons/video-$TYPE.png" width="48" height="48"><br>$FILE</a></div>
diff -Nur Apache-Gallery-0.5.1/templates/navpicture.tpl apache-gallery/templates/navpicture.tpl
--- Apache-Gallery-0.5.1/templates/navpicture.tpl	Sun Jul 28 13:11:10 2002
+++ apache-gallery/templates/navpicture.tpl	Sat Mar 22 09:02:50 2003
@@ -1 +1 @@
-<a href="$URL?width=$WIDTH" class="nav"><img src="$PICTURE"><br>$DIRECTION - $FILENAME</a>
+<a href="$URL?width=$WIDTH" class="nav"><img src="$PICTURE" width="$THUMB_WIDTH" height="$THUMB_HEIGHT"><br>$DIRECTION - $FILENAME</a>
diff -Nur Apache-Gallery-0.5.1/templates/picture.tpl apache-gallery/templates/picture.tpl
--- Apache-Gallery-0.5.1/templates/picture.tpl	Sun Jul 28 13:11:10 2002
+++ apache-gallery/templates/picture.tpl	Sat Mar 22 09:02:50 2003
@@ -1 +1 @@
-    <a href="$FILEURL"><img alt="$FILE - $DATE" src="$SRC"></a>
+    <a href="$FILEURL"><img alt="$FILE - $DATE" src="$SRC" width="$WIDTH" height="$HEIGHT"></a>
diff -Nur Apache-Gallery-0.5.1/templates/showpicture.tpl apache-gallery/templates/showpicture.tpl
--- Apache-Gallery-0.5.1/templates/showpicture.tpl	Wed Sep 11 13:01:31 2002
+++ apache-gallery/templates/showpicture.tpl	Sat Mar 22 09:02:50 2003
@@ -8,7 +8,7 @@
         <td colspan="3" id="picture">
 						<center class="nav">
 						Viewing picture $NUMBER of $TOTAL at $RESOLUTION pixels<br>
-            <img src="$SRC"><br>
+            <img src="$SRC" width="$PICTURE_WIDTH" height="$PICTURE_HEIGHT"><br>
             Size [ $SIZES ]<br>
 						Slideshow [ $SLIDESHOW ]
           </center>