การวัดข้อความรูปภาพ PHP GD

ฉันกำลังพยายามเขียนสคริปต์ที่สร้างรูปภาพ PNG จากข้อความ ขนาด และแบบอักษรที่ได้รับในอาร์กิวเมนต์ $_GET แต่ฉันไม่สามารถทราบวิธีทำให้ขนาดของรูปภาพพอดีกับข้อความทุกประการ ฉันใช้ imagettfbox อยู่แล้ว:

$widthPx = abs($ttfBox[2] - $ttfBox[0]);
$heightPx = abs($ttfBox[1] - $ttfBox[7]);

ซึ่งอาจทำให้ฉันวัดได้ถูกต้อง แต่เมื่อฉันวาดข้อความ มันออกนอกขอบเขตนิดหน่อย ตัวอย่างเช่น หากฉันพยายามวาด "a" โดยใช้ arial.ttf มันจะอยู่นอกขอบเขตอย่างน้อย 5 พิกเซล มีวิธีวาดข้อความแบบอักษรให้พอดีกับภาพโดยไม่ต้องทดสอบหรือไม่?

$text = $_GET["text"];

$cmToPixel = 15.0;

$sizeCm = floatval($_GET["sizeCm"]);
$sizePx = $cmToPixel * $sizeCm;
$fontFile = "fonts/".pathinfo($_GET["font"])["filename"].".".pathinfo($_GET["font"])["extension"];

if(!file_exists($fontFile)){
    die;
}
$ttfBox = imagettfbbox($sizePx, 0, $fontFile, $text);

$widthPx = abs($ttfBox[2] - $ttfBox[0]);
$heightPx = abs($ttfBox[1] - $ttfBox[7]);

$image = ImageCreate($widthPx, $heightPx);

$x = $ttfBox[0] + (imagesx($image)-$ttfBox[4] )/ 2 - 0;
$y = $ttfBox[1] + (imagesy($image) / 2) - ($ttfBox[5] / 2) - 5;

ImageRectangle($image,0,0,imagesx($image),imagesy($image), ImageColorAllocate($image,255,255,255));
imagettftext($image, $sizePx,0,$x,$y, ImageColorAllocate($image, 0, 0, 0), $fontFile, $text);

header("Content-Type: image/png");
ImagePng($image);
ImageDestroy($image);

person user1563232    schedule 07.02.2015    source แหล่งที่มา
comment
คุณได้ดูตัวอย่างที่ให้มาพร้อมกับคู่มือนี้แล้วหรือยัง? อาจช่วยได้: imagettfbbox — ใส่กรอบขอบของข้อความโดยใช้แบบอักษร TrueType   -  person Ryan Vincent    schedule 08.02.2015
comment
ฉันได้ดูตัวอย่างทั้งหมดแล้ว ดูเหมือนว่าฉันต้องตัดภาพโดยการทดสอบสีพิกเซล เนื่องจากข้อความที่ส่งออกนั้นไม่ถูกต้องเกินไป ทุกข้อความมีออฟเซ็ตที่แตกต่างกันเมื่อฉันวาด ดังนั้นมันจึงอยู่นอกขอบเขตเสมอ   -  person user1563232    schedule 08.02.2015
comment
เป็นไปได้ไหมที่จะโพสต์โค้ดที่คุณใช้เพื่อให้เราทดลองใช้งานได้?   -  person Ryan Vincent    schedule 08.02.2015
comment
ฉันเพิ่มโค้ดแล้ว ฉันลองสิ่งต่าง ๆ สำหรับพิกัด x และ y ของข้อความแล้ว ไม่ได้สร้างความแตกต่างเลย อาจดีกว่าถ้าลองใช้วิธีอื่น เช่น ตัดแต่งภาพตามสีพิกเซล   -  person user1563232    schedule 08.02.2015
comment
ปัญหาคือ GD ไม่ได้ใช้ 'การวัดแบบอักษร' ซึ่งให้ค่าและการชดเชยจาก 'พื้นฐาน' ของอักขระ Imagack ใช้ค่าเหล่านี้ดังนั้นจึงแม่นยำยิ่งขึ้น โดยพื้นฐานแล้วใน GD คุณจะต้องมีปัจจัย 'เหลวไหล' บางอย่างที่ขึ้นอยู่กับ 'ตระกูลแบบอักษร' การทำให้ 'imagick' ทำงานบน 'windows' นั้น 'ไม่สนุก' และฉันยังไม่ได้จัดการมันเลย   -  person Ryan Vincent    schedule 08.02.2015


