用于在php中转换为图像的开箱即用文本

Lui*_*uis 11 php fonts gd truetype imagettftext

我正在尝试将文本转换为图像.我已经这样做了,但有些情况下文本不在图像框中图片

"The"这个词的"e"被删除了.我尝试过减小字体大小或增加图像的宽度,但在某些情况下,这会再次发生在另一个文本中.这是代码:

    $new_line_position = 61;        
    $angle = 0;        
    $left = 20;
    $top = 45;
    $image_width = 1210;
    $image_line_height = 45;                

    $content_input = wordwrap($content_input,    $new_line_position, "\n", true);  

    $lineas = preg_split('/\\n/', $content_input);
    $lines_breaks = count($lineas); 
    $image_height = $image_line_height * $lines_breaks;
    $im = imagecreatetruecolor($image_width, $image_height);

    // Create some colors
    $white = imagecolorallocate($im, 255, 255, 255);        
    $black = imagecolorallocate($im, 0, 0, 0);
    imagefilledrectangle($im, 0, 0, $image_width, $image_height, $white);   

   $font_ttf =  public_path().'/fonts/'.$ttf_font;                     


    foreach($lineas as $linea){
        imagettftext($im, $font_size, $angle, $left, $top, $black, $font_ttf, $linea);        
        $top = $top + $image_line_height;
    }

    // Add the text                        
    imagepng($im);                
    imagedestroy($im);
Run Code Online (Sandbox Code Playgroud)

谢谢.

Paw*_*iel 9

问题是每个字符的宽度可能略有不同,例如Wi.因为你不能按字母数字每行分割一个字符串,你需要一个更准确的方法.

主要技巧是使用

imagettfbbox
Run Code Online (Sandbox Code Playgroud)

它使用TrueType字体给出文本的边界框,从中可以获得文本将使用的实际宽度.

这是一个在http://php.net/manual/en/function.wordwrap.php找到的像素完美分割函数, 用它代替wordwrap并传递额外的值,如图像宽度,字体大小和字体路径

<?php

/**
 * Wraps a string to a given number of pixels.
 * 
 * This function operates in a similar fashion as PHP's native wordwrap function; however,
 * it calculates wrapping based on font and point-size, rather than character count. This
 * can generate more even wrapping for sentences with a consider number of thin characters.
 * 
 * @static $mult;
 * @param string $text - Input string.
 * @param float $width - Width, in pixels, of the text's wrapping area.
 * @param float $size - Size of the font, expressed in pixels.
 * @param string $font - Path to the typeface to measure the text with.
 * @return string The original string with line-breaks manually inserted at detected wrapping points.
 */
function pixel_word_wrap($text, $width, $size, $font)
{

    #    Passed a blank value? Bail early.
    if (!$text)
        return $text;

    #    Check if imagettfbbox is expecting font-size to be declared in points or pixels.
    static $mult;
    $mult = $mult ?: version_compare(GD_VERSION, '2.0', '>=') ? .75 : 1;

    #    Text already fits the designated space without wrapping.
    $box = imagettfbbox($size * $mult, 0, $font, $text);
    if ($box[2] - $box[0] / $mult < $width)
        return $text;

    #    Start measuring each line of our input and inject line-breaks when overflow's detected.
    $output = '';
    $length = 0;

    $words      = preg_split('/\b(?=\S)|(?=\s)/', $text);
    $word_count = count($words);
    for ($i = 0; $i < $word_count; ++$i) {

        #    Newline
        if (PHP_EOL === $words[$i])
            $length = 0;

        #    Strip any leading tabs.
        if (!$length)
            $words[$i] = preg_replace('/^\t+/', '', $words[$i]);

        $box = imagettfbbox($size * $mult, 0, $font, $words[$i]);
        $m   = $box[2] - $box[0] / $mult;

        #    This is one honkin' long word, so try to hyphenate it.
        if (($diff = $width - $m) <= 0) {
            $diff = abs($diff);

            #    Figure out which end of the word to start measuring from. Saves a few extra cycles in an already heavy-duty function.
            if ($diff - $width <= 0)
                for ($s = strlen($words[$i]); $s; --$s) {
                    $box = imagettfbbox($size * $mult, 0, $font, substr($words[$i], 0, $s) . '-');
                    if ($width > ($box[2] - $box[0] / $mult) + $size) {
                        $breakpoint = $s;
                        break;
                    }
                }

            else {
                $word_length = strlen($words[$i]);
                for ($s = 0; $s < $word_length; ++$s) {
                    $box = imagettfbbox($size * $mult, 0, $font, substr($words[$i], 0, $s + 1) . '-');
                    if ($width < ($box[2] - $box[0] / $mult) + $size) {
                        $breakpoint = $s;
                        break;
                    }
                }
            }

            if ($breakpoint) {
                $w_l = substr($words[$i], 0, $s + 1) . '-';
                $w_r = substr($words[$i], $s + 1);

                $words[$i] = $w_l;
                array_splice($words, $i + 1, 0, $w_r);
                ++$word_count;
                $box = imagettfbbox($size * $mult, 0, $font, $w_l);
                $m   = $box[2] - $box[0] / $mult;
            }
        }

        #    If there's no more room on the current line to fit the next word, start a new line.
        if ($length > 0 && $length + $m >= $width) {
            $output .= PHP_EOL;
            $length = 0;

            #    If the current word is just a space, don't bother. Skip (saves a weird-looking gap in the text).
            if (' ' === $words[$i])
                continue;
        }

        #    Write another word and increase the total length of the current line.
        $output .= $words[$i];
        $length += $m;
    }

    return $output;
}
;

