Create a picture with GD containing other images - php

I would like to create a picture in PHP with GD composed by different other pictures. For example I have 6 pictures (or more) and I would like to create ONE picture who contain these different pictures.
The Difficulty is that my final picture must have a fixed width and height (304x179), so if the different pictures are too big they must be cut. This is an example from IconFinder :
This picture is composed by 6 images, but the 3rd bird (green) is cutted, and the 4, 5 and 6 are cutted in the bottom. This is what I want, can you give me some help to write this code in PHP ?
Thanks

Create your primary image and consider it your "canvas."
From there, use imagecopy() to copy the smaller images into the canvas image.
See this for example:
<?php
header('Content-Type: image/jpg');
$canvas = imagecreatetruecolor(304, 179);
$icon1 = imagecreatefromjpeg('icon.jpg');
$icon2 = imagecreatefromjpeg('icon2.jpg');
// ... add more source images as needed
imagecopy($canvas, $icon1, 275, 102, 0, 0, 100, 100);
imagecopy($canvas, $icon2, 0, 120, 0, 0, 100, 100);
// ... copy additional source images to the canvas as needed
imagejpeg($canvas);
?>
In my example, icon.jpg is a 100x100 image which I am placing in the canvas such that its top left corner is located at 275, 102 in the canvas, which cuts off the right side.
Edit
I adjusted the code to be more similar to what you're doing.

Here a none tested modify spinet from one of my scripts, hope it can be usefull:
header('Content-type: image/png');
$image = array() //Populate this array with the image paths
//Create the Letters Image Objects
foreach($image as $a){
$image['obj'][] = imageCreateFromPNG($a);
}unset($a);
$canvasW = 300;
$canvasH = 300;
//Create Canvas
$photoImage = imagecreatetruecolor($canvasW,$canvasH);
imagesavealpha($photoImage, true);
$trans_color = imagecolorallocatealpha($photoImage, 0, 0, 0, 127);
imagefill($photoImage, 0, 0, $trans_color);
//Merge Images
$Offset_y = 0;
$images_by_row = 3;
$images_rows_height = 100; // height of each image row
$counter = 0;
foreach($image['obj'] as $a){
$counter++;
$width = ceil(imagesx($a));
$height = ceil(imagesy($a));
if(!isset($offset)){ $offset = 1; }
imageComposeAlpha($photoImage, $a, $offset, $Offset_y,$width,$height);
if($offset >= 1){
$offset = $offset + $width;
}
//Check if new row next time
if($counter >= $images_by_row){
if($images_by_row%$counter){
$offset_y += $images_rows_height;
}
}
}unset($a);
imagepng($photoImage);

Related

how to center and align texts by merging two images using PHP GD

How do I centralize and align text above my main image?
The result of this code is this image:
https://i.imgur.com/Dk5pYJM.jpg
I wish it would look like this:
https://i.imgur.com/mED295l.jpg
but I do not understand much of moving the images and texts.
<?php
$fontname = 'verdana.ttf';
$i = 30;
$quality = 85;
function create_image($user){
global $fontname;
global $quality;
$file = md5($user[1]['text'].rand(30454, 343434)).".jpg";
//if (!file_exists($file)) {
$im = imagecreatefromjpeg("fundo.jpg");
$logo = imagecreatefromjpeg("img.jpeg");
$color['grey'] = imagecolorallocate($im, 255, 255, 255);
$y = imagesy($im) - $height - 365;
$font_size = 25;
$logo_x = imagesx($logo);
$logo_y = imagesy($logo);
foreach ($user as $value){
$x = center_text($value['text'], $font_size);
imagettftext($im, $font_size, 0, $x, $y+$i, $color["grey"], $fontname, $value['text']);
$i = $i+32;
}
imagecopymerge($im, $logo, 37, 370, 0, 0, $logo_x, $logo_y, 100);
imagejpeg($im, $file, $quality);
//}
return $file;
}
function center_text($string, $font_size) {
global $fontname;
$image_width = 720;
$dimensions = imagettfbbox($font_size, 0, $fontname, $string);
return ceil(($image_width - $dimensions[4]) / 2);
}
$user = array(
array('text'=> 'Our adge lacks gravitas. That’s whyaadasdasdasdasdsadasdasdasdas')
);
$filename = create_image($user);
?>
<img src="<?=$filename;?>" /><br/><br/>
Aligning text in an image using PHP's image functions is always a bit of a puzzle.
First, you need to know the x and y coordinates of the point at the bottom center of where the text should go (anchor point). This is probably half the width of the outer image for the x and the y value of the top of the smaller image in the center (minus a margin value) for the y.
After this, you have to calculate where your text has to be put (x and y) so that it will align above the smaller image in the center (centered above the anchor point).
For this you use imagettfbbox to calculate what the bounding box's coordinates will be if the text is put at x=0 y=0. Then you use these values to calculate the coordinates of the bottom center of this bounding box.
$bounding_box = imagettfbbox(......);
/* lower right x - lower left x, divided by 2 */
$relative_x = ( $bounding_box[2] - $bounding_box[0] ) / 2;
/* lower left y */
$relative_y = $bounding_box[1];
Subtracting these relative values from our first calculated anchor point, gives you the coordinates to put the text using imagettftext.
See http://php.net/manual/en/function.imagettfbbox.php for which array value is which coordinate value.

