Saving a transparent image from a URL in PHP - php

I am trying to build a class that does many photo operations, one method will upload images from a user but I am also needing to build a method to grab a photo from a URL and run other methods on it just like if it were being uploaded with a POST form from user.
Below is my start of the function for getting image from URL, it works but needs work still. Below the code you can see a image that is the result of this function being ran. Also is the original image to see what it should look like. You can see that this function makes the image have a black background on this transparent image. How can I make it look better like it should look?
$url = 'http://a0.twimg.com/a/1262802780/images/twitter_logo_header.png';
//run our function
savePhotofromURL($url, 'no');
// photo function should grab an photo from a URL
function savePhotofromURL($photo_url, $saveimage = 'yes'){
if(isset($photo_url) && $photo_url != '') {
//get info about photo
$photo_info = getimagesize($photo_url);
$source_width = $photo_info['0'];
$source_height = $photo_info['1'];
$source_type = $photo_info['mime'];
//grab the Photo from URL
$photo = imagecreatefromstring(file_get_contents($photo_url));
if (is_resource($photo) === true){
if($saveimage === 'yes'){
// TO DO: resize image and make the thumbs code would go here if we are saving image:
// TO DO: resize source image if it is wider then 800 pixels
// TO DO: make 1 thumbnail that is 150 pixels wide
}else{
// We are not saving the image show it in the user's browser
// TO DO: we will add in correct photo type soon
header('Content-Type: image/gif');
imagejpeg($photo, null, 100);
imagedestroy($photo);
}
}else{
// not a valid resource, show error
echo 'error getting URL photo from ' .$photo_url;
}
}else{
// url of image was empty
echo 'The URL was not passed into our function';
}
}
The result looks like this
alt text http://img2.pict.com/52/05/1f/2429493/0/screenshot2b181.png
Instead of like this

The following two calls will tell php to use the alpha blending present in the png image:
ImageAlphaBlending($photo, false);
ImageSaveAlpha($photo, true);
Edit:
I see you're outputting the image as a JPEG also. JPEGs don't support transparency, so no matter what you do you will end up with an incorrect background color. Also see this related question: PHP/GD ImageSaveAlpha and ImageAlphaBlending

You need to add better support for image types and by extension their transparency.
Since the image is transparent we can know that its either a GIF or a PNG yet your sending the GIF header while using imagejpeg() - jpegs dont support any kind of transparency. But if its a png you may also have to account for if its alpha trans or index transparency.

Related

PHP Image Change to Silhouette

I'm displaying an image where the URL is kept in the database, now i want to display it completely black if a condition isn't met
The URL
$url = '/images/'.$row['sprite'].'.png';
its then displayed in a normal image tag
What i want is if $row['normal'] == 0 then black the image, making it a silhouette, otherwise display the normal image
After some searching I've found about imagefilter but am not sure how to apply it, as the examples i've found don't show how to apply it when there is other content on the page
Or would it be better to make the silhouettes in photoshop, given that there is over 800 of them, though only a maximum of two on the page
Firstly you need to load GD Image Library to your server.
Define your image path and create an image object by using imagecreatefrompng if your image types are different choose correct one.
$image_path = $_SERVER['DOCUMENT_ROOT']."/assets/img/horse1.png";
$image_obj = imagecreatefrompng($image_path);
Now, we need to apply a filter, if your conditions provided. Using the imagefilter function to apply any filter to your image. In this example IMG_FILTER_GRAYSCALE is fair enough or you can change it by using the manual of function.
if($row['normal'] == 0) {
$op_result = imagefilter($image_obj,IMG_FILTER_GRAYSCALE);
}
Finally, we need save the image to server using by imagepng function.
imagepng($image_obj,$_SERVER['DOCUMENT_ROOT']."/assets/img/horse1_black.png");
Check the full code below beacuse I strongly suggest that, you shouldn't create black image for every single user. If your image is already exist in your server just show it without any creation.
$image_path = $_SERVER['DOCUMENT_ROOT']."/assets/img/horse.png";
$black_image_path = $_SERVER['DOCUMENT_ROOT']."/assets/img/horse_black.png";
if($row['normal'] == 0) {
if(file_exists($black_image_path)){
return $black_image_path; //if your black image is already exist just return and use it.
}
else {
$image_obj = imagecreatefrompng($image_path); //create a image object from a path
$op_result = imagefilter($image_obj,IMG_FILTER_GRAYSCALE); //applying grayscale filter to your image object.
if($op_result) {
imagepng($image_obj,$black_image_path); //save the image to defined path.
return $black_image_path;
}
else {
return "Error Occured.";
}
}
}

