php - 按比例在图片上写文字

标签 php image text gd

所以我有图像:enter image description here

我想在图片下添加文字(制作令人沮丧的图片)。所以我扩展了它的高度并在底部增加了额外的高度。我需要的是编写文本:

Top text

bottom longer text

我还需要将这些文字置于图像的中心。所以输出应该是:image 2

一切都在 PHP GD 库中。问题是 - 我不知道如何计算字体大小的比例并将其居中。 我的功能不起作用,计算字体大小错误,文本对齐错误..

private function __generate_text_pref($type)
{
    $data = array();
    switch ($type) {
        case 'title':
            $data['percent'] = 0.9;
            $data['text_width_percent'] = 0.8;
            break;
        case 'subtitle':
            $data['percent'] = 0.92;
            $data['text_width_percent'] = 0.6;
            break;
        default:
            $data['percent'] = 0.86;
            $data['text_width_percent'] = 0.8;
            break;
    }

    list($img_width, $img_height) = getimagesize($this->settings['__temp_image']);

    // find font-size for $txt_width = 80% of $img_width...
    $data['font_size'] = 1;
    $txt_max_width = intval($data['text_width_percent'] * $img_width);

    do {

        $data['font_size'] ++;
        $p = imagettfbbox($data['font_size'], 0, $this->settings['font'], $this->settings['__title']);
        $txt_width = $p[2] - $p[0];
        // $txt_height=$p[1]-$p[7]; // just in case you need it

    } while ( $txt_width <= $txt_max_width );

    //$data['font_size'] = ($data['font_size'] > 24) ? 24 : $data['font_size'];

    return array(
        'font_size' => $data['font_size'],
        'asys'      => array(
            'x' => (($img_width - $txt_width) / 2),
            'y' => ($img_height * $data['percent'])
        )
    );
}

它应该具有标题和副标题的默认字体大小,并且仅在文本较长且不适合包装器的情况下将其减小到较低..

最佳答案

由于在无法实际“看到”文本的情况下确定文本是否比其边界框宽似乎非常困难,因此这就是我想出的解决方案。

我使用了一张 1000 像素宽的图片并将其调整为 600。当然,您显然已经解决了所有这些问题。

我不太擅长写答案(尽管代码已经过测试并且确实有效)所以我希望这会有所帮助。

<?php
$FormAction = $_SERVER['PHP_SELF'];

