image-sizes.php

Afull advanced inc/core/image-sizes.php module for your RX theme, including custom image sizes, responsive image support, WebP/AVIF helpers, lazy loading, srcset tuning, admin columns, and safe fallbacks.

Create/replace this file:

rx-theme/inc/core/image-sizes.php

WordPress uses add_image_size() for custom sizes, and the size name can be used later with wp_get_attachment_image() or shown in the Media Library size dropdown through image_size_names_choose. WordPress also supports responsive srcset / sizes attributes through attachment image functions.

<?php
/**
 * RX Theme Image Sizes & Media Optimization
 *
 * File: inc/core/image-sizes.php
 *
 * Features:
 * - Advanced custom image sizes
 * - Responsive image sizes
 * - Featured image support
 * - WooCommerce-friendly sizes
 * - Open Graph / social sharing sizes
 * - WebP/AVIF output support where server supports it
 * - Better image quality control
 * - Lazy loading, async decoding, fetchpriority
 * - Admin media size selector names
 * - Big image threshold control
 * - Custom helper functions for theme templates
 * - Safe fallback image helpers
 *
 * @package RX_Theme
 */

defined( 'ABSPATH' ) || exit;

if ( ! defined( 'RX_THEME_IMAGE_VERSION' ) ) {
	define( 'RX_THEME_IMAGE_VERSION', '1.0.0' );
}

/**
 * Main RX image size registration.
 */
