BP_GOPP_Image_Editor_GS
GOPP Image Editor Class for producing JPEG from PDF using Ghostscript.
Description
Source
File: bp-document/classes/class-bp-gopp-image-editor-gs.php
class BP_GOPP_Image_Editor_GS extends WP_Image_Editor { /** * Override the default quality to lessen file size. * * @access protected * @var int */ protected $default_quality = 70; /** * Resolution of output JPEG (DPI). * * @access protected * @var int */ protected $resolution = null; protected $default_resolution = 128; /** * Page to render. * * @access protected * @var int */ protected $page = null; protected $default_page = 1; /** * Whether on Windows or not. * * @static * @access protected * @var bool */ protected static $is_win = null; /** * The path to the Ghostscript executable. * * @static * @access protected * @var string */ protected static $gs_cmd_path = null; /** * Checks to see if current environment supports Ghostscript and whether we're compatible with args if any. * In particular if given 'path' argument then checks filename (but not its existence or magic bytes). * * @since BuddyBoss 1.4.0 * * @static * @access public * * @param array $args * @return bool */ public static function test( $args = array() ) { // Ensure given 'mime_type' arg, as if not _wp_image_editor_choose() won't call supports_mime_type() subsequently // and will return this as a supporting implementation, which is probably not what callers expect. if ( ! isset( $args['mime_type'] ) ) { return false; } // Check that exec() is (probably) available and we're not in safe_mode. if ( ! function_exists( 'exec' ) || ini_get( 'safe_mode' ) ) { return false; } // Must have path to Ghostscript executable. if ( ! self::gs_cmd_path() ) { return false; } // No manipulation supported - dedicated to producing JPEG preview. if ( isset( $args['methods'] ) ) { $unsupported_methods = array( 'resize', 'multi_resize', 'crop', 'rotate', 'flip', 'stream' ); if ( array_intersect( $unsupported_methods, $args['methods'] ) ) { return false; } } // Do strict file name check if given path. if ( isset( $args['path'] ) && true !== self::gs_valid( $args['path'], true /*no_read_check*/ ) ) { return false; } return true; } /** * Checks to see if editor supports the mime-type specified. * * @since BuddyBoss 1.4.0 * * @static * @access public * * @param string $mime_type * @return bool */ public static function supports_mime_type( $mime_type ) { return 'pdf' === strtolower( self::get_extension( $mime_type ) ); } /** * Checks validity and existence of file and sets mime type and calls `set_resolution` and `set_page` and `set_quality` (firing filters). * * @since BuddyBoss 1.4.0 * @access protected * * @return true|WP_Error True if loaded; WP_Error on failure. */ public function load() { if ( true !== ( $result = self::gs_valid( $this->file ) ) ) { return new WP_Error( 'invalid_image', $result, $this->file ); } list( $filename, $extension, $mime_type ) = $this->get_output_format( $this->file ); $this->mime_type = $mime_type; // Allow chance for gopp_editor_set_resolution filter to fire by calling set_resolution() with null arg (mimicking set_quality() behavior). if ( is_wp_error( $result = $this->set_resolution() ) ) { return $result; } // Similarly for page to render. if ( is_wp_error( $result = $this->set_page() ) ) { return $result; } return $this->set_quality(); } /** * Creates JPEG preview from PDF. * * @since BuddyBoss 1.4.0 * @access public * * @param string $destfilename * @param string $mime_type * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} */ public function save( $destfilename = null, $mime_type = null ) { list( $filename, $extension, $mime_type ) = $this->get_output_format( $destfilename, $mime_type ); if ( 'image/jpeg' !== $mime_type ) { return new WP_Error( 'image_save_error', __( 'Unsupported MIME type.', 'buddyboss' ), $mime_type ); } if ( ! $filename || ! ( $dirname = dirname( $filename ) ) ) { return new WP_Error( 'image_save_error', __( 'Unsupported destination.', 'buddyboss' ), $filename ); } // Make sure not to overwrite existing JPEG with same name. Redundant now for WP 4.7.3+ after #39875, but keep for BC. $filename = $dirname . '/' . wp_unique_filename( $dirname, wp_basename( $filename ) ); if ( ! ( $cmd = self::gs_cmd( $this->get_gs_args( $filename ) ) ) ) { return new WP_Error( 'image_save_error', __( 'No Ghostscript.', 'buddyboss' ) ); } $return_var = -1; $output = array(); exec( $cmd, $output, $return_var ); if ( 0 !== $return_var ) { do_action( 'gopp_error', __CLASS__, __FUNCTION__, __LINE__, compact( 'cmd', 'return_var', 'output' ) ); return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed', 'buddyboss' ) ); } $size = @ getimagesize( $filename ); if ( ! $size ) { return new WP_Error( 'image_save_error', __( 'Could not read image size.', 'buddyboss' ) ); } // Transmogrify into the JPEG file. $this->file = $filename; $this->mime_type = $mime_type; $this->update_size( $size[0], $size[1] ); // Set correct file permissions $stat = stat( dirname( $filename ) ); $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits. @ chmod( $filename, $perms ); /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */ return array( 'path' => $filename, 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), 'width' => $this->size['width'], 'height' => $this->size['height'], 'mime-type' => $mime_type, ); } /** * Checks that file is local, doesn't have a funny name and is a PDF. * * @since BuddyBoss 1.4.0 * * @static * @access protected * * @param string $file File path. * @param bool $no_read_check If true then doesn't open & read file to check existence and magic bytes. * @return bool|String Returns true if valid; returns error message string if invalid. */ protected static function gs_valid( $file, $no_read_check = false ) { // Loading from URL not currently supported. if ( preg_match( '|^https?://|', $file ) ) { return __( 'Loading from URL not supported.', 'buddyboss' ); } // Check filename can't be interpreted by Ghostscript as special - see https://ghostscript.com/doc/9.20/Use.htm#Options if ( preg_match( '/^[@|%-]/', $file ) ) { return __( 'Unsupported file name.', 'buddyboss' ); } // Check for suspect chars in base filename - same as $special_chars in sanitize_file_name() with ctrls, space and del added // but (for BC with common older uploads) with "+" removed - see #16226 for its addition (along with "%") Oct 2015. if ( preg_match( '/[?\[\]\/\\\\=<>:;,\'"&$#*()|~`!{}%\x00-\x20\x7f]/', wp_basename( $file ) ) ) { return __( 'Unsupported file name.', 'buddyboss' ); } if ( $no_read_check ) { return true; } // Check existence & magic bytes. $fp = @ fopen( $file, 'rb' ); if ( false === $fp ) { return __( 'File doesn’t exist?', 'buddyboss' ); } $magic_bytes = fread( $fp, 10 ); // Max 10 chars: "%PDF-N.NN" plus optional initial linefeed. fclose( $fp ); // This is a similar test to that done by libmagic, but more strict on version format by insisting it's "0." or "1." followed by 1 or 2 numbers. if ( ! preg_match( '/^\n?%PDF-[01]\.[0-9]{1,2}/', $magic_bytes ) ) { do_action( 'gopp_error', __CLASS__, __FUNCTION__, __LINE__, compact( 'file', 'magic_bytes' ) ); return __( 'File is not a PDF.', 'buddyboss' ); } return true; } /** * Returns the path of the Ghostscript executable. * * @since BuddyBoss 1.4.0 * * @static * @access protected * * @return false|string Returns false if can't determine path, else path string. */ protected static function gs_cmd_path() { if ( null === self::$gs_cmd_path ) { /** * Returning a valid path will short-circuit determining the path of the Ghostscript executable. * Useful if your Ghostscript installation is in a non-standard location. * * @since BuddyBoss 1.4.0 * * @param string $gs_cmd_path The path to the Ghostscript executable. Default null. * @param bool $is_win True if running on Windows. */ $shortcircuit_path = apply_filters( 'gopp_image_gs_cmd_path', self::$gs_cmd_path, self::is_win() ); // See also if we've a cached value. $transient = get_transient( 'gopp_image_gs_cmd_path' ); // Only use transient if no filtered value or they're the same. if ( $transient && ( ! $shortcircuit_path || $transient === $shortcircuit_path ) ) { self::$gs_cmd_path = $transient; } else { if ( $shortcircuit_path && self::test_gs_cmd( $shortcircuit_path ) ) { self::$gs_cmd_path = $shortcircuit_path; } else { if ( self::is_win() ) { self::$gs_cmd_path = self::gs_cmd_win(); } else { self::$gs_cmd_path = self::gs_cmd_nix(); } } if ( self::$gs_cmd_path ) { set_transient( 'gopp_image_gs_cmd_path', self::$gs_cmd_path, BP_GOPP_IMAGE_EDITOR_GS_TRANSIENT_EXPIRATION ); } elseif ( $transient ) { delete_transient( 'gopp_image_gs_cmd_path' ); } } } return self::$gs_cmd_path; } /** * Tests whether a purported Ghostscript executable works. * * @since BuddyBoss 1.4.0 * * @static * @access protected * * @param string $cmd Ghostscript executable to try. * @return bool */ protected static function test_gs_cmd( $cmd ) { // Note if exec() has been disabled by means not reflected in function_exists() it may barf here and throw warnings so initial vars. $return_var = -1; $output = array(); exec( self::escapeshellarg( $cmd ) . ' -dBATCH -dNOPAUSE -dNOPROMPT -dSAFER -v 2>&1', $output, $return_var ); return 0 === $return_var && is_array( $output ) && ! empty( $output[0] ) && is_string( $output[0] ) && false !== stripos( $output[0], 'ghostscript' ); } /** * Returns the *nix path of the Ghostscript executable. * * @since BuddyBoss 1.4.0 * * @static * @access protected * * @return false|string Returns false if can't determine path, else path. */ protected static function gs_cmd_nix() { if ( self::test_gs_cmd( '/usr/bin/gs' ) ) { return '/usr/bin/gs'; } if ( self::test_gs_cmd( 'gs' ) ) { // Resort to PATH. return 'gs'; } return false; } /** * Tries to determine the Windows path of the Ghostscript executable. * * @since BuddyBoss 1.4.0 * * @static * @access protected * * @return false|string Returns false if can't determine path, else path. */ protected static function gs_cmd_win() { $win_path = false; // Try using REG QUERY to access the registry. // Do one test query first to see if it works. $cmd = 'REG QUERY HKEY_LOCAL_MACHINE\\SOFTWARE 2>&1'; $return_var = -1; $output = array(); exec( $cmd, $output, $return_var ); if ( 0 === $return_var && is_array( $output ) ) { // Might work. $products = array( 'GPL Ghostscript', 'GNU Ghostscript', 'AFPL Ghostscript', 'Aladdin Ghostscript', ); foreach ( $products as $product ) { $cmd = sprintf( 'REG QUERY "HKEY_LOCAL_MACHINE\\SOFTWARE\\%s" /S 2>&1', $product ); $output = array(); exec( $cmd, $output, $return_var ); if ( 0 === $return_var && is_array( $output ) ) { // Find latest version. $best_match = ''; $highest_ver = 0; foreach ( $output as $out ) { $out = trim( $out ); if ( preg_match( '/^GS_DLL[\t ]+REG_SZ[\t ]+(.+)\\\\gs([0-9.]+)\\\\bin\\\\gsdll(64|32)\.dll$/', $out, $matches ) ) { $ver = (float) $matches[2]; if ( $highest_ver < $ver ) { $possible_path = $matches[1] . '\\gs' . $matches[2] . '\\bin\\gswin' . $matches[3] . 'c.exe'; if ( self::test_gs_cmd( $possible_path ) ) { $best_match = $possible_path; $highest_ver = $ver; } } } } if ( $best_match ) { $win_path = $best_match; break; } } } } if ( ! $win_path ) { // Try GSC environment variable. TODO: Is this still used? if ( ! empty( $_SERVER['GSC'] ) && is_string( $_SERVER['GSC'] ) && self::test_gs_cmd( $_SERVER['GSC'] ) ) { $win_path = $_SERVER['GSC']; } } if ( ! $win_path ) { // Try default install location. $program_dirs = array(); if ( ! empty( $_SERVER['ProgramW6432'] ) && is_string( $_SERVER['ProgramW6432'] ) ) { $program_dirs[] = stripslashes( $_SERVER['ProgramW6432'] ); } if ( ! empty( $_SERVER['ProgramFiles'] ) && is_string( $_SERVER['ProgramFiles'] ) ) { $program_dirs[] = stripslashes( $_SERVER['ProgramFiles'] ); } if ( ! empty( $_SERVER['ProgramFiles(x86)'] ) && is_string( $_SERVER['ProgramFiles(x86)'] ) ) { $program_dirs[] = stripslashes( $_SERVER['ProgramFiles(x86)'] ); } if ( $program_dirs ) { $program_dirs = array_unique( $program_dirs ); } else { $program_dirs[] = 'C:\\Program Files'; } foreach ( $program_dirs as $program_dir ) { $gs_dir = glob( $program_dir . '\\gs\\gs*', GLOB_NOESCAPE ); if ( $gs_dir ) { // Find latest version. $best_match = ''; $highest_ver = 0; foreach ( $gs_dir as $gs_entry ) { if ( preg_match( '/[0-9]+\.[0-9]+$/', $gs_entry, $matches ) ) { $ver = (float) $matches[0]; if ( $highest_ver < $ver ) { if ( @ is_executable( $gs_entry . '\\bin\\gswin64c.exe' ) && self::test_gs_cmd( $gs_entry . '\\bin\\gswin64c.exe' ) ) { $best_match = $gs_entry . '\\bin\\gswin64c.exe'; $highest_ver = $ver; } elseif ( @ is_executable( $gs_entry . '\\bin\\gswin32c.exe' ) && self::test_gs_cmd( $gs_entry . '\\bin\\gswin32c.exe' ) ) { $best_match = $gs_entry . '\\bin\\gswin32c.exe'; $highest_ver = $ver; } } } } if ( $best_match ) { $win_path = $best_match; break; } } } } // Resort to PATH. if ( ! $win_path && self::test_gs_cmd( 'gswin64c.exe' ) ) { $win_path = 'gswin64c.exe'; } if ( ! $win_path && self::test_gs_cmd( 'gswin32c.exe' ) ) { $win_path = 'gswin32c.exe'; } return $win_path; } /** * Returns (shell-escaped) shell command with passed-in arguments tagged on, and stderr redirected to stdout. * * @since BuddyBoss 1.4.0 * * @static * @access protected * * @param string $args Arguments, already shell escaped. * @return false|string Returns false if no executable path, else command string. */ protected static function gs_cmd( $args ) { if ( $gs_cmd_path = self::gs_cmd_path() ) { return self::escapeshellarg( $gs_cmd_path ) . ' ' . $args . ' 2>&1'; } return false; } /** * Returns the arguments for the main Ghostscript invocation. * * @since BuddyBoss 1.4.0 * @access protected * * @param string $filename File name of output JPEG. * @return string Arguments string, shell-escaped. */ protected function get_gs_args( $filename ) { $ret = $this->initial_gs_args(); if ( ( $quality = intval( $this->get_quality() ) ) > 0 && $quality <= 100 ) { $ret .= ' -dJPEGQ=' . $quality; // Nothing escape-worthy. } if ( ( $resolution = intval( $this->get_resolution() ) ) > 0 ) { $ret .= ' -r' . $resolution; // Nothing escape-worthy. } if ( ( $page = intval( $this->get_page() ) ) > 0 ) { $ret .= " -dFirstPage=$page -dLastPage=$page"; // Nothing escape-worthy. } else { $ret .= ' -dFirstPage=1 -dLastPage=1'; } $ret .= ' ' . self::escapeshellarg( '-sOutputFile=' . $filename ); if ( self::is_win() ) { $ret .= ' -sstdout=NUL'; // Lessen noise. } else { $ret .= ' -sstdout=/dev/null'; // Lessen noise. } $ret .= ' --'; // No more options. $ret .= ' ' . self::escapeshellarg( $this->file ); return $ret; } /** * The initial non-varying arguments for the main invocation of Ghostscript. * * @since BuddyBoss 1.4.0 * @access protected * * @return string */ protected function initial_gs_args() { // -dAlignToPixels=0 combined with -dGraphicsAlphaBits=4 and -dTextAlphaBits=4 enables anti-aliasing. -dGridFitTT=2 enables font autohinting. return '-dAlignToPixels=0 -dBATCH -dDOINTERPOLATE -dGraphicsAlphaBits=4 -dGridFitTT=2 -dNOPAUSE -dNOPROMPT -dQUIET -dSAFER -dTextAlphaBits=4 -q -sDEVICE=jpeg'; } /** * It's too tiresome to have to deal with PHP's setlocale() * to avoid UTF-8 mangling so just do escaping ourselves. * * @since BuddyBoss 1.4.0 * * @static * @access protected * * @param string $arg Shell argument to escape. * @return string */ protected static function escapeshellarg( $arg ) { // Note that the only things we're really going to escape, given the strict base file name check, // is the "WP_CONTENT_DIR/uploads" directory and the path to the Ghostscript executable. if ( self::is_win() ) { // Note bang was not zapped in versions of PHP older than about Jul 2015. $arg = '"' . str_replace( array( '%', '!', '"' ), ' ', $arg ) . '"'; // So will get "not found" error if any of these chars in directory path. } else { $arg = "'" . str_replace( "'", "'\\''", $arg ) . "'"; } return $arg; } /** * Whether on Windows or not. * * @static * @access protected * * @return bool */ protected static function is_win() { if ( null === self::$is_win ) { self::$is_win = 0 === strncasecmp( 'WIN', PHP_OS, 3 ); } return self::$is_win; } /** * Deletes transient and clears caching statics. * * @since BuddyBoss 1.4.0 * * @static * @access public * * @return void */ public static function clear() { delete_transient( 'gopp_image_gs_cmd_path' ); self::$is_win = self::$gs_cmd_path = null; } /** * Gets the resolution to use for the preview. * * @since BuddyBoss 1.4.0 * @access public * * @return int $resolution Resolution of preview (DPI). */ public function get_resolution() { if ( ! $this->resolution ) { $this->set_resolution(); } return $this->resolution; } /** * Sets the resolution to use for the preview. * * @since BuddyBoss 1.4.0 * @access public * * @param int $resolution Resolution to use for preview. * * @return true|WP_Error True if set successful; WP_Error on failure. */ public function set_resolution( $resolution = null ) { if ( null === $resolution ) { /** * Filters the default PDF preview resolution setting. * * Applies only during initial editor instantiation, or when set_resolution() is run * manually without the `$resolution` argument. * * set_resolution() has priority over the filter. * * @since BuddyBoss 1.4.0 * * @param int $resolution Resolution (DPI) of the PDF preview thumbnail. * @param string $filename The PDF file name. */ $resolution = apply_filters( 'gopp_editor_set_resolution', $this->default_resolution, $this->file ); if ( ( $resolution = intval( $resolution ) ) <= 0 ) { $resolution = $this->default_resolution; } } else { $resolution = intval( $resolution ); } if ( $resolution > 0 ) { $this->resolution = $resolution; return true; } return new WP_Error( 'invalid_image_resolution', __( 'Attempted to set PDF preview resolution to an invalid value.', 'buddyboss' ) ); } /** * Gets the page to render for the preview. * * @since BuddyBoss 1.4.0 * @access public * * @return int $page The page to render. */ public function get_page() { if ( ! $this->page ) { $this->set_page(); } return $this->page; } /** * Sets the page to render for the preview. * * @since BuddyBoss 1.4.0 * @access public * * @param int $page Page number to render. * * @return true|WP_Error True if set successful; WP_Error on failure. */ public function set_page( $page = null ) { if ( null === $page ) { /** * Filters the default PDF preview page setting. * * Applies only during initial editor instantiation, or when set_page() is run * manually without the `$page` argument. * * set_page() has priority over the filter. * * @since BuddyBoss 1.4.0 * * @param int $page The page to render. * @param string $filename The PDF file name. */ $page = apply_filters( 'gopp_editor_set_page', $this->default_page, $this->file ); if ( ( $page = intval( $page ) ) <= 0 ) { $page = $this->default_page; } } else { $page = intval( $page ); } if ( $page > 0 ) { $this->page = $page; return true; } return new WP_Error( 'invalid_image_page', __( 'Attempted to set PDF preview page to an invalid value.', 'buddyboss' ) ); } /** * Resizes current image. Unsupported. * * At minimum, either a height or width must be provided. * If one of the two is set to null, the resize will * maintain aspect ratio according to the provided dimension. * * @since BuddyBoss 1.4.0 * @access public * * @param int|null $max_w Image width. * @param int|null $max_h Image height. * @param bool $crop * @return WP_Error */ public function resize( $max_w, $max_h, $crop = false ) { return new WP_Error( 'image_resize_error', __( 'Unsupported operation.', 'buddyboss' ) ); } /** * Resize multiple images from a single source. Unsupported. * * @since BuddyBoss 1.4.0 * @access public * * @param array $sizes { * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. * * @type array $size { * @type int $width Image width. * @type int $height Image height. * @type bool $crop Optional. Whether to crop the image. Default false. * } * } * @return WP_Error */ public function multi_resize( $sizes ) { return new WP_Error( 'image_multi_resize_error', __( 'Unsupported operation.', 'buddyboss' ) ); } /** * Crops Image. Unsupported. * * @since BuddyBoss 1.4.0 * @access public * * @param int $src_x The start x position to crop from. * @param int $src_y The start y position to crop from. * @param int $src_w The width to crop. * @param int $src_h The height to crop. * @param int $dst_w Optional. The destination width. * @param int $dst_h Optional. The destination height. * @param bool $src_abs Optional. If the source crop points are absolute. * @return WP_Error */ public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { return new WP_Error( 'image_crop_error', __( 'Unsupported operation.', 'buddyboss' ) ); } /** * Rotates current image counter-clockwise by $angle. Unsupported. * * @since BuddyBoss 1.4.0 * @access public * * @param float $angle * @return WP_Error */ public function rotate( $angle ) { return new WP_Error( 'image_rotate_error', __( 'Unsupported operation.', 'buddyboss' ) ); } /** * Flips current image. Unsupported. * * @since BuddyBoss 1.4.0 * @access public * * @param bool $horz Flip along Horizontal Axis * @param bool $vert Flip along Vertical Axis * @return WP_Error */ public function flip( $horz, $vert ) { return new WP_Error( 'image_flip_error', __( 'Unsupported operation.', 'buddyboss' ) ); } /** * Streams current image to browser. Unsupported. * * @since BuddyBoss 1.4.0 * @access public * * @param string $mime_type * @return WP_Error */ public function stream( $mime_type = null ) { return new WP_Error( 'image_stream_error', __( 'Unsupported operation.', 'buddyboss' ) ); } /** * Gets dimensions of image. * * @since BuddyBoss 1.4.0 * @access public * * @return array {'width'=>int, 'height'=>int} */ public function get_size() { // If size hasn't been set yet and have loaded. if ( null === $this->size && $this->mime_type ) { $this->update_size( 0, 0 ); // Do a temporary full preview to get size of image. $dirname = untrailingslashit( get_temp_dir() ); $filename = $dirname . '/' . wp_unique_filename( $dirname, 'gopp_size.jpg' ); if ( $cmd = self::gs_cmd( $this->get_gs_args( $filename ) ) ) { $return_var = -1; $output = array(); exec( $cmd, $output, $return_var ); if ( 0 === $return_var && ( $size = @ getimagesize( $filename ) ) ) { $this->update_size( $size[0], $size[1] ); } @ unlink( $filename ); } } return $this->size; } }
Changelog
Version | Description |
---|---|
BuddyBoss 1.4.0 | Introduced. |
Methods
- clear — Deletes transient and clears caching statics.
- crop — Crops Image. Unsupported.
- escapeshellarg — It's too tiresome to have to deal with PHP's setlocale() to avoid UTF-8 mangling so just do escaping ourselves.
- flip — Flips current image. Unsupported.
- get_gs_args — Returns the arguments for the main Ghostscript invocation.
- get_page — Gets the page to render for the preview.
- get_resolution — Gets the resolution to use for the preview.
- get_size — Gets dimensions of image.
- gs_cmd — Returns (shell-escaped) shell command with passed-in arguments tagged on, and stderr redirected to stdout.
- gs_cmd_nix — Returns the *nix path of the Ghostscript executable.
- gs_cmd_path — Returns the path of the Ghostscript executable.
- gs_cmd_win — Tries to determine the Windows path of the Ghostscript executable.
- gs_valid — Checks that file is local, doesn't have a funny name and is a PDF.
- initial_gs_args — The initial non-varying arguments for the main invocation of Ghostscript.
- is_win — Whether on Windows or not.
- load — Checks validity and existence of file and sets mime type and calls `set_resolution` and `set_page` and `set_quality` (firing filters).
- multi_resize — Resize multiple images from a single source. Unsupported.
- resize — Resizes current image. Unsupported.
- rotate — Rotates current image counter-clockwise by $angle. Unsupported.
- save — Creates JPEG preview from PDF.
- set_page — Sets the page to render for the preview.
- set_resolution — Sets the resolution to use for the preview.
- stream — Streams current image to browser. Unsupported.
- supports_mime_type — Checks to see if editor supports the mime-type specified.
- test — Checks to see if current environment supports Ghostscript and whether we're compatible with args if any.
- test_gs_cmd — Tests whether a purported Ghostscript executable works.
Questions?
We're always happy to help with code or other questions you might have! Search our developer docs, contact support, or connect with our sales team.