if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {  // if form is submitted

// get original image
$fileName = $_FILES["ImageName"]["name"]; // The file name
$fileTempLoc = $_FILES["ImageName"]["tmp_name"]; // File in the PHP tmp folder
$type = strtolower(substr(strrchr($fileName,"."),1));
if($type == 'jpeg') { $type = 'jpg'; }

// Temporary upload image name
$original_image = $_FILES['ImageName']['tmp_name'];

// Name to save the image as - in this case the same as the original
$new_image = $_FILES['ImageName']['name'];

// Get the image dimensions
$uploaded_size = getimagesize($original_image);
$uploaded_imgw = $uploaded_size[0];
$uploaded_imgh = $uploaded_size[1];

// Maximum image width and height
$max_width = "600";
$max_height = "600";

// Thumbnail image width and height
$thumbnail_max_width = "100";
$thumbnail_max_height = "100";

// Check to see if we need to resize the image
if ($uploaded_imgw > 600 || $uploaded_imgh > 600) { // if image is larger than 600x600
// Resize image using GD2 cmd
// Get new dimensions
list($width_orig, $height_orig) = getimagesize($original_image);
$ratio_orig = $width_orig/$height_orig;
// resize our image proportionately maintaining its original aspect
if ($thumbnail_max_width/$thumbnail_max_height > $ratio_orig) {
   $width = $max_width*$ratio_orig; //576
   $height = $max_height;
} else {
   $height = $max_height/$ratio_orig; // 576
   $width = $max_width; //600
}
// Resample / Resize the image
$orig_image_p = imagecreatetruecolor($width, $height);

if($type == "gif" || $type == "png"){
    imagecolortransparent($orig_image_p, imagecolorallocate($orig_image_p, 0, 0, 0));
}
if($type == "jpg") {
    $temp_image = imagecreatefromjpeg($original_image);
}
if($type == "gif") {
    $temp_image = imagecreatefromgif($original_image);
}
if($type == "png") {
    $temp_image = imagecreatefrompng($original_image);
}

imagecopyresampled($orig_image_p, $temp_image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);

if($type == "jpg") {
    imagejpeg($orig_image_p, $original_image, 80);
}
if($type == "gif") {
    imagegif($orig_image_p, $original_image);
}
if($type == "png") {
    imagepng($orig_image_p, $original_image, 9);
}
move_uploaded_file($original_image, '../../Images/'.$new_image);
imagedestroy($temp_image);
imagedestroy($orig_image_p);
} else { // if image is smaller than 900x900
$small_image_p = imagecreatetruecolor($uploaded_imgw, $uploaded_imgh);

if($type == "gif" || $type == "png"){
    imagecolortransparent($small_image_p, imagecolorallocate($small_image_p, 0, 0, 0));
}

if($type == "jpg") {
    $small_temp_image = imagecreatefromjpeg($original_image);
}
if($type == "gif") {
    $small_temp_image = imagecreatefromgif($original_image);
}
if($type == "png") {
    $small_temp_image = imagecreatefrompng($original_image);
}

imagecopyresampled($small_image_p, $small_temp_image, 0, 0, 0, 0, $uploaded_imgw, $uploaded_imgh, $uploaded_imgw, $uploaded_imgh);

if($type == "jpg") {
    imagejpeg($small_image_p, $original_image, 80);
}
if($type == "gif") {
    imagegif($small_image_p, $original_image);
}
if($type == "png") {
    imagepng($small_image_p, $original_image, 9);
}
move_uploaded_file($original_image, '../../Images/'.$new_image);
imagedestroy($small_temp_image);
imagedestroy($small_image_p);
} // end if smaller than 600x600

// Get the image we will work with
$new_img_src = '../../Images/'.$new_image;
list($new_width, $new_height) = getimagesize($new_img_src);

if($type == 'jpg') {
    $im = imagecreatefromjpeg($new_img_src);
}
if($type == 'png') {
    $im = imagecreatefrompng($new_img_src);
}
if($type == 'gif') {
    $im = imagecreatefromgif($new_img_src);
}

// Create a blank canvas for our new image
$new_image_p = imagecreatetruecolor($new_width, $new_height);

if($type == "gif" || $type == "png"){
    imagecolortransparent($new_image_p, imagecolorallocate($new_image_p, 0, 0, 0));
}
if($type == 'jpg') {
    $new_temp_image = imagecreatefromjpeg($new_img_src);
}
if($type == 'png') {
    $new_temp_image = imagecreatefrompng($new_img_src);
}
if($type == 'gif') {
    $new_temp_image = imagecreatefromgif($new_img_src);
}

imagecopyresampled($new_image_p, $new_temp_image, 0, 0, 0, 0, $new_width, $new_height, $new_width, $new_height);

// set dimensions for our canvas
$adj_width = $new_width+40;
$adj_height = $new_height+120;

$bkgrd = imagecreatetruecolor($adj_width, $adj_height);
imagefilledrectangle($bkgrd, 0, 0, $adj_width, $adj_height, 0x000000);
$sx = imagesx($bkgrd)-imagesx($bkgrd)+20;
$sy = imagesy($bkgrd)-imagesy($bkgrd)+20;

// Place our original image on the canvas centered and 20px from the top
imagecopymerge($bkgrd, $new_image_p, $sx, $sy, 0, 0, imagesx($bkgrd), imagesy($bkgrd), 100);

// Save the image to file and free memory
if($type == "jpg") {
    imagejpeg($bkgrd, $new_img_src, 80);
}
if($type == "gif") {
    imagegif($bkgrd, $new_img_src);
}
if($type == "png") {
    imagepng($bkgrd, $new_img_src, 9);
}
imagedestroy($im);
imagedestroy($new_image_p);
imagedestroy($bkgrd);

//Now we create our text as images to be merged with our new image

// check width of bounding box
function calculateTextBox($text,$fontFile,$fontSize,$fontAngle) {
/************
simple function that calculates the *exact* bounding box (single pixel precision).
The function returns an associative array with these keys:
left, top:  coordinates you will pass to imagettftext
width, height: dimension of the image you have to create
*************/
    $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) - 1,
     "top"    => abs($minY) - 1,
     "width"  => $maxX - $minX,
     "height" => $maxY - $minY,
     "box"    => $rect
    );
}