if ( ! function_exists( 'rx_register_image_sizes' ) ) {
	function rx_register_image_sizes() {

		/*
		 * Basic theme support.
		 */
		add_theme_support( 'post-thumbnails' );
		add_theme_support( 'responsive-embeds' );
		add_theme_support( 'align-wide' );

		/*
		 * Default post thumbnail size.
		 */
		set_post_thumbnail_size( 1280, 720, true );

		/*
		 * RX General Content Sizes.
		 */
		add_image_size( 'rx_tiny', 120, 80, true );
		add_image_size( 'rx_small', 320, 213, true );
		add_image_size( 'rx_medium', 640, 426, true );
		add_image_size( 'rx_large', 1024, 683, true );
		add_image_size( 'rx_xlarge', 1440, 960, true );
		add_image_size( 'rx_full_hd', 1920, 1080, true );

		/*
		 * RX Blog / Archive Sizes.
		 */
		add_image_size( 'rx_blog_card', 420, 280, true );
		add_image_size( 'rx_blog_grid', 560, 373, true );
		add_image_size( 'rx_blog_list', 720, 405, true );
		add_image_size( 'rx_blog_featured', 1280, 720, true );
		add_image_size( 'rx_blog_wide', 1600, 900, true );

		/*
		 * RX Hero / Banner Sizes.
		 */
		add_image_size( 'rx_hero_mobile', 768, 600, true );
		add_image_size( 'rx_hero_tablet', 1024, 650, true );
		add_image_size( 'rx_hero_desktop', 1600, 800, true );
		add_image_size( 'rx_hero_large', 1920, 900, true );
		add_image_size( 'rx_hero_ultra', 2560, 1200, true );

		/*
		 * RX Square Sizes.
		 */
		add_image_size( 'rx_square_tiny', 96, 96, true );
		add_image_size( 'rx_square_small', 240, 240, true );
		add_image_size( 'rx_square_medium', 480, 480, true );
		add_image_size( 'rx_square_large', 800, 800, true );
		add_image_size( 'rx_square_xlarge', 1200, 1200, true );

		/*
		 * RX Portrait Sizes.
		 */
		add_image_size( 'rx_portrait_small', 300, 450, true );
		add_image_size( 'rx_portrait_medium', 500, 750, true );
		add_image_size( 'rx_portrait_large', 720, 1080, true );
		add_image_size( 'rx_portrait_xlarge', 960, 1440, true );

		/*
		 * RX Landscape Sizes.
		 */
		add_image_size( 'rx_landscape_small', 480, 270, true );
		add_image_size( 'rx_landscape_medium', 800, 450, true );
		add_image_size( 'rx_landscape_large', 1280, 720, true );
		add_image_size( 'rx_landscape_xlarge', 1920, 1080, true );

		/*
		 * RX Medical / Article Specific Sizes.
		 */
		add_image_size( 'rx_medical_thumb', 360, 240, true );
		add_image_size( 'rx_medical_card', 520, 347, true );
		add_image_size( 'rx_medical_diagram', 900, 600, false );
		add_image_size( 'rx_medical_featured', 1400, 788, true );
		add_image_size( 'rx_medical_infographic', 1000, 1500, false );

		/*
		 * RX Author / Avatar / Profile Sizes.
		 */
		add_image_size( 'rx_avatar_small', 80, 80, true );
		add_image_size( 'rx_avatar_medium', 160, 160, true );
		add_image_size( 'rx_avatar_large', 300, 300, true );
		add_image_size( 'rx_author_card', 400, 400, true );

		/*
		 * RX Logo / Brand Sizes.
		 */
		add_image_size( 'rx_logo_small', 180, 90, false );
		add_image_size( 'rx_logo_medium', 360, 180, false );
		add_image_size( 'rx_logo_large', 720, 360, false );

		/*
		 * RX Social Sharing / SEO Sizes.
		 */
		add_image_size( 'rx_og_image', 1200, 630, true );
		add_image_size( 'rx_twitter_card', 1200, 675, true );
		add_image_size( 'rx_schema_image', 1200, 900, true );
		add_image_size( 'rx_pinterest', 1000, 1500, true );

		/*
		 * RX Gallery Sizes.
		 */
		add_image_size( 'rx_gallery_thumb', 300, 300, true );
		add_image_size( 'rx_gallery_masonry', 600, 0, false );
		add_image_size( 'rx_gallery_lightbox', 1600, 1200, false );

		/*
		 * RX WooCommerce / Product-Friendly Sizes.
		 * These work safely even when WooCommerce is not installed.
		 */
		add_image_size( 'rx_product_thumb', 300, 300, true );
		add_image_size( 'rx_product_card', 500, 500, true );
		add_image_size( 'rx_product_single', 900, 900, true );
		add_image_size( 'rx_product_zoom', 1400, 1400, false );

		/*
		 * RX Advertisement / Widget Sizes.
		 */
		add_image_size( 'rx_ad_square', 300, 250, true );
		add_image_size( 'rx_ad_banner', 728, 90, true );
		add_image_size( 'rx_ad_leaderboard', 970, 250, true );
		add_image_size( 'rx_sidebar_thumb', 120, 90, true );
		add_image_size( 'rx_widget_card', 360, 240, true );
	}
}
add_action( 'after_setup_theme', 'rx_register_image_sizes', 5 );

/**
 * Make custom sizes visible inside the Media Library dropdown.
 */
