/**
  * Rotate an image.  Valid options are degrees
  *
  * @param string     $input_file
  * @param string     $output_file
  * @param array      $options
  */
 static function rotate($input_file, $output_file, $options)
 {
     graphics::init_toolkit();
     module::event("graphics_rotate", $input_file, $output_file, $options);
     // BEGIN mod to original function
     $image_info = getimagesize($input_file);
     // [0]=w, [1]=h, [2]=type (1=GIF, 2=JPG, 3=PNG)
     if (module::get_var("image_optimizer", "rotate_jpg") || $image_info[2] == 2) {
         // rotate_jpg enabled, the file is a jpg.  get args
         $path = module::get_var("image_optimizer", "path_jpg");
         $exec_args = " -rotate ";
         $exec_args .= $options["degrees"] > 0 ? $options["degrees"] : $options["degrees"] + 360;
         $exec_args .= " -copy all -optimize -outfile ";
         // run it - from input_file to tmp_file
         $tmp_file = image_optimizer::make_temp_name($output_file);
         exec(escapeshellcmd($path) . $exec_args . escapeshellarg($tmp_file) . " " . escapeshellarg($input_file), $exec_output, $exec_status);
         if ($exec_status || !filesize($tmp_file)) {
             // either a blank/nonexistant file or an error - log an error and pass to normal function
             Kohana_Log::add("error", "image_optimizer rotation failed on " . $output_file);
             unlink($tmp_file);
         } else {
             // worked - move temp to output
             rename($tmp_file, $output_file);
             $status = true;
         }
     }
     if (!$status) {
         // we got here if we weren't supposed to use jpegtran or if jpegtran failed
         // END mod to original function
         Image::factory($input_file)->quality(module::get_var("gallery", "image_quality"))->rotate($options["degrees"])->save($output_file);
         // BEGIN mod to original function
     }
     // END mod to original function
     module::event("graphics_rotate_completed", $input_file, $output_file, $options);
 }
 /**
  * the main optimize function
  *
  * the function arguments are the same format as other graphics rules.  the only "option" is $target, hence why it's renamed in the function def.
  *
  * NOTE: unlike other graphics transformations, this only uses the output file!  if it isn't already there, we don't do anything.
  * among other things, this means that the original, full-size images are never touched.
  */
 static function optimize($input_file, $output_file, $target, $item = null)
 {
     // see if output file exists and is writable
     if (is_writable($output_file)) {
         // see if input is a supported file type.  if not, return without doing anything.
         $image_info = getimagesize($input_file);
         // [0]=w, [1]=h, [2]=type (1=GIF, 2=JPG, 3=PNG)
         switch ($image_info[2]) {
             case 1:
                 $type_old = "gif";
                 $convert = module::get_var("image_optimizer", "convert_" . $target . "_gif");
                 break;
             case 2:
                 $type_old = "jpg";
                 $convert = 0;
                 // no conversion possible here...
                 break;
             case 3:
                 $type_old = "png";
                 $convert = module::get_var("image_optimizer", "convert_" . $target . "_png");
                 break;
             default:
                 // not a supported file type
                 return;
         }
     } else {
         // file doesn't exist or isn't writable
         return;
     }
     // set new file type
     $type = $convert ? $convert : $type_old;
     // convert image type (if applicable).  this isn't necessarily lossless.
     if ($convert) {
         $output_file_new = legal_file::change_extension($output_file, $type);
         // perform conversion using standard Gallery toolkit (GD/ImageMagick/GraphicsMagick)
         // note: if input was a GIF, this will kill animation
         $image = Image::factory($output_file)->quality(module::get_var("gallery", "image_quality"))->save($output_file_new);
         // if filenames are different, move the new on top of the old
         if ($output_file != $output_file_new) {
             /**
              * HACK ALERT!  Gallery3 is still broken with regard to treating thumb/resizes with proper extensions.  This doesn't try to fix that.
              *   Normal Gallery setup:
              *     photo thumb -> keep photo type, keep photo extension
              *     album thumb -> keep source photo thumb type, change extension to jpg (i.e. ".album.jpg" even for png/gif)
              * Also, missing_photo.png is similarly altered...
              *
              * Anyway, to avoid many rewrites of core functions (and not-easily-reversible database changes), this module also forces the extension to stay the same.
              *   With image optimizer conversion:
              *     photo thumb -> change type, keep photo extension (i.e. "photo.png" photo becomes "photo.png" thumb even if type has changed)
              *     album thumb -> keep source photo thumb type, change extension to jpg (i.e. ".album.jpg" even for png/gif)
              */
             rename($output_file_new, $output_file);
         }
     }
     // get module variables
     $configstatus = module::get_var("image_optimizer", "configstatus_" . $type);
     $path = module::get_var("image_optimizer", "path_" . $type);
     $opt = module::get_var("image_optimizer", "optlevel_" . $target . "_" . $type);
     $meta = module::get_var("image_optimizer", "metastrip_" . $target);
     $prog = module::get_var("image_optimizer", "progressive_" . $target);
     // make sure the toolkit is configured correctly and we want to use it - if not, return without doing anything.
     if ($configstatus) {
         if (!$prog && !$meta && !$opt) {
             // nothing to do!
             return;
         }
     } else {
         // not configured correctly
         return;
     }
     /**
      * do the actual optimization
      */
     // set parameters
     switch ($type) {
         case "jpg":
             $exec_args = $opt ? " -optimize" : "";
             $exec_args .= $meta ? " -copy none" : " -copy all";
             $exec_args .= $prog ? " -progressive" : "";
             $exec_args .= " -outfile ";
             break;
         case "png":
             $exec_args = $opt ? " -o" . $opt : "";
             $exec_args .= $meta ? " -strip all" : "";
             $exec_args .= $prog ? " -i 1" : "";
             $exec_args .= " -quiet -out ";
             break;
         case "gif":
             $exec_args = $opt ? " --optimize=3" : "";
             // levels 1 and 2 don't really help us
             $exec_args .= $meta ? " --no-comments --no-extensions --no-names" : " --same-comments --same-extensions --same-names";
             $exec_args .= $prog ? " --interlace" : " --same-interlace";
             $exec_args .= " --careful --output ";
             break;
     }
     // run it - from output_file to tmp_file.
     $tmp_file = image_optimizer::make_temp_name($output_file);
     exec(escapeshellcmd($path) . $exec_args . escapeshellarg($tmp_file) . " " . escapeshellarg($output_file), $exec_output, $exec_status);
     if ($exec_status || !filesize($tmp_file)) {
         // either a blank/nonexistant file or an error - do nothing to the output, but log an error and delete the temp (if any)
         Kohana_Log::add("error", "image_optimizer optimization failed on " . $output_file);
         unlink($tmp_file);
     } else {
         // worked - move temp to output
         rename($tmp_file, $output_file);
     }
 }