WP_Image_Editor

Base image editor class from which implementations extend.

Defined (1)

The class is defined in the following location(s).

/wp-includes/class-wp-image-editor.php  
  1. abstract class WP_Image_Editor { 
  2. protected $file = null; 
  3. protected $size = null; 
  4. protected $mime_type = null; 
  5. protected $default_mime_type = 'image/jpeg'; 
  6. protected $quality = false; 
  7. protected $default_quality = 82; 
  8.  
  9. /** 
  10. * Each instance handles a single file. 
  11. * @param string $file Path to the file to load. 
  12. */ 
  13. public function __construct( $file ) { 
  14. $this->file = $file; 
  15.  
  16. /** 
  17. * Checks to see if current environment supports the editor chosen. 
  18. * Must be overridden in a sub-class. 
  19. * @since 3.5.0 
  20. * @static 
  21. * @access public 
  22. * @abstract 
  23. * @param array $args 
  24. * @return bool 
  25. */ 
  26. public static function test( $args = array() ) { 
  27. return false; 
  28.  
  29. /** 
  30. * Checks to see if editor supports the mime-type specified. 
  31. * Must be overridden in a sub-class. 
  32. * @since 3.5.0 
  33. * @static 
  34. * @access public 
  35. * @abstract 
  36. * @param string $mime_type 
  37. * @return bool 
  38. */ 
  39. public static function supports_mime_type( $mime_type ) { 
  40. return false; 
  41.  
  42. /** 
  43. * Loads image from $this->file into editor. 
  44. * @since 3.5.0 
  45. * @access protected 
  46. * @abstract 
  47. * @return bool|WP_Error True if loaded; WP_Error on failure. 
  48. */ 
  49. abstract public function load(); 
  50.  
  51. /** 
  52. * Saves current image to file. 
  53. * @since 3.5.0 
  54. * @access public 
  55. * @abstract 
  56. * @param string $destfilename 
  57. * @param string $mime_type 
  58. * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} 
  59. */ 
  60. abstract public function save( $destfilename = null, $mime_type = null ); 
  61.  
  62. /** 
  63. * Resizes current image. 
  64. * At minimum, either a height or width must be provided. 
  65. * If one of the two is set to null, the resize will 
  66. * maintain aspect ratio according to the provided dimension. 
  67. * @since 3.5.0 
  68. * @access public 
  69. * @abstract 
  70. * @param int|null $max_w Image width. 
  71. * @param int|null $max_h Image height. 
  72. * @param bool $crop 
  73. * @return bool|WP_Error 
  74. */ 
  75. abstract public function resize( $max_w, $max_h, $crop = false ); 
  76.  
  77. /** 
  78. * Resize multiple images from a single source. 
  79. * @since 3.5.0 
  80. * @access public 
  81. * @abstract 
  82. * @param array $sizes { 
  83. * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. 
  84. * @type array $size { 
  85. * @type int $width Image width. 
  86. * @type int $height Image height. 
  87. * @type bool $crop Optional. Whether to crop the image. Default false. 
  88. * } 
  89. * } 
  90. * @return array An array of resized images metadata by size. 
  91. */ 
  92. abstract public function multi_resize( $sizes ); 
  93.  
  94. /** 
  95. * Crops Image. 
  96. * @since 3.5.0 
  97. * @access public 
  98. * @abstract 
  99. * @param int $src_x The start x position to crop from. 
  100. * @param int $src_y The start y position to crop from. 
  101. * @param int $src_w The width to crop. 
  102. * @param int $src_h The height to crop. 
  103. * @param int $dst_w Optional. The destination width. 
  104. * @param int $dst_h Optional. The destination height. 
  105. * @param bool $src_abs Optional. If the source crop points are absolute. 
  106. * @return bool|WP_Error 
  107. */ 
  108. abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ); 
  109.  
  110. /** 
  111. * Rotates current image counter-clockwise by $angle. 
  112. * @since 3.5.0 
  113. * @access public 
  114. * @abstract 
  115. * @param float $angle 
  116. * @return bool|WP_Error 
  117. */ 
  118. abstract public function rotate( $angle ); 
  119.  
  120. /** 
  121. * Flips current image. 
  122. * @since 3.5.0 
  123. * @access public 
  124. * @abstract 
  125. * @param bool $horz Flip along Horizontal Axis 
  126. * @param bool $vert Flip along Vertical Axis 
  127. * @return bool|WP_Error 
  128. */ 
  129. abstract public function flip( $horz, $vert ); 
  130.  
  131. /** 
  132. * Streams current image to browser. 
  133. * @since 3.5.0 
  134. * @access public 
  135. * @abstract 
  136. * @param string $mime_type 
  137. * @return bool|WP_Error 
  138. */ 
  139. abstract public function stream( $mime_type = null ); 
  140.  
  141. /** 
  142. * Gets dimensions of image. 
  143. * @since 3.5.0 
  144. * @access public 
  145. * @return array {'width'=>int, 'height'=>int} 
  146. */ 
  147. public function get_size() { 
  148. return $this->size; 
  149.  
  150. /** 
  151. * Sets current image size. 
  152. * @since 3.5.0 
  153. * @access protected 
  154. * @param int $width 
  155. * @param int $height 
  156. * @return true 
  157. */ 
  158. protected function update_size( $width = null, $height = null ) { 
  159. $this->size = array( 
  160. 'width' => (int) $width,  
  161. 'height' => (int) $height 
  162. ); 
  163. return true; 
  164.  
  165. /** 
  166. * Gets the Image Compression quality on a 1-100% scale. 
  167. * @since 4.0.0 
  168. * @access public 
  169. * @return int $quality Compression Quality. Range: [1, 100] 
  170. */ 
  171. public function get_quality() { 
  172. if ( ! $this->quality ) { 
  173. $this->set_quality(); 
  174.  
  175. return $this->quality; 
  176.  
  177. /** 
  178. * Sets Image Compression quality on a 1-100% scale. 
  179. * @since 3.5.0 
  180. * @access public 
  181. * @param int $quality Compression Quality. Range: [1, 100] 
  182. * @return true|WP_Error True if set successfully; WP_Error on failure. 
  183. */ 
  184. public function set_quality( $quality = null ) { 
  185. if ( null === $quality ) { 
  186. /** 
  187. * Filters the default image compression quality setting. 
  188. * Applies only during initial editor instantiation, or when set_quality() is run 
  189. * manually without the `$quality` argument. 
  190. * set_quality() has priority over the filter. 
  191. * @since 3.5.0 
  192. * @param int $quality Quality level between 1 (low) and 100 (high). 
  193. * @param string $mime_type Image mime type. 
  194. */ 
  195. $quality = apply_filters( 'wp_editor_set_quality', $this->default_quality, $this->mime_type ); 
  196.  
  197. if ( 'image/jpeg' == $this->mime_type ) { 
  198. /** 
  199. * Filters the JPEG compression quality for backward-compatibility. 
  200. * Applies only during initial editor instantiation, or when set_quality() is run 
  201. * manually without the `$quality` argument. 
  202. * set_quality() has priority over the filter. 
  203. * The filter is evaluated under two contexts: 'image_resize', and 'edit_image',  
  204. * (when a JPEG image is saved to file). 
  205. * @since 2.5.0 
  206. * @param int $quality Quality level between 0 (low) and 100 (high) of the JPEG. 
  207. * @param string $context Context of the filter. 
  208. */ 
  209. $quality = apply_filters( 'jpeg_quality', $quality, 'image_resize' ); 
  210.  
  211. if ( $quality < 0 || $quality > 100 ) { 
  212. $quality = $this->default_quality; 
  213.  
  214. // Allow 0, but squash to 1 due to identical images in GD, and for backward compatibility. 
  215. if ( 0 === $quality ) { 
  216. $quality = 1; 
  217.  
  218. if ( ( $quality >= 1 ) && ( $quality <= 100 ) ) { 
  219. $this->quality = $quality; 
  220. return true; 
  221. } else { 
  222. return new WP_Error( 'invalid_image_quality', __('Attempted to set image quality outside of the range [1, 100].') ); 
  223.  
  224. /** 
  225. * Returns preferred mime-type and extension based on provided 
  226. * file's extension and mime, or current file's extension and mime. 
  227. * Will default to $this->default_mime_type if requested is not supported. 
  228. * Provides corrected filename only if filename is provided. 
  229. * @since 3.5.0 
  230. * @access protected 
  231. * @param string $filename 
  232. * @param string $mime_type 
  233. * @return array { filename|null, extension, mime-type } 
  234. */ 
  235. protected function get_output_format( $filename = null, $mime_type = null ) { 
  236. $new_ext = null; 
  237.  
  238. // By default, assume specified type takes priority 
  239. if ( $mime_type ) { 
  240. $new_ext = $this->get_extension( $mime_type ); 
  241.  
  242. if ( $filename ) { 
  243. $file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) ); 
  244. $file_mime = $this->get_mime_type( $file_ext ); 
  245. else { 
  246. // If no file specified, grab editor's current extension and mime-type. 
  247. $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) ); 
  248. $file_mime = $this->mime_type; 
  249.  
  250. // Check to see if specified mime-type is the same as type implied by 
  251. // file extension. If so, prefer extension from file. 
  252. if ( ! $mime_type || ( $file_mime == $mime_type ) ) { 
  253. $mime_type = $file_mime; 
  254. $new_ext = $file_ext; 
  255.  
  256. // Double-check that the mime-type selected is supported by the editor. 
  257. // If not, choose a default instead. 
  258. if ( ! $this->supports_mime_type( $mime_type ) ) { 
  259. /** 
  260. * Filters default mime type prior to getting the file extension. 
  261. * @see wp_get_mime_types() 
  262. * @since 3.5.0 
  263. * @param string $mime_type Mime type string. 
  264. */ 
  265. $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type ); 
  266. $new_ext = $this->get_extension( $mime_type ); 
  267.  
  268. if ( $filename ) { 
  269. $dir = pathinfo( $filename, PATHINFO_DIRNAME ); 
  270. $ext = pathinfo( $filename, PATHINFO_EXTENSION ); 
  271.  
  272. $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}"; 
  273.  
  274. return array( $filename, $new_ext, $mime_type ); 
  275.  
  276. /** 
  277. * Builds an output filename based on current file, and adding proper suffix 
  278. * @since 3.5.0 
  279. * @access public 
  280. * @param string $suffix 
  281. * @param string $dest_path 
  282. * @param string $extension 
  283. * @return string filename 
  284. */ 
  285. public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) { 
  286. // $suffix will be appended to the destination filename, just before the extension 
  287. if ( ! $suffix ) 
  288. $suffix = $this->get_suffix(); 
  289.  
  290. $dir = pathinfo( $this->file, PATHINFO_DIRNAME ); 
  291. $ext = pathinfo( $this->file, PATHINFO_EXTENSION ); 
  292.  
  293. $name = wp_basename( $this->file, ".$ext" ); 
  294. $new_ext = strtolower( $extension ? $extension : $ext ); 
  295.  
  296. if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) ) 
  297. $dir = $_dest_path; 
  298.  
  299. return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}"; 
  300.  
  301. /** 
  302. * Builds and returns proper suffix for file based on height and width. 
  303. * @since 3.5.0 
  304. * @access public 
  305. * @return false|string suffix 
  306. */ 
  307. public function get_suffix() { 
  308. if ( ! $this->get_size() ) 
  309. return false; 
  310.  
  311. return "{$this->size['width']}x{$this->size['height']}"; 
  312.  
  313. /** 
  314. * Either calls editor's save function or handles file as a stream. 
  315. * @since 3.5.0 
  316. * @access protected 
  317. * @param string|stream $filename 
  318. * @param callable $function 
  319. * @param array $arguments 
  320. * @return bool 
  321. */ 
  322. protected function make_image( $filename, $function, $arguments ) { 
  323. if ( $stream = wp_is_stream( $filename ) ) { 
  324. ob_start(); 
  325. } else { 
  326. // The directory containing the original file may no longer exist when using a replication plugin. 
  327. wp_mkdir_p( dirname( $filename ) ); 
  328.  
  329. $result = call_user_func_array( $function, $arguments ); 
  330.  
  331. if ( $result && $stream ) { 
  332. $contents = ob_get_contents(); 
  333.  
  334. $fp = fopen( $filename, 'w' ); 
  335.  
  336. if ( ! $fp ) 
  337. return false; 
  338.  
  339. fwrite( $fp, $contents ); 
  340. fclose( $fp ); 
  341.  
  342. if ( $stream ) { 
  343. ob_end_clean(); 
  344.  
  345. return $result; 
  346.  
  347. /** 
  348. * Returns first matched mime-type from extension,  
  349. * as mapped from wp_get_mime_types() 
  350. * @since 3.5.0 
  351. * @static 
  352. * @access protected 
  353. * @param string $extension 
  354. * @return string|false 
  355. */ 
  356. protected static function get_mime_type( $extension = null ) { 
  357. if ( ! $extension ) 
  358. return false; 
  359.  
  360. $mime_types = wp_get_mime_types(); 
  361. $extensions = array_keys( $mime_types ); 
  362.  
  363. foreach ( $extensions as $_extension ) { 
  364. if ( preg_match( "/{$extension}/i", $_extension ) ) { 
  365. return $mime_types[$_extension]; 
  366.  
  367. return false; 
  368.  
  369. /** 
  370. * Returns first matched extension from Mime-type,  
  371. * as mapped from wp_get_mime_types() 
  372. * @since 3.5.0 
  373. * @static 
  374. * @access protected 
  375. * @param string $mime_type 
  376. * @return string|false 
  377. */ 
  378. protected static function get_extension( $mime_type = null ) { 
  379. $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) ); 
  380.  
  381. if ( empty( $extensions[0] ) ) 
  382. return false; 
  383.  
  384. return $extensions[0];