How to display an image created by imagick php in html view?

I am using phalcon php framework. I have a blog in my application where a user can submit an image attached to his blog post, and it is displayed when viewing the post. I want to display this image on the index page of the blog where each post is listed, however, i want it to be a thumbnail to reduce its size. I was able to use imagick to save a thumbnail at a directory and load the thumbnail from there, however, i need to avoid saving the thumbnail and generate the thumbnails every time just to display them.
Here is the code I used to create the image with imagick
public function thumbnail($img)
{
$maxsize = 100;
$image = new Imagick($img);
// Resizes to whichever is larger, width or height
if($image->getImageHeight() <= $image->getImageWidth())
{
$image->resizeImage($maxsize,0,Imagick::FILTER_LANCZOS,1);
}
else
{
$image->resizeImage(0,$maxsize,Imagick::FILTER_LANCZOS,1);
}
// Set to use jpeg compression
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
// Set compression level (1 lowest quality, 100 highest quality)
$image->setImageCompressionQuality(75);
// Strip out unneeded meta data
$image->stripImage();
// Writes resultant image to output directory
$image->writeImage($uploaddir.'/thumbs/'. basename($_FILES['photo']['name']));
// Destroys Imagick object, freeing allocated resources in the process
$image->destroy();
}
I tried just to remove the last two lines where the image is saved and then the imagick object is destroyed, but couldn't go on to display the image in the index view.
Step 1 - Use the buffer.
Step 2 - Unlink the already saved image after you get its base64 code.
For example consider the following code snippet:
$im = new Imagick();
$im->setResolution(300,300);
$im->readimage('path_to_the_file.pdf');
$im->setImageFormat('jpeg');
$im->writeImages('file_name_to_save.jpg', false);
$im->clear();
$im->destroy();
$dest = imagecreatefromjpeg ('file_name_to_save.jpg');
//Step 1
ob_start();
imagejpeg($dest);
$image_data = ob_get_clean();
imagedestroy($dest);
$img_source = base64_encode($image_data);
//Step 2
unlink('file_name_to_save.jpg');
Now in the $img_source variable you have the base64 of the image that you can use it like this:
'<img src="data:image/jpg;base64,'.$img_source.'" style="max-width: 100%; max-height:100%;" />';
I'm using something similar to this:
public function thumbAction() {
// Generate thumb from image & save it on disk
$image = $this->thumbnail(); // well can be anything that return Imagick
$this->response->setHeader('Content-Type', 'image/jpg');
echo $image;
}
Anyway in above example you don't need to save the image but only echo created thumb to the user.
Also I'm storing an image on some path like thumbs/a/image.jpg. I've configured nginx to check for existing file and if file does not exists it calls Phalcon script.
In Phalcon app I have a route that points to any /thumbs* path to above action. On first call the image is saved on the path thumbs/a/ so on the next call Nginx server returns that image instead of calling PHP.

WideImage - Transparent areas of converted PNG should be white