if ( ! function_exists( 'rx_custom_image_size_names' ) ) {
	function rx_custom_image_size_names( $sizes ) {

		$rx_sizes = array(
			'rx_tiny'              => esc_html__( 'RX Tiny 120x80', 'rx-theme' ),
			'rx_small'             => esc_html__( 'RX Small 320x213', 'rx-theme' ),
			'rx_medium'            => esc_html__( 'RX Medium 640x426', 'rx-theme' ),
			'rx_large'             => esc_html__( 'RX Large 1024x683', 'rx-theme' ),
			'rx_xlarge'            => esc_html__( 'RX Extra Large 1440x960', 'rx-theme' ),
			'rx_full_hd'           => esc_html__( 'RX Full HD 1920x1080', 'rx-theme' ),

			'rx_blog_card'         => esc_html__( 'RX Blog Card', 'rx-theme' ),
			'rx_blog_grid'         => esc_html__( 'RX Blog Grid', 'rx-theme' ),
			'rx_blog_list'         => esc_html__( 'RX Blog List', 'rx-theme' ),
			'rx_blog_featured'     => esc_html__( 'RX Blog Featured', 'rx-theme' ),
			'rx_blog_wide'         => esc_html__( 'RX Blog Wide', 'rx-theme' ),

			'rx_hero_mobile'       => esc_html__( 'RX Hero Mobile', 'rx-theme' ),
			'rx_hero_tablet'       => esc_html__( 'RX Hero Tablet', 'rx-theme' ),
			'rx_hero_desktop'      => esc_html__( 'RX Hero Desktop', 'rx-theme' ),
			'rx_hero_large'        => esc_html__( 'RX Hero Large', 'rx-theme' ),
			'rx_hero_ultra'        => esc_html__( 'RX Hero Ultra', 'rx-theme' ),

			'rx_square_small'      => esc_html__( 'RX Square Small', 'rx-theme' ),
			'rx_square_medium'     => esc_html__( 'RX Square Medium', 'rx-theme' ),
			'rx_square_large'      => esc_html__( 'RX Square Large', 'rx-theme' ),

			'rx_portrait_small'    => esc_html__( 'RX Portrait Small', 'rx-theme' ),
			'rx_portrait_medium'   => esc_html__( 'RX Portrait Medium', 'rx-theme' ),
			'rx_portrait_large'    => esc_html__( 'RX Portrait Large', 'rx-theme' ),

			'rx_landscape_small'   => esc_html__( 'RX Landscape Small', 'rx-theme' ),
			'rx_landscape_medium'  => esc_html__( 'RX Landscape Medium', 'rx-theme' ),
			'rx_landscape_large'   => esc_html__( 'RX Landscape Large', 'rx-theme' ),

			'rx_medical_thumb'     => esc_html__( 'RX Medical Thumb', 'rx-theme' ),
			'rx_medical_card'      => esc_html__( 'RX Medical Card', 'rx-theme' ),
			'rx_medical_diagram'   => esc_html__( 'RX Medical Diagram', 'rx-theme' ),
			'rx_medical_featured'  => esc_html__( 'RX Medical Featured', 'rx-theme' ),
			'rx_medical_infographic' => esc_html__( 'RX Medical Infographic', 'rx-theme' ),

			'rx_og_image'          => esc_html__( 'RX Open Graph Image', 'rx-theme' ),
			'rx_twitter_card'      => esc_html__( 'RX Twitter Card Image', 'rx-theme' ),
			'rx_schema_image'      => esc_html__( 'RX Schema Image', 'rx-theme' ),

			'rx_gallery_thumb'     => esc_html__( 'RX Gallery Thumb', 'rx-theme' ),
			'rx_gallery_lightbox'  => esc_html__( 'RX Gallery Lightbox', 'rx-theme' ),

			'rx_product_thumb'     => esc_html__( 'RX Product Thumb', 'rx-theme' ),
			'rx_product_card'      => esc_html__( 'RX Product Card', 'rx-theme' ),
			'rx_product_single'    => esc_html__( 'RX Product Single', 'rx-theme' ),
		);

		return array_merge( $sizes, $rx_sizes );
	}
}
add_filter( 'image_size_names_choose', 'rx_custom_image_size_names' );

/**
 * Improve image quality.
 *
 * 82 is WordPress default-like modern compression.
 * 90 gives better quality for medical diagrams and SEO images.
 */
if ( ! function_exists( 'rx_image_quality' ) ) {
	function rx_image_quality( $quality, $mime_type = '' ) {

		if ( 'image/jpeg' === $mime_type ) {
			return 88;
		}

		if ( 'image/webp' === $mime_type ) {
			return 82;
		}

		if ( 'image/avif' === $mime_type ) {
			return 75;
		}

		return $quality;
	}
}
add_filter( 'wp_editor_set_quality', 'rx_image_quality', 10, 2 );

/**
 * Big image size threshold.
 *
 * WordPress scales very large uploaded images.
 * This sets a safe modern threshold for performance.
 */
