How can I resize an image in an HTML generated word document whilst retaining the aspect ratio?


Tags: php,html,css,ms-word

Problem :

I've been building a word document from some HTML as per these fantastic stackoverflow resources:

For those who are about to try it, prepare yourself for some pain as Word is patchy to say the least when it comes to what CSS it works with. If you want columns, you really need to go back to using tables to lay stuff out.

I've been having trouble with getting an image to size properly - There are images that the user uploads which will be used in this Word document, and I would like to resize them based on the 'height' property - to a height of 50px and then have the width scaled accordingly.

It seems there is no documentation for how to do this anywhere on the web.

I've also used some html2canvas code to turn a nice looking (CSS-based) bar-chart into an image, which is then usable directly in the word document as per the excellent http://www.kubilayerdogan.net/?p=304.

This image is not printing out well, so I'm planning to make the source HTML larger on screen (hidden in memory) (using jQuery) before running the html2canvas code on it - this way I'll have a larger image which I can then reduce in size and get a higher DPI number.

Firstly, I've learned that CSS width and height have no impact on images in Word. Similarly, the following doesn't work.

<img class="cobrandedlogo" src="' . $logourl . '" height="50px" />';

But I have found that using 'points' works like so:

<img class="cobrandedlogo" src="' . $logourl . '" height="50" />';

But this produces a very stretched image (depending on the source material of course). I want it to be scaled according to the original image.

I'm using PHP.

I've discovered this SO article which it seems will help: Calculating image size ratio for resizing

Here's some code I've been using:

jQuery code to generate the image of a div, modify the displayed HTML a bit and submit it to a PHP file:

var wordreport = jQuery('#container').clone();
jQuery(wordreport).find('#stats').html('<img src="http://improvedemployees.com/assets/teamstats/' + jQuery('#imgname').val() + '" />');
jQuery(wordreport).find('.columncontainer').each(function() {
    jQuery(this).children().wrapAll('<table><tr>');
});
// these were 3 columns on the screen - converted to a table and tds for Word
jQuery(wordreport).find('.memberstrengths').wrap('<td valign=top>'); 
jQuery(wordreport).find('.membercommunication').wrap('<td valign=top>');
jQuery(wordreport).find('.memberimproving').wrap('<td valign=top>');

jQuery(wordreport).find('#generateword').remove();
jQuery(wordreport).find('script').remove();             

var htmlpluscss = jQuery(wordreport).html();
htmlpluscss = '<style>.reportsection {border:1px solid #fff!important; padding:0px; margin-bottom:0px;}</style>' + htmlpluscss;
jQuery('#dochtml').val(htmlpluscss);
jQuery('#rawhtml').val(htmlpluscss);
jQuery('#stats').html2canvas({
    onrendered: function (canvas) {
        //Set hidden field's value to image data (base-64 string)
        jQuery('#img_val').val(canvas.toDataURL("image/png"));
        //Submit the form manually
        document.getElementById("getword").submit();
    }
});         

Also this HTML for the button to generate the word doc:

<div id="generateword">
<form method="post" action="/createword.php" target="_blank" id="getword"> 
<input type="hidden" name="docname" id="docname" />
<input type="hidden" name="dochtml" id="dochtml" />
<input type="hidden" name="orientation" id="orientation" value="landscape" />
<input type="hidden" name="logourl" value="<?php echo get_user_meta(get_current_user_id(), 'reportlogourl', true); ?>" />
<input type="hidden" name="img_val" id="img_val" value="" />
<input type="hidden" name="imgname" id="imgname" value="<?php echo $_GET['teamid']; ?>.png" />
<input type="button" value="View in Word" id="createword" />
</form>
</div>

Finally - here's the PHP file I used:

<?php

header("Content-type: application/vnd.ms-word");
header("Content-Disposition: attachment;Filename=" . $_POST['docname'] . ".doc");

$filteredData=substr($_POST['img_val'], strpos($_POST['img_val'], ",")+1);
//Decode the string
$unencodedData=base64_decode($filteredData);
//Save the image
$imgfile = $_POST['imgname'];
//file_put_contents("/assets/teamstats/" . $imgfile, $unencodedData);
file_put_contents("assets/teamstats/" . $imgfile, $unencodedData);

$orientation = 'portrait';
if(isset($_POST['orientation'])) {
$orientation = 'landscape';
}
$logourl = '';
if(isset($_POST['logourl'])) {
$logourl = $_POST['logourl'];
}

echo '<html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
xmlns="http://www.w3.org/TR/REC-html40">
<head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><title></title>
<style>
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style>
<style>
@page
{
';
if ($orientation == 'landscape') {
    echo 'mso-page-orientation: landscape;
    size:29.7cm 21cm;    margin:1cm 1cm 1cm 1cm;';
}
else {
    echo 'mso-page-orientation: portrait;
    size:21cm 29.7cm;    margin:1cm 1cm 1cm 1cm;';
}
echo '
}
@page Section1 {
    mso-header-margin:.5in;
    mso-footer-margin:.5in;
    mso-header: h1;
    mso-footer: f1;
    }
