Skip to content

Instantly share code, notes, and snippets.

@benshimmin
Created November 16, 2012 16:03
Show Gist options
  • Select an option

  • Save benshimmin/4088493 to your computer and use it in GitHub Desktop.

Select an option

Save benshimmin/4088493 to your computer and use it in GitHub Desktop.
Scale to fit and centre-align an image with FPDF
<?php
/* Caveat: I'm not a PHP programmer, so this may or may
* not be the most idiomatic code...
*
* FPDF is a free PHP library for creating PDFs:
* http://www.fpdf.org/
*/
require("fpdf.php");
class PDF extends FPDF {
const DPI = 96;
const MM_IN_INCH = 25.4;
const A4_HEIGHT = 297;
const A4_WIDTH = 210;
// tweak these values (in pixels)
const MAX_WIDTH = 800;
const MAX_HEIGHT = 500;
function pixelsToMM($val) {
return $val * self::MM_IN_INCH / self::DPI;
}
function resizeToFit($imgFilename) {
list($width, $height) = getimagesize($imgFilename);
$widthScale = self::MAX_WIDTH / $width;
$heightScale = self::MAX_HEIGHT / $height;
$scale = min($widthScale, $heightScale);
return array(
round($this->pixelsToMM($scale * $width)),
round($this->pixelsToMM($scale * $height))
);
}
function centreImage($img) {
list($width, $height) = $this->resizeToFit($img);
// you will probably want to swap the width/height
// around depending on the page's orientation
$this->Image(
$img, (self::A4_HEIGHT - $width) / 2,
(self::A4_WIDTH - $height) / 2,
$width,
$height
);
}
}
// usage:
$pdf = new PDF();
$pdf->AddPage("L");
$pdf->centreImage("path/to/my/image.jpg");
$pdf->Output();
?>
@0x1ad2
Copy link
Copy Markdown

0x1ad2 commented Apr 18, 2013

Thanks this saved my day!

@christophrumpel
Copy link
Copy Markdown

Thx, but this works only in landscape mode for me? In portrait mode the image is set to the right border.

@benshimmin
Copy link
Copy Markdown
Author

@christophrumpel, for portrait, you probably need to switch width and height around between lines 44 and 47 (untested though!). Sorry, I only needed this for handling landscape pages. :-)

@ElectricAlan
Copy link
Copy Markdown

Sweet, this is exactly what I was looking for.

@christophrumpel If you want to change the orientation, change the following constants, I also change the DPI to make the image display as large as possible

const DPI = 64;
const MM_IN_INCH = 25.4;
const A4_WIDTH = 297;
const A4_HEIGHT = 210;
const MAX_HEIGHT = 800;
const MAX_WIDTH = 500;

@crispconcepts
Copy link
Copy Markdown

This is brilliant. I'm having trouble getting text to overlay the top of it though. I don't suppose you have a solution?

...

const DPI = 300;
const MM_IN_INCH = 25.4;
const A4_HEIGHT = 297;
const A4_WIDTH = 210;
// tweak these values (in pixels)
const MAX_WIDTH = 3510;
const MAX_HEIGHT = 2481;

...
...
...

$pdf = new PDF();
$pdf->AddPage("L");
$pdf->centreImage("certificate.jpg");
$pdf->SetFont('Arial','B',300);
$pdf->Text(500, 500, 'Username');
$pdf->Output();

@mak1986
Copy link
Copy Markdown

mak1986 commented Jul 1, 2014

Nice 👍

@webjaydev
Copy link
Copy Markdown

Thx a lot!

@aijodesigns
Copy link
Copy Markdown

Thanks for this! Lifesaver!

@tmdevde
Copy link
Copy Markdown

tmdevde commented Jul 27, 2015

Thank you so so much!

@EdisAganovic
Copy link
Copy Markdown

PORTRAIT MODE

const DPI = 150;
const MM_IN_INCH = 25.4;
const A4_HEIGHT = 210;
const A4_WIDTH = 297;
// tweak these values (in pixels)
const MAX_WIDTH = 1150;
const MAX_HEIGHT = 1650;

$pdf->AddPage("P");

A4 @ 300 dpi - 3507x2480 pix
A4 @ 200 dpi - 2338 x 1653 pix
A4 @ 150 dpi - 1753x1240 pix
A4 @ 72 dpi - 841x595 pix

@jeteon
Copy link
Copy Markdown

jeteon commented Feb 20, 2016

Just saved me the time to figure out the pixel -> mm conversion.

@yohannanv
Copy link
Copy Markdown

Hi,

I have a pdf and and I am converting that to images(in A4 size) and listing the pages for the user to drag and drop an image on the top of the page. Here I am getting the position x,y of the image in pixels. Using FPDI I am regenerating the existing PDF with the dropped image in the exact position user had dropped on the image in A4 size($pdf = new FPDI('P', 'pt', 'A4');). But in my new PDF the image is not showing in the correct position.