if ( ! function_exists( 'rx_big_image_size_threshold' ) ) {
	function rx_big_image_size_threshold( $threshold ) {

		$custom_threshold = 2560;

		return absint( apply_filters( 'rx_big_image_threshold', $custom_threshold, $threshold ) );
	}
}
add_filter( 'big_image_size_threshold', 'rx_big_image_size_threshold' );

/**
 * Prefer modern image output formats when supported.
 *
 * Important:
 * - Requires server image editor support.
 * - Does not magically convert every old image.
 * - New regenerated sizes may use modern formats depending on WP/server support.
 */
if ( ! function_exists( 'rx_image_editor_output_format' ) ) {
	function rx_image_editor_output_format( $formats ) {

		if ( function_exists( 'imagewebp' ) ) {
			$formats['image/jpeg'] = 'image/webp';
			$formats['image/png']  = 'image/webp';
		}

		/*
		 * AVIF support depends on PHP/GD/Imagick/server.
		 * Keep this conservative. Uncomment only after testing server support.
		 *
		 * if ( function_exists( 'imageavif' ) ) {
		 *     $formats['image/jpeg'] = 'image/avif';
		 *     $formats['image/png']  = 'image/avif';
		 * }
		 */

		return $formats;
	}
}
add_filter( 'image_editor_output_format', 'rx_image_editor_output_format' );

/**
 * Allow AVIF upload when WordPress/server supports it.
 */
if ( ! function_exists( 'rx_allow_modern_image_mimes' ) ) {
	function rx_allow_modern_image_mimes( $mimes ) {

		$mimes['webp'] = 'image/webp';

		if ( function_exists( 'imageavif' ) || class_exists( 'Imagick' ) ) {
			$mimes['avif'] = 'image/avif';
		}

		return $mimes;
	}
}
add_filter( 'upload_mimes', 'rx_allow_modern_image_mimes' );

/**
 * Improve attachment image attributes.
 */
if ( ! function_exists( 'rx_attachment_image_attributes' ) ) {
	function rx_attachment_image_attributes( $attr, $attachment, $size ) {

		if ( empty( $attr['alt'] ) ) {
			$alt = get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true );

			if ( empty( $alt ) ) {
				$alt = get_the_title( $attachment->ID );
			}

			$attr['alt'] = esc_attr( wp_strip_all_tags( $alt ) );
		}

		if ( empty( $attr['loading'] ) ) {
			$attr['loading'] = 'lazy';
		}

		if ( empty( $attr['decoding'] ) ) {
			$attr['decoding'] = 'async';
		}

		$priority_sizes = array(
			'post-thumbnail',
			'rx_blog_featured',
			'rx_hero_desktop',
			'rx_hero_large',
			'rx_og_image',
		);

		if ( in_array( $size, $priority_sizes, true ) && is_singular() ) {
			$attr['fetchpriority'] = 'high';
			$attr['loading']       = 'eager';
		}

		if ( empty( $attr['class'] ) ) {
			$attr['class'] = 'rx-image';
		} else {
			$attr['class'] .= ' rx-image';
		}

		return $attr;
	}
}
add_filter( 'wp_get_attachment_image_attributes', 'rx_attachment_image_attributes', 10, 3 );

/**
 * Custom responsive sizes attribute.
 */
if ( ! function_exists( 'rx_calculate_image_sizes' ) ) {
	function rx_calculate_image_sizes( $sizes, $size, $image_src, $image_meta, $attachment_id ) {

		if ( is_array( $size ) ) {
			$width = isset( $size[0] ) ? absint( $size[0] ) : 0;
		} else {
			$width = 0;
		}

		if ( is_singular() ) {
			return '(max-width: 767px) 100vw, (max-width: 1199px) 92vw, 1100px';
		}

		if ( is_archive() || is_home() || is_search() ) {
			return '(max-width: 767px) 100vw, (max-width: 1199px) 50vw, 420px';
		}

		if ( $width >= 1600 ) {
			return '100vw';
		}

		return $sizes;
	}
}
add_filter( 'wp_calculate_image_sizes', 'rx_calculate_image_sizes', 10, 5 );

