PHP- Put individual images into a transparent canvas - php

I'm creating a simple php sprite image generator, I was able to calculate the possible width and height of the sprite image, but I'm stuck at creating the transparent canvas and put the images into it.
Now let's say the width of the sprite image is 200x500px (i'm creating vertical sprite). And the images to put in the sprite image is in an array like so:
array('logo.png','delete.png','open.png');
How you gonna put those images into the sprite?

$path = '/img/';
$imgs = array('logo.png','delete.png','save.png');//images needed to be put in the sprite
$canvasWidth= 0;
$canvasHeight = 0;
//calculate the posible canvas width and height
foreach($imgs as $val)
{
$info = getimagesize($path.basename($val));
$width=$info[0];
$height=$info[1];
$canvasHeight +=$height;
if($canvasWidth < $width){
$canvasWidth = $width;
}
}
// create our canvas
$img = imagecreatetruecolor($canvasWidth, $canvasHeight);
$background = imagecolorallocatealpha($img, 255, 255, 255, 127);
imagefill($img, 0, 0, $background);
imagealphablending($img, false);
imagesavealpha($img, true);
// start placing our icons from the top down.
$pos = 0;
foreach($imgs as $val){
$tmp = imagecreatefrompng($path.basename($val));
$w=imagesx($tmp);
$h=imagesy($tmp);
imagecopy($img, $tmp, 0, $pos, 0, 0, $w, $h);
$pos += $h;
imagedestroy($tmp);
}
// create our final output image.
imagepng($img, $path.'sprite.png');

Related

Placing a watermark on transparent gif

I'm trying to make a image uploader and everything is working pretty good with the exception of placing a watermark on top of a transparent gif. The gif it self stays transparent but, the part of the watermark that gets placed on the gif's transparent background gets a red background for some reason and I'm struggling to find out why. Any suggestions?
else if ($this->fileType === "image/gif") {
$newFilename = $this->placeholder();
$img = imageCreateFromGif($this->fileTmpName);
imageAlphaBlending($img, true);
imageSaveAlpha($img, true);
if($this->watermarkEnabled === true) {
$this->watermark($img);
}
$newFilename = imageGif($img, $newFilename.".".$this->fileExtension);
}
function watermark($img) {
// creating png image of watermark
$watermark = imagecreatefrompng($this->watermarkImage);
// getting dimensions of watermark image
$watermarkWidth = imagesx($watermark);
$watermarkHeight = imagesy($watermark);
// placing the watermark 10px from bottom and right
$destX = $this->imageSize[0] - $watermarkWidth - 10;
$destY = $this->imageSize[1] - $watermarkHeight - 10;
// creating a cut resource
$cut = imagecreatetruecolor($watermarkWidth, $watermarkHeight);
imagefill($cut,0,0,0x7fff0000);
// copying that section of the background to the cut
imagecopy($cut, $img, 0, 0, $destX, $destY, $watermarkWidth, $watermarkHeight);
// placing the watermark now
imagecopy($cut, $watermark, 0, 0, 0, 0, $watermarkWidth, $watermarkHeight);
// merging both of the images
imagecopymerge($img, $cut, $destX, $destY, 0, 0, $watermarkWidth, $watermarkHeight, 100);
imagedestroy($watermark);
}
I solved this by converting the image from Gif to Png and then add the watermark.

Resize image canvas with CodeIgniter Image Library - how to preserve transparency

I am trying to resize image canvas (as in Photoshop) by adding transparency around it. Somehow added part of the image is always black.
if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor'))
{
$create = 'imagecreatetruecolor';
$copy = 'imagecopyresampled';
}
else
{
$create = 'imagecreate';
$copy = 'imagecopyresized';
}
$dst_img = $create($this->width, $this->height);
if ($this->image_type == 3) // png we can actually preserve transparency
{
//teorethicaly image should be transparent?
$trans_colour = imagecolorallocatealpha($dst_img, 0, 0 ,0, 127);
imagefill($dst_img, 0, 0, $trans_colour);
imagealphablending($dst_img, FALSE);
imagesavealpha($dst_img, TRUE);
}
$copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
If I remove $copy and save new image only, it is transparent but if I merge both images the background is always black:
How I can have transparent background in that situation?
Thanks in advance!
http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/ http://www.phpfreaks.com/forums/index.php?topic=232090.0 How to preserve transparency when resizing PNG using Perl and GD.

Image transparency in imagepng() and imagegif()

