php take image, rotate and save rotated image on server - php

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.

Related

My php Watermark function is not working for png image

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.

unlink base64 encoded image not working

hi guys ive created a base64 encoded image captured with web cam now i convert the .png to .jpg all works fine but now i get two images on server both .png and .jpg how do i go about deleting the .png or is their a way to convert to jpg without saving .png image to disk thanx here my code
$rawData = $_POST['imgBase64'];
$filteredData = explode(',', $rawData);
$unencoded = base64_decode($filteredData[1]);
$randomName = rand(1000, 99999999999);
//Create the image
$fp = fopen('user/'.$randomName.'.png', 'w');
fwrite($fp, $unencoded);
//convert image from png to jpg
$image = imagecreatefrompng('user/'.$randomName.'.png');
imagejpeg($image, 'user/'.$randomName.'.jpg', 80);
unlink($fp);
ive tried it with
unlink($image);
unlink($_SERVER['DOCUMENT_ROOT'] . "/user/.$randomName.'.png'");
imagedestroy($fp);
imagedestroy($image);
Use the function unlink() but passing the file name to it instead of the file handler.
So from your example it would be:
EDIT: You might need to close the file first:
fclose( $fp );
unlink( 'user/'.$randomName.'.png' );
as far as i understand all you need is:
$data = base64_decode( $_POST['imgBase64']);
// image resource from your string
$image = imagecreatefromstring($data);
imagejpeg($image, 'user/'.$randomName.'.jpg', 80);

PHP: how can I convert jpeg to png and then zip (without making a copy)

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);

How do I get Image Data from an Image Resource?

I'm working with the Microsoft Azure cloud and need to upload images there. Its class upload methods putBlob() and putBlobData() require either the data itself (not the resource) or the directory string as arguments, none of which is available before the image is actually written to the Blob.
$fp = fopen($tmp_name, 'r');
$data = fread($fp, filesize($tmp_name));
fclose($fp);
//Setup watermark destination
$new_watermarked_image_name = "watermark.jpg";
// Create image resources
$image = imagecreatefromstring($data);
$watermark = imagecreatefrompng('images/watermark_large.png');
$copyright = imagecreatefrompng('images/copyright.png');
// Merge image resource s
$image = overlay_watermark_full_size($image, $watermark);
$image = overlay_watermark_lower_right($image, $copyright);
imagejpeg($image, $new_watermarked_image_name, 100);
//put original image
$AzureStorageBlob->putBlob("uploads", "name", $tmp_name);
//put watermarked image
$AzureStorageBlob->putBlobData("uploads", "name", ?); // ? needs to be data
You need to capture the buffer with ob_start, something like:
ob_start();
imagejpeg($tmp_img);
$i = ob_get_clean();
$i is your image blob
By using latest SDK for PHP you can do this by just passing the image stream:
$image_stream = fopen($tmp_name, 'r');
// Check README.md of how to create $blobRestProxy
$blobRestProxy->createBlockBlob('container_name', 'my_image', $image_stream);
Let me know if you have any further questions

Remove EXIF data from JPG using PHP

