I am using fpdf to create pdf from data in MySql table dynamically. And I am printing it using MultiCell() function. My Problem is I want it to auto adjust the line height of the text. I have read the documentation at the site but it only tells about auto adjust width. But I could not find any solution for line height auto adjust. Is there any way to do so. What may be the alternate ways? Please help. Here is the piece of the code. :-
<?php session_start();
include 'conn.php';
$table=$_SESSION["name"];
$testid=$_SESSION["id"];
$stuid=$_SESSION["stuid"];
$ans=$_SESSION["score1"];
//pdf creation
require('../fpdf/fpdf.php');
class PDF extends FPDF
{
function Header()
{
global $title;
$this->Image('../fpdf/logo.JPG',10,10,200);
// Arial bold 15
$this->SetFont('Arial','B',15);
// Calculate width of title and position
$w = $this->GetStringWidth($title)+6;
$this->SetX((210-$w)/2);
// Colors of frame, background and text
// Thickness of frame (1 mm)
$this->SetLineWidth(1);
// Title
// Line break
$this->Ln(20);
}
function Footer()
{
// Position at 1.5 cm from bottom
$this->SetY(-15);
// Arial italic 8
$this->SetFont('Arial','I',8);
// Text color in gray
$this->SetTextColor(128);
// Page number
$this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
}
function ChapterTitle($num, $label)
{
// Arial 12
$this->SetFont('Arial','',12);
// Background color
$this->SetFillColor(200,220,255);
// Title
$this->Cell(0,6,"Chapter $num : $label",0,1,'L',true);
// Line break
$this->Ln(4);
}
function ChapterBody($file)
{
// Read text file
$txt = file_get_contents($file);
// Times 12
$this->SetFont('Times','',12);
// Output justified text
$this->MultiCell(0,5,$txt);
// Line break
$this->Ln();
// Mention in italics
$this->SetFont('','I');
$this->Cell(0,5,'(end of excerpt)');
}
function PrintChapter($num, $title, $file)
{
$this->AddPage();
$this->ChapterTitle($num,$title);
$this->ChapterBody($file);
}
}
$pdf = new PDF();
$pdf->SetAuthor('OSP Classes');
$pdf->AddPage();
$x=1;
$i=0;
$sql1=mysql_query("select * from $table") or die (mysql_error());
while($result1=mysql_fetch_row($sql1))
{
$pdf->SetFont('Arial','B',14);
$pdf->MultiCell(0,10,'Ques No.'.$x .'.'. $result1[1]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 1.'. $result1[2]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 2.'. $result1[3]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 3.'. $result1[4]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 4.'. $result1[5]);
$pdf->Ln(10);
$pdf->MultiCell(0,0,'Right Ans . '. $result1[6].' '.'Your Ans . '. $ans[$i]);
$pdf->Ln(20);
$x++;
$i++;
}
$pdf->Output();
?>
Auto line height is not possible in FPDF MultiCell. As This page explains, Multicell creates a cell for each line of text you print. The 2e argument (h) is the height of each cell. (the line height).
Is there a better solution?
Yes there is. The people from TCPDF has taken the FPDF class and extended/improved it. They support HTML output. There you can use html for your outputs. Maybe you can use that.
$line_height = 5;
$width = 189;
$text = ("Your text goes here");
$height = (ceil(($pdf->GetStringWidth($text) / $width)) * $line_height);
$pdf->Multicell($width,$height,$text,1,1);
You can play with the values of $line_height and $width to fit with your font/margins/whatever you need to do, but the formula for height will calculate the number of lines needed and multiply that number by the height of each line.
I had the same issue and searched for awhile for a solution. Finally came to a relatively simple answer:
function GetMultiCellHeight($w, $txt, $pdf)
{
$height = 1;
$strlen = strlen($txt);
$wdth = 0;
for ($i = 0; $i <= $strlen; $i++) {
$char = substr($txt, $i, 1);
$wdth += $pdf->GetStringWidth($char);
if($char == "\n"){
$height++;
$wdth = 0;
}
if($wdth >= $w){
$height++;
$wdth = 0;
}
}
return $height;
}
you can use this code to solve this problem. Here the concept is only if string size greater than your cell width then font size will reduce.
$pdf->CellFit(30,20,"This is long string message.",1,0,'C',0,'',1,0);
check this URL
how to auto adjust cell width in fpdf using php and mysql
I was looking for a sophisticated solution for a while and could not find it.
I ended up just playing with the cell's width and height.
I discovered hat FPDF will play with the available space and based on that space it decides how much space goes in between lines.
So, considering the maximum possible amount of characters in my string, I could figure out how much space would be in between lines.
It works
Related
I have this task working great! I have successfully wrote text to an image then displayed the image using php, however the problem I'm running into is getting the font size perfect and to fit within a contained area. Im using imagettftext()
I'm getting this to work however when i move the text to the desired location im manually changing the font to then get it to fit. I would like to text to perfectly fill a "box" inside the image.
Here is my code
Main.php
check out the promo code below<br />
<img src="imagem.php?promo=DISH120" alt="" />
imagem.php
$font = 'font-type.ttf';
$rImg = ImageCreateFromJPEG( "test.jpg" );
$color = imagecolorallocate($rImg, 255, 255, 255);
imagettftext($rImg, 20, 0, 660, 130, $color, $font, urldecode($_GET['promo']));
header('Content-type: image/jpeg');
imagejpeg($rImg, NULL,100);
Here is the image im writing
i want the text to write to the bottom right next to code, however when i make the font big enough to match the CODE height it way to wide.
ADDITION
<?php
function makeTextBlock($text, $fontfile, $fontsize, $width)
{
$words = explode(' ', $text);
$lines = array($words[0]);
$currentLine = 0;
for($i = 1; $i < count($words); $i++)
{
$lineSize = imagettfbbox($fontsize, 0, $fontfile, $lines[$currentLine] . ' ' . $words[$i]);
if($lineSize[2] - $lineSize[0] < $width)
{
$lines[$currentLine] .= ' ' . $words[$i];
}
else
{
$currentLine++;
$lines[$currentLine] = $words[$i];
}
}
return implode("\n", $lines);
}
?>
I found this function re formats a text string into a text block of a given width, this is kinda what im trying to achieve however, im not sure how to integrate this. I want a box which width and height never change that will be filled with text that its character count will change.
This sounds like an issue with the font you're using. Try to make sure that the font matches the font of the text in the image, so that when you increase the size of the font to fit the image, it doesn't go too wide.
Other things I'd point out:
Based on what you're doing, I don't recommend a $_GET parameter.
You should remove the image from memory once you're done with it, like this: imagedestroy($rImg);
I am creating images with some text, when rotation is 0 then its fine but when rotation is > 0 then image looks are bad due to text alignment, because by default alignment is left.Since each and every value is dynamic so we can not fix it,please help me.
$message = 'Thanks, Deep, for making time to have a coffee today Purushottam';
$no_of_characters_line = $temp_data['no_of_characters_line'];
$lines = explode('|', wordwrap($message, $no_of_characters_line, '|'));
// Starting Y position and X position
$y = $temp_data['position_from_top'];
$x = $temp_data['position_from_left'];
$font_size = $temp_data['font_size'];
$rotation_angle = $temp_data['rotation'];
$line_height = $temp_data['line_height'];
foreach ($lines as $line)
{
imagettftext($im, $font_size,$rotation_angle, $x, $y, $black, $font, $line);
// Increment Y so the next line is below the previous line
$y += $line_height;
}
I am also attaching example template.
You can use imagettfbbox to calculate the string size in pixels. Then, with the width you will be able calculate the offset required to align the text to the right. Also, check out the imagettftext documentation for some examples of text alignment.
I'm trying to go through the code of TCPDF to understand how it calculates the height of the text to be rendered, but it's too much for me to handle without asking.
What I want to know: in the PDF from example 5 http://www.tcpdf.org/examples/example_005.pdf it gives the cell a yellow background. I'm guessing that at the basic level, it first draws a box with this fill color, then adds the text, so what method is it calling to get the height of the text to know the height of the box to fill?
I can see from the example code that MultiCell() is the entry point, but it's not clear what's the method it calls to get the height of the text. I pasted the code for MultiCell() in this pastebin
http://pastebin.com/A1niGrQG
Anyone knows how to trace this, because doing it by hand and looking through the code isn't working at all for me.
TCPDF (at least the latest version) includes the method getStringHeight() which get the estimated height needed for printing a simple text string using the Multicell() method.
Additionally, the getNumLines() method gives you the estimatad number of lines.
Check the source code documentation at http://www.tcpdf.org for further information.
The cell is being drawn by MultiCell:
http://www.tcpdf.org/examples/example_005.phps
$pdf->MultiCell(55, 5, '[LEFT] '.$txt, 1, 'L', 1, 0, '', '', true);
and from: http://api.joomla.org/com-tecnick-tcpdf/TCPDF.html
int MultiCell (float $w, float $h, string $txt, [mixed $border = 0], [string $align = 'J'], [int $fill = 0], [int $ln = 1], [int $x = ''], [int $y = ''], [boolean $reseth = true], [int $stretch = 0])
So as you can see, the first two values are statically assigning a width (55) and a height (5) to the MultiCell
Additionally:
// create new PDF document
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
You can see the unit of measurement is the program/class default PDF_UNIT
The font size is then set with
$pdf->SetFont('times', '', 10);
(or just use SetFontSize for the size only)
Just as a very simple proof of concept for what i said in my last comment on my other answer...
** You need to use a monospaced font and a line height equal to your text height (that or modify the code for line height instead of text height) fairly simple fix...
You also have to figure out your aproximate monospaced width.. Best thing to do is use a capitol M (M is the widest char - so monospaced chars are set to this width..)
<html><head></head><body style="font-family:'Courier New', Courier, monospace; line-height:12px;">
<?php
//If you are using a monospace font, this kinda works
$divWidth = 300; // in px;
$fontSize = 12; // (in px);
$fontWidth = 7; // in px - aprox monospace font width
$lineChars = floor($divWidth / $fontWidth);
$text = <<<EOT
MMMMMMMMMM (capital M is the widest character)I'm trying to go through the code of TCPDF to understand how it calculates the height of the text to be rendered, but it's too much for me to handle without asking.
What I want to know: in the PDF from example 5 it gives the cell a yellow background. I'm guessing that at the basic level, it first draws a box with this fill color, then adds the text, so what method is it calling to get the height of the text to know the height of the box to fill?
I can see from the example code that MultiCell() is the entry point, but it's not clear what's the method it calls to get the height of the text. I pasted the code for MultiCell() in this pastebin
EOT;
$wrappedText = wordwrap($text, $lineChars, "LINEHERE");
$lines = substr_count($wrappedText, "LINEHERE");
$newlines = substr_count($text, "\n");
$text = str_replace("\n", "<br>",$text);
$lines += $newlines;
$divHeight = $lines * $fontSize;
echo "With a width of: " . $divWidth . "<br>";
echo "Number of Lines: " . $lines . "<br>";
echo "Height Required: " . $divHeight . "px<br>";
echo "Wrapped Text at: " . $lineChars . " characters<br><br>";
$divsize = "width:$divWidth px; height:$divHeight px; font-size:$fontSize px; ";
$outStr = "<div style='overflow:auto; display:inline-block; background-color:aqua; $divsize'>$text</div>";
$outStr .= "<div style=' display:inline-block; background-color:fuchsia; $divsize'> </div>";
echo $outStr;
?>
</body></html>
I have a line of text that i need to wrap and center in a GD image. I am using a ttf font as well. Can anything give me some assistance please?
I have managed to get some text to wrap doing the following, but now i need to get it to center:
function wrap($fontSize, $angle, $fontFace, $string, $width){
$ret = "";
$arr = explode(' ', $string);
foreach ( $arr as $word ){
$teststring = $ret.' '.$word;
$testbox = imagettfbbox($fontSize, $angle, $fontFace, $teststring);
if ( $testbox[2] > $width ){
$ret.=($ret==""?"":"\n").$word;
} else {
$ret.=($ret==""?"":' ').$word;
}
}
return $ret;
}
User valentijn de Pagter provides, on php net manual, a nice function to calculate the box (I see you're using imagettfbbox(), indeed) and from the array it returns calculate how to center text. You can find it here:
center text with imagettfbbox
To center both horizontally and vertically: get half height from imagettfbbox of whole text (with new lines) and substract it from half height of your image ($start_x).
Now split text by new lines, create ttfbox for every line and get it's height ($h) and half width ($w). Draw line starting from half image width + $w and $start_x, add $h to $start_x, repat until all lines are written.
This is what I did. using the imagettftext function, you can add new line marks and continue on to the next line. You can add \n to the string after a certain amount of characters. This example will only break on spaces, so words won't get cut off.
$description=$property['description'];
$len=strlen($description);
$str="";
$c=0;
for($i=0;$i<$len;$i++){
$chr=substr($description,$i,1);
$str.=$chr;
if($c>40 && $chr==" ") {
$str.="\n";
$c=0;
}
$c++;
}
$result=$str;
imagettftext($img, 15, 0, $x - 60, $descmgn, $textcolor, $font, $result);
Just for fun I've been looking at how to use the GD library to create a colour palette from an image. So far I've used GD to resize a user uploaded image to an appropriate size for displaying on a webpage.
Now I'd like to be able to get about five or so different colours from the image that represent the range of colours present in it. Once I've done that I'd like to generate a complementary palette based upon those colours, which I can then use to colour different elements on the page.
Any help I can get about how I would find the initial colour palette would be much appreciated!
EDIT:
I've come to my own solution which you can see below.
Well I've spent a couple of days fiddling around and this is how I managed to build my colour palette. Its worked fairly well for me and you can change the size of the colour palette to return more or less colours from the image.
// The function takes in an image resource (the result from one
// of the GD imagecreate... functions) as well as a width and
// height for the size of colour palette you wish to create.
// This defaults to a 3x3, 9 block palette.
function build_palette($img_resource, $palette_w = 3, $palette_h = 3) {
$width = imagesx($img_resource);
$height = imagesy($img_resource);
// Calculate the width and height of each palette block
// based upon the size of the input image and the number
// of blocks.
$block_w = round($width / $palette_w);
$block_h = round($height / $palette_h);
for($y = 0; $y < $palette_h; $y++) {
for($x = 0; $x < $palette_w; $x++) {
// Calculate where to take an image sample from the soruce image.
$block_start_x = ($x * $block_w);
$block_start_y = ($y * $block_h);
// Create a blank 1x1 image into which we will copy
// the image sample.
$block = imagecreatetruecolor(1, 1);
imagecopyresampled($block, $img_resource, 0, 0, $block_start_x, $block_start_y, 1, 1, $block_w, $block_h);
// Convert the block to a palette image of just one colour.
imagetruecolortopalette($block, true, 1);
// Find the RGB value of the block's colour and save it
// to an array.
$colour_index = imagecolorat($block, 0, 0);
$rgb = imagecolorsforindex($block, $colour_index);
$colour_array[$x][$y]['r'] = $rgb['red'];
$colour_array[$x][$y]['g'] = $rgb['green'];
$colour_array[$x][$y]['b'] = $rgb['blue'];
imagedestroy($block);
}
}
imagedestroy($img_resource);
return $colour_array;
}
this may help you
<?php
$im = ImageCreateFromJpeg($source_file);
$imgw = imagesx($im);
$imgh = imagesy($im);
// n = total number or pixels
$n = $imgw*$imgh;
$colors = array();
for ($i=0; $i<$imgw; $i++)
{
for ($j=0; $j<$imgh; $j++)
{
$rgb = ImageColorAt($im, $i, $j);
if (isset($colors[$rgb])) {
$colors[$rgb]++;
}
else {
$colors[$rgb] = 1;
}
}
}
asort($colors);
print_r($colors);
The imagecolorat function will give you the colour value at a pixel which you can use to scan the image and create a colour histogram:
http://www.php.net/manual/en/function.imagecolorat.php