按比例

时间:2015-08-27 12:55:53

标签: php image text gd

所以我有了图片:enter image description here

我想在图像下添加文字(制作消极图像)。所以我将它扩展到高度并在底部增加额外的高度。我需要的是写下文字:

  

热门文字

     

底部较长的文字

我也需要这些文字以图像为中心。所以输出应该是: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'])
        )
    );
}

它应该具有标题和副标题的默认字体大小,并且只有在文本较长且不适合包装的情况下才将其降低。

3 个答案:

答案 0 :(得分:4)

由于似乎很难确定文本是否比其边界框宽,而不能实际上&#34;参见&#34;它,这是我提出的解决方案。

我使用了1000px宽的图像并将其调整为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. 最后将所有三张图片合并为一张。
  5. 您可以在此处更改默认文字尺寸... $font_size = 22$font_size = 16分别为第一行和第二行。

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

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

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

    短文This shows fonts at default size

    的示例输出

    长文本This shows same image with long text resized to fit

    的示例输出

答案 1 :(得分:0)

为了便于文本对齐,您需要使用imagettfbbox()命令。当给出正确的参数时,它将返回数组中待制作文本字段的边界,这将允许您计算需要用于居中或对齐文本的x和y坐标。

横向居中示例:

<?php

$tb = imagettfbbox(17, 0, 'airlock.ttf', 'Hello world!');

?>

$tb would contain:

Array
(
    [0] => 0 // lower left X coordinate
    [1] => -1 // lower left Y coordinate
    [2] => 198 // lower right X coordinate
    [3] => -1 // lower right Y coordinate
    [4] => 198 // upper right X coordinate
    [5] => -20 // upper right Y coordinate
    [6] => 0 // upper left X coordinate
    [7] => -20 // upper left Y coordinate
)

对于水平对齐,我们需要从图像的宽度中减去“文本框”的宽度{$ tb 2或$ tb [4]},然后减去2。

假设你的图像宽200像素,你可以这样做:

<?php

$x = ceil((200 - $tb[2]) / 2); // lower left X coordinate for text
//array imagettftext ( resource $image , float $size , float $angle , int $x , int $y , int $color , string $fontfile , string $text )
imagettftext($im, 17, 0, $x, $y, $tc, 'airlock.ttf', 'Hello world!'); // write text to image
?>

这将为您的文本提供完美的水平中心对齐,给出或取1个像素

<小时/> 参考:imagettftextimagettfbbox

答案 2 :(得分:0)

我不完全确定这是你要找的东西,但是writeCenteredText()会在给定的行$ y处写中心文本。如果文本对于该行太长,则它将换行到下一行并将该文本居中。如果我不明白这个问题,请告诉我。

Date date1 = sdf.parse("2015-12-01");
Date date2 = sdf.parse("2010-01-01");

示例输出:

enter image description here