Whenever a user uploads a photo using my script, WideImage converts it to JPEG. However, I just noticed that if I upload a PNG picture, with a transparent background, it makes it black instead.
Is there any way to make this white instead?
This is how i save the image:
$img->resizeDown('500', null)->saveToFile('annonce_billeder/'.$bnavn.'.jpeg', 70);
Not really directly. You wnt to read about how transparency is stored in pictures: it is an ordinary color value (any color) that has been marked especially as transparent.
So most likely the color specified in the example pictures you try actually is coded as black and the transparency gets lost whilst converting.
You might have a try to find out if you can detect if there is a color marked as transparent in the incoming picture and then manually change that color to non-transparcy and white before converting the picture.
Might be similar, but I was able to create an empty truecolor image and fill it with its own transparent color before doing any drawing:
$img = WideImage_TrueColorImage::create(100, 100);
$img->fill(0,0,$img->getTransparentColor());
// then text, watermark, etc
$img->save('...');
I assume you'll do something more like:
$img = WideImage::load(<source>);
if( <$img is png> ) {
$img->fill(0,0, $img->getTransparentColor());
}
$img->resizeDown(500, null)->saveToFile('target.jpg', 70);
This is how to do it:
// Load the original image
$original = WideImage::load("image.png");
$original->resizeDown(1000); // Do whatever resize or crop you need to do
// Create an empty canvas with the original image sizes
$img = WideImage::createTrueColorImage($resized->getWidth(),$resized->getHeight());
$bg = $img->allocateColor(255,255,255);
$img->fill(0,0,$bg);
// Finally merge and do whatever you need...
$img->merge($original)->saveToFile("image.jpg");
With some changes (corrections) on Ricardo Gamba's solution code, it does the job...
// Load the original image
$original = WideImage::load("image.png");
$resized = $original->resizeDown('500', null); // Do whatever resize or crop you need to do
$original->destroy(); // free some memory (original image not needed any more)
// Create an empty canvas with the resized image sizes
$img = WideImage::createTrueColorImage($resized->getWidth(), $resized->getHeight());
$bg = $img->allocateColor(255,255,255);
$img->fill(0,0,$bg);
// Finally merge and do whatever you need...
$img->merge($resized)->saveToFile("image.jpg", 70);

Adding of Image Layer Fails (GD) PHP

I've installed the GD Library on my Apache just now, and it seems that my script below doesn't work.
I'm trying to add a layer "play.png" to a youtube video thumbnail (http://img.youtube.com/vi/VIDEOID/default.jpg)
I've tried it with many different videoID's but the image doesn't load. There is a message that the graphic couldn't be opened because it contains errors.
I'm opening the file with postimage.php?v=7yV_JtFnIwo
http://img.youtube.com/vi/7yV_JtFnIwo/default.jpg opens correctly too...
Does anyone know where the issue could be?
Thanks in advance!
<?php
// The header line informs the server of what to send the output
// as. In this case, the server will see the output as a .png
// image and send it as such
header ("Content-type: image/png");
// Defining the background image. Optionally, a .jpg image could
// could be used using imagecreatefromjpeg, but I personally
// prefer working with png
$background = imagecreatefromjpeg("http://img.youtube.com/vi/".$_GET['v']."/default.jpg");
// Defining the overlay image to be added or combined.
$insert = imagecreatefrompng("play.png");
// Select the first pixel of the overlay image (at 0,0) and use
// it's color to define the transparent color
imagecolortransparent($insert,imagecolorat($insert,0,0));
// Get overlay image width and hight for later use
$insert_x = imagesx($insert);
$insert_y = imagesy($insert);
// Combine the images into a single output image. Some people
// prefer to use the imagecopy() function, but more often than
// not, it sometimes does not work. (could be a bug)
imagecopymerge($background,$insert,0,0,0,0,$insert_x,$insert_y,100);
// Output the results as a png image, to be sent to viewer's
// browser. The results can be displayed within an HTML document
// as an image tag or background image for the document, tables,
// or anywhere an image URL may be acceptable.
imagepng($background,"",100);
?>
Do not close (avoid whitespaces or newslines) your script with ?> and use NULL instead "".
imagepng($background, NULL);
Then, in imagepng the quality parameter is between 0 and 9, as in http://it.php.net/manual/en/function.imagepng.php.

PHP ImageCreateFromString and file_get_contents

