Python - fetching image from urllib and then reading EXIF data from PIL Image not working - python-2.7

I use the following code to fetch an image from a url in python :
import urllib
from PIL import Image
urllib.urlretrieve("http://www.gunnerkrigg.com//comics/00000001.jpg", "00000001.jpg")
filename = '00000001.jpg'
img = Image.open(filename)
exif = img._getexif()
However, this way the exif data is always "None". But when I download the image by hand and then read the EXIF data in python, the image data is not None.
I have also tried the following approach (from Downloading a picture via urllib and python):
import urllib
f = open('00000001.jpg','wb')
f.write(urllib.urlopen('http://www.gunnerkrigg.com//comics/00000001.jpg').read())
f.close()
filename = '00000001.jpg'
img = Image.open(filename)
exif = img._getexif()
But this gives me 'None' for 'exif' again. Could someone please point out what I may do to solve this problem?
Thank you!

The .jpg you are using contains no exif information. If you try the same python with an exif example from http://www.exif.org/samples/ , I think you will find it works.

Related

Kernel restarts when compressing tif file using PIL in Anaconda

I'm trying to compress a bunch of tiff files with the pillow package. However, when I'm executing the code in python3.7.13 in Spyder IDE within the Anaconda3 environment, the Kernel restarts in the line in which the tiff file should be compressed. I tried different compression methods (e.g. "group4", "zlib", "deflate", etc..).
I also tried other packages like libtiff and tifffile, but the same problem occurs here as well.
import os
import glob
from PIL import Image, TiffTags
from IPython.display import display
import numpy as np
images = [file for file in os.listdir("C:/Home/Slicer/tif") if file.endswith('tif')]
#search for alle the images in the path
for image in images:
img_name = str(image)
img = Image.open("C:/Home/Slicer/tif/"+img_name)
print(img_name + str(img))
display(img)
#save tiff file with new name
img.save("C:/Home/Slicer/tif/" + "compressed" + img_name, compression="tiff_lzw")
Console output

Convert image to PDF with Django?

Receive multiple images as input from the user and convert them into PDF. I don't understand how to implement it with Django.
Use this command to install the packages
pip install img2pdf
Below is the implementation:
Image can be converted into pdf bytes using img2pdf.convert() functions provided by img2pdf module, then the pdf file opened in wb mode and is written with the bytes.
# Python3 program to convert image to pfd
# using img2pdf library
# importing necessary libraries
import img2pdf
from PIL import Image
import os
# storing image path
img_path = "C:/Users/Admin/Desktop/GfG_images/do_nawab.png"
# storing pdf path
pdf_path = "C:/Users/Admin/Desktop/GfG_images/file.pdf"
# opening image
image = Image.open(img_path)
# converting into chunks using img2pdf
pdf_bytes = img2pdf.convert(image.filename)
# opening or creating pdf file
file = open(pdf_path, "wb")
# writing pdf files with chunks
file.write(pdf_bytes)
# closing image file
image.close()
# closing pdf file
file.close()
# output
print("Successfully made pdf file")
Pillow supports PDF format. Documentation is available here.
from PIL import Image
img = Image.open('/path/to/image.jpg')
img = img.convert('RGB') //This removes alpha channel from .png images.
img.save('/path/to/image.pdf', format="PDF")

Load an html5 canvas into a PIL Image with Django and save it in new File

I test this example : question source : Load an html5 canvas into a PIL Image with Django
import re
datauri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUg
AAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8 /w38GIAXDIBKE0DHxgl
jNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
imgstr = re.search(r'base64,(.*)', datauri).group(1)
output = open('output.png', 'wb')
output.write(imgstr.decode('base64'))
output.close()
but I have an error on this line:
output.write(imgstr.decode('base64'))
here is the error: File "C:\django_projects\intranet\intranet\capture\views.py", line 19, in enregistre_image output.write(imgstr.decode('base64')) AttributeError: 'str' object has no attribute 'decode'
could you tell me what I'm doing wrong thank you Christophe
Your code works fine in python-2.x (you probably searched for a solution in Python, and got a version that worked in python-2.x).
In python-3.x, a string has no .decode(..) method anymore. You can use the base64 library:
from base64 import b64decode
output.write(b64decode(imgstr))

Displaying PNG in matplotlib.pyplot framework in python 2.7

I am pulling PNG images from Jupyter Notebooks and manage to display with IPython.display.Image but not with matplotib.pyplot.plt. What am I missing? I use python 2.7.
I am using the following algorithm:
To open the notebook JSON content I do:
import nbformat
notebook_ = nbformat.read(file_notebook, 4)
After retrieving the relevant cell information I pull the png information from it using:
def cell_to_image(cell, out_value_item_number=1):
if "execution_count" in cell.keys(): # i.e version >=4
return cell["outputs"][out_value_item_number]['data']['image/png']
elif "prompt_number" in cell.keys(): # i.e version < 4
return cell["outputs"][out_value_item_number]['png']
return None
cell_image = cell_to_image(cell)
The first few characters of cell_image (which is unicode) looks like:
iVBORw0KGgoAAAANSUhEUgAAA64AAAFMCAYAAADLFeHSAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n
AAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xd8jef/x/HXyTjZiYQkCGrU3ruR0tr9oq2qGtGo0dbe
\nm5pVlJpFUSMoVb6UoEZ/lCpatWuPUiNEEiMDmef3R75OexonJKUO3s/HI4/mXPd1X/d1f+LRR965
\n7/u6DSaTyYSIiIiIiIiIjbJ70hMQERERERERyYiCq4iIiIiIiNg0BVcRERERERGxaQquIiIiIiIi
\nYtMUXEVERERERMSmKbiKiIiIiIiITVNwFRGRxyIkJIRixYqxfv36+24/e/YsxYoVo3jx4v/yzGxb
\naGgoderUIS4uDoBdu3bRsmVLKlasyCuvvMKgQYOIjo622CcsLIyGDRtSunRp6tSpw8KFC62OW7p0
\naRo2bJju53Lnzh1GjRrFyy+/TNmyZWnRogW//fbbQ835q6++olGjRpQvX5769eszc+ZMkpOTzdtT
\nU1OZNGkSNWrUoHTp0jRp0oTdu3enGyc2NpZOn
I can easily plot in my Jupityer notebook using
from IPython.display import Image
Image(cell_image)
And now to my question:
How can I manipulate cell_image to be plt.subplot friendly?
(Assuming import matplotlib.pyplot as plt).
I realise that plt.imshow wouldn't work because this would require an array, which is not my case (which is a string, as far as I understand).
If you have your image string representation in a variable string_rep, the following code should work.
from io import BytesIO
import matplotlib.image as mpimage
import matplotlib.pyplot as plt
with BytesIO(string_rep.decode('base64')) as byte_rep:
image = mpimage.imread(byte_rep)
plt.imshow(image)

