I have a function that returns base 64 image from URL. For a list of images (around 100 images - all thumbs), it takes almost 30 sec to complete. Is there anything I can do to speed up PHP image processing function (maybe some way to clear memory...) ?
<?php
// Get new dimensions
$url = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTnhDbj3HU9Sh4K71lOfJ9uMjESMTnYqLyJ7QLJf12asOj_o05N&s";;
list($width_orig, $height_orig) = getimagesize($url);
$maxWidth = 220;
$maxHeight = 220;
// Set a maximum height and width
$targetWidth = $maxWidth ? $maxWidth : $width_orig;
$targetHeight = $maxHeight ? $maxHeight : $height_orig;
// Resample
$image_p = imagecreatetruecolor($targetWidth, $targetHeight);
$image = imagecreatefromstring(file_get_contents($url));
$white = imagecolorallocate($image_p, 255, 255, 255);
imagefill($image_p, 0, 0, $white);
$dx = ($targetWidth - $width_orig) / 2;
$dy = ($targetHeight - $height_orig) / 2;
imagecopyresampled($image_p, $image, $dx, $dy, 0, 0, $width_orig, $height_orig, $width_orig, $height_orig);
ob_start();
imagepng($image_p);
$data = ob_get_contents();
imagedestroy($image_p);
imagedestroy($image);
ob_end_clean();
if ($image_p !== false) {
echo "data:image/jpg;base64,".base64_encode($data);
};
?>
Thank you!
Related
Original Image:
Desired output: (I added black border for the sack of understanding)
I want to resize image to 200/200 without cropping. See the desired output.
I have this code
<?php
// function created by www.thewebhelp.com
if (!function_exists("create_square_image")) {
function create_square_image($original_file, $destination_file = NULL, $square_size = 96) {
if (isset($destination_file) and $destination_file != NULL) {
if (!is_writable($destination_file)) {
echo '<p style="color:#FF0000">Oops, the destination path is not writable. Make that file or its parent folder wirtable.</p>';
}
}
// get width and height of original image
$imagedata = getimagesize($original_file);
$original_width = $imagedata[0];
$original_height = $imagedata[1];
if ($original_width > $original_height) {
$new_height = $square_size;
$new_width = $new_height * ($original_width / $original_height);
}
if ($original_height > $original_width) {
$new_width = $square_size;
$new_height = $new_width * ($original_height / $original_width);
}
if ($original_height == $original_width) {
$new_width = $square_size;
$new_height = $square_size;
}
$new_width = round($new_width);
$new_height = round($new_height);
// load the image
if (substr_count(strtolower($original_file), ".jpg") or substr_count(strtolower($original_file), ".jpeg")) {
$original_image = imagecreatefromjpeg($original_file);
}
if (substr_count(strtolower($original_file), ".gif")) {
$original_image = imagecreatefromgif($original_file);
}
if (substr_count(strtolower($original_file), ".png")) {
$original_image = imagecreatefrompng($original_file);
}
$smaller_image = imagecreatetruecolor($new_width, $new_height);
$square_image = imagecreatetruecolor($square_size, $square_size);
imagecopyresampled($smaller_image, $original_image, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height);
if ($new_width > $new_height) {
$difference = $new_width - $new_height;
$half_difference = round($difference / 2);
imagecopyresampled($square_image, $smaller_image, 0 - $half_difference + 1, 0, 0, 0, $square_size + $difference, $square_size, $new_width, $new_height);
}
if ($new_height > $new_width) {
$difference = $new_height - $new_width;
$half_difference = round($difference / 2);
imagecopyresampled($square_image, $smaller_image, 0, 0 - $half_difference + 1, 0, 0, $square_size, $square_size + $difference, $new_width, $new_height);
}
if ($new_height == $new_width) {
imagecopyresampled($square_image, $smaller_image, 0, 0, 0, 0, $square_size, $square_size, $new_width, $new_height);
}
// if no destination file was given then display a png
if (!$destination_file) {
imagepng($square_image, NULL, 9);
}
// save the smaller image FILE if destination file given
if (substr_count(strtolower($destination_file), ".jpg")) {
imagejpeg($square_image, $destination_file, 100);
}
if (substr_count(strtolower($destination_file), ".gif")) {
imagegif($square_image, $destination_file);
}
if (substr_count(strtolower($destination_file), ".png")) {
imagepng($square_image, $destination_file, 9);
}
imagedestroy($original_image);
imagedestroy($smaller_image);
imagedestroy($square_image);
}
}
create_square_image("image.jpg", "sample_thumb.jpg", 200);
?>
<h2>Original image</h2>
<h2><img src="image.jpg" />
</h2>
<h2>The created square thumbnail</h2>
<h2><img src="sample_thumb.jpg" />
</h2>
But my code is outputting like this
How about using a white image that matches your dimensions? I.e you get a white image that is your desired size (200x200) and merge it with your other image.
// First image is the white image that has the dimension you want.
$image1 = imagecreatefrompng('COLOR.png');
// Second image is the image you want to change size of
$image2 = imagecreatefrompng('SOURCE.png');
// Merge the two, so that the white image is below the "Dress"
// image you showed us in your question.
imagecopymerge($image1, $image2, 0, 0, 0, 0, 161, 200, 100);
// Output and free from memory
header('Content-Type: image/png');
echo imagepng($image1);
// Destroy images
imagedestroy($image1);
imagedestroy($image2);
Parameters for the function:
bool imagecopymerge ( resource $dst_im , resource $src_im , int $dst_x
, int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h , int
$pct )
Last parameter is percentage(alpha) so if you don't want a white backround then you just set it to 0, and it will be transparent.
EDIT: Check out the docs so that you get the correct position for the second image here.
EDIT 2: The above code will produce the following image(provided the color image is black):
I have found the solution that works for both situation whether image is wide or tall.
$whereToPut = "source.jpg"; // This is 200/200 blank white image
$size = getimagesize($fn);
$ratio = $size[0] / $size[1]; // width/height
$dst_y = 0;
$dst_x = 0;
if ($ratio > 1) {
$width = 200;
$height = 200 / $ratio;
$dst_y = (200 - $height) / 2;
} else {
$width = 200 * $ratio;
$height = 200;
$dst_x = (200 - $width) / 2;
}
$src = imagecreatefromstring(file_get_contents($fn));
$dst = imagecreatetruecolor($width, $height);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);
$image1 = imagecreatefromjpeg($whereToPut);
imagecopymerge($image1, $dst, $dst_x, $dst_y, 0, 0, imagesx($dst), imagesy($dst), 100);
imagejpeg($image1, $finalImage);
// $dinalImage is your final created image.
I am adding a transparant logo as watermark over an image using PHP. However, in the result the logo has poor quality (the image that is under it is high quality, so it's just the watermark). This is the code I use (its about the last 3 lines):
header("Content-Type: image/png");
$photo = imagecreatefromjpeg('photos/'.$photo['image']);
$height = imagesx($photo);
$width = imagesx($photo);
if ($width > $_POST['width']) {
$r = $width / $_POST['width'];
$newwidth = $width / $r;
$newheight = $height / $r;
}
$image = imagecreatetruecolor($width, $height);
$image2 = imagecopyresampled($image, $photo, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
$position = explode(" ", $_POST['background']);
$image3 = imagecrop($image, [
'x' => str_replace(array('-', 'px'), array('', ''), $position[0]),
'y' => str_replace(array('-', 'px'), array('', ''), $position[1]),
'width' => $_POST['width'],
'height' => $_POST['height']
]);
$stamp = imagecreatefrompng('img/logo.png');
imagecopyresized($image3, $stamp, 0, 0, 0, 0, 147, 50, imagesx($stamp), imagesy($stamp));
imagepng($image3, "created/".time().".png", 9);
imagecopyresized will copy and scale and image. This uses a fairly primitive algorithm that tends to yield more pixelated results.
a simple example for a better quality is:
<?php
// The file
$filename = 'test.jpg';
$percent = 0.5;
// Content type
header('Content-type: image/jpeg');
// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;
// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// Output
imagejpeg($image_p, null, 100);
?>
you should have a look at this post here
use quality of image from 1-100.
imagejpeg($image, $new_image_name, 99);
The following code works with intial 8bit-png's but when i use a 24 bit alpha transp png, it seems to work worse when the resulting image gets bigger. The bigger the resulting image the less colors remain. Both pictures where exported from PS via Web-Export.
How can I solve the problem? Is something wrong with the code or may it be a bug? (I am on Windows 10, PHP 5.6.6)
$imgPath = 'image-24bit-alpha-transp-from-ps-960x533.png';
$imgDirname = pathinfo($imgPath, PATHINFO_DIRNAME);
$imgFilename = pathinfo($imgPath, PATHINFO_FILENAME);
$imgExtension = pathinfo($imgPath, PATHINFO_EXTENSI
ON);
$newWidths = [80, 160, 320, 640, 960];
$img = imagecreatefrompng($imgPath);
list($width, $height) = getimagesize($imgPath);
if($width * $height > PHP_INT_MAX)
throw new Exception('The picture exceeds the maximum number of pixels ('.INT_MAX.').');
$ratio = $height / $width;
$alphaTransparency = imagecolortransparent($img) >=0 || (ord(file_get_contents($imgPath, false, null, 25, 1)) & 4);
$numberOfColors = imagecolorstotal($img);
$trueColorImage = $numberOfColors === 0;
foreach($newWidths as $newWidth)
{
$newImgPath = $imgDirname.DIRECTORY_SEPARATOR.$imgFilename.'_w'.$newWidth.'.'.$imgExtension;
$newHeight = ceil($newWidth * $ratio);
$newImg = $trueColorImage ? imagecreatetruecolor($newWidth, $newHeight) : imagecreate($newWidth, $newHeight);
imagealphablending($newImg, false);
imagesavealpha($newImg,true);
$color = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
imagefill($newImg, 0, 0, $color);
imagetruecolortopalette($newImg, false, $trueColorImage ? 255 : $numberOfColors);
imagecopyresampled($newImg, $img, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagepng($newImg, $newImgPath, 6);
imagedestroy($newImg);
}
imagedestroy($img);
I have successfully resized images using GD library. I resize any image to 350 x 250, the problem is tat some pictures don't look good (stretch) when they are resized as i am resizing them to a fixed size. I have a space of 350 x 250 where resize picture needs to be fit, I don't mind if the pic size is smaller than 350 x 250 as long as it does not stretch. How do i solve this problem?
$save = "$directory/" . $file_name; //This is the new file you saving
$file = "$directory/" . $file_name; //This is the original file
list($width, $height) = getimagesize($file) ;
$modwidth = 350;
if ($width > $height) {
$y = 0;
$x = ($width - $height) / 2;
$smallestSide = $height;
} else {
$x = 0;
$y = ($height - $width) / 2;
$smallestSide = $width;
}
$diff = $width / $modwidth;
$modheight = 250;
$tn = imagecreatetruecolor($modwidth, $modheight) ;
$image = imagecreatefromjpeg($file) ;
imagecopyresampled($tn, $image, 0, 0, 0, 0, $modwidth, $modheight, $width, $height);
imagejpeg($tn, $save, 100) ;
Try using this function I've written some time ago:
public function resize($img, $width, $height, $stretch = false)
{
$temp = imagecreatetruecolor($width, $height);
imagealphablending($temp, true);
imagesavealpha($temp, true);
$bg = imagecolorallocatealpha($temp, 0, 0, 0, 127); // Background color
imagefill($temp, 0, 0, $bg);
if ($stretch)
{
imagecopyresampled($temp, img, 0, 0, 0, 0, $width, $height, imagesx($img), imagesy($img));
}
else
{
if (imagesx($img) <= $width && imagesy($img) <= $height)
{
$fwidth = imagesx($img);
$fheight = imagesy($img);
}
else
{
$wscale = $width / imagesx($img);
$hscale = $height / imagesy($img);
$scale = min($wscale, $hscale);
$fwidth = $scale * imagesx($img);
$fheight = $scale * imagesy($img);
}
imagecopyresampled($temp,
$img,
($width - $fwidth) / 2, ($height - $fheight) / 2,
0, 0,
$fwidth, $fheight,
imagesx($img), imagesy($img)
);
}
return $temp;
}
if you say not to stretch the image, it will calculate a new size making it fit your new size.
use it as:
...
$image = imagecreatefromjpeg($file);
$resized = resize($image, 350, 250, false); // false = don't stretch
imagejpeg($resized, $save, 100);
...
now store $resized on the disk using imagepng() for example.
Do any of you know of a good php class I can use to download an image from a remote source, re-size it to 120x120 and save it with a file name of my choosing?
So basically I would have an image at "http://www.site.com/image.jpg" save to my web server "/images/myChosenName.jpg" as a 120x120 pixels.
Thanks
You can try this:
<?php
$img = file_get_contents('http://www.site.com/image.jpg');
$im = imagecreatefromstring($img);
$width = imagesx($im);
$height = imagesy($im);
$newwidth = '120';
$newheight = '120';
$thumb = imagecreatetruecolor($newwidth, $newheight);
imagecopyresized($thumb, $im, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
imagejpeg($thumb,'/images/myChosenName.jpg'); //save image as jpg
imagedestroy($thumb);
imagedestroy($im);
?>
More information about PHP image function : http://www.php.net/manual/en/ref.image.php
You can resize keeping the ratio of image
$im = imagecreatefromstring($img);
$width_orig = imagesx($im);
$height_orig = imagesy($im);
$width = '800';
$height = '800';
$ratio_orig = $width_orig/$height_orig;
if ($width/$height > $ratio_orig) {
$width = $height*$ratio_orig;
} else {
$height = $width/$ratio_orig;
}
If you're looking to have the ability to do this for both jpg and png file formats, here's what helped me:
$imgUrl = 'http://www.example.com/image.jpg';
// or $imgUrl = 'http://www.example.com/image.png';
$fileInfo = pathinfo($imgUrl);
$img = file_get_contents($imgUrl);
$im = imagecreatefromstring($img);
$originalWidth = imagesx($im);
$originalHeight = imagesy($im);
$resizePercentage = 0.5;
$newWidth = $originalWidth * $resizePercentage;
$newHeight = $originalHeight * $resizePercentage;
$tmp = imagecreatetruecolor($newWidth, $newHeight);
if ($fileInfo['extension'] == 'jpg') {
imagecopyresized($tmp, $im, 0, 0, 0, 0, $newWidth, $newHeight, $originalWidth, $originalHeight);
imagejpeg($tmp, '/img/myChosenName.jpg', -1);
}
else if ($fileInfo['extension'] == 'png') {
$background = imagecolorallocate($tmp , 0, 0, 0);
imagecolortransparent($tmp, $background);
imagealphablending($tmp, false);
imagesavealpha($tmp, true);
imagecopyresized($tmp, $im, 0, 0, 0, 0, $newWidth, $newHeight, $originalWidth, $originalHeight);
imagepng($tmp, '/img/myChosenName.png');
}
else {
// This image is neither a jpg or png
}
imagedestroy($tmp);
imagedestroy($im);
The extra code on the png side of things ensures that the saved image contains any and all transparent sections.