I am trying to resize images using cropThumbnailImage. I use cropThumbnailImage as it resizes to the shorter length of the original image and crops the image on the longer side equally on both sides so that center portion of the image remains uncropped. This works fine for jpg images but for png images, the resized pngs get a black background.
Following is the code I use.
$image = new \Imagick($src);
// resize & crop
$image->cropThumbnailImage($width, $height);
// save new resized file
$image->writeImage($dest);
Run this code for the following png image.
http://tuxpaint.org/stamps/stamps/animals/birds/cartoon/tux.png
http://www.cs.csubak.edu/~mcabrera/CS211/transparent.png
http://www.tcarms.com/media/assets/productPhotos/006_G2%20Contender/png/Pistol_12in_Ribbed_Blued_2720.png
The output image is resized as required but the png image gets black background.
Tried adding below lines from herebut did not work.
imagealphablending( $image, false );
imagesavealpha( $image, true );
There are other solutions out there in the web which achieve resizing of png images, but I did not find a solution that resizes image the way cropThumbnailImage does.
Transparency is preserved using the following snippet:
$im = new Imagick($imgPath);
$im->setImageFormat('png');
$im->writeImage('/files/thumbnails/new_title.png');
There is not transparency in your JPG... The JPG is not a transparent image... PNG and GIF are necessary here.
If you are refering to PNG, there is a PHP code who will help you to resize PNGs with transparency:
$x = "COORDINATES - X for crop";
$y = "COORDINATES - y for crop";
$w = "width";
$h = "height";
$img = imagecreatefrompng($img_path);
imagealphablending($img, true);
$img_cropped = imagecreatetruecolor($w, $h);
imagesavealpha($img_cropped, true);
imagealphablending($img_cropped, false);
$transparent = imagecolorallocatealpha($img_cropped, 0, 0, 0, 127);
imagefill($img_cropped, 0, 0, $transparent);
imagecopyresampled($img_cropped, $img, 0, 0, $x, $y, $w, $h, $w, $h); // you can also use imagecopy() here
imagepng($img_cropped, "your_image_cropped.png", 2);
imagedestroy($img);
imagedestroy($img_cropped);
EDIT: Try this:
$image = imagecreatefrompng ( $filename );
$new_image = imagecreatetruecolor ( $width, $height ); // new wigth and height
imagealphablending($new_image , false);
imagesavealpha($new_image , true);
imagecopyresampled ( $new_image, $image, 0, 0, 0, 0, $width, $height, imagesx ( $image ), imagesy ( $image ) );
$image = $new_image;
// saving
imagealphablending($image , false);
imagesavealpha($image , true);
imagepng ( $image, $filename );
Don't forget to define $filename, $width, $height!!!!
Related
Currently I would like to create a transparent png with the lowest quality .
The code:
<?php
function createImg ($src, $dst, $width, $height, $quality) {
$newImage = imagecreatetruecolor($width,$height);
$source = imagecreatefrompng($src); //imagecreatefrompng() returns an image identifier representing the image obtained from the given filename.
imagecopyresampled($newImage,$source,0,0,0,0,$width,$height,$width,$height);
imagepng($newImage,$dst,$quality); //imagepng() creates a PNG file from the given image.
return $dst;
}
createImg ('test.png','test.png','1920','1080','1');
?>
However, there are some problems:
Do I need to specific a png file before creating any new file? Or can I create without any existing png file?
Warning: imagecreatefrompng(test.png): failed to open stream: No such file or directory in
C:\DSPadmin\DEV\ajax_optipng1.5\create.php on line 4
Although there are error message , it still generate a png file , however, what I found that is the file is a black color image , do I need to specific any parameter to make it transparent?
Thanks.
To 1)
imagecreatefrompng('test.png') tries to open the file test.png which then can be edited with GD functions.
To 2)
To enable saving of the alpha channel imagesavealpha($img, true); is used.
The following code creates a 200x200px sized transparent image by enabling alpha saving and filling it with transparency.
<?php
$img = imagecreatetruecolor(200, 200);
imagesavealpha($img, true);
$color = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $color);
imagepng($img, 'test.png');
Take a look at:
imagecolorallocatealpha
imagefill
An example function copies transparent PNG files:
<?php
function copyTransparent($src, $output)
{
$dimensions = getimagesize($src);
$x = $dimensions[0];
$y = $dimensions[1];
$im = imagecreatetruecolor($x,$y);
$src_ = imagecreatefrompng($src);
// Prepare alpha channel for transparent background
$alpha_channel = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagecolortransparent($im, $alpha_channel);
// Fill image
imagefill($im, 0, 0, $alpha_channel);
// Copy from other
imagecopy($im,$src_, 0, 0, 0, 0, $x, $y);
// Save transparency
imagesavealpha($im,true);
// Save PNG
imagepng($im,$output,9);
imagedestroy($im);
}
$png = 'test.png';
copyTransparent($png,"png.png");
?>
1) You can create a new png file without any existing one.
2) You get a black color image because you use imagecreatetruecolor();. It creates a highest quality image with a black background. As you need a lowest quality image use imagecreate();
<?php
$tt_image = imagecreate( 100, 50 ); /* width, height */
$background = imagecolorallocatealpha( $tt_image, 0, 0, 255, 127 ); /* In RGB colors- (Red, Green, Blue, Transparency ) */
header( "Content-type: image/png" );
imagepng( $tt_image );
imagecolordeallocate( $background );
imagedestroy( $tt_image );
?>
You can read more in this article: How to Create an Image Using PHP
I'm refactoring an old image crop/resize library i wrote about 5 years ago and i'm stuck trying to restore one of it's functionalities. The funny part is that i'm not even sure it worked back then since i probably never actually used it.
I need to be able to work on png images while keeping transparency (which works), but i also wan't to be able to fill the transparent part of the image with a color.
Creating a blank image and filling it with a color works fine, but when i try to paste my png over it, the background is transparent again.
Here's a simplified version of my code:
<?php
$src = imagecreatefrompng($pathToSomePngFile);
imagealphablending($src, false);
imagesavealpha($src, true);
$output = imagecreatetruecolor($width, $height);
if ($backgroundColor) {
$fillColor = imagecolorallocate(
$output,
$backgroundColor['r'],
$backgroundColor['g'],
$backgroundColor['b']
);
imagefilledrectangle(
$output,
0,
0,
$width,
$height,
$fillColor
);
} else {
imagealphablending($output, false);
imagesavealpha($output, true);
}
imagecopyresampled(
$output,
$src,
0,
0,
0,
0,
$width,
$height,
$width,
$height
);
imagepng($output, $pathToWhereImageIsSaved);
UPDATE
Updated with delboy1978uk's solution to get it to work without changing my other settings.
Something like this should work.
<?php
// open original image
$img = imagecreatefrompng($originalTransparentImage);
$width = imagesx($img);
$height = imagesy($img);
// make a plain background with the dimensions
$background = imagecreatetruecolor($width, $height);
$color = imagecolorallocate($background, 127, 127, 127); // grey background
imagefill($background, 0, 0, $color);
// place image on top of background
imagecopy($background, $img, 0, 0, 0, 0, $width, $height);
//save as png
imagepng($background, '/path/to/new.png', 0);
I'm currently writing a script to add watermarks to images. Said watermarks vary in their opacity.
For example, the base watermark image is a PNG with a fully visible text and a transparent background. When added, I want to fade this base PNG to fit my needs and to make an opaque watermark.
To do that, I use imagefilter() to fade the PNG:
$opacity = 0.25;
$watermarkRes = imagecreatefrompng($filename);
imagealphablending($watermarkRes, false);
imagesavealpha($watermarkRes, true);
$transparency = 1 - $opacity;
imagefilter(
$watermarkRes,
IMG_FILTER_COLORIZE,
0,
0,
0,
127*$transparency
);
imagepng($watermarkRes, $filename);
All non-transparent areas get faded nicely, but the existing transarent areas get blackened.
This is the result of the above code:
https://preview.ibb.co/j8zePF/TEST.png
Used as a watermark it looks like this:
https://preview.ibb.co/mLvKPF/15027295625991d55a1ef081_42502547.jpg
While the desired result should be this:
https://preview.ibb.co/f81R4F/TEST_15027295625991d55a1ef081_42502547.jpg
How can I achieve to add opacity to the text while maintaining the transparent areas as they are?
Nevermind. The issue was not the function itself, but the fact that I resized the height of the watermark according to its use beforehand.
I removed this code to resize the watermark:
$new_image = imagecreatetruecolor($width, $height);
imagecopyresampled($new_image, $watermarkRes, 0, 0, 0, 0, $width, $height, imagesx($watermarkRes), imagesy($watermarkRes));
$watermarkRes = $new_image;
And instead used the resize code of Dycey provided in the answer to this question:
How do I resize pngs with transparency in PHP?
For my case I created this function to resize images:
/**
* #param int $width
* #param int $height
*/
public function resize($width, $height)
{
$new_image = imagecreatetruecolor($width, $height);
if($this->image_type === IMAGETYPE_PNG || $this->image_type === IMAGETYPE_GIF) {
imagealphablending($new_image, false);
imagesavealpha($new_image,true);
$transparent = imagecolorallocatealpha(
$new_image, 255, 255, 255, 127
);
imagefilledrectangle(
$new_image, 0, 0, $width, $height, $transparent
);
}
imagecopyresampled(
$new_image,
$this->image,
0, 0, 0, 0,
$width, $height,
imagesx($this->image), imagesy($this->image)
);
$this->image = $new_image;
}
Currently I would like to create a transparent png with the lowest quality .
The code:
<?php
function createImg ($src, $dst, $width, $height, $quality) {
$newImage = imagecreatetruecolor($width,$height);
$source = imagecreatefrompng($src); //imagecreatefrompng() returns an image identifier representing the image obtained from the given filename.
imagecopyresampled($newImage,$source,0,0,0,0,$width,$height,$width,$height);
imagepng($newImage,$dst,$quality); //imagepng() creates a PNG file from the given image.
return $dst;
}
createImg ('test.png','test.png','1920','1080','1');
?>
However, there are some problems:
Do I need to specific a png file before creating any new file? Or can I create without any existing png file?
Warning: imagecreatefrompng(test.png): failed to open stream: No such file or directory in
C:\DSPadmin\DEV\ajax_optipng1.5\create.php on line 4
Although there are error message , it still generate a png file , however, what I found that is the file is a black color image , do I need to specific any parameter to make it transparent?
Thanks.
To 1)
imagecreatefrompng('test.png') tries to open the file test.png which then can be edited with GD functions.
To 2)
To enable saving of the alpha channel imagesavealpha($img, true); is used.
The following code creates a 200x200px sized transparent image by enabling alpha saving and filling it with transparency.
<?php
$img = imagecreatetruecolor(200, 200);
imagesavealpha($img, true);
$color = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $color);
imagepng($img, 'test.png');
Take a look at:
imagecolorallocatealpha
imagefill
An example function copies transparent PNG files:
<?php
function copyTransparent($src, $output)
{
$dimensions = getimagesize($src);
$x = $dimensions[0];
$y = $dimensions[1];
$im = imagecreatetruecolor($x,$y);
$src_ = imagecreatefrompng($src);
// Prepare alpha channel for transparent background
$alpha_channel = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagecolortransparent($im, $alpha_channel);
// Fill image
imagefill($im, 0, 0, $alpha_channel);
// Copy from other
imagecopy($im,$src_, 0, 0, 0, 0, $x, $y);
// Save transparency
imagesavealpha($im,true);
// Save PNG
imagepng($im,$output,9);
imagedestroy($im);
}
$png = 'test.png';
copyTransparent($png,"png.png");
?>
1) You can create a new png file without any existing one.
2) You get a black color image because you use imagecreatetruecolor();. It creates a highest quality image with a black background. As you need a lowest quality image use imagecreate();
<?php
$tt_image = imagecreate( 100, 50 ); /* width, height */
$background = imagecolorallocatealpha( $tt_image, 0, 0, 255, 127 ); /* In RGB colors- (Red, Green, Blue, Transparency ) */
header( "Content-type: image/png" );
imagepng( $tt_image );
imagecolordeallocate( $background );
imagedestroy( $tt_image );
?>
You can read more in this article: How to Create an Image Using PHP
I'm trying to redesign my site so that my original square, tile-based rendering of images can be more of a cutout of the image... to get rid of that grid pattern.
Here's how it looked originally...
Here's a rough mock-up of what I'm going for:
So I resaved an image thumbnail with a transparent background... I just want the dog to show, and the square is transparent which will show the site's background underneath.
Yet when I render it on the page, it has this black background.
I've checked my CSS to see if there is some sort of img class, or class for the rendered comics... or even the bootstrap to see where there may be a background-color being assigned to black (and also searched for hex code 000000), but didn't find one...
Then I found that it had to do with the way my thumbnailing script was resampling the png... Since I'm getting a black background for the supposedly transparent image, I blame imagecreatetruecolor() which returns an image identifier representing a black image of the specified size..
I tried following Cheekysoft's question here about preserving transparency after resampling... but it didn't work... with his two main points being:
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );
I found if I put $img = imagecreatefrompng($image_file); before I resize/resample it, it displays transparently... which is what I want... but not after I resample it.
Thumbnailer.php code:
<?php
#Appreciation goes to digifuzz (http://www.digifuzz.net) for help on this
$image_file = $_GET['img']; //takes in full path of image
$MAX_WIDTH = $_GET['mw'];
$MAX_HEIGHT = $_GET['mh'];
global $img;
//Check for image
if(!$image_file || $image_file == "") {
die("NO FILE.");
}
//If no max width, set one
if(!$MAX_WIDTH || $MAX_WIDTH == "") {
$MAX_WIDTH="100";
}
//if no max height, set one
if(!$MAX_HEIGHT || $MAX_HEIGHT == "") {
$MAX_HEIGHT = "100";
}
$img = null;
//create image file from 'img' parameter string
if( preg_match('/\.jpg$/',$image_file) || preg_match('/\.jpeg$/',$image_file) ){
$img = imagecreatefromjpeg($image_file);
} else {
$img = imagecreatefrompng($image_file);
}
//if image successfully loaded...
if($img) {
//get image size and scale ratio
$width = imagesx($img);
$height = imagesy($img);
//takes min value of these two
$scale = min($MAX_WIDTH/$width, $MAX_HEIGHT/$height);
//if desired new image size is less than original, output new image
if($scale < 1) {
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
$tmp_img = imagecreatetruecolor($new_width, $new_height);
//copy and resize old image to new image
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
//replace actual image with new image
$img = $tmp_img;
}
}
//set the content type header
header('Content-Type: image/png', true);
imagealphablending( $img, false );
imagesavealpha( $img, true );
imagepng($img);
imagedestroy($img);
?>
Can anyone help?
Thanks!
You need to call imagealphablending() on your destination image BEFORE you resample/resize the image:
//copy and resize old image to new image
imagealphablending($tmp_img, false);
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// ...
You placed alphablending and traparent code well below after creating image. Just place them before the your createresample line and transparent image with image that created by imagecreatefrompng.
imagealphablending( $tmp_img, false );
imagesavealpha( $tmp_img, true );
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
Or you can Try following
$img = ImageCreateFromPNG($image_file);
$tmp_img = imagecreatetruecolor($new_width,$new_height);
imagecolortransparent($tmp_img, imagecolorallocate($tmp_img, 0, 0, 0));
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);