Category: Programming

June 17, 2014 / / Programming

Since I love to travel I needed a wordpress plugin to keep track on my travels. There are some plugins out there but none worked for me. Because of that I started to create my own travel map plugin. Since this is my first wordpress project and my first php programming project there are may some rough edges and small bugs. Nevertheless I decided to open the plugin to the public.

CLICK HERE FOR PROJECT PAGE

February 16, 2014 / / Programming

Hej,

I just installed the slim jetpack plugin on my self hosted wordpress site to get access to the nice tiled gallery feature and the responsive carousel. One big problem now is that the tiled gallery was made for wordpress.com sites and uses the fullsize images to display the gallery. To use the gallery features on self hosted sites I just had to create a small php script and a rewrite rule. Since I don’t code much in PHP i got inspiration from a resize script at inkplant.com. I altered the script to cache the generated images to speed up loading.

Update 16.02.2014

I update the script to also support partial ?w and ?h parameters. The missing w or h parameter is calculated according to the ratio from the original to the w/h which is set. I now alo support auto generation of thumbnails, if wordpress requests an image in the format /-400×400. and no file is available, the scripts tries if the original file /. exists and resizes and stores the image under the requested name.

Here is the Updated script (wp-resize.php):

<?php

function resizeAndCropImage($image,$width,$height) {
    $w = @imagesx($image); //current width
    $h = @imagesy($image); //current height
    if ((!$w) || (!$h)) { exit; }
    if (($w == $width) && ($h == $height)) { return $image; } //no resizing needed
    if($width > 5000) {
        $width = 5000;
    }
    if($height > 5000) {
        $height = 5000;
    }

    //try max width first...
    $ratio = $width / $w;
    $new_w = $width;
    $new_h = $h * $ratio;

    //if that created an image smaller than what we wanted, try the other way
    if ($new_h < $height) {
        $ratio = $height / $h;
        $new_h = $height;
        $new_w = $w * $ratio;
    }

    $image2 = imagecreatetruecolor ($new_w, $new_h);
    imagecopyresampled($image2,$image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);

    //check to see if cropping needs to happen
    if (($new_h != $height) || ($new_w != $width)) {
        $image3 = imagecreatetruecolor ($width, $height);
        if ($new_h > $height) { //crop vertically
            $extra = $new_h - $height;
            $x = 0; //source x
            $y = round($extra / 2); //source y
            imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
        } else {
            $extra = $new_w - $width;
            $x = round($extra / 2); //source x
            $y = 0; //source y
            imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
        }
        imagedestroy($image2);
        return $image3;
    } else {
        return $image2;
    }
}

function resizeImage($image,$width,$height) {
    $w = @imagesx($image); //current width
    $h = @imagesy($image); //current height
    if ((!$w) || (!$h)) { exit; }
    if (($w == $width) && ($h == $height)) { return $image; } //no resizing needed

    $image2 = imagecreatetruecolor ($width, $height);
    imagecopyresampled($image2,$image, 0, 0, 0, 0, $width, $height, $w, $h);

    return $image2;
}

function resizeAndStoreImage($image_loc,$new_loc,$extension,$width,$height,$crop) {
    if(!file_exists($image_loc)) {
    	header('HTTP/1.1 405 Method Not Allowed');
		exit;
    }
    if(file_exists($new_loc)) {
        return;
    }
    $width = abs(intval($width));
    if (!$width) { exit; }

    $height = abs(intval($height));
    if (!$height) { exit; }

    switch($extension) {
    	case 'jpg':
    	case 'jpeg':
    		$image = @imagecreatefromjpeg($image_loc);
    		break;
		case 'png':
			$image = @imagecreatefrompng($image_loc);
			break;
		case 'gif':
			$image = @imagecreatefromgif($image_loc);
			break;
		case 'bmp':
			$image = @imagecreatefromwbmp($image_loc);
			break;

    }
    if (!$image) {
    	exit;
    }
    else {
        $current_width = imagesx($image);
        $current_height = imagesy($image);
        if ((!$current_width) || (!$current_height)) {
        	@imagedestroy($image);
        	exit;
        }
    }

    $new_image = resizeAndCropImage($image,$width,$height); 

    switch($extension) {
    	case 'jpg':
    	case 'jpeg':
    		imagejpeg($new_image,$new_loc);
    		break;
	case 'png':
    		imagepng($new_image,$new_loc);
			break;
	case 'gif':
    		imagegif($new_image,$new_loc);
			break;
	case 'bmp':
    		imagewbmp($new_image,$new_loc);
			break;

    }

    imagedestroy($image);
    imagedestroy($new_image);

    return true;
}

