Skip to content

Instantly share code, notes, and snippets.

@axeloz
Last active January 17, 2024 16:52
Show Gist options
  • Save axeloz/c5c9c11b0241b53e47864d3b1d58a936 to your computer and use it in GitHub Desktop.
Save axeloz/c5c9c11b0241b53e47864d3b1d58a936 to your computer and use it in GitHub Desktop.
This function creates a placeholder preview image that shows original image dominant colors. Easy to use with a small and storable `data:image/gif` base64 string. Check comments for a screenshot of the ending result.
<?php
function generateImagePreview(String $file):String {
// Supported image formats
$mimetypes = [
'image/jpeg' => [
'mime' => 'image/jpeg',
'function' => 'imagecreatefromjpeg',
'extensions' => ['jpeg', 'jpg']
],
'image/png' => [
'function' => 'imagecreatefrompng',
'extensions' => ['png']
],
'image/webp' => [
'function' => 'imagecreatefromwebp',
'extensions' => ['webp']
],
'image/gif' => [
'function' => 'imagecreatefromgif',
'extensions' => ['gif']
]
];
// Checking that GD extension is enabled
if (! extension_loaded('gd')) {
throw new Exception('GD library is not installed on this instance');
}
// Reading EXIF data
if ($exif = exif_read_data($file)) {
$type = $exif['MimeType'] ?? null;
}
// Getting correct function to use
$function = $mimetypes[$type]['function'] ?? null;
if (empty($function) || ! is_callable($function) || ! function_exists($function)) {
throw new Exception('This image format is not supported');
}
// Calling the function
if (false === $gd = call_user_func($function, $file)) {
throw new Exception('Unable to generate a GD image from source');
}
// Does this image needs to be rotated or flipped?
if (! empty($exif['Orientation']) && $exif['Orientation'] !== 1) {
// It's a rotate
if (in_array($exif['Orientation'], [3, 6, 8])) {
switch ($exif['Orientation']) {
case 3:
$angle = 180;
break;
case 6:
$angle = 270;
break;
case 3:
$angle = 90;
break;
}
if (false === $gd = imagerotate($gd, $angle, 0)) {
// Should we block the preview generation because this image is not rotated?
}
}
// It's a flip
else {
switch ($exif['Orientation']) {
case 2:
$flip = IMG_FLIP_HORIZONTAL;
break;
case 4:
$flip = IMG_FLIP_VERTICAL;
break;
case 5:
$flip = IMG_FLIP_BOTH;
break;
}
if (false === $gd = imageflip($gd, $flip)) {
// Should we block the preview generation because this image is not rotated?
}
}
}
// First we generate the new image sizes
$max_width = 4;
$width = imagesx($gd);
$height = imagesy($gd);
$ratio = $width / $height;
$max_height = max(round($max_width, 1) / $ratio, 1);
// Then we create a new image with correct size and ratio
if (false === $temp = imagecreatetruecolor($max_width, $max_height)) {
throw new Exception('Cannot create a new image container');
}
// Finally we copy the original image to the new container image
if (false === imagecopyresampled($temp, $gd, 0, 0, 0, 0, $max_width, $max_height, $width, $height)) {
throw new Exception('Cannot resample image');
}
// Adding blur and smoothing
imagefilter($temp, IMG_FILTER_GAUSSIAN_BLUR);
imagefilter($temp, IMG_FILTER_SMOOTH, IMG_FILTER_SMOOTH);
// Outputting image to GIF format
ob_start();
imagegif($temp);
$image = ob_get_contents();
ob_end_clean();
return base64_encode($image);
}
<html>
<body>
<img
width="300"
src="data:image/gif;base64,<?php echo generateImagePreview('./image/myimage.png'); ?>"
/>
<!--
THIS IS THE ACTUAL SIZE OF THE BASE64 USED TO DISPLAY THE IMAGE. SHORT ENOUGHT TO BE STORED INTO A DATABASE FIELD
<img
width="300"
src="data:image/gif;base64,R0lGODdhBAACAKIAAJSanJyipKSenJSepJyWlKSipJSapKSmpCwAAAAABAACAAADBih1QTYgAQA7"
/>
-->
</body>
</html>
@axeloz
Copy link
Author

axeloz commented Jan 17, 2024

Here is a screenshot of the result (before and after)

example

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