So I just detected a problem on my fpdf, when I'm writing the description to the multicell I press enter to break line and this happens
Image with problem
but my multicell code is programmed to calculate the string size and when the size is bigger than the width of the cell it ads one break line and the height size gets bigger but when I press enter it just add the same height
example
"My name is João" -> height = 6.5
"My name is João, (line break) I'm using fpdf" -> height = 6.5 + 6.5 instead of height = 6.5 + 1
this is my pdf without pressing enter
Image
this is my pdf with multicell on action
Image
I will leave the code that it's calculating all the multicell stuff.
$size = $pdf-> h; // page size
$cellWidth=120; // width da cell
$cellHeight=6.5; // height da cell
// verificar se o texto passa a cell
if($pdf->GetStringWidth(iconv('UTF-8', 'windows-1252',$r['description'])) < $cellWidth){
//doesn't do anything because when line is multiplied it receives the same value ( 6.5 * 1 = 6.5 )
$line = 1;
}else{
$line = ceil($pdf->GetStringWidth(iconv('UTF-8', 'windows-1252',$r['description'])));
$line = round($line / $cellWidth,0) + 1;
}
// use multicell instead of cell
// as a MultiCell is always treated as end of line,
// manually set the xy position to the next cell being next.
// save a position x before writing a multicell
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
$total = $yPos + ($line * $cellHeight);
if ($total > $size - 30) { // $size = $totalheight // change page
$pdf->AddPage(); // add page
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
}
$sizecell = $pdf->GetMultiCellHeight($cellWidth, $cellHeight,iconv('UTF-8', 'windows-1252',$r['description']));
$pdf->MultiCell($cellWidth,$cellHeight,iconv('UTF-8', 'windows-1252',$r['description']),'LBR','L');
// receive the position of the cell after multicell
// equals the x with the height of the multicell
$pdf->SetXY($xPos + $cellWidth , $yPos);
// write cells
// as the variable $cellHeight is multiplied by the value of the line is going to be greater than $cellHeight
// of the multicell so we need to make a loop and subtract 0.01 until the value is the same as the multicell
$cell = $line * $cellHeight;
if ($cell > $sizecell){
while($cell > $sizecell){
$cell = $cell - 0.01;
}
} else {
$cell = $cell;
}
$pdf->Cell(15,($cell),$r['quantity'],'LBR',0);
$pdf->Cell(10,($cell),'UNI','LBR',0);
$pdf->Cell(25,($cell),$r['priceuni'].chr(128),'LBR',0);
$pdf->Cell(25,($cell),$r['sum'].chr(128),'LBR',1);
I accept any suggestions, I have no idea of how am I going to do this
Related
I am using FPDF and making table in it using FancyTable example from here http://www.fpdf.org/. Following, I am showing one glimpse of code.
$start_x = $this->GetX(); //initial x (start of column position)
$current_y = $this->GetY();
$current_x = $this->GetX();
$cell_height = 7;
$this->MultiCell($width,$cell_height,$data,0,'L',$fill);
$current_x+=$width; //calculate position for next cell
$this->SetXY($current_x, $current_y);
Output of this is following, You can see one cell data is going outside cell. I have highlighted one cell data that is going outside from cell.
If I increase the height of cell then it seems it increase the line height and not cell height. Following is sample code.
$cell_height = 25;
$this->MultiCell($width,$cell_height,$data,0,'L',$fill);
and output looks like following.
With some research, I have created the following piece of code to generate a simple image with a text string right on the center showing the resolution of this image. The challenge is, when you change X & Y dimensions to larger or smaller values, the font size remains the same.
My question is, what would be a good way to "grow" or "shrink" the font size as the user chooses between image sizes?
One idea I had would be to calculate predetermined areas, add them to an array of key value pairs where the value is the hard-coded font size for a given range of areas.
Perhaps you have a simpler idea?
PS: The font I am using can be downloaded from Google fonts here:
Montserrat-SemiBold
The output looks like this:
And the code:
<?php
// We Declare our canvas width & height dimensions
$myCanvasWidth = 256;
$myCanvasHeight = 256;
// We Create an empty and dark canvas from these dimensions above
$myCanvas = imagecreate($myCanvasWidth, $myCanvasHeight) or die("Can't create image!");
// We Allocate a color to be used as the canvas background
$colorIndigo = imagecolorallocate($myCanvas, 0x3F, 0x51, 0xB5);
// We Apply color as canvas background
imagefill($myCanvas, 0, 0, $colorIndigo);
// We Allocate a color to be used with the canvas text
$colorWhite = imagecolorallocate($myCanvas, 0xFF, 0xFF, 0xFF);
// We Declare our TTF font path in Windows 10...
$myFont = 'J:\Montserrat-SemiBold.ttf';
// We set the font size
$myFontSize = 16;
// We set the text angle
$myTextAngle = 0;
// We Declare the text string to be drawn on canvas...
$myText = $myCanvasWidth . ' x ' . $myCanvasHeight;
// We Calculate and return the bounding box in pixels for the text string to be drawn on canvas...
$myTextBoundingBox = imageftbbox($myFontSize, $myTextAngle, $myFont, $myText);
// Get the text upper, lower, left and right corner bounds of our text bounding box...
$lower_left_x = $myTextBoundingBox[0];
$lower_left_y = $myTextBoundingBox[1];
$lower_right_x = $myTextBoundingBox[2];
$lower_right_y = $myTextBoundingBox[3];
$upper_right_x = $myTextBoundingBox[4];
$upper_right_y = $myTextBoundingBox[5];
$upper_left_x = $myTextBoundingBox[6];
$upper_left_y = $myTextBoundingBox[7];
// Get Text Width and Height
$myTextWidth = $lower_right_x - $lower_left_x; //or $upper_right_x - $upper_left_x
$myTextHeight = $lower_right_y - $upper_right_y; //or $lower_left_y - $upper_left_y
//Get the starting position for centering
$start_x_offset = ($myCanvasWidth - $myTextWidth) / 2;
$start_y_offset = (($myCanvasHeight - $myTextHeight) + $myFontSize * 2) / 2;
// Write text to the image using TrueType fonts
imagettftext($myCanvas, $myFontSize, $myTextAngle, $start_x_offset, $start_y_offset, $colorWhite, $myFont, $myText);
// Draw a horizontal dashed line for reference only
imagedashedline($myCanvas, 0, $myCanvasHeight/2, $myCanvasWidth, $myCanvasHeight/2, $colorWhite);
// Draw a vertical dashed line for reference only
imagedashedline($myCanvas, $myCanvasWidth/2, 0, $myCanvasWidth/2, $myCanvasHeight, $colorWhite);
// We se the correct http header for png images...
header('Content-Type: image/png');
// We Output a PNG image to either the browser or a file
imagepng($myCanvas);
// Free any memory associated with myCanvas; image.
imagedestroy($myCanvas);
?>
Here is the comment above implemented as an answer. Interestingly enough, even though the lines and the font don't appear to align, they are indeed actually centered.
The "x" at the center creates the illusion of nonalignment; a possible side effect of NOT using mono-spaced fonts in order to achieve a more unnecessarily precise alignment..?!
Then again.. mono-spaced fonts are not that good looking...
Sample resize outputs:
<?php
// We Declare our canvas width & height dimensions
$myCanvasWidth = 640;
$myCanvasHeight = 360;
// We Create an empty and dark canvas from these dimensions above
$myCanvas = imagecreate($myCanvasWidth, $myCanvasHeight) or die("Can't create image!");
// We Allocate a color to be used as the canvas background
$colorIndigo = imagecolorallocate($myCanvas, 0x3F, 0x51, 0xB5);
// We Apply color as canvas background
imagefill($myCanvas, 0, 0, $colorIndigo);
// We Allocate a color to be used with the canvas text
$colorWhite = imagecolorallocate($myCanvas, 0xFF, 0xFF, 0xFF);
// We Declare our TTF font path in Windows 10...
$myFont = 'J:\Montserrat-SemiBold.ttf';
// Static font seed value...
$fontSize = 16;
// We set the dynamic font size
$myFontSize = $myCanvasWidth / $fontSize;
// We set the text angle
$myTextAngle = 0;
// We Declare the text string to be drawn on canvas...
$myText = $myCanvasWidth . ' x ' . $myCanvasHeight;
// We Calculate and return the bounding box in pixels for the text string to be drawn on canvas...
$myTextBoundingBox = imageftbbox($myFontSize, $myTextAngle, $myFont, $myText);
// Get the text upper, lower, left and right corner bounds of our text bounding box...
$lower_left_x = $myTextBoundingBox[0];
$lower_left_y = $myTextBoundingBox[1];
$lower_right_x = $myTextBoundingBox[2];
$lower_right_y = $myTextBoundingBox[3];
$upper_right_x = $myTextBoundingBox[4];
$upper_right_y = $myTextBoundingBox[5];
$upper_left_x = $myTextBoundingBox[6];
$upper_left_y = $myTextBoundingBox[7];
// Get Text Width and Height
$myTextWidth = $lower_right_x - $lower_left_x; //or $upper_right_x - $upper_left_x
$myTextHeight = $lower_right_y - $upper_right_y; //or $lower_left_y - $upper_left_y
//Get the starting position for centering
$start_x_offset = ($myCanvasWidth - $myTextWidth) / 2;
$start_y_offset = (($myCanvasHeight - $myTextHeight) + $myFontSize * 2) / 2;
// Write text to the image using TrueType fonts
imagettftext($myCanvas, $myFontSize, $myTextAngle, $start_x_offset, $start_y_offset, $colorWhite, $myFont, $myText);
// Draw a horizontal dashed line for reference only
imagedashedline($myCanvas, 0, $myCanvasHeight/2, $myCanvasWidth, $myCanvasHeight/2, $colorWhite);
// Draw a vertical dashed line for reference only
imagedashedline($myCanvas, $myCanvasWidth/2, 0, $myCanvasWidth/2, $myCanvasHeight, $colorWhite);
// We set the correct http header for png images...
header('Content-Type: image/png');
// We Output a PNG image to either the browser or a file
imagepng($myCanvas);
// Finally, we free any memory associated with myCanvas; the image.
imagedestroy($myCanvas);
?>
The imageftbbox() function illustrated.
The imageftbbox() returns an array with 8 elements representing four points making the bounding box of the text:
I wrote below code , it working fine but multicell row heights are not working properly.I wrote below code , it working fine but multicell row heights are not working properly.I wrote below code , it working fine but multicell row heights are not working properly.
$x=$pdf->GetY();
$pdf->SetY($x+1);
include_once("config.php");
$result = mysqli_query($mysqli, "SELECT * FROM prd"); // using mysqli_query instead
$i = 1;
while($res = mysqli_fetch_array($result))
{
$current_y = $pdf->GetY();
$current_x = $pdf->GetX();
$pdf->MultiCell(30, 5, $i, 1, 'L');
$end_y = $pdf->GetY();
$prdid = $res[0];
$empid = $res[1];
$specification = $res[2];
$prn = $res[3];
$current_x = $current_x + 30;
$pdf->SetXY($current_x, $current_y);
$pdf->MultiCell(30, 5, $empid, 1, 'L');
$end_y = ($pdf->GetY() > $end_y)?$pdf->GetY() : $end_y;
$current_x = $current_x + 30;
$pdf->SetXY($current_x, $current_y);
$pdf->MultiCell(30, 5, $specification, 1, 'L');
$end_y = ($pdf->GetY() > $end_y)?$pdf->GetY() : $end_y;
$current_x = $current_x + 30;
$pdf->SetXY($current_x, $current_y);
$pdf->MultiCell(30, 5, $prn, 1, 'L');
$end_y = ($pdf->GetY() > $end_y)?$pdf->GetY() : $end_y;
$i++;
$pdf->SetY($end_y);
}
$pdf->Output();
?>
My Result :
How to adjust row height automatically ?
So a multi cell is essentially dynamic is height. The height you put into the function is a "row" height. So what happens is that fpdf goes to write the multi cell and let's say we defined the height to be 5, it'll create a "cell" of height 5 and start writing. Then it hits the hard stop at the width and goes "i have to create a new row", which it then adds a new "cell" of height 5 directly below the top "cell". This repeats until all text is written out. Obviously this is great for dynamic content, but has its own challenges that you have hit.
The path I normally take is to record the start point, write out the multi cell first, and then record the stopping point. You can then go back and write the other cells to make for better alignment. For this GetX, GetY, SetX, SetY will be your friends. You can set heights and such dynamically with simple math.
The "lazy" option is to re-do the layout to allow for the document to scale, that being to take your way too long multi cell and put it UNDER the row so you'll have:
|1 |46 |PR2.....|
|really long text
that will scale
down here|
|2 |........
Hope that helps get you moving forward!
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
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