Last active
September 17, 2024 12:52
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 8: | |
$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); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is a screenshot of the result (before and after)