I'm trying to create a vertical button in PHP, but I have problem with the positioning, when I created a 200px height and 40px width PNG i want to put the text to the center of that image. The text long will be changing dynamically
this is a part of my code
$image = imagecreate($this->width , $this->height);
$background = ImageColorAllocate($image, $this->bg_red, $this->bg_grn, $this->bg_blu);
$foreground = ImageColorAllocate($image, $this->red, $this->grn, $this->blu);
if ($this->transparent) ImageColorTransparent($image, $background);
ImageInterlace($image, false);
// render the image
ImageTTFText($image, $this->size, $this->rot, $offset_x, $offset_y, $foreground, $this->font, $this->msg);
how can I calculate the $offset_x and $offset_y?
As you can see in the documentation of imagettftext function, it
Returns an array with 8 elements
representing four points making the
bounding box of the text. The order of
the points is lower left, lower right,
upper right, upper left. The points
are relative to the text regardless of
the angle, so "upper left" means in
the top left-hand corner when you see
the text horizontally. Returns FALSE
on error.
So you can first draw the text on another image, just to see what the dimensions will be, then calculate the needed height of your button.
Related
I can successfully add a transparent rectangle to an area of a saved PNG file, but it has a faint border around it, which can be seen on the final image. I want to remove this.
The code I use to add the rectangle is:
$dest=imagecreatefrompng("originalFilename.png");
$red = imagecolorallocate($dest, 255, 0, 0);
imagecolortransparent($dest, $red);
imagefilledrectangle($dest, 0, 0, 50, 25, $red);
imagepng($dest, "newFilename.png");
and the result looks like this:
Image showing rectangle outline
The transparency works fine, showing in this example a white background behind... but you can see that in the top left there's the faint outline of the transparent rectangle. This is what I want to remove.
I've since tried putting a box over the edge (it would be white to match the background of the image, but using green for display purposes here), but that box gets a slightly red huhe around it too!?!? Really strange.
Like this
red hue
Grateful for any clues. This is not the same as the suggested duplicate as it deals specifically with the hue that's left around the border of the transparent area and also any object made to go in that area.
This is blowing my mind. I want to merge 2 transparent PNGs.
One is a circle ($source) generated on the fly from a square image.
The second is a map marker ($marker) with a transparent circle to fit the first behind.
imagepng($source); and imagepng($marker); outputs just as one might expect.
With transparent backgrounds.
I then create an empty transparent image the size of the marker to place them both together:
//NEW BLANK TRANSPARENT IMAGE
$dest = imagecreatetruecolor(50, 61);
$transparent = imagecolorallocatealpha($dest, 0, 0, 0, 127);
imagefill($dest, 0, 0, $transparent);
imagealphablending($dest, true);
imagesavealpha($dest,true);
//COPY THE CIRCLE
imagecopy($dest, $source, 5, 5, 0, 0, 41, 41);
//AND THE MARKER ON TOP
imagecopy($dest, $marker, 0, 0, 0, 0, 50, 61);
In the result, the circle appears as a black square with the circle inside.
I tried a lot of combinations of imagealphablending and imagesavealpha both on $source and $dest and nothing seems to work.
How can I remove the black square and leave the $source transparent in the result as it is before the merge?
The problem here was:
To generate the circle on the fly, I was creating a circular mask and making everything else transparent making it red and then making red transparent.
This is incompatible with imagesavealpha(true) as it says the gd engine exactly to ignore transparent colors and save the whole alpha channel instead.
When merging both images, the color once transparent is now black.
The solution to my case was to analise it pixel per pixel and copy it to a blank image if it's inside the circle using the circular equation.
Ive been working on this project for days now and for some reason just not able to get rid of an unexpected 1px by 1px (approx) white spot that apears in each and every tile that is processed.
Summary:
I am using an original image ( say original.jpeg ) as referance to create a mosaic image ( say mosaic.jpeg which is approx 1000px by 1000px ) by merging totegher much much smaller jpeg images ( aprox 10px by 10px ).
I have a data set of approx 20,000 tile images to work with.
Process so far
I have mapped the original.jpeg image to cut it up into 5px by 5px tiles, then found the average color of each tile and saved it for further use.
I have scanned all the (10x10) tile images and stored their individual average colors as well.
i have calculated which tile image would fit closest to which tile of the original image by using Weighted ref : euclidean distance from the site mentioned.
I have managed to use PHP gd library to create a new truecolor image with all the matching tiles placed in the right position ( thus effectively creating a mosaic of the original.jpeg image )
The Problem
I am not getting a clear mosaic i had expected, for some reason the tiles do not match properly.
The Workaround
Now due to lack of time i an using a quick fix where in i take the original image, give it some 50% opacity and overlay it on top of each tile while it is being placed into the final mosaic.
NOTE: Although i am effectively overlaying the original image over the mosaic image, im NOT doing it in one go. The overlaying HAS to happen at each tile level.
So in short : Before placing each tile at the correct position of the final mosaic, i do the following
1. get that particular section of the original image ( 5x5px )
2. expand it to match the final tile size ( 10x10px )
3. set transparency for the section
4. place it over the tile that will be placed
5. merge this new tile over the final mosaic at the corresponding position.
Here is the function i have created to overlay part of the image along with transparency set to it.
public function overlay($dImg, $sImg, $opacity = null) {
// set default Opacity if not specified
$opacity = (is_null($opacity)) ? $this->opacity : $opacity;
// get width, height of sourceImage
$sWidth = imagesx($sImg);
$sHeight = imagesy($sImg);
// get width height of final image
$dWidth = imagesx($dImg);
$dHeight = imagesy($dImg);
$image = imagecreatetruecolor($dWidth, $dHeight);
imagecopyresampled($image, $sImg, 0, 0, 0, 0, $dWidth, $dHeight, $sWidth, $sHeight);
$background = imagecolorallocatealpha($image, 255, 255, 255, 127);
imagefill($image, 0, 0, $background);
imagealphablending($image, true);
imagecopymerge($dImg, $image, 0, 0, 0, 0, $dWidth, $dHeight, $opacity);
imagedestroy($image);
return $dImg;
}
THE REAL PROBLEM
in theory all of this seems perfectly fine. But the results have their own say in the matter.
I noticed an unusual almost 1x1px white patch at the start of every tile of the final mosaic.
This white patch only appears when the transparency technique above is applied. It does not happen otherwise.
I am clueless as to why this is happening, Due to this white patch the entire image looks like it has white noise all over it and degrades the overall quality immensely.
Please guide me in any direction as to why something like this could be happening.
your problem lies on these two lines:
$background = imagecolorallocatealpha($image, 255, 255, 255, 127);
imagefill($image, 0, 0, $background);
you don't need those, because imagefill is used to fill an area that have same/similar color with the color located on the supplied coordinate, in your case 0, 0 (top left), when there is no adjacent similar color, then it just change the color at the given coordinate.
you can use imagefilledrectangle instead, but i still think you don't need that, just comment out those 2 lines and see the result if it match your requirement, if not, then go ahead use imagefilledrectangle
imagefilledrectangle
I'm having some problems with a project I'm doing using Google Maps.
I have the map functionality all figured out, and it works great. I want to add dynamically generated icons to the map, and I've figured out how to do that as well using PHP to dynamically add the text I want to the icon image.
However, the icon is changed beyond the text I want added. The border around the original is made much thicker when there is nothing in the PHP code that should be doing anything like that. The image I've attached to this post shows the two icons. The top icon is the original, and the bottom one has the text added to it by my PHP script. Notice the thicker border.
Here's my PHP code:
<?php
// GETS THE NUMBER TO ADD TO THE ICON
$number = $_GET['number'];
// THE SOURCE OF THE ICON THAT I WANT TO ADD THE TEXT TO
$src = $_GET['src'];
header ("Content-type: image/png");
$font = 4;
$im = imagecreatefrompng($src);
// POSITION THE TEXT TO THE PREFERRED LOCATION
$x = 5 ;
$y = 2;
$textColor = imagecolorallocate ($im, 0, 0,0);
imagestring ($im, $font, $x, $y, $number, $textColor);
imagepng($im);
?>
Keep in mind that all of this is working, except the image is changed beyond just adding the text. The icons look much nicer without the really thick border.
I don't know for sure if this is the case but something like this can be caused if your initial image used transparency at the margin to get an effect of rounded corners. if you want to keep the transparency from the initial image you need to research other functions also. something like this should help:
imagealphablending( $im, false );
imagesavealpha( $im, true );
*right after imagecreatefrompng
I have run into some trouble with the gd library's imagefilledpolygon().
For some reason some of my lines were ending up 1px out of place so I decided to debug it using imagepixelset to set the colour of my shapes points to red.
alt text http://www.degreeshowcase.com/other/1.gif
if you look at the picture you can see some of the points are inside the shape ... some are outside....its very illogical.
(the picture has been scaled up to make it more visible)
Does anyone have a solution?
Update:
My points for the shape above were: 0,0 40,0 40,20 20,20 20,40 0,40
I require that the height and width of the shape produced should be a multiple of 20.... but for some reason some of the shape ends up 21 px high or wide.
I have made a script to work out what the points would be to get the shape I wanted but I can not work out why and so I can't work out a script to correct all my shapes.
<?php
// set up array of points for polygon
$values = array(0,0, 39,0, 39,20, 19,20, 19,39, 0,39);
//My original values were 0,0 40,0 40,20 20,20 20,40 0,40
//I do not understand why some values require minus 1 and others can remain as they were (a multiple of 20)
// create image
$image = imagecreatetruecolor(40, 40);
// allocate colors
$bg = imagecolorallocate($image, 200, 200, 200);
$blue = imagecolorallocate($image, 0, 0, 255);
// fill the background
imagefilledrectangle($image, 0, 0, 39, 39, $bg);
// draw a polygon
imagefilledpolygon($image, $values, 6, $blue);
// flush image
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>
My guess is that you're mixing up width with position.
For example a line from 0px to 9px is 10px long... if you used length as the second parameter instead of position, it would end up 11px long.
If I could see some code I could confirm this.
Normal polygon rendering ensures that each pixel can only be in one polygon, if the 2 polygons share an edge. If you imagine drawing 2 squares, next to each other, so they share a common edge, you don't want to render the pixels along that edge twice.
There is an explanation of determining which pixels on the edge of a polygon should be considered inside the polygon here: http://www.gameprogrammer.com/5-poly.html
A common solution is to say that "pixels on the left and top edges of a polygon belong to the polygon and pixels on the right and bottom edges don't". I am not 100% sure what solution GD uses, as I could not find any documentation on it, but I expect it is something similar to this.
I spoke to the guy who currently develops the GD library he explained that it follows the 'Winding number algorithm' - can be found here. Having looked at my example image, it does match how the 'winding number algorithm' works, however the function should take this into account and produce the shape that was input.
As far as I can see the only way to accurately (to the pixel) generate a concave polygon with this function is to write another function that also applies the winding rule to your coordinates and adjusts them accordingly and then put it into the function.