I have multiple Images - saved as Base64 Strings and now i want to resize these images to get thumbnails of them...
Best would be using Javascript (Node-Server) to resize them, but it would be possible to resize them with php, too.
Thanks in advance
I agree to the method from Jon Hanna: Do Parsing the Base64code then load it to GD Image before Resample. However to get it back as data it is not as easy as I though. On php in GAE it will need to enable output buffering by setting output_buffering = "On" in php.ini file.
Here I explain the step in detail.
This doc is taken as reference to Create Image Resource using the Parsing of Base64code: http://php.net/manual/en/function.imagecreatefromstring.php
// Create image resource from Base64code
$data64 = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
. 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
. 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
. '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$image = imagecreatefromstring(base64_decode($data64));
This is an image resource which can be directly put to the Resample function: http://php.net/manual/en/function.imagecopyresampled.php
// Resample
$image_p = imagecreatetruecolor($new_w, $new_h);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_w, $new_h, $org_w, $org_h);
The result is also an image resource. To get it as a data we need Buffering.
See
how to create a base64encoded string from image resource
// Buffering
ob_start();
imagepng($image_p);
$data = ob_get_contents();
ob_end_clean();
Using doc below I set a GCS bucket on my project as a website so I can Store & Display it directly:
https://cloud.google.com/storage/docs/website-configuration#tips
//Store & Display
$context = stream_context_create([
'gs' =>[
'acl'=> 'public-read',
'Content-Type' => 'image/jpeg',
'enable_cache' => true,
'enable_optimistic_cache' => true,
'read_cache_expiry_seconds' => 300,
]
]);
file_put_contents("gs://mybucket/resample/image.jpeg", $data, false, $context);
header("Location: http://mybucket/resample/image.jpeg");
Your best bet is to use PHPThumb in PHP.
An alternative is to invoke ImageMagick however you prefer:
http://coffeeshopped.com/2009/01/creating-image-thumbnails-using-php-and-imagemagick
http://www.hacksparrow.com/node-js-image-processing-and-manipulation.html
No idea how to do that (or well, anything) in node.js, but the PHP bit of your question is certainly possible. After parsing the Base64, load it into a GD image and then resample it.
http://php.net/manual/en/function.imagecopyresampled.php
Maybe you just can use a lib to handle that. Try WideImage. I have used it and worked nicely.
Example:
$image = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $req->image));
$thumbnail = WideImage::load($image)
->resize(300, 300, 'inside')
->crop('center', 'center', 300, 300);
Library Documentation: http://wideimage.sourceforge.net/
Related
In my application there is a call which might request a resized version of the image. In the case when it is resized I want to store the resized version long-term onto gridfs, exactly like the other images.
I can easily resize the image and return it using Intervention (http://image.intervention.io/getting_started/introduction) however it seems to be that it's not possible to store the resized image to the DB without saving it to a temporary file.
In particular this fails:
$bucket = DB::getMongoDB()->selectGridFSBucket();
$stream = $bucket->openDownloadStreamByName($name);
$document = $bucket->getFileDocumentForStream($stream);
$metadata = $document['metadata']->getArrayCopy();
$file = stream_get_contents($stream);
$img = Image::cache(function($image) use ($file){
$image->make($file);
}, 60, true);
$img->resize($width, $height, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
$bucket->uploadFromStream($randomName, $img, ['metadata' => $metadata]);
The call to uploadFromStream fails saying: Expected $source to have type "resource" but found "Intervention\Image\CachedImage".
Trying to change:
$bucket->uploadFromStream($randomName, $img, ['metadata' => $metadata]);
to:
$bucket->uploadFromStream($randomName, $img->stream('png'), ['metadata' => $metadata]);
Leads to the same error only that the type changes from Intevention\Image\CachedImage to GuzzleHttp\Psr7\Stream.
Now I could do:
$img->save('/tmp/test.png')
$stream = fopen('/tmp/test.png')
$bucket->uploadFromStream($randomName, $stream, ['metadata' => $metadata]);
but this is abysmally bad because:
it has a race condition. I would need to ensure the filename used is unique otherwise it might be overwritten
it writes to disk which means it's going to be way slower than just using an in-memory stream
it writes to disk which means it deteriorates more. Consider that this write is completely useless so I'd avoid using it. It can be triggered quite often.
So, is there a way to save the resized image to GridFS without passing throught the disk?
I found a solution: you can obtain the binary data as a string using $img->response()->content() and then instead of using uploadFromStream you can use openUploadStream and write the data.
The full working solution would be:
$bucket = DB::getMongoDB()->selectGridFSBucket();
$stream = $bucket->openDownloadStreamByName($name);
$document = $bucket->getFileDocumentForStream($stream);
$metadata = $document['metadata']->getArrayCopy();
$file = stream_get_contents($stream);
$img = Image::cache(function($image) use ($file){
$image->make($file);
}, 60, true);
$img->resize($width, $height, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
$stream = $bucket->openUploadStream($randomName, ['metadata' => $metadata]);
fwrite($stream, $img->response()->content());
fclose($stream);
I am using a PHP function to add my logo as the watermark on images uploaded on my website. But I don't know why my watermark function is not working for png files. however, it works for jpeg files perfectly. this is my PHP function.
function watermark($img) {
global $wm_file, $wm_right, $wm_bottom;
// image values pulled from config.inc.php
$logo = './images/' . $wm_file; // path to the watermark.png
$sp = $wm_right; // spacing from right side
$sq = $wm_bottom; // spacing from bottom
$size = getImageSize($img);
$sizel = getImageSize($logo);
$imgA = imageCreateFromJpeg($img);
imageAlphaBlending($imgA, TRUE);
if($sizel[0] > $size[0] || $sizel[1] > $size[1])
{
// logo size > img size
$sizelo[0] = $sizel[0];
$sizelo[1] = $sizel[1];
$sizel[0] = ($sizel[0]/2);
$sizel[1] = ($sizel[1]/2);
}
else
{
$sizelo[0] = $sizel[0];
$sizelo[1] = $sizel[1];
}
$imgBa = imageCreateFromPng($logo);
$imgB = imageCreateTrueColor($sizel[0], $sizel[1]);
imageAlphaBlending($imgB, TRUE);
imageCopyResampled($imgB, $imgBa, 0, 0, 0, 0, $sizel[0], $sizel[1], $sizelo[0], $sizelo[1]);
imageColorTransparent($imgB, ImageColorAllocate($imgB, 0, 0, 0));
$perc = 100;
imageCopymerge($imgA, $imgB, ($size[0]-$sizel[0]-$sp), ($size[1]-$sizel[1]-$sq), 0, 0, $sizel[0], $sizel[1], $perc);
unlink($img);
if(imageJpeg($imgA, $img, 100))
{
imageDestroy($imgB);
imageDestroy($imgA);
return true;
}
chmod($img, 0777);
}
The problem I see is that you are using imageCreateFromJpeg() as the way to generate the resource for your $img that you are passing to the function.
If you pass a jpeg through the function it will work. If you pass a png it will not.
I recommend using imagecreatefromstring() to create all your resources as it is not dependent on the file type. Like so:
$source = imagecreatefromstring(file_get_contents($filePath));
Another benefit of this is that it will return false if the function fails to create a resource from the file path that you supplied meaning that the file is not an image file.
Now that you have a resource to use for the rest of your code, imageJpeg() will save the resource as a jpeg back to the file path.
Hope that helps.
One other side note. If you intend on using bmp images, the GD library does not have a built in function for bmps. However on PHP.net, someone did write a createimagefromBMP() that works really well. Also I think that on the latest version of PHP the GD library does now actually have a createimagefromBMP() function.
I also see that you are using unlink() to delete the image from your directory. This is not necessary for two reasons. The imageJpeg() will just overwrite the original. Also, if for some reason your script fails it may delete the image prematurely and you will loose the image without the new one being written.
Please be careful when using chmod(), always make sure that you set permissions back to the original permissions when you are done.
chmod($img, 777); //Give broad permissions.
//Do something.
chmod($img, 600(or whatever they were)); //Reset permission back to where they were before you changed them.
Hi I'm using php's gd library to generate images. I've decided to integrate this into laravel, and I managed to make it work.
My problem is that if laravel sometimes overwrites my content-type header.
This is my controller:
public function imga($algorythm,$w=false,$h=false){
if (!$w) $w=rand(250,750);
if (!$h) $h=rand(250,750);
$im = imagecreatetruecolor($w, $h);
//Here some fancy function is called
if (method_exists($this,'img_'.$algorythm)){
$this->{'img_'.$algorythm}($im,$w,$h);
}
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
}
Most of the times if the image is large enough the browser displays it just as expected, but if the image is to small laravel overwrites the content type header with "text/html; charset=UTF-8".
I've read https://laravel.com/docs/5.4/responses but to make it this way I need to have a string.
So I've looked at this: PHP: create image with ImagePng and convert with base64_encode in a single file? but I'm not sure if this is the right way, it looks like a dirty hack to me.
Should I put the imagepng call inside a view and add the headers there, isn't this a bit overkill?
How to use functions that output data instead of returning it in laravel.
Laravel controller actions are usually expected to give a response of some sort, which defaults to text/html.
Your fix could be as easy as:
header("Content-Type: image/png");
imagepng($im);
imagedestroy($im);
exit;
}
Alternatively you can use a package like intervention (http://image.intervention.io). From which you can generate an image response.
One way would be to capture the image output with ob_get_contents and then make a response with that:
public function imga($algorythm,$w=false,$h=false){
if (!$w) $w=rand(250,750);
if (!$h) $h=rand(250,750);
$im = imagecreatetruecolor($w, $h);
//Here some fancy function is called
if (method_exists($this,'img_'.$algorythm)){
$this->{'img_'.$algorythm}($im,$w,$h);
}
ob_start();
$rendered_buffer = imagepng($im);
$buffer = ob_get_contents();
imagedestroy($im);
ob_end_clean();
$response = Response::make($rendered_buffer);
$response->header('Content-Type', 'image/png');
return $response;
}
EDIT: Just saw your link, this is basically just an implementation of that.
If you want a "more laravel" way, you could save the image, return it, then delete it:
public function imga($algorythm,$w=false,$h=false){
if (!$w) $w=rand(250,750);
if (!$h) $h=rand(250,750);
$im = imagecreatetruecolor($w, $h);
//Here some fancy function is called
if (method_exists($this,'img_'.$algorythm)){
$this->{'img_'.$algorythm}($im,$w,$h);
}
// store the image
$filepath = storage_path('tmpimg/' . uniqid() . '.png');
imagepng($im, $filepath);
imagedestroy($im);
$headers = array(
'Content-Type' => 'image/png'
);
// respond with the image then delete it
return response()->file($filepath, $headers)->deleteFileAfterSend(true);
}
I am newbie for codeigniter and get a chance to learn alot from it. Now i just wanted to include the elasticsearch in Codeigniter and searched for tutorial vedios there is nothing i can find and last i followed this tutorial so that i can make some changes and include in codeigniter . but i struck . Anyhelp will be great. Thank you in advance.
<?php
require_once 'vendor/autoload.php';
$es= new Elasticsearch\Client([ 'hosts' => ['127.0.0.1:9200'] ]);
I just wanted to get this code into codeigniter . it is init.php file inside the App folder when you follow the tutorial. It is like there is no much tutorials to include elasticsearch and codeigniter.
I have followed following tutorials
Ref : https://www.youtube.com/watch?v=3xb1dHLg-Lk
After trying this github demo. which given below.I have included all the files needed and tried to add the index then i got this error.
$insert_data = array('carrier' => $this->input->post('carrier'),
'shipping_type' => $this->input->post('shipping_type'),
'description' => $this->input->post('description'),
'restrictions' => $this->input->post('restrictions'),
'vendor_id' => $vendor_id,
'created_at' => date('Y-m-d h:i:s'),
'updated_at' => date('Y-m-d h:i:s'),
);
if ($insert_data != null) {
$insert_data = $this->Shipping_options_model->insert($insert_data);
var_dump($this->elasticsearch->add("people", $insert_data, $insert_data));
exit;
To use GD Library you have to enable gd library in your php.ini file
extension=php_gd2.dll
and restart server
Example
<?php
/**
* PHP GD
* create a simple image with GD library
*
*/
//setting the image header in order to proper display the image
header("Content-Type: image/png");
//try to create an image
$im = #imagecreate(800, 600)
or die("Cannot Initialize new GD image stream");
//set the background color of the image
$background_color = imagecolorallocate($im, 0xFF, 0xCC, 0xDD);
//set the color for the text
$text_color = imagecolorallocate($im, 133, 14, 91);
//adf the string to the image
imagestring($im, 5, 300, 300, "I'm a pretty picture:))", $text_color);
//outputs the image as png
imagepng($im);
//frees any memory associated with the image
imagedestroy($im);
?>
Ref:
http://code.runnable.com/UnF1kdvayk91AADH/how-to-create-a-simple-image-with-gd-library-for-php
So I currently have an upload system working using AWS S3 to upload images.
Here's the code:
//Upload image to S3
$s3 = Aws\S3\S3Client::factory(array('key' => /*mykey*/, 'secret' => /*myskey*/,));
try {
$s3->putObject(array(
'Bucket' => "bucketname",
'Key' => $file_name,
'Body' => fopen(/*filelocation*/, 'r+')
));
} catch(Exception $e) {
//Error
}
This image can be a jpeg or png, and I want to convert it to a png before uploading. To do this I use:
//This is simplified, please don't warn about transparency, etc.
$image = imagecreatetruecolor($width, $height);
imagecopyresampled($image, $source, 0, 0, 0, 0, etc.);
So I have this $image object in memory.
I want to upload this to S3 without having to save it locally, upload it and then delete it locally; this extra step seems pointless. But I can't work out how to upload this $image object directly.
Any ideas how this would be done? I'd assumed fopen() would create an object of a similar type to imagecreatetruecolor(), but I've tried passing the $image object in and it doesn't work - whereas it does if I open an image locally with fopen().
You can capture the content of a GD image resource using output buffering:
ob_start();
imagepng($image);
$pngdata = ob_get_clean();