How to print and resize an image from a DataTable

Hello guys,

Please I need help printing an image in client code. I have a server function that accepts an
input and returns an image based on the input as a BlobMedia object. I would like for the user to print this image and I don’t know how to go about it. Thanks in advance for your time and support.

I don’t know that Anvil has a straigtforward way to initiate print operations from the client’s computer (I could be wrong).

However, perhaps this previous topic will help you:

Or, if it is sufficient you can set a Link component’s URL to your media object or call:

download(media_object)

to download the media, and instruct the user to print the file using the usual approach (e.g., CTRL + P).

Hopefully this helps in some way.

1 Like

Thanks @alcampopiano for your response. I have tried setting a Link’s url property to the image but it insteads download the image when it’s clicked. I have also tried modifying @shaun’s solution to print an image but I haven’t succeeded yet.

Please find my code sample below

Javascript function



  function printImage(image){ 
    var printWindow = window.open('_blank');
    printWindow.document.open('image/svg+xml');
    printWindow.document.write(image);
    printWindow.print();
    printWindow.close(); 
  } 


In my client code I have this:

image = anvil.server.call('get_image', param)
self.call_js('printImage', image) 

When I call the javascript function, the image passed is None and it doesn’t work.
Please how can I modify my code for it to work. Thanks.

I managed to allow for a picture to be printed.

I embedded the image into an HTML block and passed the HTML to the JS function. Perhaps you could modify that to fit your needs.

Clone to try out:
https://anvil.works/build#clone:PX5GKSARBZ6AZUDK=PKX5EX72W5K3V4X3T2L67G5W

# client code for the "click" event callback
# assumes you have an Anvil Image component named image_1 on your form

def button_1_click(self, **event_args):
  """This method is called when the button is clicked"""

  image_source=get_open_form().image_1.source
    
        
  html="""
  <h1> My Image </h1>
  <img src={image_url}>
  """.format(image_url=image_source.url)
    
  self.call_js('printPage', html)
// JS inside the custom HTML editor

function printPage(html){
  var printWindow = window.open('_blank');
  printWindow.document.open('text/html');
  printWindow.document.write(html);
  printWindow.print();	
  printWindow.close();
  }

I’m sure there is a better way since I know very little about JS, but this seems to allow the printing of an image.

I hope this helps.

1 Like

Thanks again @alcampopiano for all your help and time, I really appreciate your help. With your help I’ve made significant progress but I still have some issues.

What exactly I’m trying to do is this: I have a server function that accepts input from the client, generate an image(specifically a barcode) and stores it in the database.

After the image has been generated and stored. In the client, I read the image from the database, display it and print it.

This is the code in the client

    #This server function generates a barcode and stores it in the database
    anvil.server.call_s('generate_barcode', "12345678901114")
    
    #Get image from database and display
    barcodeTable = app_tables.barcode.client_writable()
    barcode_image = barcodeTable.get(number="12345678901114")['media'] 
    self.image_1.source = barcode_image
    
    #Delete media from database
    barcodeTable.get(number="12345678901114").delete()
    #print("Source.url: ",barcode_image.url)
    
    image_url = barcode_image.url

    html = """Image is here""".\
    format(image_url=image_url)
    
    #print("Html: ", html)
    
    self.call_js('printPage', html)

This is the javascript function that prints the image

function printPage(html)
  	{
      var printWindow = window.open('_blank');
      printWindow.document.open('text/html');
      printWindow.document.write(html);
      printWindow.print()
      printWindow.close()
    }

When I get the url of the media from the database, the url contains a “=” and because the url has an equality sign, when the url is set as the src of the image in the html, it doesn’t work.

This is the link to copy the app. Once again, thank you for your time and support. I really appreciate it, it means a lot to me.
https://anvil.works/build#clone:QDR7E6CWXSQMWAFE=OMSOJO6RQZGQQ47P7ZR3OYJO

Hi Agobin,

My clone of your app seems to work for me in Firefox. In Chrome, I don’t get any errors in App Logs but the print comes out blank.