How to put an image resized with Pillow into GridFS?

Scenario
I use a formData form to upload an image via ajax which is then added to a MongoDB GridFS database.
This was working:
my_image = request.files.my_image
raw = my_image.file.read()
fs.put(raw)
Desired Behaviour
I want to resize the image with Pillow before adding to GridFS.
What I Tried
I changed the above to:
my_image = request.files.my_image
raw = Image.open(my_image.file.read())
raw_resized = raw.resize((new_dimensions))
fs.put(raw_resized)
Actual Behaviour
I am now getting 500 errors. Tail shows:
TypeError: file() argument 1 must be encoded string without NULL bytes, not str
Question
How do I properly handle the Pillow image object so that I can add it to GridFS?
Troubelshooting
This is still unresolved, but I'm just adding my attempts to understand what is happening with file types etc at different stages of the process by using the interpretor:
>>> my_image = open("my_great_image.jpg")
>>> my_image
<open file 'my_great_image.jpg', mode 'r' at 0x0259CF40>
>>> type(my_image)
<type 'file'>
>>> my_image_read = my_image.read()
>>> my_image_read
# lots of image data
>>> type(my_image_read)
<type 'str'>
>>> my_pil_image = Image.open("my_great_image.jpg")
>>> my_pil_image
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x267 at 0x2760CD8>
>>> type(my_pil_image)
<type 'instance'>
So from this I think I can deduce that, originally, GridFS was accepting of the string version of the image generated from the read() method.
So I think I need to somehow make the Pillow image object a string in order to get it into GridFS.
Solution
Wo, check this out, it works, the logic is:
Form uploads image,
Pillow does three different resizes,
Use StringIO to convert Pillow objects to strings
Put resized images, as strings, in GridFS.
Python
from PIL import Image
import StringIO
# define three new image sizes
card_dimensions = (108,108)
main_dimensions = (42,38)
thumb_dimensions = (18,14)
# covert uploaded image to Pillow object
raw_pil = Image.open(my_image.file)
# conversion to card size
raw_card_output = StringIO.StringIO()
raw_card = raw_pil.resize((card_dimensions))
raw_card.save(raw_card_output,format=raw_pil.format)
raw_card_output_contents = raw_card_output.getvalue()
# conversion to main size
raw_main_output = StringIO.StringIO()
raw_main = raw_pil.resize((main_dimensions))
raw_main.save(raw_main_output,format=raw_pil.format)
raw_main_output_contents = raw_main_output.getvalue()
#conversion to thumb size
raw_thumb_output = StringIO.StringIO()
raw_thumb = raw_pil.resize((thumb_dimensions))
raw_thumb.save(raw_thumb_output,format=raw_pil.format)
raw_thumb_output_contents = raw_thumb_output.getvalue()
# put card image into GridFS
fs.put(raw_card_output_contents)
# put main image into GridFS
fs.put(raw_main_output_contents)
# put thumb image into GridFS
fs.put(raw_thumb_output_contents)
Further Explanation
Basically I deduced that GridFS was accepting a string, so therefore I needed to transform the Pillow object into a string.
The interpreter troubleshooting below should make some of the dynamics clearer and carries on from the troubleshooting in the original post:
>>> my_pil_image
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x267 at 0x2760CD8>
>>> my_pil_image_resized = my_pil_image.resize((50,50))
>>> my_pil_image_resized
<PIL.Image.Image image mode=RGB size=50x50 at 0x2898710>
>>> output = StringIO.StringIO()
>>> my_pil_image_resized.save(output,format="JPEG")
>>> contents = output.getvalue()
>>> type(contents)
<type 'str'>
>>> contents
# lots of image data
So basically the above process show the mechanics of how to convert the Pillow object into a string which can then be added to GridFS.
I just got a simple way to do this with flask.
I am using FileStorage for file holder before uploading to gridFS.
It also help me to wrap image from pillow after resize.
Document looks like this.
from mongoengine import Document ImageField
class SomeDocument(Document):
icon = ImageField(required=False, collection_name="collection_name")
And the controller is
from io import BytesIO
from werkzeug.datastructures import FileStorage
from PIL import Image
im = Image.open(request.files.get('icon'))
im.thumbnail((400, 400))
output = BytesIO()
im.save(output, format=im.format, quality=90)
original_extension = request.files.get('icon').filename.rsplit('.', 1)[1].lower()
SomeDocument.icon.put(FileStorage(output, content_type=f"image/{original_extension"))
SomeDocument.save()
im.close()