1

I've tried every conceivable combination of getting something that seems so simple to work.

I need to place an image on a page, A4 (210mm (h) X 297mm (w)) and have that image 100% height, i.e. 297mm, then stretch the width proportionally to that and just crop the overflow (i.e. hidden in css overflow). I've tried every combination I can think of with $mpdf->Image(), or like I've done everywhere else in the PDF file, use pure HTML and CSS. E.g.

<img src="path(to/file.jpg" />

or

<div style="background: url("path(to/file.jpg") center center no-repeat;"></div>

again, with all possible CSS configurations I can think of.

Is it not possible to stretch and image to fit the entire pages height while maintaining the aspect ratio and crop the image on the sides?

I've seen background-image-resize on MPDF full page background, but again, nothing.

How can I get an image to be 100% of the page's height (I don't care if I have to define the height (i.e. 297mm) or if it's a percentage) have the image scale proportionally to that and crop any excess of the image on the sides.

I'm sure I've just missed something obvious here. I can't see what I'm doing wrong (I think I'm stuck in a loop in my head now).

An example of what shows up fine (as expected) if I do an echo and view in the browser

$html = '<div style="
    background: url('.$imageSource.') center center no-repeat;
    position: absolute;
    overflow: hidden;
    height: 297mm;
    width: 100%;
    background-size: cover;
    top: 0;
    left: 0;
"></div>';

However, doing the same with $pdf->WriteHTML( $html, 2 ) and then $pdf->Output() the image is 297mm in height, but the width is distorted (i.e. it doesn't stretch proportionally to the height).

Here is the resulting PDF (with a placeholder image) enter image description here

This is what I'm trying to achieve enter image description here

So the resulting PDF gets "squeezed". Instead of extending the width proportionally to the height (297mm).

PS. Sorry for the lack of actual tested code. But there are just so many different combinations I've tried that I can't reproduce all of them.

PPS. Using latest version of mPDF. Grabbed from GitHub three days ago.

axelra82
  • 517
  • 8
  • 23
  • It might help if you can add a screenshot of what your code produces now (how does it differ from what you want?). Also, since you're using PHP, you could read the dimensions of your image, and then add an explicit width and height (especially since you're rendering to a page with fixed dimensions e.g. A4 portrait). – halfer May 13 '18 at 09:40
  • Remember also that the CSS parsers in PDF renders are going to be much more incomplete than browsers, so don't expect too much. I think the best one is probably PrinceXML, but the commercial version is not cheap. – halfer May 13 '18 at 09:42
  • @halfer thanks for the trim (been going in circles on this). I've added images to illustrate the outcome vs. expected result. I've tried PHP and getimagesize() for width and height. Still, the outcome is always a distorted image. I don't see why the image can't have a height > visible width and just crop the overflow. – axelra82 May 13 '18 at 13:21
  • Is the aspect ratio of the image the same as the page? If so, I can't see why using the correct outputs of `getimagesize` would not work. – halfer May 13 '18 at 13:34
  • The image is 1024x680px (WxH. But this can vary), so no. This is why I need the image to be the full height of the page, stretch the width proportionally and maintain image ratio. So whatever overflow there is gets cropped (hidden). But all it does now is distorts the image. – axelra82 May 13 '18 at 13:42
  • OK. This may be a limitation of your PDF renderer. Consider adding a PHP script to place the image(s) on a white/transparent background of the correct aspect ratio. – halfer May 13 '18 at 14:11

1 Answers1

1

Since I had a lot of problems getting the logic, CSS and math right I thought I'd share my final working solution here with anyone else struggling with this. Start with the function

function image( $containerWidth, $containerHeight, $imageSource, $top, $left, $border ){
// Get image width
$imageWidth             = getimagesize( $imageSource )[0];
// Get image height
$imageHeight            = getimagesize( $imageSource )[1];
// Get image aspect ratio
$imageRatio             = $imageWidth / $imageHeight;
// Get container aspect ratio
$containerRatio         = $containerWidth / $containerHeight;
// Decide if image should increase in height or width
if( $imageRatio > $containerRatio ){
    $width                  = ( ( $imageRatio / $containerRatio ) * 100 );
}else{
    $width                  = ( ( $containerRatio / $imageRatio ) * 100 );
}
if( $border ){
    // $border array: 0 = thicknes in points, 1 = type (solid, dotted etc), 2 = color
    $border = 'border: '.$border[0].'pt '.$border[1].' '.$border[2].';';
}
return '<div style="position: absolute; top: '.$top.'mm; left: '.$left.'mm; width: '.$containerWidth.'mm; height: '.$containerHeight.'mm; overflow:hidden; margin:0;'.$border.'"><img src="'.$imageSource.'" style="width: '.$width.'%; margin: 0 -'.( ( $width - 100 ) / 2 ).'%;" /></div>';
}

Then for a centered full page image

$image1                     = image( 210, 297, $imageSource[0], 0, 0, null );

Or two images on top of each other, one with a white border

$image2                     = image( 105, 148, $imageSource[1], 15, 15, null );
$image3                     = image( 105, 148, $imageSource[2], 133, 90, [ 10, 'solid', 'white' ] );

Output

// mPDF options array
$pdfOptions = array(
    'mode'              => 'utf-8',
    'format'                => 'A4',
    'img_dpi'               => 300,
    'dpi'                   => 300,
);
// Declare $pdf and set options
$pdf                    = new \Mpdf\Mpdf( $pdfOptions );
// Stylesheets
$style                  = file_get_contents( __DIR__ . '/path/to/stylesheet.css');
$pdf->WriteHTML( $style, 1 );
$pdf->WriteHTML( $image1, 2 );
$pdf->AddPage();
$pdf->WriteHTML( $image2, 2 );
$pdf->WriteHTML( $image3, 2 );
$pdf->Output();
axelra82
  • 517
  • 8
  • 23