I am trying to make a function in PHP that will allow me to enter basically any URL and then runs some functions on it just as if a user was uploading on my server. SO I will resize and make some thumbnails but I need help just getting the image in a state that I can run my other codes on it. Another user on this site helped me get started with ImageCreateFromString() and file_get_contents()
Please note this code is missing a lot of stuff I am aware of, I am just trying to get the basic function working and then I will add in all the security measures
I tried this code below using a URL like this with the photo URL added to my script url:
http://example.com/friendproject2/testing/photos/fromurl/?url=http://a0.twimg.com/a/1262802780/images/twitter_logo_header.png
But it shows nothing and not even an error
function getphotoURL($url){
if(isset($url) && $url != 'bad') {
$image = ImageCreateFromString(file_get_contents($url));
if (is_resource($image) === true){
echo 'The URL of the image we fetch is :' .$url. '<BR><BR>';
//show image
header('Content-Type: image/jpeg');
imagejpeg($image, null, 100);
imagedestroy($image);
imagedestroy($image);
// image is valid, do your magic here
}else{
// not a valid image, show error
echo 'error getting URL photo from ' .$url;
}
}else{
//url was empty
echo 'The URL was not passed into our function';
}
}
?>
###### UPDATE #####
It seems it was a simple error on my part, something simple as checking for a POST request instead of a GET request, here is my new code below.
I have a couple of issues,
1) I am using imagejpeg($image, null, 100); and I am wondering, should I be using something else? Does it require the source image to be a jpg or will it work with any image? I need to allow the main types (jpg, jpeg, gif, png)
2) same as above question but for when showing the image on screen I have header set to this: header('Content-Type: image/jpeg'); should it not be jpg for other type of images?
3) Is there a way that I can make sure that the source URL passed in is an actual image and do whatever I want if it is not a image, like show my own error or do my own code once it detect that the URL is not a valid image url
<?PHP
// run our function
if(isset($_GET['url']) && $_GET['url'] != "") {
getphotoURL($_GET['url'],'no');
}
function getphotoURL($url, $saveimage = 'yes'){
if(isset($url) && $url != '') {
$image = imagecreatefromstring(file_get_contents($url));
if (is_resource($image) === true){
if($saveimage === 'yes'){
// resize image and make the thumbs code would go here if we are saving image:
// resize source image if it is wider then 800 pixels
// make 1 thumbnail that is 150 pixels wide
}else{
// We are not saving the image show it in the user's browser
header('Content-Type: image/png');
imagejpeg($image, null, 100);
imagedestroy($image);
}
}else{
// not a valid resource, show error
echo 'error getting URL photo from ' .$url;
}
}else{
// url of image was empty
echo 'The URL was not passed into our function';
}
}
?>
After calling imagecreatefromstring() for a PNG or GIF (For transparency)
Do the following manipulations on the image:
imagealphablending($image, true); // setting alpha blending on
imagesavealpha($image, true);
Will turn the flat black background to the alpha channel.
In response to your new questions:
1) I am using imagejpeg($image, null,
100); and I am wondering, should I be
using something else? DOes it require
the source image to be a jpg or will
it work wiht any image? I need to
allow the main types (jpg, jpeg, gif,
png)
Well, php.net says, "imagejpeg() creates a JPEG file from the given image". But the important part is this, "An image resource, returned by one of the image creation functions, such as imagecreatetruecolor().". And your using "imagecreatefromstring() returns an image identifier representing the image obtained from the given data . These types will be automatically detected if your build of PHP supports them: JPEG, PNG, GIF, WBMP, and GD2."
So, that should be ok.
2) same as above question but for when
showing the image on screen I have
header set to this:
header('Content-Type: image/jpeg');
should it not be jpg for other type of
images?
The header should be of type jpg - If that's the file type, then you're correct.
3) Is there a way that I can make sure
that the source URL passed in is an
actual image and do whatever I want if
it is not a image, like show my own
error or do my own code once it detect
that the URL is not a valid image url
Yeah - Instead of doing:
$image = ImageCreateFromString(file_get_contents($url));
You could do:
$image = imagecreatefromjpeg($url);
if (!$image) echo "error";
imagecreatefromjpeg() returns an image
identifier representing the image
obtained from the given filename.
But really, what you have is fine.
Does it display the error message
echo 'The URL was not passed into our function';
Or nothing at all?
If the error messaging is being displayed, possible the check === is failing:
An image resource will be returned on
success. FALSE is returned if the
image type is unsupported, the data is
not in a recognised format, or the
image is corrupt and cannot be loaded.
Also, do you have error logging maxed out on your development server? That way you can see any possible warnings being thrown?

Categories