Skip to content

Instantly share code, notes, and snippets.

@pqina
Last active June 29, 2023 18:13
Show Gist options
  • Save pqina/7a42bf0833d988dd81d3c9438009da21 to your computer and use it in GitHub Desktop.
Save pqina/7a42bf0833d988dd81d3c9438009da21 to your computer and use it in GitHub Desktop.
Create thumbnails with PHP
<?
// Link image type to correct image loader and saver
// - makes it easier to add additional types later on
// - makes the function easier to read
const IMAGE_HANDLERS = [
IMAGETYPE_JPEG => [
'load' => 'imagecreatefromjpeg',
'save' => 'imagejpeg',
'quality' => 100
],
IMAGETYPE_PNG => [
'load' => 'imagecreatefrompng',
'save' => 'imagepng',
'quality' => 0
],
IMAGETYPE_GIF => [
'load' => 'imagecreatefromgif',
'save' => 'imagegif'
]
];
/**
* @param $src - a valid file location
* @param $dest - a valid file target
* @param $targetWidth - desired output width
* @param $targetHeight - desired output height or null
*/
function createThumbnail($src, $dest, $targetWidth, $targetHeight = null) {
// 1. Load the image from the given $src
// - see if the file actually exists
// - check if it's of a valid image type
// - load the image resource
// get the type of the image
// we need the type to determine the correct loader
$type = exif_imagetype($src);
// if no valid type or no handler found -> exit
if (!$type || !IMAGE_HANDLERS[$type]) {
return null;
}
// load the image with the correct loader
$image = call_user_func(IMAGE_HANDLERS[$type]['load'], $src);
// no image found at supplied location -> exit
if (!$image) {
return null;
}
// 2. Create a thumbnail and resize the loaded $image
// - get the image dimensions
// - define the output size appropriately
// - create a thumbnail based on that size
// - set alpha transparency for GIFs and PNGs
// - draw the final thumbnail
// get original image width and height
$width = imagesx($image);
$height = imagesy($image);
// maintain aspect ratio when no height set
if ($targetHeight == null) {
// get width to height ratio
$ratio = $width / $height;
// if is portrait
// use ratio to scale height to fit in square
if ($width > $height) {
$targetHeight = floor($targetWidth / $ratio);
}
// if is landscape
// use ratio to scale width to fit in square
else {
$targetHeight = $targetWidth;
$targetWidth = floor($targetWidth * $ratio);
}
}
// create duplicate image based on calculated target size
$thumbnail = imagecreatetruecolor($targetWidth, $targetHeight);
// set transparency options for GIFs and PNGs
if ($type == IMAGETYPE_GIF || $type == IMAGETYPE_PNG) {
// make image transparent
imagecolortransparent(
$thumbnail,
imagecolorallocate($thumbnail, 0, 0, 0)
);
// additional settings for PNGs
if ($type == IMAGETYPE_PNG) {
imagealphablending($thumbnail, false);
imagesavealpha($thumbnail, true);
}
}
// copy entire source image to duplicate image and resize
imagecopyresampled(
$thumbnail,
$image,
0, 0, 0, 0,
$targetWidth, $targetHeight,
$width, $height
);
// 3. Save the $thumbnail to disk
// - call the correct save method
// - set the correct quality level
// save the duplicate version of the image to disk
return call_user_func(
IMAGE_HANDLERS[$type]['save'],
$thumbnail,
$dest,
IMAGE_HANDLERS[$type]['quality']
);
}
@PolliSoft
Copy link

PolliSoft commented Nov 20, 2019

Thanks a lot for this!
On my page (https://www.pollisoft.se), is use the same thumbnail size for all image size and aspect ratios. With the following change/addition (the else statement) to your script, I avoided thumbnail image distortion when sourceRatio doesn't equal targetRatio. Feel free to include if you want.

`// maintain aspect ratio when no height set
if ($targetHeight == null) {

	$startX = 0;
	$startY = 0;
	$src_w = width;
	$src_h = height;
	
    // get width to height ratio
    $ratio = $width / $height;

    // if is portrait
    // use ratio to scale height to fit in square
    if ($width > $height) {
        $targetHeight = floor($targetWidth / $ratio);
    }
    // if is landscape
    // use ratio to scale width to fit in square
    else {
        $targetHeight = $targetWidth;
        $targetWidth = floor($targetWidth * $ratio);
    }
} else {
	// Calculate starting positions and copy area 
	// to not distort the thumbnail image ratio.
	// get width to height ratio
	$ratio = $width / $height;
	$targetRatio = $targetWidth / $targetHeight;
	$combinedRatio = $ratio / $targetRatio;

	// Cut X wise in source to avoid thumb image distortion
	if ($combinedRatio >= 1) {
		$thumbRatio = $height / $targetHeight;
		$startX = ($width - ($thumbRatio * $targetWidth)) / 2;
		$src_w = ($thumbRatio * $targetWidth);
		$startY = 0;
		$src_h = $height;
	}
	// Cut Y wise in source to avoid thumb image distortion
	else {
		$thumbRatio = $width / $targetWidth;
		$startY = ($height - ($thumbRatio * $targetHeight)) / 2;
		$src_h = ($thumbRatio * $targetHeight);
		$startX = 0;
		$src_w = $width;
	}
}`

@JoomlaTema
Copy link

Hi
I am getting error for gif images : imagegif() expects at most 2 arguments, 3 given
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment