FPDF align with Image and Cell - php

I'm trying to do the following layout in an PDF file generated by FPDF in PHP.
--------------------------------------------------
| | Text1 |
| IMAGE | Text2 |
| | Text3 |
--------------------------------------------------
But I couldn't figure out how to do it by now.
This is the code I'm using
public function floatingImage($imgPath, $height) {
list($w, $h) = getimagesize($imgPath);
$ratio = $w / $h;
$imgWidth = $height * $ratio;
$this->Image($imgPath, $this->GetX(), $this->GetY(), 140, 100);
$this->x += $imgWidth;
}
/* Logbuch is our extension from FPDI, but there's nothing changed
* only a custom header, footer and the floatingImage and loadMapImage function are part of it
*/
$pdf = new logbuch();
// Frontpage
$pdf->AddPage();
$mapImage = $pdf->loadMapImage();
$pdf->setJPEGQuality(75);
$x = 15; $y = 21; $w = 100;
$pdf->floatingImage($mapImage, 100, 100);
$pdf->SetFillColor(154,222,229);
$pdf->Cell(0,0,"Test",0,0,'R',true);
$pdf->Ln();
$pdf->Cell(100,0,"Test",0,0,'R',true);
$pdf->Ln();
$pdf->Cell(100,0,"Test",0,0,'R',true);
This is the result I'm generating by now
If I change the width of the last two cells to 100 it will look like this:
This is nearly what I want, the cells just must align to the right side. How can I do this?

I found the answer myself
You can set an X value to the pdf with determines the position on the X axis.
$pdf->Cell(0,0,"Test",0,0,'R',true);
$pdf->Ln();
$pdf->SetX(100); //The next cell will be set 100 units to the right
$pdf->Cell(100,0,"Test",0,0,'R',true);
$pdf->Ln();
Importend to mention is that after every wrote Cell X will be asigned a new value from the Cell() function. So you need to SetX() before creating a new Cell!

Related

line height auto adjust in fpdf multicell ()

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

How to merge images in PHP?

I have two images which are loaded from an external URL. I want to place one image on top of another (keeping the size). I actually don't know the sizes of the images as they are from an external URL and are different each time.
So I want a function which can be called like merge($url1,$url2,$final_name). I have googled on this but none worked.
I want this 3.png :
--------------------------------------------------------------------------
|
IMAGE 1 |
|
|
___________________________________________________________________________
|
IMAGE 2 |
|
|
___________________________________________________________________________
$top_file = 'image1.png';
$bottom_file = 'image2.png';
$top = imagecreatefrompng($top_file);
$bottom = imagecreatefrompng($bottom_file);
// get current width/height
list($top_width, $top_height) = getimagesize($top_file);
list($bottom_width, $bottom_height) = getimagesize($bottom_file);
// compute new width/height
$new_width = ($top_width > $bottom_width) ? $top_width : $bottom_width;
$new_height = $top_height + $bottom_height;
// create new image and merge
$new = imagecreate($new_width, $new_height);
imagecopy($new, $top, 0, 0, 0, 0, $top_width, $top_height);
imagecopy($new, $bottom, 0, $top_height+1, 0, 0, $bottom_width, $bottom_height);
// save to file
imagepng($new, 'merged_image.png');
This does the job but the merged image loses its color and becomes nearly black and white like this:
Instead of this:
// create new image and merge
$new = imagecreate($new_width, $new_height);
I used:
// create new image and merge
$new = imagecreatetruecolor($new_width, $new_height);
It worked!
Thanks!
i looked up ur code but i would save the folder in something like that:
$time = date('d-M-Y') . '-TIME-' . date('H-i-s');
$save_finalimage_socialmedia = public_path("storage/image-{$time}.jpeg");
imagejpeg($new, $save_finalimage_socialmedia);
PS: i did it in the jpeg format, so if you want, you can change in ur format (png,jpg,...)
PS: #user4273356 ur code worked for me

imagecopyresampled in PHP, can someone explain it?

