Is it possible to create encoded base64 URL from Image object?
I am looking to create base64 inline encoded data of images for display in a table using canvases. Python generates and creates the web page dynamically. As it stands python uses the Image module to create thumbnails. After all of the thumbnails are created Python then generates base64 data of each thumbnail and puts the b64 data into hidden spans on the user's webpage. A user then clicks check marks by each thumbnail relative to their interest. They then create a pdf file containing their selected images by clicking a generate pdf button. The JavaScript using jsPDF generates the hidden span b64 data to create the image files in the pdf file and then ultimately the pdf file.
I am looking to hopefully shave down Python script execution time and minimize some disk I/O operations by generating the base64 thumbnail data in memory while the script executes.
Here is an example of what I would like to accomplish.
import os, sys
import Image
size = 128, 128
im = Image.open("/original/image/1.jpeg")
im.thumbnail(size)
thumb = base64.b64encode(im)
This doesn't work sadly, get a TypeErorr -
TypeError: must be string or buffer, not instance
Any thoughts on how to accomplish this?
Solution 1:
You first need to save the image again in JPEG format; using the im.tostring()
method would otherwise return raw image data that no browser would recognize:
from io import BytesIO
output = BytesIO()
im.save(output, format='JPEG')
im_data = output.getvalue()
This you can then encode to base64:
image_data = base64.b64encode(im_data)
if not isinstance(image_data, str):
# Python 3, decode from bytes to string
image_data = image_data.decode()
data_url = 'data:image/jpg;base64,' + image_data
Here is one I made with this method:
data:image/jpg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCACAAIADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigAooooAKwde8Y6D4aQ/2nqEccuNwhU7pG/4CKx/iX4zfwd4eEtqEN/cv5cAb+Hj5nx3xx+JFfMF3fXN/dSXN1M808rbnkc5LE0mwPeNU+PGkwoRpmm3NxJ6zkRr+mTWK/wAfb8x4TRLYP6mViPyryq10XVL5A9rp11Mn96OFmH5gVfj8H+IWOP7GvR/2xap5l3HZnpNt8fbsSD7VokDJ38qYqf1Brp9D+Nfh7UW2ajHLpshOAW/eIf8AgQHH5V4o3gnxGASNGvDj0iNUbjSL6y/4+rO4g/66xMv86FJPZhys+u7HUbLU7fz7G7guYTxvhkDj8xVuvjzS9b1Tw9fLc6Zey28gI+43DezDuPY19QeB/EbeKfClpqciqs7ZSZU6B1OD+fX8apMR0dFFFMAooooAKKKKACiiigD5u+NuqzXvjo2DcQ2MKIg93UMT+o/Kt/wJ4As7LT4NR1O3Sa+lUSKkgysQ7cetYPju2Gq/G97OQBkea3Rgf7uxC36ZrvPGmsz6F4amubQhZiRGjldwTPfFcmIk9IR6m9KK1kzpkjQD5AMDtUoTHSvIPhl4s1XVNYS1ubme6DKzz+ZGAseD8u1h1/KvZVHNcc4OErM6Iy5ldDVHA45oeOCVTHKiujcFWXIP4VMi5GO9fPuqeLvENv4y1BXm1EXCShbaFMLEp3DKsuDuXGR2PQ1VODnsKU+U6H4meAbexs21rSIRHCp/0iFBwuf4l9B6itX4B30pXWLAsTEvlzKPRjkH+Q/Ku8vkN54YuUnjGZbVg6H1KmvNfgJME1vV4CeXt1cD/dbH/s1dmHm5KzOetFJ3R7zRRRXSYhRRRQAUUVyXi74iaH4PxDdyNPesu5baHBYD1b+6KAOtorxf/hoG36f8I/J/4FD/AOJqpffH6ZomWz0FUc9GluNwH4BRSA5bxNr0Fn8a7vVJRvgt7wI+OcBVCE/hj9K9aivdH1mwIFxZ3dpIvILqwI9xXzPcXE11dzXM775pnLux/iYnJqLNYVaPtNTSnU5D6dsU8PaOjCzfT7Td94q6gn61cbxFosX+s1iwX63Cf418sq3NSbiO9ZfVe7NPb+R9RJ4q8P4z/benf+BKf41HJrHhGa6S7lv9Ge4X7srSxlx+PWvmRJOeSalEhC9x9Kf1Vdxe28j3fxh8SdEsdHubXTrlLy9ljaNPK5RMjG4t049q8/8AgxqP2T4hW8RbC3UMkJ/LcP1UVw5y55yTU+j6nPoWt2ep265ltpVkUHocdj9a2p01TWhlObkfZVFeU2Hx30CaIfbrC+tpO4QLIv55B/Srcnxy8KoQEh1GT3EKj+bVqSel0Vg+G/GGi+KoGl0u63sn34nG10+o/rW9TArX9yLPT7m6K7hDE0mPXAzXxrqup3OralcX95KZLidy7sfWvrjxe0y+DtZNum+YWU21f+AGvjl+DSAA2DS76jzSHjvSAl3CkJqEHNPzQBID83pUvT3quDzT1bNAEoJGKeDUOcUoegCyHx7+opGcE8jn1qv5mO5ppk5wKALW1OTnA9KcCmKo7yKkWT6UAdD4W12Xw54lstSjJxDKN6A43IfvL+VfXKOJI1deQwyK+Ko23MtfZumKV0qzUnJECAn1+UUwLLKGUqQCDxg18w/Er4c33hnVJ760gMukzuWjeNSfJzzsb09jX1BSEBhgjIpgfDeDyKawNfap0HRjKZDpNiXPVvs6ZP44p8ui6VNEY5dMs3Q/wtApH8qVgPicCn4x1rqfiHokPh/x1qlhbIEgWQPEg6KrKGC/hux+FcuaQhueeKUdabRmgCdenpTgKiVvenhs0DApimgU8/N3rd8IaOmueKtN02XPlTzqsmOPl6t+gNAHPeW7thVJ9gKmWzuCceS+RzjbX2Xp+iaXpMCQ2On21tGnQRRAVeEaA5CDPrinYD5S8EeB9R8VaxFCsMkVmrZuLgr8qr6A+voK+rY4xFEka8KoAFOAA6DFLTAKKKKACiiigD5l+N8bL8Q5mOMNbxFcemMf0rzVq9J+Nu//AIWJcb8bfs8W3Hpt/wAc15sxqRDDzSCn96aRg0AKKeDUfHSnA+tAEymuu+Gz7PiForetwB+YIrkB9a634cjd4+0b/r5WgZ9Z0Ug6UtUAUUUUAMSRHGVYGnVwVvq1wmMOavJ4guFH3qm5XKdhSEgCuRPiWUdWFV5/EUjr980XDlPHfjfKJPH74TaBbRjP97rz/T8K80Ndv8UbtrzxZvZs7YEX+Z/rXEdaCRMZ5FNbg89DUgrs/hl4OtfGfio2d+zizghM8qocF8EALnt1/SgRwwb5sU8V6D8YvBemeEfEFgdIiMNpdwFvJLltrKcHBJzzkfrXn69KAHqea7r4VQ+b8Q9JXHR2bn2RjXDL1r0L4PIG+I2nn+6kp/8AIbUDPp+iiiqAKKKKAMCPw3EB8zUTeHUKnYwJrfozSsPmZ59qGh3cGWWI7fWsGXfCSH4r11lVlIIBB7Vi6l4YstQU8eWx7ilYdz5p+IwB1yFxg7rden+81cbwa988ZfCXU9ViWSxlhlmizsBbbuB7HNefN8H/ABuD/wAgXP8A28xf/FUEs4Va9C+D+qHSfGhkIzFJbsknsMqf6UkPwZ8aSMA2mxRj1a5j/oa9M8FfCNNI0yZtVn/0+fGfJOVjUds96AOF+O+pR6nrmkmFt0Mdu+D7luf6V5Wte8eLPhFq+ooBaTxXAQ5jLNtYexz/AI1wFx8I/GluxA0dpR6xyof/AGagDiV613Hwr83/AIWNpHlHne2f93Y2f0qsnww8ZF9v9g3WffaB+ea9i+GHwzl8LSNq2qsrag6bI4l5EIPXnue350wPUKKKKYBRRRQB/9k=
Unfortunately the Markdown parser doesn't let me use this as an actual image, but you can see it in action in a snippet instead:
<img src="data:image/jpg;base64,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"/>
Solution 2:
thumb = base64.b64encode(im.tostring())
I think would work
Solution 3:
In Python 3, you may need to use BytesIO
:
from io import BytesIO
...
outputBuffer = BytesIO()
bg.save(outputBuffer, format='JPEG')
bgBase64Data = outputBuffer.getvalue()
# http://stackoverflow.com/q/16748083/2603230
return 'data:image/jpeg;base64,' + base64.b64encode(bgBase64Data).decode()
Solution 4:
I use PNG when I save to the buffer. With JPEG the numpy arrays are a bit different.
import base64
import io
import numpy as np
from PIL import Image
image_path = 'dog.jpg'
img2 = np.array(Image.open(image_path))
# Numpy -> b64
buffered = io.BytesIO()
Image.fromarray(img2).save(buffered, format="PNG")
b64image = base64.b64encode(buffered.getvalue())
# b64 -> Numpy
img = np.array(Image.open(io.BytesIO(base64.b64decode(b64image))))
print(img.shape)
np.testing.assert_almost_equal(img, img2)
Note that it will be slower.