I have a script that downloads favicons and turns them in to PNGs.
To handle the conversion, I am using ImageMagick. My current approach involves downloading the data, writing it to a file, converting the file, then deleting the originally downloaded file. Here's what I mean:
$source = 'http://google.com/favicon.ico';
$image = file_get_contents($source);
// I'd like to skip these lines
$favicon = fopen('favicon.ico', 'w');
fwrite($favicon, $image);
fclose($favicon);
$im = new Imagick();
$im->readimage('favicon.ico');
$im = $im->flattenImages();
$im->setImageFormat('png');
$im->writeImage('favicon.png');
unlink('favicon.ico');
This works, but ideally I could do it without writing the $image variable to the file favicon.ico and instead I might just convert the data within the $image variable and then $im->writeImage('favicon.png') on that.
I checked out the method getImageBlob but when I tried that I got this error:
PHP Fatal error: Uncaught exception 'ImagickException' with message 'no decode delegate for this image format `' # error/blob.c/BlobToImage/364' in /home/vagrant/test/test_image.php:73
Stack trace:
#0 /home/vagrant/test/test_image.php(73): Imagick->readimageblob('\x00\x00\x01\x00\x02\x00\x10\x10\x00\x00\x01\x00 \x00h...')
#1 {main}
thrown in /home/vagrant/test/test_image.php on line 73
Any ideas?
You'll need to invoke Imagick::setFormat before reading blob.
<?php
$source = 'http://google.com/favicon.ico';
$image = file_get_contents($source);
$im = new Imagick();
$im->setFormat('ICO');
$im->readImageBlob($image);
$im = $im->flattenImages();
$im->setImageFormat('PNG');
$im->writeImage('favicon.png');
Update
Flattening the .ico image may have negative effects on files containing more than one image. Simplest solution would be to iterate over all the images, and determine which sub-image to use.
$im = new Imagick();
$im->setFormat('ICO');
$im->readImageBlob($image);
for( $idx = 0, $len = $im->getNumberImages(); $idx < $len; $idx++ ) {
// If this is the sub-image you want, do the following, else skip
$im->setImageFormat('png');
$im->setImageIndex($idx);
$im->writeImage(sprintf('favicon_%d.png', $idx));
}
Related
Want to take image from own server rotate certain angle and save the image.
Image file $filename = 'kitten_rotated.jpg'; With echo '<img src='.$filename.'>'; i see the image.
Then
$original = imagecreatefromjpeg($filename);
$angle = 90.0;
$rotated = imagerotate($original, $angle, 0);
Based on this https://stackoverflow.com/a/3693075/2118559 answer trying create image file
$output = 'google.com.jpg';
If i save the same image with new file name, all works
file_put_contents( $output, file_get_contents($filename) );
But if i try to save rotated image, then file_put_contents(): supplied resource is not a valid stream resource.
file_put_contents( $output, $rotated );
Here https://stackoverflow.com/a/12185462/2118559 read $export is going to be a GD image handle. It is NOT something you can simply dump out to a file and expect to get a JPG or PNG image.. but can not understand how to use the code in that answer.
How to create image file from $rotated?
Tried to experiment, based on this http://php.net/manual/en/function.imagecreatefromstring.php
$fh = fopen( 'some_name.png' , 'w') or die("can't open file");
fwrite($fh, $data );
fclose($fh);
Does it means that need something like
$data = base64_encode($rotated);
And then write in new file?
I have not tested this, but I think you need to encode the image as base 64 first.
If you check the string from any Image URL, you'd see data:image/png;base64, preceding the hash. Prepending this to your image string and saving.
Here is a function that may help, based on what you already have:
// Function settings:
// 1) Original file
// 2) Angle to rotate
// 3) Output destination (false will output to browser)
function RotateJpg($filename = '',$angle = 0,$savename = false)
{
// Your original file
$original = imagecreatefromjpeg($filename);
// Rotate
$rotated = imagerotate($original, $angle, 0);
// If you have no destination, save to browser
if($savename == false) {
header('Content-Type: image/jpeg');
imagejpeg($rotated);
}
else
// Save to a directory with a new filename
imagejpeg($rotated,$savename);
// Standard destroy command
imagedestroy($rotated);
}
// Base image
$filename = 'http://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg';
// Destination, including document root (you may have a defined root to use)
$saveto = $_SERVER['DOCUMENT_ROOT']."/images/test.jpg";
// Apply function
RotateJpg($filename,90,$saveto);
If you want to save image just use one of GD library functions: imagepng() or imagepng().
imagerotate() returns image resource so this is not something like string.
In your case just save rotate image:
imagejpg($rotated, $output);
And now You can use $output variable as your new filename to include in view like before:
echo '<img src='.$output.'>';
Don't forget to include appropriate permissions in directory where You're saveing image.
I have the following bit of code which uploads a PDF to Amazon S3, what I need to do is create an image from the 1st page of the PDF and upload that to s3 as well.
//instantiate the class
$s3 = new S3(awsAccessKey, awsSecretKey);
//check whether a form was submitted
if($_SERVER['REQUEST_METHOD'] == "POST")
{
//retreive post variables
$fileName = $_FILES['file']['name'];
$fileTempName = $_FILES['file']['tmp_name'];
$fileSize = $_FILES['file']['size'];
$extension=end(explode(".", $fileName));
$rand = rand(1,100000000);
$sha1 = sha1($rand);
$md5 = md5($sha1);
$fName = substr($md5, 0, 20);
$finalName = $fName.'.'.$extension;
//create a new bucket
$s3->putBucket("bucket", S3::ACL_PUBLIC_READ);
//move the file
if ($s3->putObjectFile($fileTempName, "bucket", 'publications/'.$finalName, S3::ACL_PUBLIC_READ)) {
$s3file='http://bucket.s3.amazonaws.com/publications/'.$finalName;
$aS3File = 'publications/'.$finalName;
$im = new imagick($s3file[0]);
// convert to jpg
$im->setImageColorspace(255);
$im->setCompression(Imagick::COMPRESSION_JPEG);
$im->setCompressionQuality(75);
$im->setImageFormat('jpeg');
//resize
$im->resizeImage(640, 877, imagick::FILTER_LANCZOS, 1);
//write image on server (line 54)
$s3->putObjectFile("","bucket", 'publications/'.$im->writeImage($fName.'.jpg'), S£::ACL_PUBLIC_READ);
}else{
echo "<strong>Something went wrong while uploading your file... sorry.</strong>";
}
I have replace my actual bucket name with 'bucket' for security, can anyone tell me what I am doing wrong here as I get the following error:
PHP Fatal error: Uncaught exception 'ImagickException' with message
'Unable to read the file: h' in
/var/www/ams/pub-new-issue.php:45\nStack trace:\n#0
/var/www/ams/pub-new-issue.php(45): Imagick->__construct('h')\n#1
{main}\n thrown in /var/www/ams/pub-new-issue.php on line 45,
thanks
$s3file='http://bucket.s3.amazonaws.com/publications/'.$finalName;
$im = new imagick($s3file[0]);
$s3file is a string, but you're accessing an array index in it. As a result, you fetch the first character, h. Use just $s3file in your Imagick instantiation and you should be fine.
So what I'm trying to do is:
- given an image url -> convert image to png
- zip resulting png
I have the following code which successfully does the conversion and zipping (I'm going to expand it later to test the extension to auto convert formats):
$file = "../assets/test.jpg";
$img = imagecreatefromjpeg($file);
imagePng($img, "files/temp.png" );
$zip->addFile( "files/temp.png", "test.png" );
What I want to know is, is it possible to do this without creating a copy of image before it's zipped
See ZipArchive::addFromString().
$file = "../assets/test.jpg";
// capture output into the internal buffer
ob_start();
$img = imagecreatefromjpeg($file);
imagepng($img);
// get contents from the buffer
$contents = ob_get_clean();
$zip = new ZipArchive();
$zip->open('archive.zip', ZipArchive::CREATE);
// and put them in the zip file...
$zip->addFromString('name_in_the_zip.png', $contents);
I am manipulating images with js, and I'd like to save these transformed images. I'm posting this data with ajax:
image : canvas.toDataURL('image/jpeg')
This way, I get the base64 code for the image, but I can't find a way to read it with Imagick.
This is my process:
$img = new Imagick();
$decoded = base64_decode($_POST['image']);
$img->readimageblob($decoded);
But this fails:
Fatal error: Uncaught exception 'ImagickException' with message 'no decode delegate for this image format `' # error/blob.c/BlobToImage/360' in /Library/WebServer/Documents/test/save.php:7
Stack trace:
#0 /Library/WebServer/Documents/test/save.php(7): Imagick->readimageblob('u?Z?f?{??z?????...')
Any ideas why?
Figured out.
I had to remove the data:image/png;base64, part from the posted string, and then imagick could interpret it as blob.
readImageBlob — Reads image from a binary string : http://php.net/manual/en/imagick.readimageblob.php
$base64 = "iVBORw0KGgoAAAAN....";
$imageBlob = base64_decode($base64);
$imagick = new Imagick();
$imagick->readImageBlob($imageBlob);
header("Content-Type: image/png");
echo $imagick;
Read this url;--
PHP-Imagemagick image display
or try it:-
$thumbnail = $img->getImageBlob();
$contents = ob_get_contents();
ob_end_clean();
echo "<img src='data:image/jpg;base64,".base64_encode($contents)."' />";
i am generating a screen grab jpg using html2canvas from this code. However i cant target a particaular div so i am grabbing the entire screen.
$canvasImg = $_POST['img'];
$data = base64_decode($canvasImg);
$File = "z.jpg";
$Handle = fopen($File, 'w');
fwrite($Handle, $data);
fclose($Handle);
question: how can i crop the image?
this is my attampt
$canvasImg = $_POST['img'];
$image = base64_decode($canvasImg);
$dest_image = 'z.jpg';
$img = imagecreatetruecolor('200','150');
$org_img = imagecreatefromstring($image);
$ims = getimagesize($image);
imagecopy($img,$org_img, 0, 0, 20, 20, 200, 150);
imagejpeg($img,$dest_image,90);
imagedestroy($img);
but im getting a errors
Warning: getimagesize(�PNG ) [<a href='function.getimagesize'>function.getimagesize</a>]: failed to open stream: Invalid argument
You want imagecreatefromstring();, not imagecreatefrompng();. This'll turn it into a PHP image object, which you can then output as a JPEG using imagejpeg();
Your problem inlies that you are passing the buffer of the PNG to the function. Hence why you get the magic number of a PNG (89 50 4e 47 0d 0a 1a 0a ---OR--- 0x89 "PNG" CR LF 0x1A LF). You need to save the file to a temp location and pass the location to getimagesize and such. Hence why they complain about a stream.
You could use imagecreatefromstring(...) which will take the buffer and output a handle to the resource.
the first param of getimagesize($image); must be the image's filename.