OK i thought i understood this function but i have a complete mental block on this one.
I wanted to create cropped thumbnails of size 75x75 from photos that are 800x536.
the imagecopyresampled function has 10 possible parameters. i first tried this:
// Starting point of crop
$tlx = floor(($width / 2) - ($new_width / 2)); //finds halfway point of big image and subtracts half of thumb.
$tly = floor(($height / 2) - ($new_height / 2)); //gets centre of image to be cropped.
imagecopyresampled($tmp_img,$img,0,0,$tlx,$tly,$new_width,$new_height,$orig_width,$orig_height);
this finds either side of the halfway mark on the large image and crops it out. or so i thought. but it actuall crops a bit of the picture and leaves the right hand side and bottom in black (presumably from the imagecreatetruecolor earlier.
so i found a way to do what i want but i want you to explain how it is working.
i now have:
//Create thumbnails.
$new_width = 75; //pixels.
$new_height = 75;
if($width > $height) $biggest_side = $width;
else $biggest_side = $height;
//The crop size will be half that of the largest side
$crop_percent = .5;
$crop_width = $biggest_side*$crop_percent;
$crop_height = $biggest_side*$crop_percent;
$c1 = array("x"=>($width-$crop_width)/2, "y"=>($height-$crop_height)/2);
//Create new image with new dimensions to hold thumb
$tmp_img = imagecreatetruecolor($new_width,$new_height);
//Copy and resample original image into new image.
imagecopyresampled($tmp_img,$img,0,0,$c1['x'],$c1['y'],$new_width,$new_height,$crop_width,$crop_height);
it's doing it perfectly, shrinking the image and then cropping out the middle, but my maths isn't very sharp and also i think it's definitely that i don't fully understand the imagecopyresampled function.
can someone walk me through it? parameter by parameter. especially the last two. originally i entered the width and height of the original image, but this enters 400 and 400 (half of the longest side). sorry for the rant. hope my mind understands this soon :)
Alex
It's fairly simple, documented here
The parameters:
1) $dst_image, a valid GD handle representing the image you want to copy INTO
2) $src_image, a valid GD Handle represending the image you're copying FROM
3) $dst_x - X offset in the destination image you want to place the resampled image into
4) $dst_y - Y offset, ditto
5) $src_x - X offset in the source image you want to start copying from
6) $src_y - Y offset, ditto
7) $dst_x - X width of the newly resampled image in $dst_image
8) $dst_y - Y width, ditto
9) $src_x - X width of the area to copy out of the $src_image
10) $src_y - Y width, ditto
So...
You've got a $src_image that's 800x536, and a $dst_image that's 75x75
$width = 800 $new_width = 75
+-----------------------+ +----+
| | | |
| | | | $new_height = 75
| | $height = 536 +----+
| |
| |
+-----------------------+
Sounds like you want to take the middle chunk of the source image and make a thumbnail from that, right? This middle chunk should represent half the height & width of the original image, so you want:
$start_X = floor($width / 4); // 200
$width_Y = floor($height / 4); // 134
200 400 200
+-----------------------+
| | | | 134
|-----+----------+------|
| | This part| | 268
|-----+----------+------|
| | | | 134
+-----------------------+
$end_x = $start_X + (2 * $start_x) // 3 * $start_x = 600
$end_y = $start_Y + (2 * $start_y) // 3 * $start_y = 402
imagecopyresampled($src, $dst, 0, 0, $startX, $start_y, 75, 75, $end_x, $end_y);
a b c d e f g h
a,b - start pasting the new image into the top-left of the destination image
c,d - start sucking pixels out of the original image at 200,134
e,f - make the resized image 75x75 (fill up the thumbnail)
g,h - stop copying pixels at 600x402 in the original image
Now, this is assuming that you want the thumbnail to be completely filled up. If you want the source image to be shrunk proportionally (so it has the same ration of height/width as the original, then you'll have to do some math to adjust the a,b and e,f parameters.

Create a picture with GD containing other images

I would like to create a picture in PHP with GD composed by different other pictures. For example I have 6 pictures (or more) and I would like to create ONE picture who contain these different pictures.
The Difficulty is that my final picture must have a fixed width and height (304x179), so if the different pictures are too big they must be cut. This is an example from IconFinder :
This picture is composed by 6 images, but the 3rd bird (green) is cutted, and the 4, 5 and 6 are cutted in the bottom. This is what I want, can you give me some help to write this code in PHP ?
Thanks
Create your primary image and consider it your "canvas."
From there, use imagecopy() to copy the smaller images into the canvas image.
See this for example:
<?php
header('Content-Type: image/jpg');
$canvas = imagecreatetruecolor(304, 179);
$icon1 = imagecreatefromjpeg('icon.jpg');
$icon2 = imagecreatefromjpeg('icon2.jpg');
// ... add more source images as needed
imagecopy($canvas, $icon1, 275, 102, 0, 0, 100, 100);
imagecopy($canvas, $icon2, 0, 120, 0, 0, 100, 100);
// ... copy additional source images to the canvas as needed
imagejpeg($canvas);
?>
In my example, icon.jpg is a 100x100 image which I am placing in the canvas such that its top left corner is located at 275, 102 in the canvas, which cuts off the right side.
Edit
I adjusted the code to be more similar to what you're doing.
Here a none tested modify spinet from one of my scripts, hope it can be usefull:
header('Content-type: image/png');
$image = array() //Populate this array with the image paths
//Create the Letters Image Objects
foreach($image as $a){
$image['obj'][] = imageCreateFromPNG($a);
}unset($a);
$canvasW = 300;
$canvasH = 300;
//Create Canvas
$photoImage = imagecreatetruecolor($canvasW,$canvasH);
imagesavealpha($photoImage, true);
$trans_color = imagecolorallocatealpha($photoImage, 0, 0, 0, 127);
imagefill($photoImage, 0, 0, $trans_color);
//Merge Images
$Offset_y = 0;
$images_by_row = 3;
$images_rows_height = 100; // height of each image row
$counter = 0;
foreach($image['obj'] as $a){
$counter++;
$width = ceil(imagesx($a));
$height = ceil(imagesy($a));
if(!isset($offset)){ $offset = 1; }
imageComposeAlpha($photoImage, $a, $offset, $Offset_y,$width,$height);
if($offset >= 1){
$offset = $offset + $width;
}
//Check if new row next time
if($counter >= $images_by_row){
if($images_by_row%$counter){
$offset_y += $images_rows_height;
}
}
}unset($a);
imagepng($photoImage);

Generate colour palette from an image

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

Categories