Previously I tried to rotate the image on the server side using PIL and it failed. The cause is the following error
".../PIL-1.1.7/PIL/ImageFile.py", line 476, in _save
fh = fp.fileno()
UnsupportedOperation: fileno
There seems to be something wrong with fileno (). If you search the net, you can see other people who are struggling with this error. I'm not sure about this error.
So this time, as a plan to overcome this, I will try to rotate it on the server side using GAE's ** Images Python API **.
** What is the Images Python API ** A function to operate image data provided by App Engine. You can resize, rotate, flip, and crop the image. The API can also extract information about the image, such as format, width, height, and histogram of color values. You can either receive data from the app or use Google Cloud Storage values. In addition to the Images API, you can also use the transformations provided by the Python 2.7 ** Python Imaging Library (PIL) **. (For more information, click here](https://cloud.google.com/appengine/docs/standard/python/images/))
from google.appengine.api import images
binary = base64.b64decode(base64_string)
gae_img = images.Image(binary)
I will get EXIF information from here, but when I get it using the Image Python API, I get an error if I do not follow the steps below.
# 1.Some processing on the image(conversion)
gae_img.rotate(0)
# 2.Perform conversion to image
gae_img.execute_transforms(parse_source_metadata=True)
# 3.Get EXIF information
exif = gae_img.get_original_metadata()
To explain step by step, I want to get EXIF information suddenly with gae_img.get_original_metadata ()
, but to do this, I want to do this with gae_img.execute_transforms (parse_source_metadata = True)
in the source image metadata (EXIF). Need to be analyzed.
As mentioned above, this gae_img.execute_transforms ()
is a method that "performs a transformation on the image", so before doing this, "assuming that the image has been transformed" is there. So, before this, I purposely wrote a seemingly meaningless process called gae_img.rotate (0)
. This gae_img.rotate ()
will be explained later.
So far, print exif
{u'MimeType': 0, u'ColorProfile': False, u'Orientation': 6, u'ColorSpace': 1, u'ImageWidth': 3264, u'ImageLength': 2448}
You can see that it is a dictionary type. The orientation of the image can be determined by the item ʻOrientation`.
print exif['Orientation']
# "1"From"8"Any of the numbers up to is output.
Now you can get the EXIF information.
I will summarize what I have done so far.
from google.appengine.api import images
binary = base64.b64decode(base64_string)
gae_img = images.Image(binary)
gae_img.rotate(0)
gae_img.execute_transforms(parse_source_metadata=True)
exif = gae_img.get_original_metadata()
From here, rotate the image based on ʻOrientation in ʻexif
.
if exif['Orientation'] == 3:
gae_img.rotate(180)
elif exif['Orientation'] == 6:
gae_img.rotate(90)
elif exif['Orientation'] == 8:
gae_img.rotate(270)
else :
gae_img.rotate(0)
converted_img = gae_img.execute_transforms(parse_source_metadata=True)
You can rotate the image by 90 degrees with gae_img.rotate ()
.
As mentioned above, due to the nature of gae_img.execute_transforms ()
, an error will occur if the image is not converted once, so ʻelse` is used to perform the conversion once.
This time, I don't think that the images that are flipped upside down or flipped horizontally are not sent, so the processing for 2,4,5,7 is not written.
Then, after rotating, execute gae_img.execute_transforms (parse_source_metadata = True)
to execute the changes made to the image.
From here, upload to Cloud Storage. As a procedure
import cloudstorage as gcs
def upload_gcs(self, name, type, binary):
#Extract environment variables
env = os.getenv('SERVER_SOFTWARE')
#Upload to Google Cloud Storage in any environment
if (env and (env.startswith('Google App Engine/') or env.startswith('Development/'))):
# FileLogic.GCS_The ID contains a url that indicates the location to save.
file_url = FileLogic.GCS_ID + name
#Open file with Google Cloud Storage API
with gcs.open(file_url, 'w', content_type=type, options={'x-goog-acl': 'public-read'}) as gcs_file:
#Writing (uploading) images
gcs_file.write(binary)
# FileLogic.GCS_HOST_The host name is pre-filled in NAME
file_url = FileLogic.GCS_HOST_NAME + file_url
else:
#Write locally if not in any environment
file_url = 'local_file/' + name
with open(file_url, 'w') as file:
file.write(binary)
return file_url
Open with the Google Cloud Storage API to open an existing object in your Cloud Storage bucket. At this time, you can open the file in write mode by passing 'w'
.
After opening any location in write mode, upload the image with write
.
Recommended Posts