All pastes #61037 Raw Edit

Miscellany

public text v1 · immutable
#61037 ·published 2006-06-02 14:34 UTC
rendered paste body
<?php

/*******************************************************************************
 * i.php: Zenphoto image processor. All image requests go through this file.   *
 *******************************************************************************
 * URI Parameters:
 *   s  - size (logical): Based on config, makes an image of "size s."
 *   h  - height (explicit): Image is always h pixels high, w is calculated.
 *   w  - width (explicit): Image is always w pixels wide, h is calculated.
 *   cw - crop width: crops the image to cw pixels wide.
 *   ch - crop height: crops the image to ch pixels high.
 *   cx - crop x position: the x (horizontal) position of the crop area.
 *   cy - crop y position: the y (vertical) position of the crop area.
 *   q  - JPEG quality (1-100): sets the quality of the resulting image.
 *
 * - cx and cy are measured from the top-left corner of the _scaled_ image.
 * - One of s, h, or w _must_ be specified; the others are optional.
 * - If more than one of s, h, or w are specified, s takes priority, then w+h:
 * - If both w and h are given, the image is resized to shortest side, then
 *     cropped on the remaining dimension. Image output will always be WxH.
 * - If none of s, h, or w are specified, the original image is returned.
 *******************************************************************************
 */

define('OFFSET_PATH', true);
// i.php - image generation.
require_once("functions.php");

// Set the config variables for convenience.
$thumb_crop = zp_conf('thumb_crop');
$thumb_size = zp_conf('thumb_size');
$thumb_crop_width = zp_conf('thumb_crop_width');
$thumb_crop_height = zp_conf('thumb_crop_height');
$image_use_longest_side = zp_conf('image_use_longest_side');
$image_default_size = zp_conf('image_size');
$quality = zp_conf('image_quality');
$thumb_quality = zp_conf('thumb_quality');
$upscale = zp_conf('image_allow_upscale');

// Don't let anything get above this, to save the server from burning up...
define('MAX_SIZE', 3000);

// Generate an image from the given file ($_GET['f']) at the given size ($_GET['s'])
if (!isset($_GET['a']) || !isset($_GET['i'])) {
	die("<b>Zenphoto error:</b> Please specify both an album and an image.");
	// TODO: Return a default image (possibly with an error message) instead of just dying.
}

// Fix special characters in the album and image names if mod_rewrite is on:
if (zp_conf('mod_rewrite')) {
  $zppath = substr($_SERVER['REQUEST_URI'], strlen(WEBPATH)+1);
  $qspos = strpos($zppath, '?');
  if ($qspos !== false) $zppath = substr($zppath, 0, $qspos); 
  $zpitems = explode("/", $zppath);
  if (isset($zpitems[1]) && $zpitems[1] == 'image') {
    $req_album = $zpitems[0];
    // This next line assumes the image filename is always last. Take note.
    $req_image = $zpitems[count($zpitems)-1];
    if (!empty($req_album)) $_GET['a'] = urldecode($req_album);
    if (!empty($req_image)) $_GET['i'] = urldecode($req_image);
  }
}


$album = sanitize($_GET['a']);
$image = sanitize($_GET['i']);

// Disallow abusive size requests.
if ((isset($_GET['s']) && $_GET['s'] < MAX_SIZE) 
  || (isset($_GET['w']) && $_GET['w'] < MAX_SIZE)
  || (isset($_GET['h']) && $_GET['h'] < MAX_SIZE)) {

  // Set default variable values.
  $thumb = $size = $width = $height = $crop = $cw = $ch = $cx = $cy = false;
  
  // If s=thumb, Set up for the default thumbnail settings.
  $size = $_GET['s'];
	if ($size == "thumb") {
		$thumb = true;
    if ($thumb_crop) {
      if ($thumb_crop_width > $thumb_size)  $thumb_crop_width  = $thumb_size;
      if ($thumb_crop_height > $thumb_size) $thumb_crop_height = $thumb_size;
      $cw = $thumb_crop_width;
      $ch = $thumb_crop_height;
      $crop = true;
    } else {
      $crop = $cw = $ch = false;
    }
    $size = round($thumb_size);
    $quality = round($thumb_quality);

  // Otherwise, populate the parameters from the URI
	} else {
    if ($size == "default") {
      $size = $image_default_size;
    } else if (empty($size) || !is_numeric($size)) {
      $size = false; // 0 isn't a valid size anyway, so this is OK.
    } else {
      $size = round($size);
    }
    
    if (isset($_GET['w']))  { $width   = round($_GET['w']); }
    if (isset($_GET['h']))  { $height  = round($_GET['h']); }
    if (isset($_GET['cw'])) { $cw      = round($_GET['cw']); $crop = true; }
    if (isset($_GET['ch'])) { $ch      = round($_GET['ch']); $crop = true; }
    if (isset($_GET['cx'])) { $cx      = round($_GET['cx']); }
    if (isset($_GET['cy'])) { $cy      = round($_GET['cy']); }
    if (isset($_GET['q']))  { $quality = round($_GET['q']); }
	}
  
  $postfix_string = ($size ? "_$size" : "") . ($width ? "_w$width" : "") 
    . ($height ? "_h$height" : "") . ($cw ? "_cw$cw" : "") . ($ch ? "_ch$ch" : "") 
    . (is_numeric($cx) ? "_cx$cx" : "") . (is_numeric($cy) ? "_cy$cy" : "");
    
} else {
  // No image parameters specified; return the original image.
  header("Location: " . PROTOCOL . "://" . $_SERVER['HTTP_HOST'] . WEBPATH 
    . "/albums/" . rawurlencode($album) . "/" . rawurlencode($image));
  return;
}