Is there any way to remove the EXIF data from a JPG using PHP? I have heard of PEL, but I'm hoping there's a simpler way. I am uploading images that will be displayed online and would like the EXIF data removed.
Thanks!
EDIT: I don't/can't install ImageMagick.
Use gd to recreate the graphical part of the image in a new one, that you save with another name.
See PHP gd
edit 2017
Use the new Imagick feature.
Open Image:
<?php
$incoming_file = '/Users/John/Desktop/file_loco.jpg';
$img = new Imagick(realpath($incoming_file));
Be sure to keep any ICC profile in the image
$profiles = $img->getImageProfiles("icc", true);
then strip image, and put the profile back if any
$img->stripImage();
if(!empty($profiles)) {
$img->profileImage("icc", $profiles['icc']);
}
Comes from this PHP page, see comment from Max Eremin down the page.
A fast way to do it in PHP using ImageMagick (Assuming you have it installed and enabled).
<?php
$images = glob('*.jpg');
foreach($images as $image)
{
try
{
$img = new Imagick($image);
$img->stripImage();
$img->writeImage($image);
$img->clear();
$img->destroy();
echo "Removed EXIF data from $image. \n";
} catch(Exception $e) {
echo 'Exception caught: ', $e->getMessage(), "\n";
}
}
?>
I was looking for a solution to this as well. In the end I used PHP to rewrite the JPEG with ALL Exif data removed. I didn't need any of it for my purposes.
This option has several advantages...
The file is smaller because the EXIF data is gone.
There is no loss of image quality (because the image data is unchanged).
Also a note on using imagecreatefromjpeg: I tried this and my files got bigger. If you set quality to 100, your file will be LARGER, because the image has been resampled, and then stored in a lossless way. And if you don't use quality 100, you lose image quality. The ONLY way to avoid resampling is to not use imagecreatefromjpeg.
Here is my function...
/**
* Remove EXIF from a JPEG file.
* #param string $old Path to original jpeg file (input).
* #param string $new Path to new jpeg file (output).
*/
function removeExif($old, $new)
{
// Open the input file for binary reading
$f1 = fopen($old, 'rb');
// Open the output file for binary writing
$f2 = fopen($new, 'wb');
// Find EXIF marker
while (($s = fread($f1, 2))) {
$word = unpack('ni', $s)['i'];
if ($word == 0xFFE1) {
// Read length (includes the word used for the length)
$s = fread($f1, 2);
$len = unpack('ni', $s)['i'];
// Skip the EXIF info
fread($f1, $len - 2);
break;
} else {
fwrite($f2, $s, 2);
}
}
// Write the rest of the file
while (($s = fread($f1, 4096))) {
fwrite($f2, $s, strlen($s));
}
fclose($f1);
fclose($f2);
}
The code is pretty simple. It opens the input file for reading and the output file for writing, and then starts reading the input file. It data from one to the other. Once it reaches the EXIF marker, it reads the length of the EXIF record and skips over that number of bytes. It then continues by reading and writing the remaining data.
The following will remove all EXIF data of a jpeg file. This will make a copy of original file without EXIF and remove the old file. Use 100 quality not to loose any quality details of picture.
$path = "/image.jpg";
$img = imagecreatefromjpeg ($path);
imagejpeg ($img, $path, 100);
imagedestroy ($img);
(simple approximation to the graph can be found here)
function remove_exif($in, $out)
{
$buffer_len = 4096;
$fd_in = fopen($in, 'rb');
$fd_out = fopen($out, 'wb');
while (($buffer = fread($fd_in, $buffer_len)))
{
// \xFF\xE1\xHH\xLLExif\x00\x00 - Exif
// \xFF\xE1\xHH\xLLhttp:// - XMP
// \xFF\xE2\xHH\xLLICC_PROFILE - ICC
// \xFF\xED\xHH\xLLPhotoshop - PH
while (preg_match('/\xFF[\xE1\xE2\xED\xEE](.)(.)(exif|photoshop|http:|icc_profile|adobe)/si', $buffer, $match, PREG_OFFSET_CAPTURE))
{
echo "found: '{$match[3][0]}' marker\n";
$len = ord($match[1][0]) * 256 + ord($match[2][0]);
echo "length: {$len} bytes\n";
echo "write: {$match[0][1]} bytes to output file\n";
fwrite($fd_out, substr($buffer, 0, $match[0][1]));
$filepos = $match[0][1] + 2 + $len - strlen($buffer);
fseek($fd_in, $filepos, SEEK_CUR);
echo "seek to: ".ftell($fd_in)."\n";
$buffer = fread($fd_in, $buffer_len);
}
echo "write: ".strlen($buffer)." bytes to output file\n";
fwrite($fd_out, $buffer, strlen($buffer));
}
fclose($fd_out);
fclose($fd_in);
}
It is a prototype for a call from a command line.
this is the simplest way:
$images = glob($location.'/*.jpg');
foreach($images as $image) {
$img = imagecreatefromjpeg($image);
imagejpeg($img,$image,100);
}
I completely misunderstood your question.
You could use some command line tool to do this job. or write your own php extension to do it. have a look at this lib that would be useful: http://www.sno.phy.queensu.ca/~phil/exiftool/
Cheers,
vfn
I'm not pretty sure about it, but if its possible using GD o ImageMagick, the first thing that come to my mind is to create a new Image and add the old image to the new one.

Categories