Drawing rectangles in php not working

I am creating an image in php and populating it with 10x10 pixel rectangles filled with a color.
$image = imagecreate(150,150);
$background = imagecolorallocate($image, 0, 0, 0); //black background
for ($row=0; $row < 15; $row++) {
for ($col=0; $col < 15; $col++) {
$x1 = 10* $col;
$y1 = 10*$row;
$x2 = 10*($col + 1);
$y2 = 10*($row + 1);
imagefilledrectangle($image, $x1,$y1,$x2,$y2, imagecolorallocate($image, 100,100,100)); //grey rectangle
}
}
imagepng($image, "ciph.png");
This works for small images no bigger than 150x150 pixels and i get a completely grey filled rectangle. but soon as i try bigger images. it only adds rectangles to part of the image. Any idea what is causing this? it appears there is a limit on the number of individual objects i can draw.
15x15
18x18
ive counted and it appears to only draw 256 rectangles... doesnt seem like a coincidence that that is 2 to the 8th power.
Any help would be much appreciated! thanks.
The problem lies in how you're creating the image. If you change first line from:
$image = imagecreate(150,150);
to:
$image = imagecreatetruecolor(150,150);
it will allow more than 256 rectangles to be drawn to the image.
imagecreatetruecolor() also gives the image a black background by default, instead of the blank background that imagecreate() gives, so you won't need the second line as well.

Merge a lot of images with PHP GD (imagecopymerge) in a good time

So, I need to merge some images ( 36 or 48 ) images to another image ( );
The resolution of this is 4800x4800 pixels. So each square will have 695x695; I currently came up with this solution:
$i = 1;
$x = 140; $y = 140;
foreach($files as $file):
if($i > 1) $template = 'test.png';
else $template = 'templates/24x24-TEMPLATE.png';
$this->save_image($file,'templates/temp.jpg');
$src = imagecreatefromjpeg('templates/temp.jpg');
$src2 = imagecreatetruecolor(695,695);
imagecopyresampled($src2, $src, 0, 0, 0, 0, 695, 695, 612, 612);
imagejpeg($src2,'templates/temp.jpg');
imagedestroy($src2);
$src = imagecreatefromjpeg('templates/temp.jpg');
$dest = imagecreatefrompng($template);
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagealphablending($src, false);
imagesavealpha($src, true);
imagecopymerge($dest, $src, $x, $y, 0, 0, 695, 695, 100); //have to play with these numbers for it to work for you, etc.
imagepng($dest,'test.png');
/* Destroy the images to free up space */
imagedestroy($dest);
imagedestroy($src);
$x = $x + 695 + 65;
if($i % 6 == 0):
$y = $y + 695 + 65;
$x = 140;
endif;
$i++;
endforeach;
witch downloads the file to be put onto the square, merges it with the squares, and does that for all the images until all squares are filled. But that code, for 20 images it takes up to 5 minutes! I would need something that can run under 30 seconds to fill up the squares with the images and then generate a single file PDF.
Is there anyway to improve this? Or is there any other way to do this faster and better?
I presume by "in a good time" you mean quickly and efficiently.
Then the answer is probably to do it outside of PHP. Even though the data is mostly held in custom data structures using the GD extension there's still a lot of overhead in the PHP code. There are lots of tools for merging images for the purpose of generating CSS sprites - however they don't all provide control over the layout of the images. You could write your own using GD and C.
But why bother? If you utlimately want the output as a PDF, why not just write the individual images directly into the PDF?

