Display image in PDF using fpdf - php

I want to insert an image in my created PDF file. However, it won't position well at all.
If I do this:
$fpdf->Image($row_products['prod_imagelarge'], 10);
The images will appear however, they're too big.
If I do this:
$fpdf->Image($row_products['prod_imagelarge'],30, 40, 40, 40);
Not all images will appear. Only 1 image per page will appear but with
the right size.
Actually, I am inserting an image inside a while loop.
What I would want to display in the pdf file is: (in order)
-product name (works fine)
-product image (the problem is here!)
-product description (works fine)

Similar to Naveed, but a little more complete with the rest of your row data. The trick is to capture the X and Y position before placing the image and then manually set the abscissa ("position") to the proper place, given the new image.
$image_height = 40;
$image_width = 40;
while ($row_products = mysql_fetch_array($products)) {
$fpdf->Cell(0, 0, $row_products['prod_name'], 0, 2);
$fpdf->Cell(0, 0, $row_products['prod_description'], 0, 2);
// get current X and Y
$start_x = $fpdf->GetX();
$start_y = $fpdf->GetY();
// place image and move cursor to proper place. "+ 5" added for buffer
$fpdf->Image($row_products['prod_imagelarge'], $fpdf->GetX(), $fpdf->GetY() + 5,
$image_height, $image_width)
$fpdf->SetXY($start_x, $start_y + $image_height + 5);
}

If one page contains many images then may be your images are placed on each others. You should change position for each image on one page. Try something like this.
for( $i=10; $i<=200; $i=$i+10 ) {
$fpdf->Image($row_products['prod_imagelarge'],30, $i, 40, 40);
}

Related

Merging two images via gradient

