/** * @param WP_Image_Editor $image */ protected function get_target_sizes(\WP_Image_Editor $image) { $w = $this->w; $h = $this->h; $crop = $this->crop; $current_size = $image->get_size(); $src_w = $current_size['width']; $src_h = $current_size['height']; $src_ratio = $src_w / $src_h; if (!$h) { $h = round($w / $src_ratio); } if (!$w) { //the user wants to resize based on constant height $w = round($h * $src_ratio); } if (!$crop) { return array('x' => 0, 'y' => 0, 'src_w' => $src_w, 'src_h' => $src_h, 'target_w' => $w, 'target_h' => $h); } // Get ratios $dest_ratio = $w / $h; $src_wt = $src_h * $dest_ratio; $src_ht = $src_w / $dest_ratio; $src_x = $src_w / 2 - $src_wt / 2; $src_y = ($src_h - $src_ht) / 6; //now specific overrides based on options: switch ($crop) { case 'center': // Get source x and y $src_x = round(($src_w - $src_wt) / 2); $src_y = round(($src_h - $src_ht) / 2); break; case 'top': $src_y = 0; break; case 'bottom': $src_y = $src_h - $src_ht; break; case 'top-center': $src_y = round(($src_h - $src_ht) / 4); break; case 'bottom-center': $src_y = $src_h - $src_ht - round(($src_h - $src_ht) / 4); break; case 'left': $src_x = 0; break; case 'right': $src_x = $src_w - $src_wt; break; } // Crop the image return $dest_ratio > $src_ratio ? array('x' => 0, 'y' => $src_y, 'src_w' => $src_w, 'src_h' => $src_ht, 'target_w' => $w, 'target_h' => $h) : array('x' => $src_x, 'y' => 0, 'src_w' => $src_wt, 'src_h' => $src_h, 'target_w' => $w, 'target_h' => $h); }
/** * Tests which editors are capable of supporting the request. * * @since 3.5.0 * @access private * * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request. */ private static final function choose_implementation() { if (null === self::$implementation) { $request_order = apply_filters('wp_editors', array('imagick', 'gd')); // Loop over each editor on each request looking for one which will serve this request's needs foreach ($request_order as $editor) { $class = 'WP_Image_Editor_' . $editor; // Check to see if this editor is a possibility, calls the editor statically if (!call_user_func(array($class, 'test'))) { continue; } self::$implementation = $class; break; } } return self::$implementation; }
/** * Scale down an image to fit a particular size and save a new copy of the image. * * The PNG transparency will be preserved using the function, as well as the * image type. If the file going in is PNG, then the resized image is going to * be PNG. The only supported image types are PNG, GIF, and JPEG. * * Some functionality requires API to exist, so some PHP version may lose out * support. This is not the fault of WordPress (where functionality is * downgraded, not actual defects), but of your PHP version. * * @since 2.5.0 * @deprecated 3.5.0 * @see WP_Image_Editor * * @param string $file Image file path. * @param int $max_w Maximum width to resize to. * @param int $max_h Maximum height to resize to. * @param bool $crop Optional. Whether to crop image or resize. * @param string $suffix Optional. File suffix. * @param string $dest_path Optional. New image file path. * @param int $jpeg_quality Optional, default is 90. Image quality percentage. * @return mixed WP_Error on failure. String with new destination path. */ function image_resize($file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90) { _deprecated_function(__FUNCTION__, '3.5', 'WP_Image_Editor'); $editor = WP_Image_Editor::get_instance($file); if (is_wp_error($editor)) { return $editor; } $editor->set_quality($jpeg_quality); $resized = $editor->resize($max_w, $max_h, $crop); if (is_wp_error($resized)) { return $resized; } $dest_file = $editor->generate_filename($suffix, $dest_path); $saved = $editor->save($dest_file); if (is_wp_error($saved)) { return $saved; } return $dest_file; }
/** * Either calls editor's save function or handles file as a stream. * * @since 3.5.0 * @access protected * * @param string|stream $filename * @param callable $function * @param array $arguments * @return boolean */ protected function make_image($filename, $function, $arguments) { if (wp_is_stream($filename)) { $arguments[1] = null; } return parent::make_image($filename, $function, $arguments); }
/** * Generate post thumbnail attachment meta data. * * @since 2.1.0 * * @param int $attachment_id Attachment Id to process. * @param string $file Filepath of the Attached image. * @return mixed Metadata for attachment. */ function wp_generate_attachment_metadata($attachment_id, $file) { $attachment = get_post($attachment_id); $metadata = array(); if (preg_match('!^image/!', get_post_mime_type($attachment)) && file_is_displayable_image($file)) { $imagesize = getimagesize($file); $metadata['width'] = $imagesize[0]; $metadata['height'] = $imagesize[1]; // Make the file path relative to the upload dir $metadata['file'] = _wp_relative_upload_path($file); // make thumbnails and other intermediate sizes global $_wp_additional_image_sizes; foreach (get_intermediate_image_sizes() as $s) { $sizes[$s] = array('width' => '', 'height' => '', 'crop' => false); if (isset($_wp_additional_image_sizes[$s]['width'])) { $sizes[$s]['width'] = intval($_wp_additional_image_sizes[$s]['width']); } else { $sizes[$s]['width'] = get_option("{$s}_size_w"); } // For default sizes set in options if (isset($_wp_additional_image_sizes[$s]['height'])) { $sizes[$s]['height'] = intval($_wp_additional_image_sizes[$s]['height']); } else { $sizes[$s]['height'] = get_option("{$s}_size_h"); } // For default sizes set in options if (isset($_wp_additional_image_sizes[$s]['crop'])) { $sizes[$s]['crop'] = intval($_wp_additional_image_sizes[$s]['crop']); } else { $sizes[$s]['crop'] = get_option("{$s}_crop"); } // For default sizes set in options } $sizes = apply_filters('intermediate_image_sizes_advanced', $sizes); $editor = WP_Image_Editor::get_instance($file); if (!is_wp_error($editor)) { $metadata['sizes'] = $editor->multi_resize($sizes); } // fetch additional metadata from exif/iptc $image_meta = wp_read_image_metadata($file); if ($image_meta) { $metadata['image_meta'] = $image_meta; } } return apply_filters('wp_generate_attachment_metadata', $metadata, $attachment_id); }
/** * Test that wp_save_image_file doesn't have a deprecated argument when passed a WP_Image_Editor * @ticket 6821 */ public function test_wp_save_image_file_not_deprecated_with_wp_image_editor() { // Call wp_save_image_file include_once ABSPATH . 'wp-admin/includes/image-edit.php'; $file = wp_tempnam(); $img = WP_Image_Editor::get_instance(DIR_TESTDATA . '/images/canola.jpg'); wp_save_image_file($file, $img, 'image/jpeg', 1); unset($img); @unlink($file); // Check if the arg was deprecated $check = $this->was_deprecated('argument', 'wp_save_image_file'); $this->assertFalse($check); }
/** * Test that mime types are correctly inferred from file extensions * @ticket 6821 */ public function test_inferred_mime_types() { // Mime types $mime_types = array('jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', 'unk' => 'image/jpeg'); // Test each image editor engine $classes = array('WP_Image_Editor_GD', 'WP_Image_Editor_Imagick'); foreach ($classes as $class) { // If the image editor isn't available, skip it if (!call_user_func(array($class, 'test'))) { continue; } $filter = create_function('', "return '{$class}';"); add_filter('image_editor_class', $filter); // Save the image as each file extension, check the mime type $img = WP_Image_Editor::get_instance(DIR_TESTDATA . '/images/canola.jpg'); $temp = get_temp_dir(); foreach ($mime_types as $ext => $mime_type) { $file = wp_unique_filename($temp, uniqid() . ".{$ext}"); $ret = $img->save(trailingslashit($temp) . $file); $this->assertNotEmpty($ret); $this->assertNotInstanceOf('WP_Error', $ret); $this->assertEquals($mime_type, $this->get_mime_type($ret['path'])); @unlink($file); @unlink($ret['path']); } // Clean up unset($img); } }
/** * Sets or updates current image size. * * @since 3.5.0 * @access protected * * @param int $width * @param int $height */ protected function update_size($width = false, $height = false) { if (!$width) { $width = imagesx($this->image); } if (!$height) { $height = imagesy($this->image); } return parent::update_size($width, $height); }
/** * Saves image to post along with enqueued changes * in $_REQUEST['history'] * * @param int $post_id * @return \stdClass */ function wp_save_image($post_id) { $return = new stdClass(); $success = $delete = $scaled = $nocrop = false; $post = get_post($post_id); $img = WP_Image_Editor::get_instance(_load_image_to_edit_path($post_id, 'full')); if (is_wp_error($img)) { $return->error = esc_js(__('Unable to create new image.')); return $return; } $fwidth = !empty($_REQUEST['fwidth']) ? intval($_REQUEST['fwidth']) : 0; $fheight = !empty($_REQUEST['fheight']) ? intval($_REQUEST['fheight']) : 0; $target = !empty($_REQUEST['target']) ? preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['target']) : ''; $scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do']; if ($scale && $fwidth > 0 && $fheight > 0) { $size = $img->get_size(); $sX = $size['width']; $sY = $size['height']; // check if it has roughly the same w / h ratio $diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2); if (-0.1 < $diff && $diff < 0.1) { // scale the full size image if ($img->resize($fwidth, $fheight)) { $scaled = true; } } if (!$scaled) { $return->error = esc_js(__('Error while saving the scaled image. Please reload the page and try again.')); return $return; } } elseif (!empty($_REQUEST['history'])) { $changes = json_decode(stripslashes($_REQUEST['history'])); if ($changes) { $img = image_edit_apply_changes($img, $changes); } } else { $return->error = esc_js(__('Nothing to save, the image has not changed.')); return $return; } $meta = wp_get_attachment_metadata($post_id); $backup_sizes = get_post_meta($post->ID, '_wp_attachment_backup_sizes', true); if (!is_array($meta)) { $return->error = esc_js(__('Image data does not exist. Please re-upload the image.')); return $return; } if (!is_array($backup_sizes)) { $backup_sizes = array(); } // generate new filename $path = get_attached_file($post_id); $path_parts = pathinfo($path); $filename = $path_parts['filename']; $suffix = time() . rand(100, 999); if (defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE && isset($backup_sizes['full-orig']) && $backup_sizes['full-orig']['file'] != $path_parts['basename']) { if ('thumbnail' == $target) { $new_path = "{$path_parts['dirname']}/{$filename}-temp.{$path_parts['extension']}"; } else { $new_path = $path; } } else { while (true) { $filename = preg_replace('/-e([0-9]+)$/', '', $filename); $filename .= "-e{$suffix}"; $new_filename = "{$filename}.{$path_parts['extension']}"; $new_path = "{$path_parts['dirname']}/{$new_filename}"; if (file_exists($new_path)) { $suffix++; } else { break; } } } // save the full-size file, also needed to create sub-sizes if (!wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id)) { $return->error = esc_js(__('Unable to save the image.')); return $return; } if ('nothumb' == $target || 'all' == $target || 'full' == $target || $scaled) { $tag = false; if (isset($backup_sizes['full-orig'])) { if ((!defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE) && $backup_sizes['full-orig']['file'] != $path_parts['basename']) { $tag = "full-{$suffix}"; } } else { $tag = 'full-orig'; } if ($tag) { $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']); } $success = update_attached_file($post_id, $new_path); $meta['file'] = _wp_relative_upload_path($new_path); $size = $img->get_size(); $meta['width'] = $size['width']; $meta['height'] = $size['height']; if ($success && ('nothumb' == $target || 'all' == $target)) { $sizes = get_intermediate_image_sizes(); if ('nothumb' == $target) { $sizes = array_diff($sizes, array('thumbnail')); } } $return->fw = $meta['width']; $return->fh = $meta['height']; } elseif ('thumbnail' == $target) { $sizes = array('thumbnail'); $success = $delete = $nocrop = true; } if (isset($sizes)) { $_sizes = array(); foreach ($sizes as $size) { $tag = false; if (isset($meta['sizes'][$size])) { if (isset($backup_sizes["{$size}-orig"])) { if ((!defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE) && $backup_sizes["{$size}-orig"]['file'] != $meta['sizes'][$size]['file']) { $tag = "{$size}-{$suffix}"; } } else { $tag = "{$size}-orig"; } if ($tag) { $backup_sizes[$tag] = $meta['sizes'][$size]; } } $crop = $nocrop ? false : get_option("{$size}_crop"); $_sizes[$size] = array('width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop); } $meta['sizes'] = $img->multi_resize($_sizes); } unset($img); if ($success) { wp_update_attachment_metadata($post_id, $meta); update_post_meta($post_id, '_wp_attachment_backup_sizes', $backup_sizes); if ($target == 'thumbnail' || $target == 'all' || $target == 'full') { $file_url = wp_get_attachment_url($post_id); if ($thumb = $meta['sizes']['thumbnail']) { $return->thumbnail = path_join(dirname($file_url), $thumb['file']); } else { $return->thumbnail = "{$file_url}?w=128&h=128"; } } } else { $delete = true; } if ($delete) { $delpath = apply_filters('wp_delete_file', $new_path); @unlink($delpath); } $return->msg = esc_js(__('Image saved')); return $return; }
/** * Sets Image Compression quality on a 1-100% scale. * * @since 3.5.0 * @access public * * @param int $quality Compression Quality. Range: [1,100] * @return true|WP_Error True if set successfully; WP_Error on failure. */ public function set_quality($quality = null) { $quality_result = parent::set_quality($quality); if (is_wp_error($quality_result)) { return $quality_result; } else { $quality = $this->get_quality(); } try { if ('image/jpeg' == $this->mime_type) { $this->image->setImageCompressionQuality($quality); $this->image->setImageCompression(imagick::COMPRESSION_JPEG); } else { $this->image->setImageCompressionQuality($quality); } } catch (Exception $e) { return new WP_Error('image_quality_error', $e->getMessage()); } return true; }
/** * Resize an image to make a thumbnail or intermediate size. * * The returned array has the file size, the image width, and image height. The * filter 'image_make_intermediate_size' can be used to hook in and change the * values of the returned array. The only parameter is the resized file path. * * @since 2.5.0 * * @param string $file File path. * @param int $width Image width. * @param int $height Image height. * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize. * @return bool|array False, if no image was created. Metadata array on success. */ function image_make_intermediate_size($file, $width, $height, $crop = false) { if ($width || $height) { $editor = WP_Image_Editor::get_instance($file); if (is_wp_error($editor->resize($width, $height, $crop))) { } return false; $resized_file = $editor->save(); if (!is_wp_error($resized_file) && $resized_file) { unset($resized_file['path']); return $resized_file; } } return false; }
/** * Test get_suffix * @ticket 6821 */ public function test_get_suffix() { $editor = WP_Image_Editor::get_instance(DIR_TESTDATA . '/images/canola.jpg'); // Size should be false by default $this->assertFalse($editor->get_suffix()); // Set a size $size = array('height' => 50, 'width' => 100); $property = new ReflectionProperty($editor, 'size'); $property->setAccessible(true); $property->setValue($editor, $size); $this->assertEquals('100x50', $editor->get_suffix()); }
/** * Sets or updates current image size. * * @since 3.5.0 * @access protected * * @param int $width * @param int $height */ protected function update_size($width = null, $height = null) { $size = null; if (!$width || !$height) { try { $size = array('width' => $this->image->getimagewidth(), 'height' => $this->image->getimageheight()); } catch (Exception $e) { return new WP_Error('invalid_image', __('Could not read image size', 'connections'), $this->file); } } if (!$width) { $width = $size['width']; } if (!$height) { $height = $size['height']; } return parent::update_size($width, $height); }
/** * Sets or updates current image size. * * @since 3.5.0 * @access protected * * @param int $width * @param int $height * * @return true|WP_Error */ protected function update_size($width = null, $height = null) { $size = null; if (!$width || !$height) { try { $size = $this->image->getImageGeometry(); } catch (Exception $e) { return new WP_Error('invalid_image', __('Could not read image size'), $this->file); } } if (!$width) { $width = $size['width']; } if (!$height) { $height = $size['height']; } return parent::update_size($width, $height); }