$text_string = $_POST['TopLine']; //"This is a very long first line to see what happens if it is too long";
$font_ttf = "arial.ttf";
$font_size = 22;
$text_angle = 0;
$text_padding = 10; // Img padding - around text

$the_box = calculateTextBox($text_string, $font_ttf, $font_size, $text_angle);

$imgWidth = $the_box["width"] + $text_padding;
$imgHeight = $the_box["height"] + $text_padding;

$image = imagecreatetruecolor($imgWidth,$imgHeight);
imagefill($image, imagecolorallocate($image, 0, 0, 0));

$color = imagecolorallocate($image, 255, 255, 255);

imagettftext($image,
    $font_size,
    $text_angle,
    $the_box["left"] + ($imgWidth / 2) - ($the_box["width"] / 2),
    $the_box["top"] + ($imgHeight / 2) - ($the_box["height"] / 2),
    $color,
    $font_ttf,
    $text_string);

// save file
imagepng($image, '../../Images/NewTopImg.png', 9);

// destroy the image and start over
imagedestroy($image);

$text_string = $_POST['BottomLine']; //"This is a very long second line to see what happens if it is too long. Even a longer line than the first one.";
$font_ttf = "arial.ttf";
$font_size = 16;
$text_angle = 0;
$text_padding = 10; // Img padding - around text

$the_box = calculateTextBox($text_string, $font_ttf, $font_size,     $text_angle);

$imgWidth = $the_box["width"] + $text_padding;
$imgHeight = $the_box["height"] + $text_padding;

$image = imagecreatetruecolor($imgWidth,$imgHeight);
imagefill($image, imagecolorallocate($image, 0, 0, 0));

$color = imagecolorallocate($image, 255, 255, 255);

imagettftext($image,
    $font_size,
    $text_angle,
    $the_box["left"] + ($imgWidth / 2) - ($the_box["width"] / 2),
    $the_box["top"] + ($imgHeight / 2) - ($the_box["height"] / 2),
    $color,
    $font_ttf,
    $text_string);

// save file
imagepng($image, '../../Images/NewBottomImg.png', 9);

imagedestroy($image);

// Now merge the three images together
//function merge($filename_x, $filename_y, $filename_result) {

// Get dimensions for specified images
$filename_vs = '../../Images/'.$new_image;
$filename_x = '../../Images/NewTopImg.png';
$filename_y = '../../Images/NewBottomImg.png';
list($width_x, $height_x) = getimagesize($filename_x);
list($width_y, $height_y) = getimagesize($filename_y);
list($width_vs, $height_vs) = getimagesize($filename_vs);

// before we go any farther lets find out if our text is wider than our image
if($width_x > $new_width) { // if it is too wide lets resize it
    // create smaller image using GD2 cmd to the smallest side
    $line1_img_src = '../../Images/NewTopImg.png';
    $line1_img_path = '../../Images/NewTopImg.png';
    list($src_width, $src_height) = getimagesize($line1_img_src);

    $min = $new_width; // set our max width to that of the original image
    $ratio = $src_height/$src_width;
    $line1_width = $min;
    $Line1_height = round($min * $ratio);

    $blank_image_line1 = imagecreatetruecolor($line1_width, $Line1_height);

    imagecolortransparent($blank_image_line1, imagecolorallocate($blank_image_line1, 0, 0, 0));

    $image = imagecreatefrompng($line1_img_src);

    imagecopyresampled($blank_image_line1, $image, 0, 0, 0, 0, $line1_width, $Line1_height, $src_width, $src_height);

    imagepng($blank_image_line1, $line1_img_path, 9);

    imagedestroy($blank_image_line1);
    imagedestroy($image);

    // Because we resized the first line we need to get the new dimensions
    $filename_x = '../../Images/NewTopImg.png';
    list($width_x, $height_x) = getimagesize($filename_x);
    // End resize first line
}

