So, i have a script for resize, save a gif and save a preview image of this gif on my server.
This is my script :
public function createImageGif($gif, $x, $y, $w, $h)
{
$image = new Imagick();
$decoded = base64_decode($gif);
$image->readimageblob($decoded);
$image = $image->coalesceImages();
$image_name = uniqid(rand()).'.gif';
foreach ($image as $frame) { //gif creation
$frame->cropImage($w, $h, $x, $y);
$frame->thumbnailImage(117, 135);
$frame->setImagePage(117, 135, 0, 0);
}
$image = $image->deconstructImages();
$image->writeImages('uploads/profiles/'.$image_name, true);
//preview creation
$im = imagecreatefromstring($decoded);
if ($im !== false) {
header('Content-Type: image/gif');
$newimage = imagecreatetruecolor(117, 135);
imagecopyresampled($newimage, $im, 0, 0, $x, $y, 117, 135, $w, $h);
imagegif($newimage, 'uploads/profiles-preview/'.$image_name.'', 100);
imagedestroy($newimage);
imagedestroy($im);
}
return $image_name;
}
So, $gif is at first a long string blob (about 2 000 000 characters). At the end, gif size on my server is approximatly 300ko.
This script take more of 20s to execute. I have a good connexion and a good server.
How can i optimize this script ? Any ideas ?
Edit : this is my script for the creation of my data in javascript :
var base64data;
var img = document.createElement('img');
var reader = new window.FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
base64data = reader.result;
img.src = base64data;
}
Why your script uses a blob binary64 encoded as input? There are many sound reasons to do this thing, but are you sure it's necessary? Can't you just load the image from PHP temp's folder?
Maybe, you're uploading an image from a javascript function, through ajax, base-64 encoding an image (created on the fly from canvas?) and sending it as a string in a POST parameter
Also, I see that you first save your image, then re-open it for sending back the reply to the client. Why don't you send back the image you just resized (the one contained in the $image variable)
Related
My image file size is 800x600 and I want to resize this 800x600 to 400x300 then save both images(800x600 and 400x300) in the database base64_encode format. I can save in database first image (800x600) but how to convert a second image (400x300) in base64_encode format and save in database? I don't want to use two input fields. I think one input field enough for that.
$image = ($_FILES["my_image"]["name"]);
$theme_image = ($_FILES["my_image"]["tmp_name"]);
$bin_string = file_get_contents("$theme_image");
$theme_image_enc = base64_encode($bin_string);
You have to make a little script for create the new image from the first one and make the base64_encode on it
$WIDTH = 400; // The size of your new image
$HEIGHT = 300; // The size of your new image
$QUALITY = 100; //The quality of your new image
$DESTINATION_FOLDER = DependOfYourRepository; // The folder of your new image
// The directory where is your image
$filePath = DependOfYourRepository;
// This little part under depend if you wanna keep the ratio of the image or not
list($width_orig, $height_orig) = getimagesize($filePath);
$ratio_orig = $width_orig/$height_orig;
if ($WIDTH/$HEIGHT > $ratio_orig) {
$WIDTH = $HEIGHT*$ratio_orig;
} else {
$HEIGHT = $WIDTH/$ratio_orig;
}
// The function using are different for png, so it's better to check
if ($file_ext == "png") {
$image = imagecreatefrompng($filePath);
} else {
$image = imagecreatefromjpeg($filePath);
}
// I create the new image with the new dimension and maybe the new quality
$bg = imagecreatetruecolor($WIDTH, $HEIGHT);
imagefill($bg, 0, 0, imagecolorallocate($bg, 255, 255, 255));
imagealphablending($bg, TRUE);
imagecopyresampled($bg, $image, 0, 0, 0, 0, $WIDTH, $HEIGHT, $width_orig, $height_orig);
imagedestroy($image);
imagejpeg($bg, $DESTINATION_FOLDER.$filename, $QUALITY);
$bin_string_little = file_get_contents($DESTINATION_FOLDER.$filename);
// I remove the image created because you just wanna save the base64 version
unlike($DESTINATION_FOLDER.$filename);
imagedestroy($bg);
$theme_image_enc_little = base64_encode($bin_string_little);
// And now do what you want with the result
EDIT 1
It's possible to do it without using a directory for the second image but it's quite tricky.
$theme_image_little = imagecreatefromstring(base64_decode($theme_image_enc));
$image_little = imagecreatetruecolor($WIDTH, $HEIGHT);
// $org_w and org_h depends of your image, in your case, i guess 800 and 600
imagecopyresampled($image_little, $theme_image_little, 0, 0, 0, 0, $WIDTH, $HEIGHT, $org_w, $org_h);
// Thanks to Michael Robinson
// start buffering
ob_start();
imagepng($image_little);
$contents = ob_get_contents();
ob_end_clean();
$theme_image_enc_little = base64_encode($contents):
i have the following script for coping a JPEG and a PNG to an existing PNG called base.png. Within the function "transparent_background" i replace the white background with transparency. This function is the problem. Standlone the function is working with output directly in the browser. please see the comment out "//imagepng($img);". but if i return the $img out of the function its still a jpeg i think, thats why it isnt transparent. The second function is just for resize.
<?php
function transparent_background($img)
{
$img = imagecreatefromjpeg($img); //or whatever loading function you need
$colors= array("255","255","255");
$remove = imagecolorallocate($img, $colors[0], $colors[1], $colors[2]);
imagecolortransparent($img, $remove);
//imagepng($img);
return $img;
imagedestroy($img);
}
function resize($img, $w){
$img = imagecreatefromjpeg($img);
$ratio = imagesx($img)/imagesy($img);
if( $ratio > 1) {
$width = $w;
$height = $w/$ratio;
}
else {
$width = $w*$ratio;
$height = $w;
}
$dst = imagecreatetruecolor($width,$height);
imagecopyresampled($dst,$img,0,0,0,0,$width,$height,imagesx($img),imagesy($img));
return $dst;
imagedestroy($dst);
imagedestroy($img);
}
$h="https://images-eu.ssl-images-amazon.com/images/I/415zYwg2-TL.jpg";
$base = imagecreatefrompng("base.png");
$logo = imagecreatefrompng("fs_logo_line.png");
$pos1=resize($h,"730");
$pos1=transparent_background($h);
imagecopy($base,$pos1,0, 5, 0, 0, imagesx($pos1),imagesy($pos1));
imagecopy($base,$logo,0, 1136, 0,0,imagesx($logo),imagesy($logo));
imagepng($base);
?>
I think the problem is, that i get a jpeg back from the transparent_background function and thats why the image in $pos1 is not transparent. Any ideas how i can solve that? I have tried with ob_start & ob_get_contents but this also didn't work.
You can merge the two images together using the PHP GD2 library.
Example:
<?php
# If you don't know the type of image you are using as your originals.
$image = imagecreatefromstring(file_get_contents($your_original_image));
$frame = imagecreatefromstring(file_get_contents($your_frame_image));
# If you know your originals are of type PNG.
$image = imagecreatefrompng($your_original_image);
$frame = imagecreatefrompng($your_frame_image);
imagecopymerge($image, $frame, 0, 0, 0, 0, 50, 50, 100);
# Save the image to a file
imagepng($image, '/path/to/save/image.png');
# Output straight to the browser.
imagepng($image);
?>
Add imagealphablending($frame,true); before imagecopymerge() if you want to keep PNG frame transparancy over the image.
I'm trying to crop of the bottom part of an image, which i get from a remote site.
Got it also working with the following code:
$u = $xmlString->xpath('//*[contains(#u, "/fds/")]');
foreach($u as $result) {
$itemLinks = 'http://exampleurl/'.$result['u'].'.png';
$in_filename = $itemLinks;
list($width, $height) = getimagesize($in_filename);
$offset_x = 0;
$offset_y = 0;
$new_height = $height - 264;
$new_width = $width;
$image = imagecreatefrompng($in_filename);
$new_image = imagecreatetruecolor($new_width, $new_height);
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
$transparentindex = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
imagefill($new_image, 0, 0, $transparentindex);
imagecopy($new_image, $image, 0, 0, $offset_x, $offset_y, $width, $height);
header("Content-Type: image/png");
imagepng($new_image);
}
The only problem with this code is the following:
I'm getting the Image Path from a remote XML file, which i filtered with xpath. So all my finished Image url's are stored in an array. But my code is just generating 1 image which contains the perfect size which i need.
It happens because its just generating 1 img in the end. Maybe also happens because it just returns 1 image with the name img.
Question: Does anyone have a idea why it wouldnt return all images?
For example:
Array contains 15 image links.
Im running my foreach loop through the array.
Foreach loop returns only 1 image.
Your issue is caused by the last two lines:
header("Content-Type: image/png");
imagepng($new_image);
This has the same effect as opening a single image file (like a .PNG) in your browser. You can't view multiple image files at the same time unless they are embedded in a HTML page.
If you want to show all fifteen images at once in the browser you'll need to save each image as you process it and then output an HTML file, something like this:
$images = '';
foreach($u as $result) {
// your existing code...
imagepng($new_image, './'.$result['u'].'.png');
$images .= '<img src="'.$result['u'].'.png">';
}
// wrap this in valid HTML syntax (<head>, <body>, etc.)
echo $images;
I have a script for capture a video with your webcam, and convert this video to a .gif.
I have this script for resize and save the file with PHP in .gif :
$image = new Imagick();
$decoded = base64_decode($gif);
$image->readimageblob($decoded);
$image = $image->coalesceImages();
foreach ($image as $frame) {
$frame->cropImage($w, $h, $x, $y);
$frame->thumbnailImage(117, 135);
$frame->setImagePage(117, 135, 0, 0);
}
$image_name = uniqid(rand()).'.gif';
$image = $image->deconstructImages();
$image->writeImages('uploads/profiles/'.$image_name, true);
return $image_name;
So, with this script, i retrieve .gif with a sizez of 400-500ko, i think it's very big for a simply gif of 117px/135px...
How can i optimize this gif for reduce the size ? Thanks !
It's very large because it is an animated GIF, which has multiple frames. One option is to use Imagick::optimizeImageLayers() to optimize the layers of the image.
Here's an example (from PHP documentation):
<?php
/* create new imagick object */
$im = new Imagick("test.gif");
/* optimize the image layers */
$im->optimizeImageLayers();
/* write the image back */
$im->writeImages("test_optimized.gif", true);
?>
you can skip some frames to make it smaller
// Use every other frame only
foreach ($image as $k => $frame) {
if ($k%2) { // Use last frame if odd
$frame = $lastFrame;
} else {
$frame->cropImage($w, $h, $x, $y);
$frame->thumbnailImage(117, 135);
$frame->setImagePage(117, 135, 0, 0);
}
$lastFrame = $frame;
}
you can use ob_gzhandler in php
for more detail look this
http://php.net/manual/en/function.ob-gzhandler.php
or
this sample maybe help you
http://www.devirtuoso.com/2009/07/how-to-compress-cssjavascript-files-with-php/
if none did not help ,you can use system function and use terminal or command line command
for compress you result file with os commands
be successfull
I have a problem here when I need create a image with transparent background. I still don´t know if the problem is with fabricjs or with php. Everything works fine when I sent a image with colored background. The problem occurs when I send a image with transparent background.
The generated image is created with black background.
So, let me explain better:
When the user click in save button, I´m sending the string representation of the canvas to php in the server-side, to be generated the image of the canvas. So I´m using the follow function to sending the string representation of the canvas by Ajax (POST function of jQuery):
function sendStringRepresentation(){
var strDataURI = canvas.toDataURL();
strDataURI = strDataURI.substr(22, strDataURI.length);
$.post("action/createImage.php",
{
str: strDataURI
},
function(data){
if(data == "OK"){
$("#msg").html("Image created.");
}
else{
$("#msg").html("Image not created.");
}
});
}
In PHP file I´m using the follow code to generate the image:
// createImage.php
$data = base64_decode($_POST["str"]);
$urlUploadImages = "../uploads/img/";
$nameImage = "test.png";
$img = imagecreatefromstring($data);
if($img) {
imagepng($img, $urlUploadImages.$nameImage, 0);
imagedestroy($img);
// [database code]
echo "OK";
}
else {
echo 'ERROR';
}
Again, the problem is just with background transparent canvas. With colored background everything works fine.
The last step is quite the opposite:
imagecopyresampled( $img, $alpha_image, 0, 0, 0, 0, $w, $h, $w, $h );
And voila! The image is transparent!
Why did you use GD for this? You can use file_put_contents for save png file from your canvas.
// createImage.php
$data = base64_decode($_POST["str"]);
$urlUploadImages = "../uploads/img/test.png";
file_put_contents($urlUploadImages, $data);
I don't know if this is exactly the problem you're experiencing, but some of the GD library's imagecreate* functions create images without the alpha channel.
The workaround I've found is to create an image using imagecreatetruecolor and copy your transparent image onto it.
Try a process like this:
$img = imagecreatefromstring($data);
$w = imagesx($img);
$h = imagesy($img);
$alpha_image = imagecreatetruecolor( $w, $h );
imagecopyresampled( $alpha_image, $img, 0, 0, 0, 0, $w, $h, $w, $h );
That should ensure that you end up with a "true color" image with the proper alpha channel.
JPG toDataURL transforms transparent background to black.
I had the exact same problem and added this
imageAlphaBlending($img, true);
imageSaveAlpha($img, true);
to rodrigopandini's code and it works perfect now.:)
// createImage.php
$data = base64_decode($_POST["str"]);
$urlUploadImages = "../uploads/img/";
$nameImage = "test.png";
$img = imagecreatefromstring($data);
imageAlphaBlending($img, true);
imageSaveAlpha($img, true);
if($img) {
imagepng($img, $urlUploadImages.$nameImage, 0);
imagedestroy($img);
// [database code]
echo "OK";
}
else {
echo 'ERROR';
}