/** * Generate the necessary DataUploadEvent for a given image and tags. */ private function add_image($tmpname, $filename, $tags, $source, $rating, $thumbfile) { assert(file_exists($tmpname)); $pathinfo = pathinfo($filename); if (!array_key_exists('extension', $pathinfo)) { throw new UploadException("File has no extension"); } $metadata = array(); $metadata['filename'] = $pathinfo['basename']; $metadata['extension'] = $pathinfo['extension']; $metadata['tags'] = $tags; $metadata['source'] = $source; $event = new DataUploadEvent($tmpname, $metadata); send_event($event); if ($event->image_id == -1) { throw new UploadException("File type not recognised"); } else { if (class_exists("RatingSetEvent") && in_array($rating, array("s", "q", "e"))) { $ratingevent = new RatingSetEvent(Image::by_id($event->image_id), $rating); send_event($ratingevent); } if (file_exists($thumbfile)) { copy($thumbfile, warehouse_path("thumbs", $event->hash)); } } }
/** * Generate the Thumbnail image for particular file. * * @param string $hash * @return bool Returns true on successful thumbnail creation. */ protected function create_thumb($hash) { global $config; $ok = false; switch ($config->get_string("video_thumb_engine")) { default: case 'static': $outname = warehouse_path("thumbs", $hash); copy("ext/handle_video/thumb.jpg", $outname); $ok = true; break; case 'ffmpeg': $ffmpeg = escapeshellcmd($config->get_string("thumb_ffmpeg_path")); $w = (int) $config->get_int("thumb_width"); $h = (int) $config->get_int("thumb_height"); $inname = escapeshellarg(warehouse_path("images", $hash)); $outname = escapeshellarg(warehouse_path("thumbs", $hash)); if ($config->get_bool("video_thumb_ignore_aspect_ratio") == true) { $cmd = escapeshellcmd("{$ffmpeg} -i {$inname} -ss 00:00:00.0 -f image2 -vframes 1 {$outname}"); } else { $scale = 'scale="' . escapeshellarg("if(gt(a,{$w}/{$h}),{$w},-1)") . ':' . escapeshellarg("if(gt(a,{$w}/{$h}),-1,{$h})") . '"'; $cmd = "{$ffmpeg} -i {$inname} -vf {$scale} -ss 00:00:00.0 -f image2 -vframes 1 {$outname}"; } exec($cmd, $output, $returnValue); if ((int) $returnValue == (int) 1) { $ok = true; } log_debug('handle_video', "Generating thumbnail with command `{$cmd}`, returns {$returnValue}"); break; } return $ok; }
public function onPageRequest(PageRequestEvent $event) { global $config, $database, $page; if ($event->page_matches("get_svg")) { $id = int_escape($event->get_arg(0)); $image = Image::by_id($id); $hash = $image->hash; $page->set_type("image/svg+xml"); $page->set_mode("data"); $page->set_data(file_get_contents(warehouse_path("images", $hash))); } }
public function onImageAddition(ImageAdditionEvent $event) { global $config; $access = $config->get_string("amazon_s3_access"); $secret = $config->get_string("amazon_s3_secret"); $bucket = $config->get_string("amazon_s3_bucket"); if (!empty($bucket)) { log_debug("amazon_s3", "Mirroring Image #" . $event->image->id . " to S3 #{$bucket}"); $s3 = new S3($access, $secret); $s3->putBucket($bucket, S3::ACL_PUBLIC_READ); $s3->putObjectFile(warehouse_path("thumbs", $event->image->hash), $bucket, 'thumbs/' . $event->image->hash, S3::ACL_PUBLIC_READ, array(), array("Content-Type" => "image/jpeg", "Content-Disposition" => "inline; filename=image-" . $event->image->id . ".jpg")); $s3->putObjectFile(warehouse_path("images", $event->image->hash), $bucket, 'images/' . $event->image->hash, S3::ACL_PUBLIC_READ, array(), array("Content-Type" => $event->image->get_mime_type(), "Content-Disposition" => "inline; filename=image-" . $event->image->id . "." . $event->image->ext)); } }
public function receive_event(Event $event) { if (is_null($this->theme)) { $this->theme = get_theme_object($this); } if ($event instanceof DataUploadEvent && $this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { $hash = $event->hash; $ha = substr($hash, 0, 2); if (!move_upload_to_archive($event)) { return; } send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); $image = $this->create_image_from_data(warehouse_path("images", $hash), $event->metadata); if (is_null($image)) { throw new UploadException("SVG handler failed to create image object from data"); } $iae = new ImageAdditionEvent($event->user, $image); send_event($iae); $event->image_id = $iae->image->id; } if ($event instanceof ThumbnailGenerationEvent && $this->supported_ext($event->type)) { $hash = $event->hash; $ha = substr($hash, 0, 2); global $config; // if($config->get_string("thumb_engine") == "convert") { // $w = $config->get_int("thumb_width"); // $h = $config->get_int("thumb_height"); // $q = $config->get_int("thumb_quality"); // $mem = $config->get_int("thumb_max_memory") / 1024 / 1024; // IM takes memory in MB // // exec("convert images/{$ha}/{$hash}[0] -geometry {$w}x{$h} -quality {$q} jpg:thumbs/{$ha}/{$hash}"); // } // else { copy("ext/handle_svg/thumb.jpg", warehouse_path("thumbs", $hash)); // } } if ($event instanceof DisplayingImageEvent && $this->supported_ext($event->image->ext)) { global $page; $this->theme->display_image($page, $event->image); } if ($event instanceof PageRequestEvent && $event->page_matches("get_svg")) { global $config, $database, $page; $id = int_escape($event->get_arg(0)); $image = Image::by_id($id); $hash = $image->hash; $page->set_type("image/svg+xml"); $page->set_mode("data"); $page->set_data(file_get_contents(warehouse_path("images", $hash))); } }
protected function create_thumb($hash) { $inname = warehouse_path("images", $hash); $outname = warehouse_path("thumbs", $hash); global $config; $ok = false; switch ($config->get_string("thumb_engine")) { default: case 'gd': $ok = $this->make_thumb_gd($inname, $outname); break; case 'convert': $ok = $this->make_thumb_convert($inname, $outname); break; } return $ok; }
/** * @param string $hash * @return bool */ protected function create_thumb($hash) { copy("ext/handle_mp3/thumb.jpg", warehouse_path("thumbs", $hash)); return true; }
private function create_thumb($hash) { global $config; $inname = warehouse_path("images", $hash); $outname = warehouse_path("thumbs", $hash); $w = $config->get_int("thumb_width"); $h = $config->get_int("thumb_height"); $q = $config->get_int("thumb_quality"); $mem = $config->get_int("thumb_max_memory") / 1024 / 1024; // IM takes memory in MB if ($config->get_bool("ico_convert")) { // "-limit memory $mem" broken? exec("convert {$inname}[0] -geometry {$w}x{$h} -quality {$q} jpg:{$outname}"); } else { copy($inname, $outname); } return true; }
public function receive_event(Event $event) { if (is_null($this->theme)) { $this->theme = get_theme_object($this); } if ($event instanceof DataUploadEvent && $this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { if (!move_upload_to_archive($event)) { return; } send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); /* Check if we are replacing an image */ if (array_key_exists('replace', $event->metadata) && isset($event->metadata['replace'])) { /* hax: This seems like such a dirty way to do this.. */ /* Validate things */ $image_id = int_escape($event->metadata['replace']); /* Check to make sure the image exists. */ $existing = Image::by_id($image_id); if (is_null($existing)) { throw new UploadException("Image to replace does not exist!"); } if ($existing->hash === $event->metadata['hash']) { throw new UploadException("The uploaded image is the same as the one to replace."); } // even more hax.. $event->metadata['tags'] = $existing->get_tag_list(); $image = $this->create_image_from_data(warehouse_path("images", $event->metadata['hash']), $event->metadata); if (is_null($image)) { throw new UploadException("Data handler failed to create image object from data"); } $ire = new ImageReplaceEvent($image_id, $image); send_event($ire); $event->image_id = $image_id; } else { $image = $this->create_image_from_data(warehouse_path("images", $event->hash), $event->metadata); if (is_null($image)) { throw new UploadException("Data handler failed to create image object from data"); } $iae = new ImageAdditionEvent($event->user, $image); send_event($iae); $event->image_id = $iae->image->id; // Rating Stuff. if (!empty($event->metadata['rating'])) { global $user; $rating = $event->metadata['rating']; send_event(new RatingSetEvent($image, $user, $rating)); } // Locked Stuff. if (!empty($event->metadata['locked'])) { $locked = $event->metadata['locked']; send_event(new LockSetEvent($image, !empty($locked))); } } } if ($event instanceof ThumbnailGenerationEvent && $this->supported_ext($event->type)) { $this->create_thumb($event->hash); } if ($event instanceof DisplayingImageEvent && $this->supported_ext($event->image->ext)) { global $page; $this->theme->display_image($page, $event->image); } if ($event instanceof SetupBuildingEvent) { $sb = $this->setup(); if ($sb) { $event->panel->add_block($sb); } } }
protected function create_thumb($hash) { copy("ext/handle_flash/thumb.jpg", warehouse_path("thumbs", $hash)); }
/** * Figure out where the thumbnail is on disk. * * @return string */ public function get_thumb_filename() { return warehouse_path("thumbs", $this->hash); }
private function download_all_images() { global $database, $page; $images = $database->get_all("SELECT hash, ext FROM images"); $filename = data_path('imgdump-' . date('Ymd') . '.zip'); $zip = new ZipArchive(); if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === TRUE) { foreach ($images as $img) { $img_loc = warehouse_path("images", $img["hash"], FALSE); $zip->addFile($img_loc, $img["hash"] . "." . $img["ext"]); } $zip->close(); } $page->set_mode("redirect"); $page->set_redirect(make_link($filename)); //TODO: Delete file after downloaded? return false; // we do want a redirect, but a manual one }
private function resize_image($image_id, $width, $height) { global $config; global $user; global $page; global $database; if ($height <= 0 && $width <= 0) { throw new ImageResizeException("Invalid options for height and width. ({$width} x {$height})"); } $image_obj = Image::by_id($image_id); $hash = $image_obj->hash; if (is_null($hash)) { throw new ImageResizeException("Image does not have a hash associated with it."); } $image_filename = warehouse_path("images", $hash); $info = getimagesize($image_filename); /* Get the image file type */ $pathinfo = pathinfo($image_obj->filename); $filetype = strtolower($pathinfo['extension']); if ($image_obj->width != $info[0] || $image_obj->height != $info[1]) { throw new ImageResizeException("The image size does not match what is in the database! - Aborting Resize."); } /* Check memory usage limits */ $memory_use = filesize($image_filename) * 2 + $width * $height * 4 + 4 * 1024 * 1024; $memory_limit = get_memory_limit(); if ($memory_use > $memory_limit) { throw new ImageResizeException("The image is too large to resize given the memory limits. ({$memory_use} > {$memory_limit})"); } /* Calculate the new size of the image */ if ($height > 0 && $width > 0) { $new_height = $height; $new_width = $width; } else { // Scale the new image if ($width == 0) { $factor = $height / $image_obj->height; } elseif ($height == 0) { $factor = $width / $image_obj->width; } else { $factor = min($width / $image_obj->width, $height / $image_obj->height); } $new_width = round($image_obj->width * $factor); $new_height = round($image_obj->height * $factor); } /* 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 ImageResizeException("Unsupported image type."); } /* Resize and resample the image */ $image_resized = 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_resized, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']); imagefill($image_resized, 0, 0, $transparency); imagecolortransparent($image_resized, $transparency); } elseif ($info[2] == IMAGETYPE_PNG) { imagealphablending($image_resized, false); $color = imagecolorallocatealpha($image_resized, 0, 0, 0, 127); imagefill($image_resized, 0, 0, $color); imagesavealpha($image_resized, true); } } imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $new_width, $new_height, $image_obj->width, $image_obj->height); /* Temp storage while we resize */ $tmp_filename = tempnam("/tmp", 'shimmie_resize'); if (empty($tmp_filename)) { throw new ImageResizeException("Unable to save temporary image file."); } /* Output to the same format as the original image */ switch ($info[2]) { case IMAGETYPE_GIF: imagegif($image_resized, $tmp_filename); break; case IMAGETYPE_JPEG: imagejpeg($image_resized, $tmp_filename); break; case IMAGETYPE_PNG: imagepng($image_resized, $tmp_filename); break; default: throw new ImageResizeException("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 (!file_exists(dirname($target))) { mkdir(dirname($target), 0755, true); } if (!@copy($tmp_filename, $target)) { throw new ImageResizeException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ({$target})"); } $new_filename = 'resized-' . $image_obj->filename; /* 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 \n\t\t\t\t\tfilename = :filename, filesize = :filesize,\thash = :hash, width = :width, height = :height\n\t\t\t\tWHERE \n\t\t\t\t\tid = :id\n\t\t\t\t", array("filename" => $new_filename, "filesize" => $new_size, "hash" => $new_hash, "width" => $new_width, "height" => $new_height, "id" => $image_id)); log_info("resize", "Resized Image #{$image_id} - New hash: {$new_hash}"); }
protected function create_thumb($hash) { // FIXME: scale image, as not all boards use 192x192 copy("ext/handle_flash/thumb.jpg", warehouse_path("thumbs", $hash)); }
/** * This function could be made much smaller by using the ImageReplaceEvent * ie: Pretend that we are replacing the image with a resized copy. * * @param Image $image_obj * @param int $width * @param int $height * @throws ImageResizeException */ private function resize_image(Image $image_obj, $width, $height) { global $config, $user, $page, $database; if ($height <= 0 && $width <= 0) { throw new ImageResizeException("Invalid options for height and width. ({$width} x {$height})"); } $hash = $image_obj->hash; $image_filename = warehouse_path("images", $hash); $info = getimagesize($image_filename); /* Get the image file type */ $pathinfo = pathinfo($image_obj->filename); $filetype = strtolower($pathinfo['extension']); if ($image_obj->width != $info[0] || $image_obj->height != $info[1]) { throw new ImageResizeException("The current image size does not match what is set in the database! - Aborting Resize."); } /* 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 */ if (isset($info['bits']) && isset($info['channels'])) { $memory_use = $info[0] * $info[1] * ($info['bits'] / 8) * $info['channels'] * 2.5 / 1024; } else { // // If we don't have bits and channel info from the image then assume default values // of 8 bits per color and 4 channels (R,G,B,A) -- ie: regular 24-bit color // $memory_use = $info[0] * $info[1] * 1 * 4 * 2.5 / 1024; } $memory_limit = get_memory_limit(); if ($memory_use > $memory_limit) { throw new ImageResizeException("The image is too large to resize given the memory limits. ({$memory_use} > {$memory_limit})"); } /* Calculate the new size of the image */ if ($height > 0 && $width > 0) { $new_height = $height; $new_width = $width; } else { // Scale the new image if ($width == 0) { $factor = $height / $image_obj->height; } elseif ($height == 0) { $factor = $width / $image_obj->width; } else { $factor = min($width / $image_obj->width, $height / $image_obj->height); } $new_width = round($image_obj->width * $factor); $new_height = round($image_obj->height * $factor); } /* 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 ImageResizeException("Unsupported image type (Only GIF, JPEG, and PNG are supported)."); } // Handle transparent images $image_resized = imagecreatetruecolor($new_width, $new_height); if ($info[2] == IMAGETYPE_GIF) { $transparency = imagecolortransparent($image); // If we have a specific transparent color if ($transparency >= 0) { // Get the original image's transparent color's RGB values $transparent_color = imagecolorsforindex($image, $transparency); // Allocate the same color in the new image resource $transparency = imagecolorallocate($image_resized, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']); // Completely fill the background of the new image with allocated color. imagefill($image_resized, 0, 0, $transparency); // Set the background color for new image to transparent imagecolortransparent($image_resized, $transparency); } } elseif ($info[2] == IMAGETYPE_PNG) { // // More info here: http://stackoverflow.com/questions/279236/how-do-i-resize-pngs-with-transparency-in-php // imagealphablending($image_resized, false); imagesavealpha($image_resized, true); $transparent_color = imagecolorallocatealpha($image_resized, 255, 255, 255, 127); imagefilledrectangle($image_resized, 0, 0, $new_width, $new_height, $transparent_color); } // Actually resize the image. imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $new_width, $new_height, $image_obj->width, $image_obj->height); /* Temp storage while we resize */ $tmp_filename = tempnam("/tmp", 'shimmie_resize'); if (empty($tmp_filename)) { throw new ImageResizeException("Unable to save temporary image file."); } /* Output to the same format as the original image */ switch ($info[2]) { case IMAGETYPE_GIF: imagegif($image_resized, $tmp_filename); break; case IMAGETYPE_JPEG: imagejpeg($image_resized, $tmp_filename); break; case IMAGETYPE_PNG: imagepng($image_resized, $tmp_filename); break; default: throw new ImageResizeException("Failed to save the new image - 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 ImageResizeException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ({$target})"); } $new_filename = 'resized-' . $image_obj->filename; /* 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 \n\t\t\t\t\tfilename = :filename, filesize = :filesize,\thash = :hash, width = :width, height = :height\n\t\t\t\tWHERE \n\t\t\t\t\tid = :id\n\t\t\t\t", array("filename" => $new_filename, "filesize" => $new_size, "hash" => $new_hash, "width" => $new_width, "height" => $new_height, "id" => $image_obj->id)); log_info("resize", "Resized Image #{$image_obj->id} - New hash: {$new_hash}"); }
/** * This function could be made much smaller by using the ImageReplaceEvent * ie: Pretend that we are replacing the image with a resized copy. * * @param Image $image_obj * @param int $width * @param int $height * @throws ImageResizeException */ private function resize_image(Image $image_obj, $width, $height) { global $database; if ($height <= 0 && $width <= 0) { throw new ImageResizeException("Invalid options for height and width. ({$width} x {$height})"); } $hash = $image_obj->hash; $image_filename = warehouse_path("images", $hash); $info = getimagesize($image_filename); /* Get the image file type */ $pathinfo = pathinfo($image_obj->filename); $filetype = strtolower($pathinfo['extension']); if ($image_obj->width != $info[0] || $image_obj->height != $info[1]) { throw new ImageResizeException("The current image size does not match what is set in the database! - Aborting Resize."); } $memory_use = $this->calc_memory_use($info); $memory_limit = get_memory_limit(); if ($memory_use > $memory_limit) { throw new ImageResizeException("The image is too large to resize given the memory limits. ({$memory_use} > {$memory_limit})"); } list($new_height, $new_width) = $this->calc_new_size($image_obj, $width, $height); /* 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 ImageResizeException("Unsupported image type (Only GIF, JPEG, and PNG are supported)."); } // Handle transparent images $image_resized = imagecreatetruecolor($new_width, $new_height); if ($info[2] == IMAGETYPE_GIF) { $transparency = imagecolortransparent($image); // If we have a specific transparent color if ($transparency >= 0) { // Get the original image's transparent color's RGB values $transparent_color = imagecolorsforindex($image, $transparency); // Allocate the same color in the new image resource $transparency = imagecolorallocate($image_resized, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']); // Completely fill the background of the new image with allocated color. imagefill($image_resized, 0, 0, $transparency); // Set the background color for new image to transparent imagecolortransparent($image_resized, $transparency); } } elseif ($info[2] == IMAGETYPE_PNG) { // // More info here: http://stackoverflow.com/questions/279236/how-do-i-resize-pngs-with-transparency-in-php // imagealphablending($image_resized, false); imagesavealpha($image_resized, true); $transparent_color = imagecolorallocatealpha($image_resized, 255, 255, 255, 127); imagefilledrectangle($image_resized, 0, 0, $new_width, $new_height, $transparent_color); } // Actually resize the image. imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $new_width, $new_height, $image_obj->width, $image_obj->height); /* Temp storage while we resize */ $tmp_filename = tempnam("/tmp", 'shimmie_resize'); if (empty($tmp_filename)) { throw new ImageResizeException("Unable to save temporary image file."); } /* Output to the same format as the original image */ switch ($info[2]) { case IMAGETYPE_GIF: imagegif($image_resized, $tmp_filename); break; case IMAGETYPE_JPEG: imagejpeg($image_resized, $tmp_filename); break; case IMAGETYPE_PNG: imagepng($image_resized, $tmp_filename); break; default: throw new ImageResizeException("Failed to save the new image - 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 ImageResizeException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ({$target})"); } $new_filename = 'resized-' . $image_obj->filename; /* 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("\n\t\t\tUPDATE images SET filename = :filename, filesize = :filesize, hash = :hash, width = :width, height = :height\n\t\t\tWHERE id = :id\n\t\t", array("filename" => $new_filename, "filesize" => $new_size, "hash" => $new_hash, "width" => $new_width, "height" => $new_height, "id" => $image_obj->id)); log_info("resize", "Resized Image #{$image_obj->id} - New hash: {$new_hash}"); }
/** * @param DataUploadEvent $event * @throws UploadException */ public function onDataUpload(DataUploadEvent $event) { $supported_ext = $this->supported_ext($event->type); $check_contents = $this->check_contents($event->tmpname); if ($supported_ext && $check_contents) { if (!move_upload_to_archive($event)) { return; } send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); /* Check if we are replacing an image */ if (array_key_exists('replace', $event->metadata) && isset($event->metadata['replace'])) { /* hax: This seems like such a dirty way to do this.. */ /* Validate things */ $image_id = int_escape($event->metadata['replace']); /* Check to make sure the image exists. */ $existing = Image::by_id($image_id); if (is_null($existing)) { throw new UploadException("Image to replace does not exist!"); } if ($existing->hash === $event->metadata['hash']) { throw new UploadException("The uploaded image is the same as the one to replace."); } // even more hax.. $event->metadata['tags'] = $existing->get_tag_list(); $image = $this->create_image_from_data(warehouse_path("images", $event->metadata['hash']), $event->metadata); if (is_null($image)) { throw new UploadException("Data handler failed to create image object from data"); } $ire = new ImageReplaceEvent($image_id, $image); send_event($ire); $event->image_id = $image_id; } else { $image = $this->create_image_from_data(warehouse_path("images", $event->hash), $event->metadata); if (is_null($image)) { throw new UploadException("Data handler failed to create image object from data"); } $iae = new ImageAdditionEvent($image); send_event($iae); $event->image_id = $iae->image->id; // Rating Stuff. if (!empty($event->metadata['rating'])) { $rating = $event->metadata['rating']; send_event(new RatingSetEvent($image, $rating)); } // Locked Stuff. if (!empty($event->metadata['locked'])) { $locked = $event->metadata['locked']; send_event(new LockSetEvent($image, !empty($locked))); } } } elseif ($supported_ext && !$check_contents) { throw new UploadException("Invalid or corrupted file"); } }
/** * This function could be made much smaller by using the ImageReplaceEvent * ie: Pretend that we are replacing the image with a rotated copy. * * @param int $image_id * @param int $deg * @throws ImageRotateException */ private function rotate_image($image_id, $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(ini_get('upload_tmp_dir'), '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 \n\t\t\t\t\tfilename = :filename, filesize = :filesize,\thash = :hash, width = :width, height = :height\n\t\t\t\tWHERE \n\t\t\t\t\tid = :id\n\t\t\t\t", 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}"); }
public function receive_event(Event $event) { if (is_null($this->theme)) { $this->theme = get_theme_object($this); } if ($event instanceof DataUploadEvent && $this->supported_ext($event->type) && $this->check_contents($event->tmpname)) { if (!move_upload_to_archive($event)) { return; } send_event(new ThumbnailGenerationEvent($event->hash, $event->type)); $image = $this->create_image_from_data(warehouse_path("images", $event->hash), $event->metadata); if (is_null($image)) { throw new UploadException("Data handler failed to create image object from data"); } $iae = new ImageAdditionEvent($event->user, $image); send_event($iae); $event->image_id = $iae->image->id; } if ($event instanceof ThumbnailGenerationEvent && $this->supported_ext($event->type)) { $this->create_thumb($event->hash); } if ($event instanceof DisplayingImageEvent && $this->supported_ext($event->image->ext)) { global $page; $this->theme->display_image($page, $event->image); } }
<?php // custom routing for stand-alone mode if (PHP_SAPI !== 'cli-server') { die('cli only'); } // warehouse files $matches = array(); if (preg_match('/\\/_(images|thumbs)\\/([0-9a-f]{32}).*$/', $_SERVER["REQUEST_URI"], $matches)) { header('Content-Type: image/jpeg'); print file_get_contents(warehouse_path($matches[1], $matches[2])); return true; } unset($matches); // use the default handler (serve static files, interpret php files) if (preg_match('/\\.(?:png|jpg|jpeg|gif|css|js|php)(\\?.*)?$/', $_SERVER["REQUEST_URI"])) { return false; } // all other requests (use shimmie routing based on URL) $_SERVER["PHP_SELF"] = '/'; $_GET['q'] = $_SERVER["REQUEST_URI"]; require_once "index.php";