div.Section1 { page:Section1; 
font-family:Helvetica; 
';
if ($orientation == 'landscape') {
    echo 'font-size:12px; ';
}
else {
    echo 'font-size:14px; line-height:20px;';
}
echo '
text-align:left;}
table#hrdftrtbl
{
    margin:0in 0in 0in 900in;
    width:1px;
    height:1px;
    overflow:hidden;
}
p.MsoHeader {
';
if ($orientation == 'landscape') {
    echo '    tab-stops:right 29.0cm;';
}
else {
    echo '    tab-stops:right 21.0cm;';
}
echo '
}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{
    margin:0in;
    margin-bottom:.0001pt;
    mso-pagination:widow-orphan;
';
if ($orientation == 'landscape') {
    echo 'tab-stops:center 14.5cm right 29.0cm;';
}
else {
    echo 'tab-stops:center 10.5cm right 21.0cm;';
}
echo '
    font-size:12px;
}

</style>
<xml>
<w:WordDocument>
<w:View>Print</w:View>
<w:Zoom>100</w:Zoom>
<w:DoNotOptimizeForBrowser/>
</w:WordDocument>
</xml>
</head>';
echo "<body>";
echo '<div class="Section1">';
echo $_POST['dochtml'];
echo '<style>h3, table {
margin-top:0px!important;
}
div.membername {
margin-bottom:0px!important;
margin-top:0px!important;
height:39px!important;
line-height:25px!important;
}
div.membername, span.membershape, span.membertraits {
height:39px!important;
line-height:25px!important;
padding:0px!important;
margin:0px!important;
}
h2.membername {
margin-top:0px!important;
margin-bottom:0px!important;
padding-top:0px!important;
padding-bottom:0px!important;
line-height:25px;
height:25px!important;
font-size:24px!important;
}
table.tdmembername, table.tdmembername tr, table.tdmembername td, table.tdmembername span {
background-color:black!important;
}
div.columncontainer {
margin-top:0px!important;
}
img.cobrandedlogo {
max-height:50px;
height:50px;
}
</style>
';
echo '
<br/>
    <table id="hrdftrtbl" border="0" cellspacing="0" cellpadding="0">
    <tr><td>        <div style="mso-element:header" id=h1 >
            <p class=MsoHeader ><img src="http://improvedemployees.com/img/logo-x50.png" style="height:50px" height="50px"/><span style=mso-tab-count:1"></span>';
if ($logourl != "") {
    $newheight = 50;
    list($originalwidth, $originalheight) = getimagesize($logourl);
    $ratio = $originalheight / $newheight;
    $newwidth = $originalwidth / $ratio;
    echo '<img class="cobrandedlogo" src="' . $logourl . '" height="50" width="' . $newwidth . '" />';

}
echo '</p>
        </div>
    </td>
    <td>
    <div style="mso-element:footer" id=f1><span style="position:relative;z-index:-1"> 
        <p class=MsoFooter>
           <span style=mso-tab-count:1"></span>
            www.improvedemployees.com
           <span style=mso-tab-count:1"></span>
           Page <span style="mso-field-code: PAGE "><span style="mso-no-proof:yes"></span> of <span style="mso-field-code: NUMPAGES "></span></span>
        </p>
    </div>



    <div style="mso-element:header" id=fh1>
        <p class=MsoHeader><span lang=EN-US style="mso-ansi-language:EN-US">&nbsp;<o:p></o:p></span></p>
        </div>
        <div style="mso-element:footer" id=ff1>
        <p class=MsoFooter><span lang=EN-US style="mso-ansi-language:EN-US">&nbsp;<o:p></o:p></span></p>
    </div>

    </td></tr>
    </table>
</div>';
echo "</body>";
echo "</html>";

?>

How can I resize the images I'm inserting into word (using HTML) using just the height or width, so that Word retains the aspect ratio?



Solution :

I've managed to solve this myself:

If you want to scale an image based on one side in word using HTML then this code will do it:

$newheight = 50;
list($originalwidth, $originalheight) = getimagesize($logourl);
$ratio = $originalheight / $newheight;
$newwidth = $originalwidth / $ratio;
echo '<img class="cobrandedlogo" src="' . $logourl . '" height="50" width="' . $newwidth . '" />';

Swap newheight and newwidth if you want to scale based on the width instead.


    CSS Howto..

    How can I reposition a DIV with jQuery? [closed]

    How to get table-row css and border property work together?

    How to create and apply CSS to javascript Alert

    How do I add a class to a default bootstrap class

    How to Layout a Watermark Image that is transparent along with a banner image and content div?

    Bootstrap: How to get part of my banner image to hide under my sidebar?

    Bootstrap: navbar showing a line

    How to make div stack first vertically then horizontally? [duplicate]

    How to slice an Image Border for use in CSS?

    How to get the CSS width of a mobile device in ASP.NET MVC?

    How to cancel left or right rules with an !important tag?

    Showing images next to paragraph

    How to make a pure CSS div with a gradient background?

    How do I get only two form fields to show instead of all 5 on initial page load? CSS

    How to override PrimeFace CSS to customize my button?

    How do I remove the text underline (that I set myself) from a on hover?

    How to trigger CSS-Filter animation on Click (or Scrolling)

    How to set Highcharts data series in x-axis using crosshairs?

    How to make div size bigger?

    How to make a site have a built in user-friendly editor?

    How to do CSS nth-child in span tags?

    How to set width of a
    in CSS to X number of pixels less than the width:auto?

    How to add element to existing css class [closed]

    How can I turn off hardware acceleration for certain HTML elements via CSS?

    how to show button and images in one line using css

    How to create a underline with small break in middle with css?

    How do I auto play my slideshow

    How to detect which button is clicked in javascript?

    How to allow my CSS slide out element to push its neighboring content?

    background image of div element can't show in php file