$newfilename = "{$album}_{$image}{$postfix_string}.jpg";
$newfile = SERVERCACHE . "/" . $newfilename;
$imgfile = SERVERPATH  . "/albums/$album/$image";

// Check for the source image.
if (!file_exists($imgfile)) {
  die("<b>Zenphoto error:</b> Image not found.");
}

// If the file hasn't been cached yet, create it.
if (!file_exists($newfile)) {
	if ($im = get_image($imgfile)) {
		$w = imagesx($im);
		$h = imagesy($im);
    
    // Give the sizing dimension to $dim
    if (!empty($size)) {
      $dim = $size;
      $width = $height = false;
    } else if (!empty($width) && !empty($height)) {
      $ratio_in = $h / $w;
      $ratio_out = $height / $width;
      $crop = true;
      if ($ratio_in > $ratio_out) {
        $thumb = true;
        $dim = $width;
        $ch = $height;
      } else {
        $dim = $height;
        $cw = $width;
        $height = true;
      }
      
    } else if (!empty($width)) {
      $dim = $width;
      $size = $height = false;
    } else if (!empty($height)) {
      $dim = $height;
      $size = $width = false;
    } else {
      // There's a problem up there somewhere...
      die("<b>Zenphoto error:</b> Image processing error. Please report to the developers.");
    }
    
    // Calculate proportional height and width.
    $hprop = round(($h / $w) * $dim);
    $wprop = round(($w / $h) * $dim);
    
		if ($thumb) {
      // Use the shortest side.
			if ($h > $w) {
				$neww = $dim;
				$newh = $hprop;
			} else {
				$neww = $wprop;
				$newh = $dim;
			}
    } else {
      if (($size && $image_use_longest_side && $h > $w) || $height) {
        $newh = $dim;
        $neww = $wprop;
      } else {
        $newh = $hprop;
  			$neww = $dim;
      }
      
      // If the requested image is the same size or smaller than the original, redirect to it.
      if (!$upscale && $newh >= $h && $neww >= $w && !$crop) {
        header("Location: " . PROTOCOL . "://" . $_SERVER['HTTP_HOST'] . WEBPATH
          . "/albums/" . rawurlencode($album) . "/" . rawurlencode($image));
        return;
      }
    }
    
    $newim = imagecreatetruecolor($neww, $newh);
    imagecopyresampled($newim, $im, 0, 0, 0, 0, $neww, $newh, $w, $h);
    
    // Crop the image if requested.
    if ($crop) {
      if ($cw === false || $cw > $neww) $cw = $neww;
      if ($ch === false || $ch > $newh) $ch = $newh;
      if ($cx === false) $cx = round(($neww - $cw) / 2);
      if ($cy === false) $cy = round(($newh - $ch) / 2);
      if ($cw + $cx > $neww) $cx = $neww - $cw;
      if ($ch + $cy > $newh) $cy = $newh - $ch;
      $newim_crop = imagecreatetruecolor($cw, $ch);
      imagecopy($newim_crop, $newim, 0, 0, $cx, $cy, $cw, $ch);
      imagedestroy($newim);
      $newim = $newim_crop;
    }

    // Create the cached file (with lots of compatibility)...
		touch($newfile);
		imagejpeg($newim, $newfile, $quality);
    chmod($newfile,0644);
		imagedestroy($newim);
		imagedestroy($im);
	}
}

// ... and redirect the browser to it.
header("Location: " . PROTOCOL . "://" . $_SERVER['HTTP_HOST'] . WEBPATH . "/cache/" . rawurlencode($newfilename));
exit();
?>