From 7ec7ca623bfb5d46141f452e0f0180c57dd3ec77 Mon Sep 17 00:00:00 2001 From: Shish Date: Sat, 18 Aug 2012 21:10:35 +0100 Subject: [PATCH] rotate ext from Agasa --- ext/rotate/main.php | 237 +++++++++++++++++++++++++++++++++++++++++++ ext/rotate/style.css | 5 + ext/rotate/theme.php | 57 +++++++++++ 3 files changed, 299 insertions(+) create mode 100644 ext/rotate/main.php create mode 100644 ext/rotate/style.css create mode 100644 ext/rotate/theme.php diff --git a/ext/rotate/main.php b/ext/rotate/main.php new file mode 100644 index 00000000..ad194012 --- /dev/null +++ b/ext/rotate/main.php @@ -0,0 +1,237 @@ + / Agasa + * Description: Allows admins to rotate images. + * License: GPLv2 + * Version: 0.1 + * Notice: + * The image resize and resample code is based off of the "smart_resize_image" + * function copyright 2008 Maxim Chernyak, released under a MIT-style license. + * Documentation: + * This extension allows admins to rotate images. + */ + +/** + * This class is just a wrapper around SCoreException. + */ +class ImageRotateException extends SCoreException { + var $error; + + public function __construct($error) { + $this->error = $error; + } +} + +/** + * This class handles image rotate requests. + */ +class RotateImage extends Extension { + + public function onInitExt(InitExtEvent $event) { + global $config; + $config->set_default_bool('rotate_enabled', true); + $config->set_default_int('rotate_default_deg', 180); + } + + public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) { + global $user, $config; + if($user->is_admin() && $config->get_bool("rotate_enabled")) { + /* Add a link to rotate the image */ + $event->add_part($this->theme->get_rotate_html($event->image->id)); + } + } + + public function onSetupBuilding(SetupBuildingEvent $event) { + $sb = new SetupBlock("Image Rotate"); + $sb->add_bool_option("rotate_enabled", "Allow rotating images: "); + $sb->add_label("
Default Orientation: "); + $sb->add_int_option("rotate_default_deg"); + $sb->add_label(" deg"); + $event->panel->add_block($sb); + } + + public function onPageRequest(PageRequestEvent $event) { + global $page, $user; + + if ( $event->page_matches("rotate") && $user->is_admin() ) { + // Try to get the image ID + $image_id = int_escape($event->get_arg(0)); + if (empty($image_id)) { + $image_id = isset($_POST['image_id']) ? $_POST['image_id'] : null; + } + if (empty($image_id)) { + throw new ImageRotateException("Can not rotate Image: No valid Image ID given."); + } + + $image = Image::by_id($image_id); + if(is_null($image)) { + $this->theme->display_error(404, "Image not found", "No image in the database has the ID #$image_id"); + } else { + + /* Check if options were given to rotate an image. */ + if (isset($_POST['rotate_deg'])) { + + /* get options */ + + $deg = 0; + + if (isset($_POST['rotate_deg'])) { + $deg = int_escape($_POST['rotate_deg']); + } + + /* Attempt to rotate the image */ + try { + $this->rotate_image($image_id, $deg); + + //$this->theme->display_rotate_page($page, $image_id); + + $page->set_mode("redirect"); + $page->set_redirect(make_link("post/view/".$image_id)); + + } catch (ImageRotateException $e) { + $this->theme->display_rotate_error($page, "Error Rotating", $e->error); + } + } else { + /* Display options for resizing */ + $this->theme->display_rotate_page($page, $image_id); + } + } + } + } + + + // Private functions + /* ----------------------------- */ + + /* + This function could be made much smaller by using the ImageReplaceEvent + ie: Pretend that we are replacing the image with a rotated copy. + */ + private function rotate_image(/*int*/ $image_id, /*int*/ $deg) { + global $config, $user, $page, $database; + + if ( ($deg <= -360) || ($deg >= 360) ) { + throw new ImageRotateException("Invalid options for rotation angle. ($deg)"); + } + + $image_obj = Image::by_id($image_id); + $hash = $image_obj->hash; + if (is_null($hash)) { + throw new ImageRotateException("Image does not have a hash associated with it."); + } + + $image_filename = warehouse_path("images", $hash); + if (file_exists ( $image_filename )==false) { throw new ImageRotateException("$image_filename does not exist."); } + $info = getimagesize($image_filename); + /* Get the image file type */ + $pathinfo = pathinfo($image_obj->filename); + $filetype = strtolower($pathinfo['extension']); + + /* + Check Memory usage limits + + Old check: $memory_use = (filesize($image_filename)*2) + ($width*$height*4) + (4*1024*1024); + New check: memory_use = width * height * (bits per channel) * channels * 2.5 + + It didn't make sense to compute the memory usage based on the NEW size for the image. ($width*$height*4) + We need to consider the size that we are GOING TO instead. + + The factor of 2.5 is simply a rough guideline. + http://stackoverflow.com/questions/527532/reasonable-php-memory-limit-for-image-resize + */ + $memory_use = ($info[0] * $info[1] * ($info['bits'] / 8) * $info['channels'] * 2.5) / 1024; + $memory_limit = get_memory_limit(); + + if ($memory_use > $memory_limit) { + throw new ImageRotateException("The image is too large to rotate given the memory limits. ($memory_use > $memory_limit)"); + } + + + /* Attempt to load the image */ + switch ( $info[2] ) { + case IMAGETYPE_GIF: $image = imagecreatefromgif($image_filename); break; + case IMAGETYPE_JPEG: $image = imagecreatefromjpeg($image_filename); break; + case IMAGETYPE_PNG: $image = imagecreatefrompng($image_filename); break; + default: + throw new ImageRotateException("Unsupported image type or "); + } + + /* Rotate and resample the image */ + /* + $image_rotated = imagecreatetruecolor( $new_width, $new_height ); + + if ( ($info[2] == IMAGETYPE_GIF) || ($info[2] == IMAGETYPE_PNG) ) { + $transparency = imagecolortransparent($image); + + if ($transparency >= 0) { + $transparent_color = imagecolorsforindex($image, $trnprt_indx); + $transparency = imagecolorallocate($image_rotated, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']); + imagefill($image_rotated, 0, 0, $transparency); + imagecolortransparent($image_rotated, $transparency); + } + elseif ($info[2] == IMAGETYPE_PNG) { + imagealphablending($image_rotated, false); + $color = imagecolorallocatealpha($image_rotated, 0, 0, 0, 127); + imagefill($image_rotated, 0, 0, $color); + imagesavealpha($image_rotated, true); + } + } + */ + + $image_rotated = imagerotate($image, $deg, 0); + + /* Temp storage while we rotate */ + $tmp_filename = tempnam("/tmp", 'shimmie_rotate'); + if (empty($tmp_filename)) { + throw new ImageRotateException("Unable to save temporary image file."); + } + + /* Output to the same format as the original image */ + switch ( $info[2] ) { + case IMAGETYPE_GIF: imagegif($image_rotated, $tmp_filename); break; + case IMAGETYPE_JPEG: imagejpeg($image_rotated, $tmp_filename); break; + case IMAGETYPE_PNG: imagepng($image_rotated, $tmp_filename); break; + default: + throw new ImageRotateException("Unsupported image type."); + } + + /* Move the new image into the main storage location */ + $new_hash = md5_file($tmp_filename); + $new_size = filesize($tmp_filename); + $target = warehouse_path("images", $new_hash); + if(!@copy($tmp_filename, $target)) { + throw new ImageRotateException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ($target)"); + } + $new_filename = 'rotated-'.$image_obj->filename; + + list($new_width, $new_height) = getimagesize($target); + + + /* Remove temporary file */ + @unlink($tmp_filename); + + /* Delete original image and thumbnail */ + log_debug("image", "Removing image with hash ".$hash); + $image_obj->remove_image_only(); + + /* Generate new thumbnail */ + send_event(new ThumbnailGenerationEvent($new_hash, $filetype)); + + /* Update the database */ + $database->Execute( + "UPDATE images SET + filename = :filename, filesize = :filesize, hash = :hash, width = :width, height = :height + WHERE + id = :id + ", + array( + "filename"=>$new_filename, "filesize"=>$new_size, "hash"=>$new_hash, + "width"=>$new_width, "height"=>$new_height, "id"=>$image_id + ) + ); + + log_info("rotate", "Rotated Image #{$image_id} - New hash: {$new_hash}"); + } +} +?> diff --git a/ext/rotate/style.css b/ext/rotate/style.css new file mode 100644 index 00000000..b9f1003d --- /dev/null +++ b/ext/rotate/style.css @@ -0,0 +1,5 @@ +form#form_rotate { + float: left; + margin: 0; + width: 60%; +} diff --git a/ext/rotate/theme.php b/ext/rotate/theme.php new file mode 100644 index 00000000..9ebce039 --- /dev/null +++ b/ext/rotate/theme.php @@ -0,0 +1,57 @@ + + + + "; + + return $html; + } + + public function display_rotate_error(Page $page, /*string*/ $title, /*string*/ $message) { + $page->set_title("Rotate Image"); + $page->set_heading("Rotate Image"); + $page->add_block(new NavBlock()); + $page->add_block(new Block($title, $message)); + } + + public function display_rotate_page(Page $page, /*int*/ $image_id) { + global $config; + + $default_deg = $config->get_int('rotate_default_deg'); + + $image = Image::by_id($image_id); + $thumbnail = $this->build_thumb_html($image, null); + + $html = "
+

Rotate Image ID ".$image_id."
".$thumbnail."

+

Please note: You will have to refresh the image page, or empty your browser cache.

+

Enter the degrees to rotate the image of, counterclockwise.


" + .make_form(make_link('rotate/'.$image_id), 'POST', $multipart=True,'form_rotate')." + + + + +
Degrees
+ + "; + + $page->set_title("Rotate Image"); + $page->set_heading("Rotate Image"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("Rotate Image", $html, "main", 20)); + + } +} +?>