Skip to content

Instantly share code, notes, and snippets.

@benshimmin
Created November 16, 2012 16:03
Show Gist options
  • Save benshimmin/4088493 to your computer and use it in GitHub Desktop.
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();
?>
@ElectricAlan
Copy link

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

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

mak1986 commented Jul 1, 2014

Nice 👍

@webjaydev
Copy link

Thx a lot!

@aijodesigns
Copy link

Thanks for this! Lifesaver!

@tmdevde
Copy link

tmdevde commented Jul 27, 2015

Thank you so so much!

@EdisAganovic
Copy link

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

jeteon commented Feb 20, 2016

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

@yohannanv
Copy link

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

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

@thomasdesmoulin
Copy link

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

Amazing! Thank you so much!

@gabs086
Copy link

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

Thank you benshimmin and other contributors, great job !

@stone-4
Copy link

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

Thankyou thomasdesmoulin its works for me

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