I am trying to merge two images in PHP, overlapping each other in the middle like in here : http://i.stack.imgur.com/ejdDQ.jpg
However, I am having no luck.
On the ImageMagick page, they are using this method to do it in the command line:
http://www.imagemagick.org/Usage/photos/#overlap
But since I cannot use exec on my server, I have to do it somehow with the help of the imagick extension installed on the server (http://us1.php.net/manual/en/book.imagick.php).
Is there any way to make this work?
Using the source files from the link and the code below generates the image:
//Load the images
$left = new Imagick(realpath('../images/im/holocaust_tn.gif'));
$right = new Imagick(realpath('../images/im/spiral_stairs_tn.gif'));
$gradient = new Imagick(realpath('../images/im/overlap_mask.png'));
//The right bit will be offset by a certain amount - avoid recalculating.
$offsetX = $gradient->getImageWidth() - $right->getImageWidth();
//When doing the fading of the images, ImageMagick uses "White == show image".
//The gradient is setup with black on the left, white on the right. So the for
//the left image we need to reverse the gradient to make it white on the left.
$negativeGradient = clone $gradient;
$negativeGradient->negateimage(false);
//Fade out the left part
$left->compositeimage(
$negativeGradient,
Imagick::COMPOSITE_COPYOPACITY,
0, 0
);
//Fade out the right part - offset the gradient
//to make it align in the final image
$right->compositeimage(
$gradient,
Imagick::COMPOSITE_COPYOPACITY,
-$offsetX, 0
);
//Create a new canvas to render everything in to.
$canvas = new Imagick();
$canvas->newImage($gradient->getImageWidth(), $gradient->getImageHeight(), new ImagickPixel('black'));
//Blend left half into final image
$canvas->compositeimage(
$left,
Imagick::COMPOSITE_BLEND,
0, 0
);
//Blend Right half into final image
$canvas->compositeimage(
$right,
Imagick::COMPOSITE_BLEND,
$offsetX, 0
);
//Output the final image
$canvas->setImageFormat('png');
header("Content-Type: image/png");
echo $canvas->getImageBlob();
// And Robert is your father's brother.

How to maintain image quality with FPDF and PHP?

I'm using FPDF with PHP to add an image to a PDF. But the image quality in the PDF is much worse than the original image, as you can see here:
Relevant code:
$image_height = 40;
$image_width = 40;
$pdf = new FPDF();
$pdf->AddPage();
$start_x = $pdf->GetX();
$start_y = $pdf->GetY();
$pdf->Image('./images/ds_pexeso_ros_0_17.jpg', $pdf->GetX(), $pdf->GetY(), $image_height, $image_width);
$pdf->Output("pexeso".date("Y-m-d"),"I");
The original image is 150x150 pixels.
I faced the same problem in projects for customers.
Blurry pictures in a generated pdf document even with hires images.
It took me a couple of hours, but this is what worked for me.
I have a taken a look at the code and saw that there was a scale factor being set in the constructor of the pdf document:
//Scale factor
if($unit=='pt')
$this->k=1;
elseif($unit=='mm')
$this->k=72/25.4;
elseif($unit=='cm')
$this->k=72/2.54;
elseif($unit=='in')
$this->k=72;
else
$this->Error('Incorrect unit: '.$unit);
The scalefactor is depending on the value given in the constructor of the pdf document:
function FPDF($orientation='P',$unit='mm',$format='A4')
The default is 'mm'. In most of my documents I initiate a pdf document like:
$pdf = new PDF('P');
This means that there will be a scalefactor of 72/25.4 = 2.83 used.
When I placed an image before I just used:
$this->Image('path/to/file', 0, 0);
This way I got the blurry images.
It is also possible to give the width of the image in the command
$this->Image('path/to/file', 0, 0, 200); // for a image width 200
This gave me an image that was far too large. But - and here comes the trick - when you divide the real width by the scalefactor (in my case 2.83) and put this in this statement it gives a perfectly sharp image:
$this->Image('path/to/file', 0, 0, 71); // for a image width 200 / 2.83 = app 71
I hope this works for you too!
I think the problem could be related to:
$image_height = 40;
$image_width = 40;
With these two instructions your are setting the dimensions the image will have in the pdf.
But if the original image is bigger than 40x40 the scaling of the image can cause quality problem.
So what i suggest:
Do a correct resize of the image (php provides GD library). Resize it to 40x40. The GD function imagecopyresampled is your friend: resize and resample the image! Complete reference: http://www.php.net/manual/en/function.imagecopyresampled.php
Insert now the image in the pdf
FPDF with a statement like this to set the user unit to mm
$pdf=new FPDF('P','mm','Letter');
<?php
require_once('fpdf.php');
$image_height = 40;
$image_width = 40;
$pdf = new FPDF('P','mm','Letter');
$pdf->AddPage();
$start_x = $pdf->GetX();
$start_y = $pdf->GetY();
$pdf->Image('./images/ds_pexeso_ros_0_17.jpg',$start_x+0,$start_y-2,40);
$pdf->Output("pexeso".date("Y-m-d"),"I");
?>
FPDF made a very good looking result.

Add styled backgrounds to images in PHP

I am working on improving one of my Facebook apps by allowing the user to upload an image and apply a styled border, or frame to it (i.e. clouds, stars, sky etc). The user chould also be able to save the image, with the border after it has been applied. This explains a little better what I need:
http://zbrowntechnology.info/ImgDisp/imgdisp.php
If you have any other questions or need more details, please let me know.. I'll edit this post.
Use imagecopy(). The example on that page is done using the transparency option with imagecopymerge() but I don't think you need that.
Using imagecopy() you'll specify the X/Y coordinates to use for positioning:
imagecopy( $borderimage, $topimage, 20, 20, 0, 0, $width, $height);
Where $width and $height will be the entire width and height of the top image. You'll want to replace 20 and 20 with the measurement for how much of the border image will be showing around the borders. You will probably have to resize the top image to the exact dimensions you want, or else it might overlap the border a little too far to the right or bottom. (see imagecopyresampled())
Edit:
Here's a rough way to do the whole process (assuming chosenborder.png is the border they chose, and uploadedimage.png is the image they uploaded. If it's a different image type you'll use the corresponding function).
$borderx = 20; // The width of our border
$border = imagecreatefrompng("chosenborder.png");
$topimage = imagecreatefrompng("uploadedimage.png");
$bordersize = getimagesize($border);
$topimagesize = getimagesize($topimage);
/* The new dimensions of topimage. $borderx*2 means we account for
the border on both left and right, top and bottom. */
$newx = $bordersize[0] - ($borderx*2);
$newy = $bordersize[1] - ($borderx*2);
imagecopyresampled( $topimage_scaled, $topimage, 0, 0, 0, 0,
$newx, $newy, $topimagesize[0], $topimagesize[1]);
/* Merge the images */
imagecopy( $border, $topimage_scaled, $borderx, $borderx,
0, 0, $width, $height);
/* Output the image */
imagepng($border, "newimage.png");
/* Free up the memory occupied by the image resources */
imagedestroy($border);
imagedestroy($topimage);
After the user uploads their image, find chosenborder.png and uploadedimage.png, run the above script, then display newimage.png to the user and you're good to go. Just make sure you call imagedestroy() on the temporary image resources or they'll eat up memory.
If you don't want to keep the generated image on your server, you can omit the second argument to imagepng() which will make it send the image information directly as an image to the browser, in which case you'll want to write the correct image HTTP headers.
Client-side solution by using css3:
checkout the css3 property border-image
(dosen't meet the requirement of saving the img with the border)
Server-side solution by merging 2 different images:
<?php
$imgFile = 'img.jpg';
$brdFile = 'brd.jpg';
$img = addBorder($imgFile,$brdFile);
outputImage($img);
function addBorder($imgFile,$brdFile)
{
$img=imagecreatefromjpeg($imgFile);
$brd=imagecreatefromjpeg($brdFile);
$imgSize = getimagesize($imgFile);
$brdSize = getimagesize($brdFile);
//NOTE: the border img MUST be bigger then the src img
$dst_x = ceil(($brdSize[0] - $imgSize[0])/2);
$dst_y = ceil(($brdSize[1] - $imgSize[1])/2);
imagecopymerge ( $brd, $img, $dst_x, $dst_y, 0, 0, $imgSize[0], $imgSize[1] ,100 );
return $brd;
}
function outputImage($img)
{
header('Content-type: image/png');
imagepng($img);
}
?>

php adding images to another image, exact positioning

I have a cool snippet of code that works well, except one thing.
The code will take an icon I want to add to an existing picture. I can position it where I want too! Which is exactly what I need to do.
However, I'm stuck on one thing, concerning the placement.
The code "starting position" (on the main image: navIcons.png) is from the Bottom Right.
I have 2 variables: $move_left = 10; & $move_up = 8;.
So, the means I can position the icon.png 10px left, and 8px up, from the bottom right corner.
I really really want to start the positioning from the Top Left of the image, so I'm really moving the icon 10px right & 8px down, from the top left position of the main image.
Can someone look at my code and see if I'm just missing something that inverts that starting position?
<?php
function attachIcon($imgname)
{
$mark = imagecreatefrompng($imgname);
imagesavealpha($mark, true);
list($icon_width, $icon_height) = getimagesize($imgname);
$img = imagecreatefrompng('images/sprites/navIcons.png');
imagesavealpha($img, true);
$move_left = 10;
$move_up = 9;
list($mainpic_width, $mainpic_height) = getimagesize('images/sprites/navIcons.png');
imagecopy($img, $mark, $mainpic_width-$icon_width-$move_left, $mainpic_height-$icon_height-$move_up, 0, 0, $icon_width, $icon_height);
imagepng($img); // display the image + positioned icon in the browser
//imagepng($img,'newnavIcon.png'); // rewrite the image with icon attached.
}
header('Content-Type: image/png');
attachIcon('icon.png');
?>
For those who are wondering why I'd even bother doing this. In a nutshell, I like to add 16x16 icons to 1 single image, while using css to display that individual icon. This does involve me downloading the image (sprite) and open photoshop, add the new icon (positioning it), and reuploading it to the server. Not a massive ordeal, but just having fun with php.
bool imagecopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h )
Copy a part of src_im onto dst_im starting at the x,y coordinates src_x, src_y with a width of src_w and a height of src_h. The portion defined will be copied onto the x,y coordinates, dst_x and dst_y. (PHP.net
$move_right = 10;
$move_down = 8;
imagecopy($img, $mark, $move_right, $move_down, 0, 0, $icon_width, $icon_height);
turns out, I'm not being more simple than I should be.
It's already to the positioning I need, I just need to NOT complicate the int $dst_x/$dst_y.
I put simple integers there, and it works.

Dynamic GD image width text

I'm trying to spice up my website by using custom fonts for headings. For me, the most appropriate way to do this is using PHP and GD. I have written a little script which will output the dynamic text based on the $_GET value, however sometimes the image is too wide, which moves everything else about.
How can I get the image to adjust the width of it, based on the width of the text? Here is the code I've written so far:
<?php
// Settings
$sText = $_GET['t']; // Text of heading
$sFont = "font/AvantGarde-Book.ttf"; // Default font for headings
$sMain = $_GET['c'] ? $_GET['c'] : 0xF2AB27; // Get a font or default it
// Create the image
header("content-type: image/png"); // Set the content-type
$hImage = imagecreatetruecolor(200, 24);
ImageFill($hImage, 0, 0, IMG_COLOR_TRANSPARENT);
imagesavealpha($hImage, true);
imagealphablending($hImage, false);
imagettftext($hImage, 20, 0, 0, 24, $sMain, $sFont, $sText); // Draw the text
imagepng($hImage); // Generate the image
imagedestroy($hImage); // Destroy it from the cache ?>
Thanks!
Ok, I figured it out! For anyone else who may have this problem, you need to add:
// Calcuate the width of the image
$arSize = imagettfbbox(24, 0, $sFont, $sText);
$iWidth = abs($arSize[2] - $arSize[0]);
$iHeight = abs($arSize[7] - $arSize[1]);
Before the imagecreatetruecolor()
The function imagettfbbox will calculate the size of what the text will be based on the font you picked. Use the results in your call to imagecreatetruecolor.

Categories