imagetools.php
author Dan
Tue, 23 Sep 2008 23:26:18 -0400
changeset 50 1b4288399b1f
parent 40 bd3372a2afc1
child 73 1f55c324efcf
permissions -rw-r--r--
Added graphical configuration, at this point only for the grey theme but others will follow soon. (This has been nearly done for two weeks or more but was on hold due to the bugs with multithreading)

<?php

/**
 * Greyhound - real web management for Amarok
 * Copyright (C) 2008 Dan Fuhry
 *
 * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
 */

/**
 * Determines an image's filetype based on its signature.
 * @param string Path to image file
 * @return string One of gif, png, or jpg, or false if none of these.
 */

function get_image_filetype($filename)
{
  $filecontents = @file_get_contents($filename);
  if ( empty($filecontents) )
    return false;
  
  if ( substr($filecontents, 0, 8) == "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" )
    return 'png';
  
  if ( substr($filecontents, 0, 6) == 'GIF87a' || substr($filecontents, 0, 6) == 'GIF89a' )
    return 'gif';
  
  if ( substr($filecontents, 0, 2) == "\xFF\xD8" )
    return 'jpg';
  
  return false;
}

/**
 * Scales an image to the specified width and height, and writes the output to the specified
 * file. Will use ImageMagick if present, but if not will attempt to scale with GD. This will
 * always scale images proportionally, unless $preserve_ratio is set to false.
 * 
 * Ported from Enano CMS (which is also my project)
 * 
 * @param string Path to image file
 * @param string Path to output file
 * @param int Image width, in pixels
 * @param int Image height, in pixels
 * @param bool If true, the output file will be deleted if it exists before it is written
 * @param bool If true, preserves the image's aspect ratio (default)
 * @return bool True on success, false on failure
 */

function scale_image($in_file, $out_file, $width = 225, $height = 225, $unlink = false, $preserve_ratio = true)
{
  global $db, $session, $paths, $template, $plugins; // Common objects
  
  if ( !is_int($width) || !is_int($height) )
    return false;
  
  if ( !file_exists($in_file) )
    return false;
  
  if ( preg_match('/["\'\/\\]/', $in_file) || preg_match('/["\'\/\\]/', $out_file) )
    return false;
  
  if ( file_exists($out_file) && !$unlink )
    return false;
  else if ( file_exists($out_file) && $unlink )
    @unlink($out_file);
  if ( file_exists($out_file) )
    // couldn't unlink (delete) the output file
    return false;
    
  $file_ext = substr($in_file, ( strrpos($in_file, '.') + 1));
  switch($file_ext)
  {
    case 'png':
      $func = 'imagecreatefrompng';
      break;
    case 'jpg':
    case 'jpeg':
      $func = 'imagecreatefromjpeg';
      break;
    case 'gif':
      $func = 'imagecreatefromgif';
      break;
    case 'xpm':
      $func = 'imagecreatefromxpm';
      break;
    default:
      return false;
  }
    
  // try to find convert in the PATH
  // FIXME: unix specific (won't work on windows)
  $path = ( isset($_ENV['PATH']) ) ? $_ENV['PATH'] : ( isset($_SERVER['PATH']) ? $_SERVER['PATH'] : '/usr/local/bin:/usr/bin:/bin' );
  $path = explode(':', $path);
  foreach ( $path as $dir )
  {
    if ( file_exists("$dir/convert") && is_executable("$dir/convert") )
    {
      $magick_path = "$dir/convert";
    }
  }
  
  $can_use_magick = isset($magick_path);
  $can_use_gd = (
      function_exists('getimagesize')         &&
      function_exists('imagecreatetruecolor') &&
      function_exists('imagecopyresampled')   &&
      function_exists($func)
    );
  if ( $can_use_magick )
  {
    if ( !preg_match('/^([\/A-z0-9_-]+)$/', $magick_path) )
    {
      // ImageMagick path seems screwy
      return false;
    }
    $op = ( $preserve_ratio ) ? '>' : '!';
    $cmdline = "\"$magick_path\" \"$in_file\" -resize '{$width}x{$height}$op' \"$out_file\"";
    exec($cmdline, $output, $return);
    if ( !file_exists($out_file) )
      return false;
    return true;
  }
  else if ( $can_use_gd )
  {
    @list($width_orig, $height_orig) = @getimagesize($in_file);
    if ( !$width_orig || !$height_orig )
      return false;
    // calculate new width and height
    
    if ( $preserve_ratio )
    {
      $ratio = $width_orig / $height_orig;
      if ( $ratio > 1 )
      {
        // orig. width is greater that height
        $new_width = $width;
        $new_height = round( $width / $ratio );
      }
      else if ( $ratio < 1 )
      {
        // orig. height is greater than width
        $new_width = round( $height / $ratio );
        $new_height = $height;
      }
      else if ( $ratio == 1 )
      {
        $new_width = $width;
        $new_height = $width;
      }
      if ( $new_width > $width_orig || $new_height > $height_orig )
      {
        // Too big for our britches here; set it to only convert the file
        $new_width = $width_orig;
        $new_height = $height_orig;
      }
    }
    else
    {
      $new_width = $width;
      $new_height = $height;
    }
    
    $newimage = @imagecreatetruecolor($new_width, $new_height);
    if ( !$newimage )
      return false;
    $oldimage = @$func($in_file);
    if ( !$oldimage )
      return false;
    
    // Perform scaling
    imagecopyresampled($newimage, $oldimage, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig);
    
    // Get output format
    $out_ext = substr($out_file, ( strrpos($out_file, '.') + 1));
    switch($out_ext)
    {
      case 'png':
        $outfunc = 'imagepng';
        break;
      case 'jpg':
      case 'jpeg':
        $outfunc = 'imagejpeg';
        break;
      case 'gif':
        $outfunc = 'imagegif';
        break;
      case 'xpm':
        $outfunc = 'imagexpm';
        break;
      default:
        imagedestroy($newimage);
        imagedestroy($oldimage);
        return false;
    }
    
    // Write output
    $outfunc($newimage, $out_file);
    
    // clean up
    imagedestroy($newimage);
    imagedestroy($oldimage);
    
    // done!
    return true;
  }
  if ( file_exists($out_file) )
    return true;
  return false;
}