I want to resize 2 types of images (png, gif) with transparent background...
But in png it works well in big size of the original image.
eg. Original file dimension is 150x150
change into 200x200 or exceeding the original size it works well. but in 100x100 it displays
Then the last GIF it doesn't work.
Here my code for png
$new_img = imagecreatetruecolor($max_w, $max_h);
imagealphablending($new_img, false);
imagesavealpha($new_img, true);
$transparentindex = imagecolorallocatealpha($new_img, 255, 255, 255, 127);
imagefill($new_img, 0, 0, $transparentindex);
imagepng($new_img, $dir);
Here my code for gif
imagegif($new_img, $dir);
I know no PHP, but this seems to do the trick:
#!/usr/local/bin/php -f
<?php
$neww=100;
$newh=100;
// Load original image and get its dimensions
$img = imagecreatefrompng("badge.png");
$w=imagesx($img);
$h=imagesy($img);
// Create output image, and fill with lots of transparency
$out = imagecreatetruecolor($neww,$newh);
imagealphablending($out,false);
$transparentindex = imagecolorallocatealpha($out,0,0,0,127);
imagefill($out,0,0,$transparentindex);
imagesavealpha($out, true);
// Copy original image, reized on top
imagecopyresized($out,$img,0,0,0,0,$neww,$newh,$w,$h);
imagepng($out,"out.png");
?>
Here is a little hack :)
Don't have any other ideas.
It involves a second image (1x1 trasparent gif)
create image
resize
create a transparent background with same size as resized image
use imagecolortransparent() to get the rgb index
imagecopymerge() images
voilà
.
$dir = 'http://i.stack.imgur.com/DbhrJ.png';
$max_w = 50;
$max_h = 50;
// get image size
list($src_w, $src_h) = getimagesize($dir);
if ($src_w > $max_w) {
$ratio = $max_w / $src_w;
$max_w = $src_w * $ratio;
}
else if ($src_h > $max_h) {
$ratio = $max_h / $src_h;
$max_h = $src_h * $ratio;
}
// resize image to $max_w and $max_h, and also save alpha
$src = imagecreatefromstring(file_get_contents($dir));
$new_img = imagecreatetruecolor($max_w, $max_h);
imagealphablending($new_img, false);
imagesavealpha($new_img, true);
imagecopyresampled($new_img, $src, 0, 0, 0, 0, $max_w, $max_h, $src_w, $src_h);
// create a new image with $max_w and $max_h
$maxsize = imagecreatetruecolor($max_w, $max_h);
// add 1x1 gif and resize, then copy over $maxsize
$background = imagecreatefromgif("http://i.imgur.com/atRjCdk.gif"); // transparent 1x1 gif
imagecopyresampled($maxsize, $background, 0, 0, 0, 0, $max_w, $max_h, 1, 1);
// allocate transparency
$transparent = imagecolortransparent($maxsize);
$transparent_index = imagecolorallocate($maxsize, $transparent['red'], $transparent['green'], $transparent['blue']);
imagecolortransparent($maxsize, $transparent_index);
// image copy
imagecopymerge($maxsize, $new_img, 0, 0, 0, 0, $max_w, $max_h, 100);
// save or output
imagegif($maxsize, $path_to_save);
// destroy images
imagedestroy($maxsize);
imagedestroy($new_img);
imagedestroy($background);
imagedestroy($src);

Empty space getting filled with black after GD imagecopy but only in some scenarios