$wPdf = $customPdfClass->getWPt(); //PDF width through FPDF
$hPdf = $customPdfClass->getHPt(); //PDF height through FPDF
$xImage = $positionLeft;//left of the image from jquery
$yImage = $positionTop; // top of the image from jquery
$screenWidth = $screenWidth; //pdf images width from jquery
$screenHeight = $screenHeight; //pdf images height from jquery
$signImage = "uploads/img/".$imageFileName;//dropped image save in my folder
$size = getimagesize($signImage);
$signImageWidth = $size[0]; //Actual width of the image
$signImageHeight = $size[1]; //Actual height of the image
$scalex=$signImageWidth/$screenWidth * ($wPdf);
$scaley=$signImageHeight/$screenHeight * ($hPdf);
$xadj = 0;
$yadj=0;
//Converting pixel values to points and adjusting with the height and width of the PDF
$xImage = ($xImage/$screenWidth);
$yImage = ($yImage/$screenHeight);
$xpt = (($xImage_$wPdf)-$xadj);
$ypt = (($yImage_$hPdf)-$yadj);
// iterate through all pages
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
// import a page
$templateId = $pdf->importPage($pageNo);
// get the size of the imported page
$size = $pdf->getTemplateSize($templateId);
// create a page (landscape or portrait depending on the imported page size)
if ($size['w'] > $size['h']) {
$pdf->AddPage('L', array($size['w'], $size['h']));
} else {
$pdf->AddPage('P', array($size['w'], $size['h']));
}
// use the imported page
$pdf->useTemplate($templateId);
if($pageNo==$page) {
$pdf->Image('uploads/img/'.$imageFileName,$xpt, $ypt, $scalex, $scaley, "png");
}
}

What should I do to position the image in PDF where the user dropped position? Please give me a solution for this? Thanks.

@glabarbera
Copy link
Copy Markdown

This is not scale-able in the least bit. Constants for file images?

@thomasdesmoulin
Copy link
Copy Markdown

thomasdesmoulin commented Apr 1, 2018

<?php
require("fpdf.php");

class Pdf extends \FPDF
{

    const DPI = 300;
    const MM_IN_INCH = 25.4;
    const A4_HEIGHT = 297;
    const A4_WIDTH = 210;

     /**
     * Resize et fit une image image
     *
     * @param string $imgPath
     * @param integer $x
     * @param integer $y
     * @param integer $containerWidth
     * @param integer $containerHeight
     * @param string $alignment
     * @return void
     */
    public function imageUniformToFill(string $imgPath, int $x = 0, int $y = 0, int $containerWidth = 210, int $containerHeight = 297, string $alignment = 'C')
    {
        list($width, $height) = $this->resizeToFit($imgPath, $containerWidth, $containerHeight);

        if ($alignment === 'R')
        {
            $this->Image($imgPath, $x+$containerWidth-$width, $y+($containerHeight-$height)/2, $width, $height);
        }
        else if ($alignment === 'B')
        {
            $this->Image($imgPath, $x, $y+$containerHeight-$height, $width, $height);
        }
        else if ($alignment === 'C')
        {
            $this->Image($imgPath, $x+($containerWidth-$width)/2, $y+($containerHeight-$height)/2, $width, $height);
        }
        else
        {
            $this->Image($imgPath, $x, $y, $width, $height);
        }
    }
    
    /**
     * Convertit des pixels en mm
     *
     * @param integer $val
     * @return integer
     */
    protected function pixelsToMm(int $val) : int
    {
        return (int)(round($val * $this::MM_IN_INCH / $this::DPI));
    }

    /**
     * Convertit des mm en pixels
     *
     * @param integer $val
     * @return integer
     */
    protected function mmToPixels(int $val) : int
    {
        return (int)(round($this::DPI * $val / $this::MM_IN_INCH));
    }

    /**
     * Resize une image
     *
     * @param string $imgPath
     * @param integer $maxWidth en mm
     * @param integer $maxHeight en mm
     * @return int[]
     */
    protected function resizeToFit(string $imgPath, int $maxWidth = 210, int $maxHeight = 297) : array
    {
        list($width, $height) = getimagesize($imgPath);
        $widthScale = $this->mmtopixels($maxWidth) / $width;
        $heightScale = $this->mmToPixels($maxHeight) / $height;
        $scale = min($widthScale, $heightScale);
        return array(
            $this->pixelsToMM($scale * $width),
            $this->pixelsToMM($scale * $height)
        );
    }
}

// usage:
$pdf = new Pdf();
$pdf->AddPage();
$pdf->imageUniformToFill($imgPath, $x, $y ,$containerWidth, $containerHeight, $alignment) //$alignment "B", "T", "L", "R", "C"
$pdf->Output();

Merci à https://gist.github.com/benshimmin/4088493
https://gist.github.com/thomasdesmoulin/398886164ffd0566f6fa3b3171bb86f4

@sdushkevych
Copy link
Copy Markdown

Amazing! Thank you so much!

@gabs086
Copy link
Copy Markdown

gabs086 commented Feb 18, 2021

Thank you so much for this!!! I'm finding this kind of solution for weeks now. Really made my day. Thank you

@mouss340
Copy link
Copy Markdown

Thank you benshimmin and other contributors, great job !

@stone-4
Copy link
Copy Markdown

stone-4 commented Dec 31, 2022

Thanks a lot! Its works, but just one detail... if the image has a small width, with a long height, the image overflows from the top and bottom of the PDF sheet.

@hamzahzu
Copy link
Copy Markdown

Thankyou thomasdesmoulin its works for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment