I am successfully posting an image to my Google AppEngine application using the following code:
def post(self):
image_data = self.request.get('file')
file_name = files.blobstore.create(mime_type='image/png')
# Open the file and write to it
with files.open(file_name, 'a', exclusive_lock=True) as f:
f.write(image_data)
# Finalize the file. Do this before attempting to read it.
files.finalize(file_name)
# Get the file's blob key
blob_key = files.blobstore.get_blob_key(file_name)
self.response.out.write(images.get_serving_url( blob_key ))
However, when I browse the the URL outputted by get_serving_url(), the image is always at a reduced resolution. Why? I've checked and double checked that the image being posted is of the correct size (from an iPhone camera, so approx 3200x2400 resolution). Yet, the served image is always 512x384.
I'm fairly new to GAE, but I thought that the code above should store the image in the BlobStore rather than the datastore, circumventing the 1 MB limit.
Does anyone have any idea what could be going on?
Cheers,
Brett
Found a solution. Or at least something that works for me.
My appending =sXX onto the end of the served URL, AppEngine will serve the image at the XX resolution. For instance, if the line:
self.response.out.write(images.get_serving_url( blob_key ))
returns:
http://appengine.sample.com/appengineurlkey
Then when calling the url above results, the image will be a lower resolution image,
Then by calling the URL:
http://appengine.sample.com/appengineurlkey**=s1600**
the resulting served image will be at 1600x1200 resolution (or a similar resolution restricted by maintaining the aspect ratio).
The explanation for what you're seeing is explained in https://developers.google.com/appengine/docs/python/images/functions
In the doc for get_serving_url:
When resizing or cropping an image, you must specify the new size using an integer 0 to 1600. The maximum size is defined in IMG_SERVING_SIZES_LIMIT. The API resizes the image to the supplied value, applying the specified size to the image's longest dimension and preserving the original aspect ratio.
An alternative approach, if you want to serve full-sized images, is to upload your images directly to the blobstore, then serve them from there. (I.e., bypass the image API completely.) See https://developers.google.com/appengine/docs/python/blobstore/overview
Related
I downloaded an image from a url such as "https://www.xxxx.com/filename.jpeg. I expected that that image is a jpeg image whose format is acceptable for Computer Vision Annotation Tool (CVAT). However, it was saved as filename.heif or filename.jpeg.heif, so it causes an error when I tried to create a task with that image because heif format is not acceptable in CVAT. (CVAT automatically downloads images and create a task once I put image urls and submit them.)
I usually put more than 1000 image urls to create a task, and it is really hard to find invalid url or image among them.
Is there any way to find the "actual format" only by looking at the image url? Or can I just skip invalid urls in CVAT?
Thank you.
I am trying to create an image thumbnail creation function using python, running in a google cloud platform's function. The image is sent as a base64 string to the cloud function, manipulated and made smaller with Python's Pillow package. It is then uploaded as an image, going from a Pillow Image object, to a BytesIO object, then saved to google cloud storage. This is all done successfully.
The problem here is very strange: Google Cloud Storage does not recognize the image until an access token is created manually. Otherwise, the image is left in an infinite loop, never loading, and never being able to be used.
I have reviewed this SO post, which has a very similar problem to mine (the image here shows exactly my problem: an uploaded file cannot be loaded properly), but it differs in two imporant categories: 1) They are manipulating the image array directly, while my code never touches it and 2) they are working in Node.js, where the Firebase SDK is different than in Python.
The code to generate the image is as follows:
def thumbnailCreator(request):
# Setting up the resourcse we are going to use
storage_client = storage.Client()
stor_bucket = storage_client.bucket(BUCKET_LINK)
# Retriving the Data
sent_data = request.get_json()['data']
name = sent_data['name']
userID = sent_data['userID']
# Process to go between base64 string to bytes, to a file object
imageString = stor_bucket.blob(PATH_TO_FULL_SIZE_IMAGE).download_as_string()
imageFile = BytesIO(imageString)
image = Image.open(imageFile)
# Resizing the image is the goal
image = image.resize(THUMBNAIL_SIZE)
# Go between pillow Image object to a file
imageFile = BytesIO()
image.save(imageFile, format='PNG')
imageBytes = imageFile.getvalue()
image64 = base64.b64encode(imageBytes)
imageFile.seek(0)
# Uploading the Data
other_blob = stor_bucket.blob(PATH_FOR_THUMBNAIL_IMAGE)
other_blob.upload_from_file(imageFile, content_type = 'image/png')
return {'data': {'response': 'ok', 'status': 200}}
Again, this works. I have a feeling there is something wrong with the MIME type. I am a novice when it comes to this type of programming/networking/image manipulation, so I'm always looking for a better way to do this. Anyway, thanks for any and all help.
It appears that the premise of this question - that a access token must be made manually for the image to work - is not accurate. After further testing, the error came from other parts of the code base I was working in. The above python script does work for image manipulation. An access token to the image can be generated via code, and be provided client-side.
Leaving this up in case someone stumbles upon it in the future when they need to work with Pillow/PIL in the Google Cloud Platform.
I am trying to reduce(compress) image file size dynamically.
Reason being I need it dynamically, because I need to use it in full size as well on another pages.(Hence I cant make any changes to original images at server)
The project I'm working on is like blog post. on main page there are few featured_post which contains image and post data. when we clicked on the post, it will in full where the post image will load in in background and on main page it acts like a thumbnail
issue: on main page when images load into the featured_post it should load in reduced size than original to finish the loading of page quick
Note : at least 20 featured_post per page
I suggest you generate all the needed sizes and resolutions when saving a blog post - not on the fly. Obviously for performance reasons.
For image manipulation in Python I recommend you to use the pillow library:
https://pillow.readthedocs.io/en/stable/
I'm trying to make some code on python to edit someone's profile pic, but all I've got so far is this:
image = ctx.message.author.avatar_url
background = Image.open(image)
Apparently that just gets the URL itself, but i need the image itself to edit a picture with PIL. Any insight on how to get it?
with requests.get(ctx.message.author.avatar_url) as r:
img_data = r.content
with open('image_name.jpg', 'wb') as handler:
handler.write(img_data)
So I played about with this link a bit:
https://cdn.discordapp.com/avatars/190434822328418305/6a56d4edf2a82409ffc8253f3afda455.png
And I was able to save my own avatar image (the one I use for my accounts everywhere). I was then able to open the file regularly with the photo viewer app within Pycharm.
After, it would simply become a case of opening the new jpeg file with PIL or pillow instead of trying to open anything from a website, if that makes sense.
You should consider that this will save a file onto your Discord bot server, so this is extremely crude, a malformed or maliciously formed jpeg file could lead to some sort of remote vulnerability.
Furthermore to your comment, if you want the size of the image you download to be bigger, for example, please see the amended link below to solve your problem there:
https://cdn.discordapp.com/avatars/190434822328418305/6a56d4edf2a82409ffc8253f3afda455.png?size=<Number from list [16,32,64,128,256,512,1024,2048]>
Hope this helps :)
I am writing a flask application that receives two image URLs as parameters. Traditionally, I would download this images on the server local disk and carry out my image processing operations. I am downloading them using following code.
urllib.request.urlretrieve(image1url, image_id + '.jpg')
After this I read the image using :
original_image = Image.open(image_id + '.jpg')
and carry out my Image Processing operations like crop and applying a few filters.
original_crop = original_image.crop((x, y, x + width / 3, y + height / 3))
Also, I use ImageFilter operations on this image. Now this code will be deployed on a server. If i continue this way I will keep downloading and saving images on the disk of the server. Of course, I understand that deleting the images after I am done with my Image Processing operations is one option. But if I get a few 100 calls per second, I might at some point of time use up a lot of space. The application is multi threaded using the call
app.run(threaded=true)
which works like a charm.
I want to know if there is a way to load an image without using disk storage of the server. Thus reducing the hard disk space requirements of my service.
if you don't want to store images in temporary files you can wrap URL content in stream and pass it to Image.open
import io
import urllib.request
from PIL import Image
# your avatar URL as example
url = ('https://www.gravatar.com/avatar/3341748e9b07c9854d50799e0e247fa3'
'?s=328&d=identicon&response=PG&f=1')
content = urllib.request.urlopen(url).read()
original_image = Image.open(io.BytesIO(content))
You could move them to a known remote location and fetch them back as needed. Using Amazon S3 or a hosted FTP service like BrickFTP are both easy. S3 is especially cheap since you only pay for what you use -- no monthly fee. Brick is a great service if you want to make access to the images as simple as possible for other applications and users but there is a minimum monthly fee.