?>
Run Code Online (Sandbox Code Playgroud)

下面是工作代码示例:我pixel_word_wrap稍微修改了这个函数.此外,修改了代码中的一些计算.现在正在给我一个正确计算边距的完美图像.我不是很满意代码注意到有一个$调整变量,当你使用更大的字体大小时应该更大.我认为这取决于imagettfbbox功能上的不完美.但这是一种实用的方法,适用于大多数字体大小.

<?php

$angle = 0;
$left_margin = 20;
$top_margin = 20;
$image_width = 1210;
$image_line_height = 42;
$font_size = 32;
$top = $font_size + $top_margin;

$font_ttf = './OpenSans-Regular.ttf';

$text = 'After reading Mr. Gatti`s interview I finally know what bothers me so much about his #elenaFerrante`s unamsking. The whole thing is about him, not the author, not the books, just himself and his delusion of dealing with some sort of unnamed corruption';$adjustment=  $font_size *2; //

$adjustment=  $font_size *2; // I think because imagettfbbox is buggy adding extra adjustment value for text width calculations,

function pixel_word_wrap($text, $width, $size, $font) {

  #    Passed a blank value? Bail early.
  if (!$text) {
    return $text;
  }


  $mult = 1;
  #    Text already fits the designated space without wrapping.
  $box = imagettfbbox($size * $mult, 0, $font, $text);

  $g = $box[2] - $box[0] / $mult < $width;

  if ($g) {
    return $text;
  }

  #    Start measuring each line of our input and inject line-breaks when overflow's detected.
  $output = '';
  $length = 0;

  $words = preg_split('/\b(?=\S)|(?=\s)/', $text);
  $word_count = count($words);
  for ($i = 0; $i < $word_count; ++$i) {

    #    Newline
    if (PHP_EOL === $words[$i]) {
      $length = 0;
    }

    #    Strip any leading tabs.
    if (!$length) {
      $words[$i] = preg_replace('/^\t+/', '', $words[$i]);
    }

    $box = imagettfbbox($size * $mult, 0, $font, $words[$i]);
    $m = $box[2] - $box[0] / $mult;

    #    This is one honkin' long word, so try to hyphenate it.
    if (($diff = $width - $m) <= 0) {
      $diff = abs($diff);

      #    Figure out which end of the word to start measuring from. Saves a few extra cycles in an already heavy-duty function.
      if ($diff - $width <= 0) {
        for ($s = strlen($words[$i]); $s; --$s) {
          $box = imagettfbbox($size * $mult, 0, $font,
            substr($words[$i], 0, $s) . '-');
          if ($width > ($box[2] - $box[0] / $mult) + $size) {
            $breakpoint = $s;
            break;
          }
        }
      }

      else {
        $word_length = strlen($words[$i]);
        for ($s = 0; $s < $word_length; ++$s) {
          $box = imagettfbbox($size * $mult, 0, $font,
            substr($words[$i], 0, $s + 1) . '-');
          if ($width < ($box[2] - $box[0] / $mult) + $size) {
            $breakpoint = $s;
            break;
          }
        }
      }

      if ($breakpoint) {
        $w_l = substr($words[$i], 0, $s + 1) . '-';
        $w_r = substr($words[$i], $s + 1);

        $words[$i] = $w_l;
        array_splice($words, $i + 1, 0, $w_r);
        ++$word_count;
        $box = imagettfbbox($size * $mult, 0, $font, $w_l);
        $m = $box[2] - $box[0] / $mult;
      }
    }

    #    If there's no more room on the current line to fit the next word, start a new line.
    if ($length > 0 && $length + $m >= $width) {
      $output .= PHP_EOL;
      $length = 0;

      #    If the current word is just a space, don't bother. Skip (saves a weird-looking gap in the text).
      if (' ' === $words[$i]) {
        continue;
      }
    }

    #    Write another word and increase the total length of the current line.
    $output .= $words[$i];
    $length += $m;
  }

  return $output;
}


$out = pixel_word_wrap($text, $image_width -$left_margin-$adjustment,
  $font_size, $font_ttf);


$lineas = preg_split('/\\n/', $out);
$lines_breaks = count($lineas);
$image_height = $image_line_height * $lines_breaks;
$im = imagecreatetruecolor($image_width, $image_height + $top);

// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, $image_width, $image_height + $top, $white);


foreach ($lineas as $linea) {
  imagettftext($im, $font_size, $angle, $left_margin, $top, $black, $font_ttf,
    $linea);
  $top = $top + $image_line_height;
}


header('Content-Type: image/png');
imagepng($im);
Run Code Online (Sandbox Code Playgroud)

这是一个例子

在此输入图像描述 在此输入图像描述

您也可以使用等宽字体.等宽字体是一种字体,其字母和字符各自占据相同数量的水平空间.