20
Jul
Rhino vs Php Image Processing Faceoff
By Joseph Montanez
0 Comment

In php its a common task is scale images with GD, and much so with java's ImageIO. To interface with java I used rhino, which is a very loving javascript way to script the JVM. So I just took a folder of images, made a new folder called images and made 100x100 thumbnails.

Applications used:
Php 5.3
Java 1.6.0_14 & Rhino 1.7 R2

Rhino:
java -cp js.jar org.mozilla.javascript.tools.shell.Main index.js

Php:
php -c /opt/lampp/etc/php.ini index.php

Result:
Rhino: ~10.1 seconds @ 89 MB memory useage
Php: ~7.3 seconds @ 38 MB memory useage

Now dont jump to the gun and think php is a much better fit. On larger images 13 megs in size php couldn't even open them, while the jvm took it like nothing and made virtually no dent in the time spent. So I tried adding 100 more images and the more images I added the the more php would take. After 150+ images rhino started to leave php in the dust while time it took to make thumbnails. While rhino has a lot of startup time, which is why its longer then php's time, it certainly will beat it with larger images, and more to process. Another aspect I left out of the demos was threading. Php has no real builtin threading, you have to fake it. While Rhino runs on the JVM and threading is dead simple. So I could cut the time down.

This really cuts into php's core, its hard to create more "enterprise" software because php isn't able to deal with these problems. Instead you need to create pecl modules to get around them. This is fine, but in rhino you can just create Java classes and use them. On a personal level its a LOT easier to create java classes for rhino then create c coded module for php. The other issue with php is deployment. But I will leave that for another day.

function scaleImage(p_infile, p_outfile, p_width, p_height) {
    var file = new java.io.File(p_infile);
    var image = javax.imageio.ImageIO.read(file);
    var thumbWidth = p_width;
    var thumbHeight = p_height;        
 
    var thumbRatio = thumbWidth / thumbHeight;
    var imageWidth = image.getWidth(null);
    var imageHeight = image.getHeight(null);
    var imageRatio = imageWidth / imageHeight;
    
    if (thumbRatio < imageRatio) {
      thumbHeight = (thumbWidth / imageRatio);
    } else {
      thumbWidth = (thumbHeight * imageRatio);
    }

    var thumbImage = new java.awt.image.BufferedImage(
        thumbWidth, 
        thumbHeight,
        java.awt.image.BufferedImage.TYPE_INT_RGB
    );
    var graphics2D = thumbImage.createGraphics();
    graphics2D.setRenderingHint(
        java.awt.RenderingHints.KEY_INTERPOLATION,
        java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR
    );
    graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
    javax.imageio.ImageIO.write(thumbImage, 'jpg', new java.io.File(p_outfile)); 
}

var directory = new java.io.File('./');
new java.io.File('./images').mkdir();

var filter = new java.io.FilenameFilter({
    accept: function(file, name) {
        name = name.toLowerCase();
        return !name.startsWith(".") && (
        name.endsWith(".jpg") || name.endsWith(".jpeg") || 
        name.endsWith(".gif") ||  name.endsWith(".png")  && 
        file.canRead() && file.isFile()
        );
    }
});

var files = directory.listFiles(filter);
for each(var file in files) {
    var image = scaleImage(file, 'images/' + file, 100, 100);
}
<?php

function scaleImage($p_infile, $p_outfile, $p_width, $p_height) {
	$image = imagecreatefromjpeg($p_infile);
	if (!$image) {
		$image = imagecreatefrompng($p_infile);
	}
	
	$width = imagesx($image);    
	$height = imagesy($image);  
	$newwidth  = $p_width;
	$newheight = $height * $newwidth / $width;
	
	if($p_height < $newheight) {
    	$newheight =& $maxheight;
    	$newwidth  = $width * $newheight / $height;
	}
	if($p_width < $newwidth) {
    	$newwidth  =& $maxwidth;
    	$newheight = $height * $newwidth / $width;
	}
	
	$resampled = imagecreatetruecolor($newwidth, $newheight);
	imagecopyresampled($resampled, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height); 
	imagejpeg($resampled, $p_outfile, 85);
	unset($resampled);
}

$files = scandir('./');

mkdir("images");
$filter = function ($file) {
    $file = strtolower($file);
    return (
        $file{0} !== '.' &&
        (
            substr($file, strlen($file) - strlen('.jpeg')) === '.jpeg' ||
            substr($file, strlen($file) - strlen('.jpg')) === '.jpg' ||
            substr($file, strlen($file) - strlen('.png')) === '.png' ||
            substr($file, strlen($file) - strlen('.gif')) === '.gif'
        )
    );
};

foreach ($files as $file) {
	if(!$filter($file)) {
	    continue;
	}
	scaleImage($file, 'images/' . $file, 100, 100);
}
?>

« Back to my notebook
Next Note > < Previous Note
Comment Pages: 1


esign