If = in the URL is causing you problems, perhaps you can try using a public URL? That won’t have the access token in it, so it won’t include an =. (Of course, that means somebody could find your app and access it, but you don’t seem to be exposing any sensitive data.)

1 Like

Thank you guys so much for all your support. I finally found a fix by getting the raw binary data (get_bytes()) of the image and just writing it to my html page.

This was able to display the image but the dimension was too small. The barcode printer didn’t print the barcode correctly because it was too small. Any ideas on how I could change the dimension? I have tried the following:

  1. Using PIL to resize the image but when I call Image.open(barcode_image.get_bytes()), PIL doesn’t recognize the image type.

  2. I have tried encoding the url of the generated image, read from the database to a base64 string and setting it as the source of the image in my html, the image didn’t display at all. I wonder why.

  3. I have tried encoding the url with javascript’s encodeURIComponent to eliminate the “=” from the image’s source, and setting it as the source of my image in html, this didn’t work either.

Any thoughts on how I could go about modifying the dimension of the svg image so that it occupies the whole html page, in order to be printed accurately by the barcode printer?

Thanks for all your contributions.

Probably a couple ways to do that but have you tried the PIL instructions here?

If that doesn’t work, is it possible to share your app

I actually used that as a reference for my resize_image function.
This is a clone of the app.
https://anvil.works/build#clone:NCRR2UFVBBD5ZIFR=G2GNWORPCU5LZKDPSTVRJ3WT

Hmm, I though I could just add height and width parameters to the HTML in your printImage JS function. Example:

html = "<img src=\"" + url + "\" alt='Barcode image' width=\"100\"/>"

But first I get the error (at the JS function):

"ExternalError: TypeError: Cannot read property 'document' of null"

Then if I click the button again, it initiates the print, but the image is still just as small.

Maybe I messed up my JS syntax, but anyway, I’m sorry I can’t be of more help here.

1 Like

When you run the program, all the different methods that I try to display the image run. When you run the program, you’ll see the alert box that pops up notifying you of which method is about to run/execute.

Thanks for all your help @alcampopiano

Yes, I am aware of that as I had run the app yesterday when I wrote my previous message.

As I noted above, I was unable to find a way to increase the image size.

I’m sure it is possible though. Someone more skilled than I will likely solve the problem.

@Agobin

Okay, I modified @bridget’s recent app (since it was easy to work with), and managed to resize the barcode image for printing. This works when using the image’s URL, not the base64 encoding.

As @shaun mentioned above, Chrome does not show any print image, so I suggest using Firefox.

So, basically, just add the width and height parameters to your HTML, as I mentioned above:

Your client-side Python (likely triggered by a button click)

def initiate_print_window_for_image(self, **event_args):

    # get image from DataTable
    image = app_tables.images.get(name='barcode')['img']

    # get the image's URL
    url = image.url

    # make some HTML with width and height parameters
    html = '<h1>Hello</h1><img src="{0}" width=1000 height=1000 />'.format(url)

    # call the JS function to initiate print window
    self.call_js('printPage', html)

Your JS function:

function printPage(html){
    var printWindow = window.open('_blank');
    printWindow.document.open('text/html');
    printWindow.document.write(html);
    printWindow.print()
    printWindow.close()
    } 

Side-by-side comparison of the original and modified barcode images:

Clone app:

I hope this helps.

4 Likes

Thanks very much @alcampopiano, you’ve been immensely helpful. This approach works fine, but for some reason, it doesn’t work with the base64 string of the svg file created with the

generate_barcode() function 

I found another fix by drawing the image on a canvas to the required dimension, and using:

get_image() 
on the canvas element to get the drawn image in png format, and setting the url of the image (which is a base64 string) as the source of my image in html. This works fine!!!

Yeah, the necessities of the request kind of changed under my feet a bit here. I’m glad to hear it is all sorted out.

Lots of good information here for future visitors to learn from.

Indeed, should someone ever need to implement this in the future, I hope this thread helps them, though I believe there is a more efficient way of doing this. They won’t have to go through what I went through to figure this out.

1 Like