I am experiencing an issue where I am allowing the user to resize images in a container and then need to create a resulting image that is the size of the container but with the image scaled and adjusted as per the users choices.
So for example say the container is 400 x 200 and the user wants to be able to put in a logo that is 600 x 100 they may wish to shrink the logo so it fits and leave space at the top and bottom. I need to be able to save that as an image that is 400x200 with the appropriate gaps at the top and bottom.
What I have found though is that if the image content (the logo in this example) extends beyond BOTH the top and the right of the container everything is fine OR if it DOESNT extend beyond either it is fine but if it extends beyond one and not the other then I get black fill- or something like that- see examples below...
Below are some examples of the results and this is the code I am using...
$cropped = wp_imagecreatetruecolor( $frame_w, $frame_h);
$backgroundColor = imagecolorallocatealpha($cropped, 0, 0, 0, 127);
//imageantialias( $cropped, true );
//if $img_y or $img_x are negative we need to apply the value to $img_x and $img_y
//if $img_y or $img_x are positive we need to apply the value to $dest_x and $dest_y
$dest_x = strstr($img_x,'-') ? 0 : abs($img_x);//if neg is true = 0 else offset inside
$dest_y = strstr($img_y,'-') ? 0 : abs($img_y);
$img_x = strstr($img_x,'-') ? abs($img_x) : 0;//if neg is true offset outside else 0
$img_y = strstr($img_y,'-') ? abs($img_y) : 0;
$img_w = $img_w > $frame_w ? $frame_w : $img_w;
$img_h = $img_h > $frame_h ? $frame_h : $img_h;
imagecopy( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $img_w, $img_h);
//imagecopymerge( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $img_w, $img_h,100);
//imagecopyresampled( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $frame_w, $frame_h, $img_w, $img_h );
imagefill($cropped, 0, 0, $backgroundColor);//putting this after the copy makes any black borders transparent again unless $resized does not extend beyond both dimensions
Examples
Image does not extend beyond top or beyond right (fine)
Image extends beyond bottom but not right (not fine)
Image extends beyond both (fine)
Image extends beyond right but not bottom (not fine)
Image Extends beyond neither (fine)
I have been literally tearing my hair out trying to fix this and tried every possible combination of imagesavealpha, imagecopymerged, imagecolorallocatealpha, imagealphablending etc I can think of but nothing seems to fix this...
So is this a bug/limitation of GD? Or can someone out there come to my rescue!
I don't know if this will help you, but I had an issue with this earlier today. The box expands but the area was black. Here's my code (which fixes it):
<?php
function createImage($text)
{
// Adds an extra space to fill underline
$text = " $text";
// Adds one line at the end
$text .= "\n";
// Wrap the text to fit the image
$text = wordwrap($text, 40, "\n");
// Count new lines
$newlines = substr_count($text, "\n");
// Count how long to expand
if($newlines == 0)
{
$height = 30;
}
else
{
$height = 30*$newlines-$newlines*5;
}
putenv('GDFONTPATH=' . realpath('.'));
header('Content-Type: image/png');
// Adding underline
$e = explode('<', $text);
for($i=0;$i<count($e);$i++)
{
$e[$i] = implode('̲', str_split($e[$i]));
}
// Creating image
$text = implode(' ', $e);
$im = imagecreatetruecolor(315, $height);
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
$purple = imagecolorallocate($im, 97, 26, 139);
imagefilledrectangle($im, 0, 0, 399, $height, $white);
$font = 'arialbd.ttf';
imagettftext($im, 11, 0, 10, 20, $purple, $font, $text);
imagepng($im);
imagedestroy($im);
}
createImage("asbdasddsa");
?>
i think this will happen only for PNG check with other formats
I'm not sure if this is an actual answer since it is basically 'Use ImageMagick' but anyway for those for whom ImageMagick is an option the code below might help them achieve the same thing as I was trying to above... Basically ImageMagick seems far superior to GD, no borders around rotated images, no hassles with transparency, no onwanted black fill, clearer resizing if you are enlarging...
$img_x = -50; //left offset of the image within the frame
$img_y = 50; //top offset of the image within the frame
$img_w = 400; //width of the image to be put in the frame
$img_h = 200; // height of the image to be put in the frame
$angle = 45; //rotation to be applied to the image before it is put into the frame
$frame_w = 300; //width of the frame the image is going into
$frame_h = 300; //height of the frame the image is going into
$img_path = 'path/to/image/file.jpg';
$image = new Imagick( $img_path );
$size = $image->getImageGeometry();
$orig_w = $size['width']; $orig_h = $size['height'];
$image->scaleImage( $img_w, $img_h );
//rotate if necessary
if($angle)
{
$image->rotateImage( new ImagickPixel('none'), $angle );
$size = $image->getImageGeometry();
$img_w = $size['width']; $img_h = $size['height'];
}
//composite into frame
//in imagemagick we create an image that is the size of the frame and make it transparent
$frame = new Imagick();
$frame->newImage($frame_w, $frame_h, new ImagickPixel("none"));
//then we composite the image itself into this with the respective offset values
$frame->compositeImage( $image, Imagick::COMPOSITE_DEFAULT, $img_x, $img_y );
//save it
$destfilename = "{$dir}/{$name}-{$img_suffix}.{$ext}";
$frame->writeImage($destfilename);
$frame->clear();
$frame->destroy();
$image->clear();
$image->destroy();
The above code produces this...yay!

Applying text to png transparency issue PHP

I am trying to write text onto a png, however when I do it puts a dark border around it, I am not sure why.
The original image:
The processed image:
Code:
// Load the image
$im = imagecreatefrompng("admin/public/images/map/order/wally.png");
// If there's an error, gtfo
if(!$im) {
die("");
}
$textColor = imagecolorallocate($im, 68, 68, 68);
$width = imagesx($im);
$height = imagesy($im);
$fontSize = 5;
$text = "AC";
// Calculate the left position of the text
$leftTextPos = ($width - imagefontwidth($fontSize)*strlen($text)) / 2;
// Write the string
imagestring($im, $fontSize, $leftTextPos, $height-28, $text, $textColor);
// Output the image
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
I've had this issue several times, let me find the answer...
Ok, found something:
imagesavealpha($im, true);
imagealphablending($im, true);
Write that before imagepng.
Yes, saving with alpha is important but loading it is important as well. Your PNG image might have transparency but it is good practice to account for that as well.
You'd need to create true color image, set alpha color and then draw your loaded image with text over it. So something like this:
// create true color image
$img = imagecreatetruecolor($width, $height);
$transparent_color = imagecolorallocatealpha($img, 255, 255, 255, 0);
imagealphablending($img, false);
imagefillrectangle($img, 0, 0, $width, $height, $transparent_color);
imagealphablending($img, true);
// draw previously loaded PNG image
imagecopy($img, $loaded_img, 0, 0, 0, 0, $width, $height);
// draw your text
// save the whole thing
imagesavealpha($img, true);
imagepng($img, $file);

Categories