我正在尝试将文本转换为图像。我已经这样做了,但在某些情况下,文本会超出图像框
单词“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);
谢谢。
最佳答案
问题是每个字符的宽度可能略有不同,例如 W 和 i。由于您无法按每行的字母数拆分字符串,因此您需要一种更准确的方法。
主要技巧是使用
imagettfbbox
它给出了使用 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;
}
;
?>
下面是工作代码示例:
我修改了这个函数 pixel_word_wrap 一点点。另外,修改了代码中的一些计算。现在正在为我提供正确计算边距的完美图像。我对代码不太满意,注意到有一个 $adjustment 变量,当您使用更大的字体大小时,它应该更大。我认为这归因于 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);
举个例子
您也可以使用等宽字体。等宽字体是一种字体,其字母和字符各自占据相同数量的水平空间。
关于php - 用于在 php 中转换为图像的开箱即用的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39901581/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我有一大串格式化数据(例如JSON),我想使用Psychinruby同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
当我使用has_one时,它工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290
我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/
我正在使用带有Rails的Devise,我想添加一个方法“getAllComments”,所以我这样写:classUser在我的Controller中:defdashboard@user=current_user@comments=@user.getAllComments();end当我访问我的url时,我得到了undefinedmethod`getAllComments'for#我做错了什么?谢谢 最佳答案 因为getAllComments是一个类方法,而您正试图将其作为实例方法访问。您要么需要访问它:User.getAllCom