/**
 * Increase srcset max width for large displays.
 */
if ( ! function_exists( 'rx_max_srcset_image_width' ) ) {
	function rx_max_srcset_image_width( $max_width, $size_array ) {
		return 2560;
	}
}
add_filter( 'max_srcset_image_width', 'rx_max_srcset_image_width', 10, 2 );

/**
 * Add custom intermediate image sizes to metadata generation.
 */
if ( ! function_exists( 'rx_intermediate_image_sizes_advanced' ) ) {
	function rx_intermediate_image_sizes_advanced( $sizes, $metadata, $attachment_id ) {

		/*
		 * You can disable very heavy sizes for small uploads.
		 */
		$width  = isset( $metadata['width'] ) ? absint( $metadata['width'] ) : 0;
		$height = isset( $metadata['height'] ) ? absint( $metadata['height'] ) : 0;

		if ( $width > 0 && $width < 1200 ) {
			unset(
				$sizes['rx_hero_large'],
				$sizes['rx_hero_ultra'],
				$sizes['rx_blog_wide'],
				$sizes['rx_full_hd']
			);
		}

		if ( $height > 0 && $height < 1000 ) {
			unset(
				$sizes['rx_medical_infographic'],
				$sizes['rx_portrait_xlarge'],
				$sizes['rx_pinterest']
			);
		}

		return $sizes;
	}
}
add_filter( 'intermediate_image_sizes_advanced', 'rx_intermediate_image_sizes_advanced', 10, 3 );

/**
 * Helper: get default fallback image URL.
 */
if ( ! function_exists( 'rx_get_fallback_image_url' ) ) {
	function rx_get_fallback_image_url( $size = 'rx_blog_card' ) {

		$fallback = get_template_directory_uri() . '/assets/images/fallback.jpg';

		return esc_url( apply_filters( 'rx_fallback_image_url', $fallback, $size ) );
	}
}

/**
 * Helper: get attachment alt text safely.
 */
if ( ! function_exists( 'rx_get_image_alt' ) ) {
	function rx_get_image_alt( $attachment_id = 0 ) {

		$attachment_id = absint( $attachment_id );

		if ( ! $attachment_id ) {
			return '';
		}

		$alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );

		if ( empty( $alt ) ) {
			$alt = get_the_title( $attachment_id );
		}

		return esc_attr( wp_strip_all_tags( $alt ) );
	}
}

/**
 * Helper: get featured image ID with fallback.
 */
if ( ! function_exists( 'rx_get_featured_image_id' ) ) {
	function rx_get_featured_image_id( $post_id = 0 ) {

		$post_id = $post_id ? absint( $post_id ) : get_the_ID();

		if ( ! $post_id ) {
			return 0;
		}

		return absint( get_post_thumbnail_id( $post_id ) );
	}
}

/**
 * Helper: output optimized image HTML.
 *
 * Example:
 * echo rx_get_image( get_post_thumbnail_id(), 'rx_blog_card', array( 'class' => 'my-class' ) );
 */
if ( ! function_exists( 'rx_get_image' ) ) {
	function rx_get_image( $attachment_id = 0, $size = 'rx_blog_card', $attr = array() ) {

		$attachment_id = absint( $attachment_id );

		$default_attr = array(
			'class'    => 'rx-image rx-image-' . sanitize_html_class( $size ),
			'loading'  => 'lazy',
			'decoding' => 'async',
		);

		if ( $attachment_id ) {
			$default_attr['alt'] = rx_get_image_alt( $attachment_id );
			$attr                = wp_parse_args( $attr, $default_attr );

			return wp_get_attachment_image( $attachment_id, $size, false, $attr );
		}

		$fallback_url = rx_get_fallback_image_url( $size );
		$attr         = wp_parse_args( $attr, $default_attr );

		$alt      = isset( $attr['alt'] ) ? esc_attr( $attr['alt'] ) : '';
		$class    = isset( $attr['class'] ) ? esc_attr( $attr['class'] ) : '';
		$loading  = isset( $attr['loading'] ) ? esc_attr( $attr['loading'] ) : 'lazy';
		$decoding = isset( $attr['decoding'] ) ? esc_attr( $attr['decoding'] ) : 'async';

		return sprintf(
			'<img src="%1$s" alt="%2$s" class="%3$s" loading="%4$s" decoding="%5$s">',
			esc_url( $fallback_url ),
			$alt,
			$class,
			$loading,
			$decoding
		);
	}
}