// Now lets check line two
if($width_y > $new_width) { // if it is too wide lets resize it
    // create smaller image using GD2 cmd to the smallest side
    $line2_img_src = '../../Images/NewBottomImg.png';
    $line2_img_path = '../../Images/NewBottomImg.png';
    list($src_width, $src_height) = getimagesize($line2_img_src);

    $min = $new_width; // set our max width to that of the original image
    $ratio = $src_height/$src_width;
    $line2_width = $min;
    $line2_height = round($min * $ratio);

    $blank_image_line2 = imagecreatetruecolor($line2_width, $line2_height);

    imagecolortransparent($blank_image_line2, imagecolorallocate($blank_image_line2, 0, 0, 0));

    $image = imagecreatefrompng($line2_img_src);

    imagecopyresampled($blank_image_line2, $image, 0, 0, 0, 0, $line2_width, $line2_height, $src_width, $src_height);

    imagepng($blank_image_line2, $line2_img_path, 9);

    imagedestroy($blank_image_line2);
    imagedestroy($image);

    // Because we resized the second line we need to get the new dimensions
    $filename_y = '../../Images/NewBottomImg.png';
    list($width_y, $height_y) = getimagesize($filename_y);
    // End resize second line
}

// Create new image with desired dimensions
$image = imagecreatetruecolor($width_vs, $height_vs);

// Load images and then copy to destination image
if($type == "gif" || $type == "png"){
    imagecolortransparent($image, imagecolorallocate($image, 0, 0, 0));
}
if($type == 'jpg') {
    $image_vs = imagecreatefromjpeg($filename_vs);
}
if($type == 'png') {
    $image_vs = imagecreatefrompng($filename_vs);
}
if($type == 'gif') {
    $image_vs = imagecreatefromgif($filename_vs);
}
$image_x = imagecreatefrompng($filename_x);
$image_y = imagecreatefrompng($filename_y);

//set location for merged images
$vs_x = imagesx($image); // width of our completed image
$vs_y = imagesy($image);// height of our completed image
$x_x = $width_x; // width of the top line
$x_x = ($vs_x/2)-($x_x/2);
$x_y = $new_height+30; // height of the original img + 20px we dropped it from the top of the canvas + 10px more for spacing below our "picture" placed on the canvas
$y_x = $width_y; // width of the bottom line
$y_x = ($vs_x/2)-($y_x/2);
$y_y = $new_height+70; // height of the original img + 20px we dropped it from the top of the canvas + 40px more for spacing below the first line of text

imagecopy($image, $image_vs, 0, 0, 0, 0, $width_vs, $height_vs);
imagecopy($image, $image_x, $x_x, $x_y, 0, 0, $width_vs, $height_vs);
imagecopy($image, $image_y, $y_x, $y_y, 0, 0, $width_vs, $height_vs);


// set dimensions for our canvas
$adj_width = $new_width+40;
$adj_height = $new_height+120;

$bkgrd = imagecreatetruecolor($adj_width, $adj_height);
imagefilledrectangle($bkgrd, 0, 0, $adj_width, $adj_height, 0x000000);
$sx = imagesx($bkgrd)-imagesx($bkgrd)+20;
$sy = imagesy($bkgrd)-imagesy($bkgrd)+20;

// Place our original image on the canvas centered and 20px from the top
imagecopymerge($bkgrd, $new_image_p, $sx, $sy, 0, 0, imagesx($bkgrd),     imagesy($bkgrd), 100);

