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.
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.
# 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.
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 = """""".\
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.
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.)
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:
Using PIL to resize the image but when I call Image.open(barcode_image.get_bytes()), PIL doesn’t recognize the image type.
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.
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?
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.
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:
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!!!
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.