/**
 * Helper: output post thumbnail safely.
 *
 * Example:
 * echo rx_get_post_thumbnail( get_the_ID(), 'rx_blog_card' );
 */
if ( ! function_exists( 'rx_get_post_thumbnail' ) ) {
	function rx_get_post_thumbnail( $post_id = 0, $size = 'rx_blog_card', $attr = array() ) {

		$post_id       = $post_id ? absint( $post_id ) : get_the_ID();
		$attachment_id = rx_get_featured_image_id( $post_id );

		if ( empty( $attr['alt'] ) && $post_id ) {
			$attr['alt'] = get_the_title( $post_id );
		}

		return rx_get_image( $attachment_id, $size, $attr );
	}
}

/**
 * Helper: get image URL by attachment ID and size.
 */
if ( ! function_exists( 'rx_get_image_url' ) ) {
	function rx_get_image_url( $attachment_id = 0, $size = 'full' ) {

		$attachment_id = absint( $attachment_id );

		if ( ! $attachment_id ) {
			return rx_get_fallback_image_url( $size );
		}

		$image = wp_get_attachment_image_src( $attachment_id, $size );

		if ( ! empty( $image[0] ) ) {
			return esc_url( $image[0] );
		}

		return rx_get_fallback_image_url( $size );
	}
}

/**
 * Helper: get featured image URL.
 */
if ( ! function_exists( 'rx_get_post_thumbnail_url' ) ) {
	function rx_get_post_thumbnail_url( $post_id = 0, $size = 'rx_blog_card' ) {

		$post_id       = $post_id ? absint( $post_id ) : get_the_ID();
		$attachment_id = rx_get_featured_image_id( $post_id );

		return rx_get_image_url( $attachment_id, $size );
	}
}

/**
 * Helper: background image inline style.
 *
 * Example:
 * echo rx_background_image_style( get_post_thumbnail_id(), 'rx_hero_desktop' );
 */
if ( ! function_exists( 'rx_background_image_style' ) ) {
	function rx_background_image_style( $attachment_id = 0, $size = 'full' ) {

		$url = rx_get_image_url( $attachment_id, $size );

		if ( ! $url ) {
			return '';
		}

		return 'style="background-image:url(' . esc_url( $url ) . ');"';
	}
}

/**
 * Helper: simple responsive picture-like wrapper.
 *
 * This keeps normal WordPress srcset support while adding a wrapper.
 */
if ( ! function_exists( 'rx_responsive_image_figure' ) ) {
	function rx_responsive_image_figure( $attachment_id = 0, $size = 'rx_blog_card', $caption = '', $attr = array() ) {

		$image = rx_get_image( $attachment_id, $size, $attr );

		if ( ! $image ) {
			return '';
		}

		$html  = '<figure class="rx-image-figure rx-image-figure-' . esc_attr( sanitize_html_class( $size ) ) . '">';
		$html .= $image;

		if ( ! empty( $caption ) ) {
			$html .= '<figcaption class="rx-image-caption">' . wp_kses_post( $caption ) . '</figcaption>';
		}

		$html .= '</figure>';

		return $html;
	}
}

/**
 * Add useful image classes to post thumbnails.
 */