คำตอบ (1)


การคำนวณของคุณจากกรอบขอบเขตปิดอยู่ วิธีนี้ได้ผล:

<?php
/*-
 * $MirOS: www/mk/ttf2png,v 1.8 2016/11/02 16:16:26 tg Exp $
 *-
 * Copyright (c) 2009, 2016
 *  mirabilos <[email protected]>
 *
 * Provided that these terms and disclaimer and all copyright notices
 * are retained or reproduced in an accompanying document, permission
 * is granted to deal in this work without restriction, including un-
 * limited rights to use, publicly perform, distribute, sell, modify,
 * merge, give away, or sublicence.
 *
 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
 * the utmost extent permitted by applicable law, neither express nor
 * implied; without malicious intent or gross negligence. In no event
 * may a licensor, author or contributor be held liable for indirect,
 * direct, other damage, loss, or other issues arising in any way out
 * of dealing in the work, even if advised of the possibility of such
 * damage or existence of a defect, except proven that it results out
 * of said person's immediate fault when using the work as intended.
 *-
 * Syntax:
 *  php ttf2png [text [size [/path/to/font.ttf]]] >out.png
 */

if (!function_exists('gd_info'))
    die("Install php5-gd first.");
$gd = gd_info();
if ($gd["FreeType Support"] == false)
    die("Compile php5-gd with FreeType 2 support.");


$font = "/usr/src/www/files/FNT/GenI102.ttf";
$fontsize = 30;
$text = "EINVAL";

if (isset($argv[1]))
    $text = $argv[1];
if (isset($argv[2]))
    $fontsize = $argv[2];
if (isset($argv[3]))
    $font = $argv[3];


// Get bounding box
$bbox = imageftbbox($fontsize, 0, $font, $text);
// Transform coordinates into width+height and position
$ascender = abs($bbox[7]);
$descender = abs($bbox[1]);
$size_w = abs($bbox[0]) + abs($bbox[2]);
$size_h = $ascender + $descender;
$x = -$bbox[0];
$y = $ascender;

// Create image
$im = imagecreatetruecolor($size_w, $size_h);
// Allocate colours
$bgcol = imagecolorallocate($im, 0x24, 0x24, 0x24);
$fgcol = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);

// Fill image with background colour
imagefilledrectangle($im, 0, 0, $size_w - 1, $size_h - 1, $bgcol);
// Render text into image
imagefttext($im, $fontsize, 0, $x, $y, $fgcol, $font, $text);

// Convert true colour image (needed for above) to palette image
imagetruecolortopalette($im, FALSE, 256);

// Output created image
imagepng($im, NULL, 9);

exit(0);

หากคุณเขียนหลายสตริงในบรรทัดเดียวกันและจำเป็นต้องคำนวณความสูงรวมและออฟเซ็ตของเส้น ค่าสูงสุดของตัวขึ้นทั้งหมดบวกค่าสูงสุดของตัวจากมากไปน้อยทั้งหมด และ $y สำหรับการเรียก ทั้งหมด imagefttext เส้นนี้เป็นค่าสูงสุดของผู้ขึ้นทั้งหมดเช่นเดียวกัน

person mirabilos    schedule 02.11.2016
comment
@MarcielFonseca นั่นคือ PNG บันทึกลงในไฟล์หรือไปป์ผ่าน xloadimage stdin หรือโปรแกรมดูรูปภาพอื่น ๆ ที่เหมาะสม เป็นเรื่องปกติที่เครื่องมือ Unix จะดัมพ์ผลลัพธ์ไปที่ stdout เพื่อให้สามารถใช้เป็นตัวกรองผ่านไพพ์ได้ - person mirabilos; 25.03.2017