function outputFile($path, $extension) {

	if(!file_exists($path)) {
    	header('HTTP/1.1 404 File Not Found');
		exit;
    }

	header('Content-Description: File Transfer');
	switch($extension) {
		case "jpg":
		case "jpeg":
			header('Content-Type: image/jpeg');
			break;
		case "png":
			header('Content-Type: image/png');
			break;
		case "gif":
			header('Content-Type: image/gif');
			break;
		case "bmp":
			header('Content-Type: image/bmp');
			break;
	}
    header('Content-Length: ' . filesize($path));
    ob_clean();
    flush();
    readfile($path);
    exit;
}

if(!isset($_GET['src'])) {
    header('HTTP/1.1 404 File Not Found');
    exit;
}

$src = $_GET['src'];
$matches = array();

if(preg_match('/(wp-content\/uploads\/\d{4}\/\d{2}\/)([a-zA-Z0-9\-_\.]*)\.(png|jpg|jpeg|bmp|gif)/', $src, $matches)) {
	$basefile = $matches[0];
	$path = $matches[1];
	$name = $matches[2];
	$extension = $matches[3];

	if(!in_array($extension,array('jpg','jpeg','png','gif','bmp'))) {
		header('HTTP/1.1 405 Method Not Allowed');
		exit;
	}

        if(!file_exists($basefile)) { //base file doesnt exist, maybe its a resized file
            $pattern = '/(wp-content\/uploads\/\d{4}\/\d{2}\/)([a-zA-Z0-9\-_\.]*)-(\d+)x(\d+)(?)\.(png|jpg|jpeg|bmp|gif)/is';
            //echo("pattern:".$pattern);
            if(preg_match($pattern, $src, $matches)) { //check if its a resized file
                //echo("matching to resized file \n");
                $pathToResizedFile = $matches[0];
                $path = $matches[1];
                $name = $matches[2];
                $width = $matches[3];
                $height = $matches[4];
                $crop = ($matches[5] === 'c');
                $extension = $matches[6];

                $basefile = $path . $name . "." . $extension;
                //echo("basefile:".$basefile."\n");
                //echo("width:".$width."\n");
                //echo("height:".$height."\n");
                //echo("crop".$crop."\n");
                if(!file_exists($basefile)) {
                    header('HTTP/1.1 404 File Not Found');
                    exit;
                } else {
                    resizeAndStoreImage($basefile,$pathToResizedFile,$extension,$width, $height, $crop);
                    outputFile($pathToResizedFile, $extension);
                }
            } else {
		header('HTTP/1.1 404 File Not Found');
                exit;
            }
        } else {
            if((isset($_GET['w'])&& is_numeric(intval($_GET['w']))) ||
               (isset($_GET['h'])&& is_numeric(intval($_GET['h'])))) {
		//echo("w or set\n");
                $newWidth = -1;
                $newHeight = -1;
                $crop = isset($_GET['crop']);
                if(isset($_GET['w'])) {
                    $newWidth = intval($_GET['w']);
                }
                if(isset($_GET['h'])) {
                    $newHeight = intval($_GET['h']);
                }
                if($newWidth == -1 || $newHeight == -1) {
                    list($width, $height, $type, $attr) = @getimagesize($basefile);
	            echo($width . 'x' . $height);
                    if($newWidth == -1) {
                        $ratio = $newHeight/$height;
                        $newWidth = round($width * $ratio);
                    }
                    if($newHeight == -1) {
                        $ratio = $newWidth/$width;
                        $newHeight = round($height * $ratio);
                    }
                }
                //echo("newheight:".$newHeight."\n");
                //echo("newWidth:".$newWidth."\n");
                $pathToResizedFile = $path . $name . '-' . $newWidth . 'x' . $newHeight . ( $crop ? 'c' : '') . "." .$extension;
                //echo("pathtoresizedfile".$pathToResizedFile);
                resizeAndStoreImage($basefile,$pathToResizedFile,$extension,$newWidth, $newHeight, $crop);
                outputFile($pathToResizedFile, $extension);
            } else {
                //echo("output:".$basefile."\n");
                outputFile($basefile, $extension);
            }
        }
} else {
	header('HTTP/1.1 404 File Not Found');
	exit;
}

?>

To get everything working we just need a small rewrite rule and save it in the .htaccess file in the webroot dir.

The .htaccess file:

RewriteEngine on

RewriteBase /

RewriteRule ^(wp-content/uploads/\d{4}/\d{2}/([a-zA-Z0-9\-_\.]*)\.(jpg|gif|png)) wp-resize.php?src=$1&%{QUERY_STRING}

I may have to harden the script file by security means. maybe there is an attack vector hidden somewhere. But for now it works and thescript generates nice thumbnails for the slim jetpack plugins image features.

I hope i could help some slim jetpack users with this little script. If you have questions just let me know.