// Save the image to file and free memory
if($type == "jpg") {
    imagejpeg($image, $filename_vs, 80);
}
if($type == "gif") {
    imagegif($image, $filename_vs);
}
if($type == "png") {
    imagepng($image, $filename_vs, 9);
}

// Clean up
imagedestroy($image);
imagedestroy($image_x);
imagedestroy($image_y);
imagedestroy($image_vs);

//merge($filename_x, $filename_y, $filename_vs);

} // end if form submitted
?>
<table width="800" border="0" cellspacing="0" cellpadding="5" align="center">
  <tr>
<td><div id="FormContainer">
  <table width="100%" border="0" cellpadding="0" cellspacing="0">
    <tr>
      <td><div id="Heading">IMAGE UPLOAD</div></td>
      </tr>
    </table>
<form enctype="multipart/form-data" id="form1" name="form1" method="post" action="<?php echo $FormAction; ?>">
    <table border="0" align="center" cellpadding="5" cellspacing="0">
      <tr>
        <td colspan="2">Only JPG, JPEG, PNG and GIF files are allowed.</td>
        </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        </tr>
      <tr>
        <td><div align="right" class="Strong">File:</div></td>
        <td><input name="ImageName" type="file" id="ImageName" size="50" /></td>
        </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        </tr>
      <tr>
        <td nowrap="nowrap" class="ElementTitle"><div align="right">Line 1 Text:</div></td>
        <td><input name="TopLine" type="text" id="TopLine" value="This is a very long first line to see what happens if it is too long" size="75" maxlength="100" /></td>
        </tr>
      <tr>
        <td nowrap="nowrap" class="ElementTitle"><div align="right">Line 2 Text:</div></td>
        <td><input name="BottomLine" type="text" id="BottomLine" value="This is a very long second line to see what happens if it is too long. Even a longer line than the first one." size="75" maxlength="100" /></td>
      </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        </tr>
      <tr>
        <td colspan="2"><table width="150" border="0" align="center" cellpadding="5" cellspacing="0">
          <tr>
            <td><div align="center" style="width:80px; height:37px;">
              <input name="Submit" type="submit" class="Submit" value="Upload" />
            </div></td>
            <td><div align="center" style="width:75px; height:37px;">
              <input name="Submit22" type="reset" class="Submit" value="Reset" />
            </div></td>
          </tr>
        </table></td>
        </tr>
      <tr>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        </tr>
      </table><input type="hidden" name="MM_insert" id="MM_insert" value="form1">
  </form>
</div><!-- end form container -->
</td>
</tr>
  <tr>
    <td>&nbsp;</td>
  </tr>
</table>

基本上你正在做的是

  1. 为第一行和第二行创建两个图像
  2. 检查这些图片是否比您现有的图片宽 如果是的话
  3. 调整它们的大小以适合您的原始图像宽度
  4. 最后将所有三张图片合并为一张。

您可以在此处更改默认文本大小...$font_size = 22$font_size = 16 分别用于第一行和第二行。

不要忘记上传您的 ttf 字体文件并正确指向它。

最后,您可以在最后添加代码以在完成后删除您的两个临时文件。

我在此处修改和使用的 calculateTextBox 函数部分归功于 jodebrabec。 You can find it here

带有短文本的示例输出 This shows fonts at default size

带有长文本的示例输出 This shows same image with long text resized to fit

关于php - 按比例在图片上写文字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32250008/

相关文章:

javascript - Node.js + Express.js : express. 静态不提供图像(包含错误)

C# - 图片问题

用于注释文本的 Javascript 库?

php - Zend Paginator - 如何获取分页器中的第一个元素?

python - 在python中更改图像的hsv值

android - 查询文本文件到数据库中

java - 微调器文本不显示默认值,也不显示所选值

PHP 提前关闭连接。如果完成任何输出,脚本将挂起

PHP:如何按名称创建类?

php - 修复多维 foo[a][][b] 数组输入