queryFormats( 'WEBP' ); $imagick->clear(); $imagick->destroy(); return ! empty( $formats ); } catch ( \Exception $e ) { return false; } } return false; } /** * Check if AVIF format is supported. * * Requires PHP 8.1+ with --with-avif flag OR ImageMagick with libheif/libavif. * * @return bool True if AVIF is supported. * @since 1.3.0 */ public static function supports_avif() { // Check GD library (PHP 8.1+ with AVIF support). if ( function_exists( 'gd_info' ) ) { $gd_info = gd_info(); if ( isset( $gd_info['AVIF Support'] ) && $gd_info['AVIF Support'] ) { return true; } } // Check for imageavif function (PHP 8.1+). if ( function_exists( 'imageavif' ) && function_exists( 'imagecreatefromavif' ) ) { return true; } // Check ImageMagick as fallback. if ( extension_loaded( 'imagick' ) ) { try { $imagick = new \Imagick(); $formats = $imagick->queryFormats( 'AVIF' ); $imagick->clear(); $imagick->destroy(); return ! empty( $formats ); } catch ( \Exception $e ) { return false; } } return false; } /** * Get array of all supported output formats. * * @return array Array of supported MIME types. * @since 1.3.0 */ public static function get_supported_output_formats() { $formats = array(); // JPEG and PNG are always supported (core GD requirement). $formats[] = 'image/jpeg'; $formats[] = 'image/png'; // GIF support (check GD). if ( function_exists( 'gd_info' ) ) { $gd_info = gd_info(); if ( isset( $gd_info['GIF Create Support'] ) && $gd_info['GIF Create Support'] ) { $formats[] = 'image/gif'; } } // WebP support. if ( self::supports_webp() ) { $formats[] = 'image/webp'; } // AVIF support. if ( self::supports_avif() ) { $formats[] = 'image/avif'; } return $formats; } /** * Get the best fallback format for a requested format that's not supported. * * Fallback chain: * - AVIF → WebP (if supported) → JPEG * - WebP → JPEG * - Smart mode → WebP/JPEG based on support * - PNG/GIF → Preserve (if supported) → JPEG * * @param string $requested_format Requested MIME type (e.g., 'image/avif'). * @param string $original_format Optional. Original image format for context. * @return string Fallback MIME type. * @since 1.3.0 */ public static function get_fallback_format( $requested_format, $original_format = '' ) { switch ( $requested_format ) { case 'image/avif': // AVIF not supported → try WebP → JPEG. if ( self::supports_webp() ) { return 'image/webp'; } return 'image/jpeg'; case 'image/webp': // WebP not supported → JPEG. return 'image/jpeg'; case 'image/png': case 'image/gif': // If PNG/GIF requested but not supported, fall back to JPEG. return 'image/jpeg'; default: // Default fallback is always JPEG (universally supported). return 'image/jpeg'; } } /** * Detect and cache all format support. * * @since 1.3.0 */ private static function detect_all_formats() { self::$support_cache = array( 'jpeg' => true, // Always supported (GD requirement). 'png' => true, // Always supported (GD requirement). 'gif' => self::supports_gif(), 'webp' => self::supports_webp(), 'avif' => self::supports_avif(), ); } /** * Check if GIF format is supported. * * @return bool True if GIF is supported. * @since 1.3.0 */ private static function supports_gif() { if ( function_exists( 'gd_info' ) ) { $gd_info = gd_info(); if ( isset( $gd_info['GIF Create Support'] ) && $gd_info['GIF Create Support'] ) { return true; } } return false; } /** * Get human-readable format requirements. * * Returns information about what's needed to enable unsupported formats. * * @param string $format Format to check ('webp', 'avif'). * @return string|null Requirements message, or null if supported. * @since 1.3.0 */ public static function get_format_requirements( $format ) { $format = strtolower( $format ); if ( self::supports_format( $format ) ) { return null; // Already supported. } switch ( $format ) { case 'webp': return __( 'Requires GD library with WebP support or ImageMagick extension.', 'gatewell' ); case 'avif': return __( 'Requires PHP 8.1+ with AVIF enabled or ImageMagick with libheif/libavif.', 'gatewell' ); default: return __( 'Format not available on this server.', 'gatewell' ); } } /** * Check if a conversion mode is supported. * * @param string $mode Conversion mode ('preserve', 'jpeg', 'webp', 'avif', 'smart'). * @return bool True if mode is supported. * @since 1.3.0 */ public static function supports_conversion_mode( $mode ) { switch ( $mode ) { case 'preserve': case 'jpeg': // Always supported. return true; case 'webp': return self::supports_webp(); case 'avif': return self::supports_avif(); case 'smart': // Smart mode requires at least WebP or AVIF support. return self::supports_webp() || self::supports_avif(); default: return false; } } }