PDFGeneratorUtils - Image Handling - Get Height/Width of user photo

Nathan49
Tera Contributor

Hi All,

 

I have a requirement to get the height/width of a users profile photo with a business rule/script, based on all current reading this is a state secret, and we simply aren't allowed to have it.

 

I'd like to workflow ID Card creation, my solution is using a fillable PDF to send to the card printer, using the sign PDF sign feature to insert the user photo. The PDFGeneratorUtils have gotten me most of the way there, and great advice provided here helped: https://www.servicenow.com/community/developer-articles/add-an-image-signature-in-a-pdf-using-quebec...

 

I have everything working, Except for centering of the signature (user profile image).

 

I'm testing so far with the user record for Andrew Och in my PDI, as the profile photo is narrower and inserts too far left. (square images work very well).

 

The PDFGenerationAPI scales the image proportionally, I've got a solution to center the image by calculating an updated left margin, but I need the original image size to calculate this

 

if I can get the images height/width, as manually set in the code example below I can adjust the padding accordingly.

 

var original_width = 297; // from user profile photo
var original_height = 433; // from user profile photo
var newHeight = 107; // height set of PDF signature based on boxHeight
var pad_leftmargin = 23.5417; //default padding for square photo


var new_width = (original_width * newHeight) / original_height; // calculate the new width in points after PDF generator scales to boxHeight.

var pad_leftmargin = pad_leftmargin + (new_width / 4); // setup new margin padding by adding 1/4 of the photo width to push image to center.

 

 

The script to get the users photo (which is working) is:

 

    var userGr = new GlideRecord('sys_user'); // Needed for Employee ID & Photo

    if (userGr.get(requestedForSysId)) {
        var employeeid = userGr.employee_number || ''; // handle potential null value
        var photo = userGr.photo.getDisplayValue() || ''; //handle potential null value
        var photo = photo.substring(0, photo.length -4); // remove .iix from photo value to produce sys_id
    }

 

 

And the signature generation block currently in use for the PDF generation API:

 

// use the photo for as a signature, not the intended use but it works
    var signature = {
        pageNumber: 1,
        leftMargin: 23.5417, // To replace with pad_leftmargin
        topMargin: 50,
        boxWidth: 107,
        boxHeight: 107,
        attachmentImageSysId: photo
    };

 

 

It's frustrating that the sys_attachment table has blank height/width fields for the images seemingly by design.

 

Cheers,

Nathan

2 REPLIES 2

Nathan49
Tera Contributor

Solved ! (I'll credit the solve to another individual who isn't registered here, They know who they are).

 

It would appear that example users in the PDI don't have this data available to them, if you delete and re-upload the photos  (or put a new photo on another user) the basics work just fine, updated examples below.

 

(If you've circled back here for other image use cases, like catalog items the same may apply)

 

 

if (userGr.get('<insert_sys_id_of_user>')) {
        var photo = userGr.photo.getDisplayValue() || ''; //handle potential null value
        var photo = photo.substring(0, photo.length - 4); // remove .iix from photo value to produce sys_id of file in sys_attachment table
    }

var grimage = new GlideRecord("sys_attachment");
    if (grimage.get(photo)) {
        gs.info("Width: " + grimage.image_width + " and Height: " + grimage.image_height);
    };

 

With that solved, you'll see very quickly my mathetmatics aren't great, So here's a fix for that too..

 

var imagewidth = grimage.image_width; 
var imageheight = grimage.image_height;
var ratio = imagewidth/imageheight; // Note case if wide image is irelevant.. Squares? Good, Portraits? Good, Landscapes :{
var offmid = (ratio * 53.5); //Multiply ratio by box width/2
var midpoint = 77.0417; // how many pixels to the middle of the PDF.. mines CR80 2.13" x 3.38" for ID Cards
var hoffset = midpoint - offmid; // set hoffset to the leftMargin variable in the signature settings..

 

Nathan49
Tera Contributor

Solved.

 

the OOB images in the PDI don't let you get this detail, images uploaded to other user records do. If I download the image from andrew och, delete the pic from the sys_user record and re-upload it, it works.

 

Updated code sample below. Fingers crossed the image width/height holds up once images ingest (integration work for that is ongoing, I'm just getting ready to use it if I can).

    if (userGr.get(requestedForSysId)) {
        var employeeid = userGr.employee_number || ''; // handle potential null value
        var photo = userGr.photo.getDisplayValue() || ''; //handle potential null value
        var photo = photo.substring(0, photo.length - 4); // remove .iix from photo value to produce sys_id of file in sys_attachment table
    }

    // Get profile image so we can do some math on its dimensions
    var grimage = new GlideRecord("sys_attachment");

    if (grimage.get(photo)) {
        var imagewidth = grimage.image_width;
        var imageheight = grimage.image_height;
        var ratio = imagewidth / imageheight; // What if it's a landscape image (not portrait)? a logic test and more math will fix that
        var offmid = (ratio * 53.5); //Multiply ratio by box width/2
        var midpoint = 77.0417; // width of my page, CR80 ID Card 2.13 x 3.38 inches
        var hoffset = midpoint - offmid; // set this as your leftMargin for the signature
    };