How to generate a completely random image?

I'm trying to generate a completely random image of a given size.
Here is what I have so far:
<?php
$Width = 64;
$Height = 32;
$Image = imagecreate($Width, $Height);
for($Row = 1; $Row <= $Height; $Row++) {
for($Column = 1; $Column <= $Width; $Column++) {
$Red = mt_rand(0,255);
$Green = mt_rand(0,255);
$Blue = mt_rand(0,255);
$Colour = imagecolorallocate ($Image, $Red , $Green, $Blue);
imagesetpixel($Image,$Column - 1 , $Row - 1, $Colour);
}
}
header('Content-type: image/png');
imagepng($Image);
?>
The problem is that after 4 rows it stops being random and fills with a solid colour like this
if you change imagecreate to imagecreatetruecolor it should work (everything else is the same, including the parameters)
By allocating a new color for each pixel, you are quickly exhausting the color palate. 4 rows at 64 pixels per row is 256. After the palate is full, any new color will use the last color on the palate.
Mishu's answer uses a full-color image, rather than and indexed color image, which is why you are able to allocate more colors.
See this answer in the PHP docs http://us.php.net/manual/en/function.imagecolorallocate.php#94785
Both create images with different palletes. True color has more color ranges so its better to use imagecreatetruecolor()

Adding one image at the bottom of another in PHP

I'd like to add one image to the bottom of another in php
I've this to load the images:
//load top
$top = #imagecreatefrompng($templateTop);
//load bottom
$bottom = #imagecreatefrompng($templateBottom);
Now I'd like to add them to one picture and display top and bottom together.
What way can I do this?
Thanks!
Use imagecopy:
$top_file = 'image1.png';
$bottom_file = 'image2.png';
$top = imagecreatefrompng($top_file);
$bottom = imagecreatefrompng($bottom_file);
// get current width/height
list($top_width, $top_height) = getimagesize($top_file);
list($bottom_width, $bottom_height) = getimagesize($bottom_file);
// compute new width/height
$new_width = ($top_width > $bottom_width) ? $top_width : $bottom_width;
$new_height = $top_height + $bottom_height;
// create new image and merge
$new = imagecreate($new_width, $new_height);
imagecopy($new, $top, 0, 0, 0, 0, $top_width, $top_height);
imagecopy($new, $bottom, 0, $top_height+1, 0, 0, $bottom_width, $bottom_height);
// save to file
imagepng($new, 'merged_image.png');
To achieve this you would have to
a) Combine the image and store the result in a file
b) generate a suitable tag to point to it.
c) Avoid using that filename again, until that person had left.
If you want to combine two images just once, then use image magic.
If you frequently want to display two images one under the other, do so using suitable html, and let the browser do it.
E.g. Put the images in a
<div><div><img.../></div><div><img .../></div></div>
which you generate with php in the normal way.
(Which is easier than getting tags to appear here :)
$photo_to_paste = "photo_to_paste.png";
$white_image = "white_image.png";
$im = imagecreatefrompng($white_image);
$im2 = imagecreatefrompng($photo_to_paste);
// Place "photo_to_paste.png" on "white_image.png"
imagecopy($im, $im2, 20, 10, 0, 0, imagesx($im2), imagesy($im2));
// Save output image.
imagepng($im, "output.png", 0);

Categories