I am making avatars with PHP GD. There's annoying space between the avatar's feet, and the bottom of the image. I want to possibly get rid of that space by "pushing" the avatar down to the bottom (see below).
Here's the original image that I don't like, alongside the image I want to get:
Is there a method to this? Thanks. Below is the main part of the code being used for image generation.
$assets = array(
"../assets/shirt/Default.png",
"../assets/body/Default.png",
"../assets/hair/Default.png",
"../assets/eyes/Default.png",
"../assets/eyebrows/Default.png",
"../assets/mouth/Default.png",
"../assets/pants/Default.png"
);
$baseImage = imagecreatefrompng($assets[0]);
imagealphablending($baseImage, true);
imagesavealpha($baseImage, true);
foreach($assets as $item) {
$newImage = imagecreatefrompng($item);
imagecopy($baseImage, $newImage, 0, 0, 0, 0, 350, 550);
imagealphablending($baseImage, true);
imagesavealpha($baseImage, true);
}
if($_GET['x']) {
$sizex = $_GET['x']; if($sizex > 350) $sizex = 350;
$sizey = $_GET['y']; if($sizey > 550) $sizey = 550;
$png = imagecreatetruecolor($sizex, $sizey);
imagesavealpha($png, true);
$trans_colour = imagecolorallocatealpha($png, 0, 0, 0, 127);
imagefill($png, 0, 0, $trans_colour);
$blankImage = $png;
imagealphablending($blankImage, true);
imagesavealpha($blankImage, true);
imagecopyresampled($blankImage, $baseImage, 0, 0, 0, 0, $sizex, $sizey, 350, 550);
header("Content-type: image/png");
imagepng($blankImage);
}
else {
header("Content-type: image/png");
imagepng($baseImage);
}
Note: The if($_GET['x']) { part of that code is to allow me to generate different sizes of the avatar on the spot. It works fine.
Here is the code to crop the bottom and move the cropped image to bottom.
<?php
example();
function example(){
$img = imagecreatefrompng('http://i.stack.imgur.com/UUiMK.png');
imagealphablending($img, true);
imagesavealpha($img, true);
// copy cropped portion
$img2 = imageCropBottom($img);
// output cropped image to the browser
header('Content-Type: image/png');
imagepng($img2);
imagedestroy($img2);
}
function imageCropBottom($image) {
$background1 = imagecolorat($image, 0, 0);
$background2 = imagecolorat($image, 1, 1);
$imageWidth = imageSX($image);
$imageHeight = imageSY($image);
$bottom = 0;
for ($y = $imageHeight ; $y > 0 ; $y--) {
for ($x = 0 ; $x < imagesx($image) ; $x++) {
$imageColor = imagecolorat($image, $x, $y);
if (($imageColor != $background1) && ($imageColor != $background2)) {
$bottom = $y;
break;
}
}
if ($bottom > 0) break;
}
$bottom++;
// create new image with padding
$img = imagecreatetruecolor($imageWidth, $imageHeight);
imagealphablending($img, true);
imagesavealpha($img, true);
$trans_colour = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $trans_colour);
// copy
imagecopy($img, $image, 1, $imageHeight-$bottom, 1, 1, $imageWidth-2, $bottom-1);
// Draw a black rectangle
$black = imagecolorallocate($img, 0, 0, 0);
imagerectangle($img, 0, 0, $imageWidth-1, $imageHeight-1, $black);
// destroy old image cursor
imagedestroy($image);
return $img;
}
References:
Crop whitespace from image in PHP
http://www.php.net/manual/en/function.imagecopy.php#97836
I think the solution is to build the avatar in a bottom-up fashion. i.e. shoe -> pant -> shirt -> face -> hair
(pseudo-code)
position = (x,y) // where y is the height of the canvas initially
if(need(shoe)){
position = position - shoe.height
add shoe at position
}
if(need(pant)) {
position = position - pant.height
add pant at position
}
... and so on
If you look at the imagecopy method it has the following method signature
bool imagecopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h )
By varying $dst_x and $dst_y you could achieve what I have described.
Related
Im trying to crop a square image and merge it with a Marker, but i cant get the copped circle image to be transparent.
When is save the circle image as a PNG , it shows it OK with Transparent corners, but when i open it in Photoshop it has a White Color on the corners like the final image below.
here is the code im using:
//SAVED THE CIRCLE PNG IMAGE
$width = 320;
$height = 320;
$img1 = '';
switch($fileExt){
case '.png':
$img1 = ImageCreateFrompng($img= $image_config['new_image']);
break;
case '.jpg':
$img1 = ImageCreateFromjpeg($img= $image_config['new_image']);
break;
case '.gif':
$img1 = ImageCreateFromgif($img= $image_config['new_image']);
break;
}
$x=$width ;
$y=$height;
$img2 = imagecreatetruecolor($x, $y);
$bg = imagecolorallocate($img2, 255, 255, 255);
imagefill($img2, 0, 0, $bg);
$e = imagecolorallocate($img2, 0, 0, 0);
$r = $x <= $y ? $x : $y;
imagefilledellipse ($img2, ($x/2), ($y/2), $r, $r, $e);
imagecolortransparent($img2, $e);
imagecopymerge($img1, $img2, 0, 0, 0, 0, $x, $y, 100);
imagecolortransparent($img1, $bg);
header("Content-type: image/png");
imagepng($img1, './img/deviceImg/pin'.$datetime.'.png');
imagedestroy($img2); // kill mask first
imagedestroy($img1); // kill canvas last
//MERGING IT WITH THE PIN
$width = 320;
$height = 320;
$image_1 = imagecreatefrompng('./img/deviceImg/pin.png');
imagesavealpha($image_1, true);
imagealphablending($image_1, true);
$image_2 = imagecreatefrompng('./img/deviceImg/pin'.$datetime.'.png');
imagesavealpha($image_2, true);
imagealphablending($image_2, true);
imagecopy($image_1, $image_2, 40, 22, 0, 0, $width, $height);
imagepng($image_1, './img/deviceImg/pinASD'.$datetime.'.png');
Transparency is only copied with imagecopymerge(), not imagecopy(). So your penultimate line:
imagecopy($image_1, $image_2, 40, 22, 0, 0, $width, $height);
Should be changed to:
imagecopymerge($image_1, $image_2, 40, 22, 0, 0, $width, $height, 100);
Note the extra parameter (pct) at the end. As per the manual:
The two images will be merged according to pct which can range from 0 to 100. When pct = 0, no action is taken, when 100 this function behaves identically to imagecopy() for pallete images, except for ignoring alpha components, while it implements alpha transparency for true colour images.
I am getting unwanted dashed black border when I rotate an image. I have tried to remove that but I am not finding any success. I am using the following function for image rotation. I try to preserve transparency. I have provided a image as well.
Here is an Image URL: http://s23.postimg.org/hep2pkol7/border.png
function imageRotation ($source, $rotang)
{
imagealphablending($source, false);
imagesavealpha($source, true);
$rotation = imagerotate($source, $rotang, imageColorAllocateAlpha($source, 0, 0, 0, 127));
imagealphablending($rotation, false);
imagesavealpha($rotation, true);
return $rotation;
}
I call the function something like that:
$rotatedImage = imageRotation($image, 10);
Here is the full code
<?php
// Some settings
$text = "Previously blogging";
$fontFace = 'Days.ttf';
$fontSize = 90;
$angle = 0;
$bbox = calculateTextBox($text, $fontFace, $fontSize, $angle);
$image = imagecreatetruecolor($bbox['width'], $bbox['height']);
// Define some colors
$black = imagecolorallocate($image, 0, 0, 0);
$yellow = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
//Fill the image with background color
imagefill($image, 0, 0, $yellow);
// Draw text
imagettftext($image, $fontSize, $angle, $bbox['left'], $bbox['top'], $black, $fontFace, $text);
$image = imageRotation($image, 20);
$im = imagecreatefromjpeg('weight-loss.jpg');
// Switch antialiasing on for one image
imageantialias($im, true);
$destWidth = imagesx($im);
$destHeight = imagesy($im);
$src_w = imagesx($image);
$src_h = imagesy($image);
$dst_x = ($destWidth - $src_w)/2;
$dst_y = ($destHeight - $src_h)/2;
imagecopy($im, $image, $dst_x, $dst_y, 0, 0, $src_w, $src_h);
header ('Content-Type: image/jpeg');
imagejpeg($im, null, 100);
imagedestroy($im);
imagedestroy($image);
function calculateTextBox($text,$fontFile,$fontSize,$fontAngle)
{
$rect = imagettfbbox($fontSize,$fontAngle,$fontFile,$text);
$minX = min(array($rect[0],$rect[2],$rect[4],$rect[6]));
$maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6]));
$minY = min(array($rect[1],$rect[3],$rect[5],$rect[7]));
$maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7]));
return array(
"left" => abs($minX),
"top" => abs($minY),
"width" => $maxX - $minX,
"height" => $maxY - $minY,
"box" => $rect
);
}
function imageRotation ($source, $rotang)
{
imagealphablending($source, false);
imagesavealpha($source, true);
$rotation = imagerotate($source, $rotang, imageColorAllocateAlpha($source, 0, 0, 0, 127), 0);
imagealphablending($rotation, false);
imagesavealpha($rotation, true);
return $rotation;
}
?>
This is neither a dashed border, nor a border at all actually. This happens because your images are low-resolution, what cause the the rotated borders to "break", because actual pixels don't rotate.
That's what I'm trying to explain:
A line, parallel to the "pixel construction"; one px is three dashes long:
-------------------------------------
It would look smooth.
Rotated line:
---
---
---
---
---
---
---
As you see, due to low resolution, it steps, not smoothly goes down.
If you use the higher resolution, the issue would go away. The visual effect of the "black" border appears because your white image contrasts with the other part of image.
I have one problem with PHP create image. What is wrong with my following code?
<?php
$filename = 'play';
$img = "http://www.slcentral.com/ipod-mp3-player/5.JPG";
$image = imagecreatefromjpeg($img);
$cleft = 0;
$ctop = 45;
$canvas = imagecreatetruecolor(480, 270);
imagecopy($canvas, $image, 0, 0, $cleft, $ctop, 480, 360);
$image = $canvas;
$imageWidth = imagesx($image);
$imageHeight = imagesy($image);
// ADD THE PLAY ICON
$play_icon = "f-play.png";
$logoImage = imagecreatefrompng($play_icon);
imagealphablending($logoImage, TRUE);
$logoWidth = imagesx($logoImage);
$logoHeight = imagesy($logoImage);
// CENTER PLAY ICON
$left = round($imageWidth / 2) - round($logoWidth / 2);
$top = round($imageHeight / 2) - round($logoHeight / 2);
// CONVERT TO PNG SO WE CAN GET THAT PLAY BUTTON ON THERE
imagecopy( $image, $logoImage, $left, $top, 0, 0, $logoWidth, $logoHeight);
imagepng( $image, $filename .".png", 9);
// MASHUP FINAL IMAGE AS A JPEG
$input = imagecreatefrompng($filename .".png");
$output = imagecreatetruecolor($imageWidth, $imageHeight);
$white = imagecolorallocate($output, 255, 255, 255);
imagefilledrectangle($output, 0, 0, $imageWidth, $imageHeight, $white);
imagecopy($output, $input, 0, 0, 0, 0, $imageWidth, $imageHeight);
// OUTPUT TO 'i' FOLDER
header("Content-type: image/jpeg");
imagejpeg($output, $filename . ".jpg", 95);
// UNLINK PNG VERSION
#unlink($filename .".png");
die();
?>
Above code is create one image from giving url and add play icon to it. And I want to access to http://coolrss.com/create-img.php it will show image with play icon.
Please help!
Make sure the path has the right permission or you will get:
PHP Warning: imagepng(): Unable to open 'play.png' for writing: Permission denied in /var/www/coolrss/public_html/create-img.php on line 32
Make sure you have installed GD.
Start your code with this header (after the php tag (<?php))
header("Content-Type: image/jpeg");
At the end (last line) add
imagejpeg($output, NULL, 100);
Your code looks like this now:
<?php
header("Content-Type: image/jpeg");
$filename = 'play';
$img = "http://www.slcentral.com/ipod-mp3-player/5.JPG";
$image = imagecreatefromjpeg($img);
$cleft = 0;
$ctop = 45;
$canvas = imagecreatetruecolor(480, 270);
imagecopy($canvas, $image, 0, 0, $cleft, $ctop, 480, 360);
$image = $canvas;
$imageWidth = imagesx($image);
$imageHeight = imagesy($image);
// ADD THE PLAY ICON
$play_icon = "f-play.png";
$logoImage = imagecreatefrompng($play_icon);
imagealphablending($logoImage, TRUE);
$logoWidth = imagesx($logoImage);
$logoHeight = imagesy($logoImage);
// CENTER PLAY ICON
$left = round($imageWidth / 2) - round($logoWidth / 2);
$top = round($imageHeight / 2) - round($logoHeight / 2);
// CONVERT TO PNG SO WE CAN GET THAT PLAY BUTTON ON THERE
imagecopy( $image, $logoImage, $left, $top, 0, 0, $logoWidth, $logoHeight);
imagepng( $image, $filename .".png", 9);
// MASHUP FINAL IMAGE AS A JPEG
$input = imagecreatefrompng($filename .".png");
$output = imagecreatetruecolor($imageWidth, $imageHeight);
$white = imagecolorallocate($output, 255, 255, 255);
imagefilledrectangle($output, 0, 0, $imageWidth, $imageHeight, $white);
imagecopy($output, $input, 0, 0, 0, 0, $imageWidth, $imageHeight);
imagejpeg($output, NULL, 100);
Screenshot - Works for me
Friends i want to generate one png image from multiple transparent PNG image but the issue is that i can generate only last image
Both images can not combine.
My code is given below
$x = 363;
$y = 267;
$im_dest = imagecreatetruecolor ($x, $y);
imagealphablending($im_dest, false);
$im = imagecreatefrompng('2.png');
$im1 = imagecreatefrompng('1.png');
imagecopy($im_dest, $im1, 0, 0, 0, 0, $x, $y);
imagecopy($im_dest, $im, 0, 0, 0, 0, $x, $y);
imagesavealpha($im_dest, true);
imagepng($im_dest, 'small_redfade.png');
These are the images which i am using to join in single image
http://s11.postimg.org/h6lui7yjn/image.png
http://s21.postimg.org/o7zdnwcnb/image.png
Here is code which works:
$width = 210;
$height = 190;
$layers = array();
$layers[] = imagecreatefrompng("img/01_boy_faceB.png");
$layers[] = imagecreatefrompng("img/01_boy_hairB.png");
$image = imagecreatetruecolor($width, $height);
// to make background transparent
imagealphablending($image, false);
$transparency = imagecolorallocatealpha($image, 0, 0, 0, 127);
imagefill($image, 0, 0, $transparency);
imagesavealpha($image, true);
/* if you want to set background color
$white = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $white);
*/
imagealphablending($image, true);
for ($i = 0; $i < count($layers); $i++) {
imagecopy($image, $layers[$i], 0, 0, 0, 0, $width, $height);
}
imagealphablending($image, false);
imagesavealpha($image, true);
imagepng($image, 'final_img.png');
?>
ImageMagick::Composite can handle this, sadly haven't done in GD so will leave others to explain how to do it there.
Something like:
<?php
$firstImage = new Imagick("firstImage.png");
$secondImage = new Imagick("secondImage.png");
$firstImage->compositeImage($secondImage, Imagick::COMPOSITE_COPYOPACITY, 0, 0 );
header('Content-type: image/png');
echo $firstImage;
?>
This should preserve alpha.
I'm having some major issues getting PNG transparency on a PNG that is being rotated.
$filename = 'bird_up.png';
$source = imagecreatefrompng($filename) or die('Error opening file '.$filename);
imagealphablending($source, false);
imagesavealpha($source, true);
$rotation = imagerotate($source, $degrees, imageColorAllocateAlpha($source, 0, 0, 0, 127));
imagealphablending($source, false);
imagesavealpha($source, true);
header('Content-type: image/png');
imagepng($rotation);
imagedestroy($source);
imagedestroy($rotation);
I've added a working commented version below
<?php
// this file writes the image into the http response,
// so we cant have any output other than headers and the file data
ob_start();
$filename = 'tibia.png';
$degrees = 45;
// open the image file
$im = imagecreatefrompng( $filename );
// create a transparent "color" for the areas which will be new after rotation
// r=0,b=0,g=0 ( black ), 127 = 100% transparency - we choose "invisible black"
$transparency = imagecolorallocatealpha( $im,0,0,0,127 );
// rotate, last parameter preserves alpha when true
$rotated = imagerotate( $im, $degrees, $transparency, 1);
// disable blendmode, we want real transparency
imagealphablending( $rotated, false );
// set the flag to save full alpha channel information
imagesavealpha( $rotated, true );
// now we want to start our output
ob_end_clean();
// we send image/png
header( 'Content-Type: image/png' );
imagepng( $rotated );
// clean up the garbage
imagedestroy( $im );
imagedestroy( $rotated );
Demo
Original image from Wikipedia
rotated -45 degrees, new areas with ~50% opacity for a demo
$transparency = imagecolorallocatealpha( $im,0,0,0,55 );
rotated -45 degress, new areas with 100% opacity
$transparency = imagecolorallocatealpha( $im,0,0,0,127 );
<?php
$text ="New"; $font = "fonts/AARDV.ttf"; $size = 100;
function html2rgb()
{
$color='FF0000';
if(strlen($color)==6)
list($r, $g, $b)=array($color[0].$color[1],$color[2].$color[3],$color[4].$color[5]);
elseif (strlen($color) == 3)
list($r, $g, $b) = array($color[0].$color[0], $color[1].$color[1], $color[2].$color[2]);
else
return false;
$r = hexdec($r);
$g = hexdec($g);
$b = hexdec($b);
return array($r, $g, $b);
}
$c=html2rgb();
$bbox = imagettfbbox($size, 0, $font, $text);
$width = abs($bbox[2] - $bbox[0]);
$height = abs($bbox[7] - $bbox[1]);
$image = imagecreatetruecolor($width, $height);
$bgcolor = imagecolorallocate($image, 1, 1,0);
imagecolortransparent($image, $bgcolor);
$color = imagecolorallocate($image, $c[0],$c[1],$c[2]);
$x = $bbox[0] + ($width / 2) - ($bbox[4] / 2);
$y = $bbox[1] + ($height / 2) - ($bbox[5] / 2);
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
$last_pixel= imagecolorat($image, 0, 0);
for ($j = 0; $j < $height; $j++)
{
for ($i = 0; $i < $width; $i++)
{
if (isset($blank_left) && $i >= $blank_left)
{
break;
}
if (imagecolorat($image, $i, $j) !== $last_pixel)
{
if (!isset($blank_top))
{
$blank_top=$j;
}
$blank_left=$i;break;
}
$last_pixel=imagecolorat($image, $i, $j);
}
}
$x -= $blank_left;
$y -= $blank_top;
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
header('Content-type: image/png');
$transparency = imagecolorallocatealpha( $image,0,0,0,127 );
$image=imagerotate($image, 10, $transparency, 1);
imagealphablending( $image, false );
imagesavealpha( $image, true );
ob_end_clean();
imagepng($image);
imagedestroy($image);
?>
This one not work..Black color
any one please answer this..
enter code here