Home > Software engineering >  Centering text within an image and rounding corners
Centering text within an image and rounding corners

Time:01-15

I'm a php beginner and I couldn't find a fix how to make rounded corners for the dynamic image or to add the text that displays the IP in the center of the image

<?php
// Create the image
$image = imagecreatetruecolor(333, 33);

// Allocate colors for the image
$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);

// Fill the image with white
imagefill($image, 0, 0, $white);

// Calculate the center position of the image
$image_width = imagesx($image);
$image_height = imagesy($image);

// Get the client's IP address
// Use the IP Geolocation API to get the country of the IP address
// Decode the JSON response
// Get the country code and name from the response

// Get the flag image file
$flag_file = "images/flags/$country_code.png";

// Load the flag image
$flag_image = imagecreatefrompng($flag_file);

// Set the font size
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  $font_size = 15;
} elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
  $font_size = 7;
}
$font_file = '/css/SatrevaNeue-lgJ6V.ttf';

// Add a border radius to the image
$radius = 10;

// Draw the four ellipses to the corners of the image
imagefilledellipse($image, $radius, $radius, $radius * 2, $radius * 2, $white);
imagefilledellipse($image, 333 - $radius, $radius, $radius * 2, $radius * 2, $white);
imagefilledellipse($image, $radius, 33 - $radius, $radius * 2, $radius * 2, $white);
imagefilledellipse($image, 333 - $radius, 33 - $radius, $radius * 2, $radius * 2, $white);

// Calculate the center position of the image
$text = "Your IP is $ip";
$text_box_width = imagefontwidth($font_size) * strlen($text);
$text_box_height = imagefontheight($font_size);
$x = ($image_width / 2) - ($text_box_width / 2);
$y = ($image_height / 2) - ($text_box_height / 2);

// Add the IP address to the image
imagettftext($image, $font_size, 0, $x, $y, $black, $font_file, $text);

// Calculate the position of the flag image
$flag_width = 20;
$flag_height = 20;
$flag_x = $x   $text_box_width   10; // Add some spacing between the text and the flag image
$flag_y = ($image_height / 2) - ($flag_height / 2);

// Get the width and height of the flag image
$src_w = imagesx($flag_image);
$src_h = imagesy($flag_image);

// Resize and copy the flag image onto the canvas
imagecopyresampled($image, $flag_image, $flag_x, $flag_y, 0, 0, $flag_width, $flag_height, $src_w, $src_h);

// Set the content type header so the image is displayed properly
header('Content-Type: image/png');

// Output the image
imagepng($image);

// Free up memory
imagedestroy($image);

I tried to draw the polygon shapes to cut out the corners imagefilledpolygon() but same output here is the image it generates:

enter image description here

CodePudding user response:

A couple of issues to point out in the script you have provided:

  • If filter_var fails in both cases of validating the IP, you will be attempting to add text to the image with no font size set. You should move your IP and country logic to the top, and make sure they're set correctly before proceeding to generate the image.
  • You are calculating the width and height of the text, when you should be calculating the width and height of the bounding text box.
  • To achieve transparency on your corners, you will need to disable alpha blending, and fill the image with a transparent color
  • imagefilledellipse is only adding circles to the corners, you will need a couple of imagefilledrectangle to fill the gaps between those corners.

Centering the text

To ensure your text is vertically centered correctly, utilize the enter image description here

Rounding the corners

The rounded corners is a little more difficult, first you have to disable alpha blending, and then fill the image with the transparent color:

Note: Don't forget to re-enable alpha blending otherwise your text will not be very readable when you want to add some.

// Allocate colors
$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);
$transparency = imagecolorallocatealpha($image, 0, 0, 0, 127); // 127 indicates "completely transparent"

// Transparent Background
imagealphablending($image, false);
imagefill($image, 0, 0, $transparency);
imagesavealpha($image, true);
imagealphablending($image, true); // turn blending back on otherwise text will be ugly

// Create 4 circles in each corner, emulating our rounded corners
imagefilledellipse($image, 10, 10, 20, 20, $white);
imagefilledellipse($image, 323, 10, 20, 20, $white);
imagefilledellipse($image, 10, 23, 20, 20, $white);
imagefilledellipse($image, 323, 23, 20, 20, $white);

// Connect the circles with a couple of rectangles
imagefilledrectangle($image, 10, 0, 323, 33, $white);
imagefilledrectangle($image, 0, 10, 333, 23, $white);

// add your text etc...

If you don't use rectangles to fill the gaps between the circles placed in the corner, the result would look like:

enter image description here

However with the rectangles, it falls together nicely and the result looks like:

enter image description here

Bonus tip: When dealing with pixels, I generally like to avoid using even numbers as the diameter of the rounded corners as there is no perfect center in even numbers...

In the number 10 for example... the central numbers are 4, 5 and 6. However in the number 11, the central number is simply 6)

I created this GIF to help illustrate exactly what is happening here:

enter image description here

  • Related