if ( ! function_exists( 'rx_post_thumbnail_html' ) ) {
	function rx_post_thumbnail_html( $html, $post_id, $post_thumbnail_id, $size, $attr ) {

		if ( empty( $html ) ) {
			return $html;
		}

		$size_class = is_string( $size ) ? sanitize_html_class( $size ) : 'custom-size';

		$html = str_replace(
			'class="',
			'class="rx-post-thumbnail rx-post-thumbnail-' . esc_attr( $size_class ) . ' ',
			$html
		);

		return $html;
	}
}
add_filter( 'post_thumbnail_html', 'rx_post_thumbnail_html', 10, 5 );

/**
 * Admin media column: show dimensions.
 */
if ( is_admin() ) {

	if ( ! function_exists( 'rx_media_columns' ) ) {
		function rx_media_columns( $columns ) {
			$columns['rx_dimensions'] = esc_html__( 'Dimensions', 'rx-theme' );
			return $columns;
		}
	}
	add_filter( 'manage_media_columns', 'rx_media_columns' );

	if ( ! function_exists( 'rx_media_custom_column' ) ) {
		function rx_media_custom_column( $column_name, $post_id ) {

			if ( 'rx_dimensions' !== $column_name ) {
				return;
			}

			$metadata = wp_get_attachment_metadata( $post_id );

			if ( ! empty( $metadata['width'] ) && ! empty( $metadata['height'] ) ) {
				echo esc_html( absint( $metadata['width'] ) . ' × ' . absint( $metadata['height'] ) );
			} else {
				echo esc_html__( 'Unknown', 'rx-theme' );
			}
		}
	}
	add_action( 'manage_media_custom_column', 'rx_media_custom_column', 10, 2 );
}

/**
 * Add body class when current page/post has featured image.
 */
if ( ! function_exists( 'rx_featured_image_body_class' ) ) {
	function rx_featured_image_body_class( $classes ) {

		if ( is_singular() && has_post_thumbnail() ) {
			$classes[] = 'rx-has-featured-image';
		}

		return $classes;
	}
}
add_filter( 'body_class', 'rx_featured_image_body_class' );

/**
 * Add custom image sizes to REST response for easier headless usage.
 */
if ( ! function_exists( 'rx_rest_prepare_attachment' ) ) {
	function rx_rest_prepare_attachment( $response, $post, $request ) {

		if ( 'attachment' !== $post->post_type ) {
			return $response;
		}

		$sizes = array(
			'rx_blog_card',
			'rx_blog_featured',
			'rx_hero_desktop',
			'rx_og_image',
			'rx_medical_card',
			'rx_medical_featured',
		);

		$rx_urls = array();

		foreach ( $sizes as $size ) {
			$image = wp_get_attachment_image_src( $post->ID, $size );

			if ( ! empty( $image[0] ) ) {
				$rx_urls[ $size ] = array(
					'url'    => esc_url_raw( $image[0] ),
					'width'  => isset( $image[1] ) ? absint( $image[1] ) : 0,
					'height' => isset( $image[2] ) ? absint( $image[2] ) : 0,
				);
			}
		}

		$data                  = $response->get_data();
		$data['rx_image_urls'] = $rx_urls;
		$response->set_data( $data );

		return $response;
	}
}
add_filter( 'rest_prepare_attachment', 'rx_rest_prepare_attachment', 10, 3 );

/**
 * Preload featured image on singular pages.
 */
if ( ! function_exists( 'rx_preload_featured_image' ) ) {
	function rx_preload_featured_image() {

		if ( ! is_singular() || ! has_post_thumbnail() ) {
			return;
		}

		$attachment_id = get_post_thumbnail_id();
		$image_url     = rx_get_image_url( $attachment_id, 'rx_blog_featured' );

		if ( ! $image_url ) {
			return;
		}

		printf(
			'<link rel="preload" as="image" href="%s" fetchpriority="high">' . "\n",
			esc_url( $image_url )
		);
	}
}
add_action( 'wp_head', 'rx_preload_featured_image', 1 );

/**
 * Add DNS prefetch/preconnect for CDN image domain if used.
 *
 * Change this domain to your real CDN domain.
 */
