imagesassas-stored-process

Use image in a SAS Stored Process's HTML Stream


I am creating a report with SAS STP and I want to display a image(a logo) on the report. Okay here is what is happening:

data _null_;
    file _webout;
    put '<html>';
    put '</html>';
run;

I am PUTing HTML because I have complex table formats which I need to display and I am not using %STPBEGIN & %STPEND because that opens up an ODS Stream which frankly I do not know how to handle and I am having problems. Not using %STPBEGIN means the above code. This has been a very successful mechanism for me. I can show beautiful reports with CSS and everything. The only problem is images. A client has recently requested to put logo on every report. i though this was going to be easy but it has not been. Ok here is the deal, I tried to use <img src=" "/ > tag and I thought I would use some relative path and my image will show. This technique succeeded and failed.

I am stuck, how can I use a custom images here?


Solution

  • If your image is static, you can embed it into your results using a datastep without having to copy files to the server.

    The trick to doing this is to encode the image into Base64 encoding, then you can embed the image into an <img src="" /> statement by using this magical notation:

    <img src="data:image/png;base64,...." />
    

    You can see that the src= attribute contains metadata to tell the browser that the value contains image data, that represents a png file (I used a png file when testing this post, you may have a JPG/BMP etc...) and that the value is encoded using base64. The 4 periods at the end would be replaced by your image data represented in base64 notation. This would look something like this:

    <img src="data:image/png;base64,iVBORw0KGgoAAAAN ... much much more base64 content here ... HSLyz+h9xy+7HbHRL83L1tv9h8+4d/+Ic/Gf8DiYav3mpqHAMAAAAASUVORK5CYII=" />

    Converting your image to base64 is simple. You can simply google for an "online base64 image converter" such as this one. Drag and drop your image and it will produce your base64 code for you.

    To get this into a datastep in sas, it's simply a case of:

    data _null_;
        file _webout;
        put '<html>';
        put '<img src="data:image/png;base64,iVBORw0KGgoAAAAN......etc..." />';
        put '</html>';
    run;
    

    If you image is particularly big (say greater than ~32k) you may run into issues trying to output it from a datastep. I probably need to test this to clarify. You can work around this by reading the base64 image from a file in SAS and streaming it directly to _webout, using code similar to below:

    data _null_;
      file _webout;
      infile '\path\to\base64\file.ext';
      input;
      put _infile_;
    run;
    

    If you want to get really tricky, you can take any image you like (such as a chart generated in SAS) and convert it to base64 on the fly, then stream it out. Here is some SAS code that will take an image file and convert it to Base64:

    data _null_;
      length base64_format $20 base64_string $32767;
    
      infile "\your_sasdir\hi.png" recfm=n;
      file "\your_sasdir\hi.base64";
      input byte $16000. ;
    
      * FORMAT LENGTH NEEDS TO BE 4n/3 ROUNDED UP TO NEAREST MULTIPLE OF 4;
      format_length = 4*(lengthn(byte)/3);
      mod = mod(format_length,4);
      if mod ne 0 then do;
        format_length = format_length - mod + 4;
      end;
      base64_format = cats("$base64x",format_length,".");
    
      base64_string = putc(cats(byte), base64_format);
      put base64_string;
    run;
    

    Here is the image I used to test this with:

    enter image description here

    Once converted, the Base64 representation should look like:

    iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABaSURBVDhP5YxbCsAgDAS9/6XTvJTWNUSIX3ZAYXcdGxW4QW6Khw42Axne81LG0shlRvVVLyeTI2aZ2fcPyXwPdBI8B999NK/gKTaGyxaMX8gTJRkpyREFmegBTt8lFJjOey0AAAAASUVORK5CYII=
    

    I'm going to see if I can find a way to streamline this as this is something we do frequently at work.


    EDIT : Interestingly, SAS9.4 seems to support doing this directly using ODS HTML5 in conjunction with the inline option. See the doc here.

    See also this post, by Don Henderson, that provides a similar way to approach this problem. Thanks to Vasilij for the link.