if ( ! function_exists( 'rx_image_resource_hints' ) ) {
	function rx_image_resource_hints( $urls, $relation_type ) {

		$cdn_host = apply_filters( 'rx_image_cdn_host', '' );

		if ( empty( $cdn_host ) ) {
			return $urls;
		}

		if ( in_array( $relation_type, array( 'dns-prefetch', 'preconnect' ), true ) ) {
			$urls[] = esc_url( $cdn_host );
		}

		return $urls;
	}
}
add_filter( 'wp_resource_hints', 'rx_image_resource_hints', 10, 2 );

/**
 * Optional: Disable image attachment pages.
 *
 * Attachment pages often create thin SEO pages.
 */
if ( ! function_exists( 'rx_redirect_attachment_pages' ) ) {
	function rx_redirect_attachment_pages() {

		if ( ! is_attachment() ) {
			return;
		}

		global $post;

		if ( ! $post ) {
			return;
		}

		$parent_id = wp_get_post_parent_id( $post->ID );

		if ( $parent_id ) {
			wp_safe_redirect( get_permalink( $parent_id ), 301 );
			exit;
		}

		wp_safe_redirect( home_url( '/' ), 301 );
		exit;
	}
}
add_action( 'template_redirect', 'rx_redirect_attachment_pages' );

/**
 * Add RX image size list helper for other theme files.
 */
if ( ! function_exists( 'rx_get_registered_image_sizes' ) ) {
	function rx_get_registered_image_sizes() {

		$sizes = array(
			'rx_tiny',
			'rx_small',
			'rx_medium',
			'rx_large',
			'rx_xlarge',
			'rx_full_hd',
			'rx_blog_card',
			'rx_blog_grid',
			'rx_blog_list',
			'rx_blog_featured',
			'rx_blog_wide',
			'rx_hero_mobile',
			'rx_hero_tablet',
			'rx_hero_desktop',
			'rx_hero_large',
			'rx_hero_ultra',
			'rx_square_tiny',
			'rx_square_small',
			'rx_square_medium',
			'rx_square_large',
			'rx_square_xlarge',
			'rx_portrait_small',
			'rx_portrait_medium',
			'rx_portrait_large',
			'rx_portrait_xlarge',
			'rx_landscape_small',
			'rx_landscape_medium',
			'rx_landscape_large',
			'rx_landscape_xlarge',
			'rx_medical_thumb',
			'rx_medical_card',
			'rx_medical_diagram',
			'rx_medical_featured',
			'rx_medical_infographic',
			'rx_avatar_small',
			'rx_avatar_medium',
			'rx_avatar_large',
			'rx_author_card',
			'rx_logo_small',
			'rx_logo_medium',
			'rx_logo_large',
			'rx_og_image',
			'rx_twitter_card',
			'rx_schema_image',
			'rx_pinterest',
			'rx_gallery_thumb',
			'rx_gallery_masonry',
			'rx_gallery_lightbox',
			'rx_product_thumb',
			'rx_product_card',
			'rx_product_single',
			'rx_product_zoom',
			'rx_ad_square',
			'rx_ad_banner',
			'rx_ad_leaderboard',
			'rx_sidebar_thumb',
			'rx_widget_card',
		);

		return apply_filters( 'rx_registered_image_sizes', $sizes );
	}
}

Add this line in your main functions.php:

require_once get_template_directory() . '/inc/core/image-sizes.php';

Use in templates like this:

echo rx_get_post_thumbnail( get_the_ID(), 'rx_blog_card' );

For hero image:

echo rx_get_post_thumbnail( get_the_ID(), 'rx_hero_desktop', array(
	'class' => 'rx-hero-img',
	'alt'   => get_the_title(),
) );

Important: after adding new image sizes, old uploaded images will not automatically create all new sizes. Use Regenerate Thumbnails or re-upload images to generate the new versions.

Leave a Reply

Your email address will not be published. Required fields are marked *