Pixel by pixel operation on image in Google App Engine using Python - python

I would like to go over an image and do some pixel by pixel operation. The image API provided by Google App Engine seems to be incapable to do this. And it doesn't include Python Imaging Library. So, how should I proceed with it.
Thanks..

You could maybe use the image API to convert to PNG, then use the png module (which is pure python, so should hopefully run on app engine) to load the PNG and modify the pixels. Then convert back to PNG using the png module, and back to whatever format you need using the image API.

Related

GCP - Reading images in GCS into Datalab using Python

I have a store of images in Google Cloud Storage and I am looking to read them into OpenCV in Datalab. I can find information on how to read text files but can't find anthing on how I can read in an image. How would I go about doing this?
I am not really familiar with OpenCV, so let me cover the Datalab ⟷ GCS part and I hope that is enough for you to go on with the OpenCV part.
In Datalab, you can use two different approaches to access Google Cloud Storage resources. They are both documented (with working examples) in these Jupyter notebooks: access GCS using Storage commands ( %%gcs ) or access GCS using Storage APIs ( google.datalab.storage ).
I'll provide an example using Storage commands, but feel free to adapt it to the Datalab GCS Python library if you prefer.
# Imports
from google.datalab import Context
from IPython.display import Image
# Define the bucket and and an example image to read
bucket_path = "gs://BUCKET_NAME"
bucket_object = bucket_path + "/google.png"
# List all the objects in your bucket, and read the example image file
%gcs list --objects $bucket_path
%gcs read --object $bucket_object -v img
# Print the image content (see it is in PNG format) and show it
print(type(img))
img
Image(img)
Using the piece of code I shared, you are able to perform a simple object-listing for all the objects in your bucket and also read an example PNG image. Having its content stored in a Python variable, I hope you are able to consume it in OpenCV.

Qt - Loading image with wrong extension

I'm currently working on a Qt program that works with images that are supplied by the users. One problem I've run into is that a lot of images are saved with the wrong extension - e.g. an image is saved in JPG format but has a PNG extension.
Qt doesn't seem to deal well with this. When I load an image like this into a QImage, the QImage fails to load. I've been looking through the docs, but I haven't come across anything relating to this.
Other programs I've used are able to correctly identify the image as a JPG despite the PNG extension, so there should be no reason for Qt to be unable to do this, but I'm not having any luck.
Any suggestions?
I solved this by using a QImageReader. An example is shown below using PySide.
First I created an instance of QImageReader and set it to read the format from the content.
image_reader = QtGui.QImageReader()
image_reader.setDecideFromContent(True)
This setting tells the reader to only look at the image's data to determine its format and not the extension.
Then I set the filename to the filename of the image I wanted to load and called read().
image_reader.setFileName(file_path_here)
image = image_reader.read()
Read returns a QImage object, so I proceeded with the rest of my code from there.

Options for Image Caching

I am running a website on google app engine written in python with jinja2. I have gotten memcached to work for most of my content from the database and I am fuzzy on how I can increase the efficiency of images served from the blobstore. I don't think it will be much different on GAE than any other framework but I wanted to mention it just in case.
Anyway are there any recommended methods for caching images or preventing them from eating up my read and write quotas?
Blobstore is fine.
Just make sure you set the HTTP cache headers in your url handler. This allows your files to be either cached by the browser (in which case you pay nothing) or App Engine's Edge Cache, where you'll pay for bandwidth but not blobstore accesses.
Be very careful with edge caching though. If you set an overly long expiry, users will never see an updated version. Often the solution to this is to change the url when you change the version.
You can use google images api
https://developers.google.com/appengine/docs/python/images/functions
What I usually do is on upload, i store the url created by the images.get_serving_url(blob_key). Not sure if its cheaper but on my dev server each call to get_serving_url creates a datastore write.
My advice would be to use Google Cloud Storage for storing your images. It's better suited and recommended for serving static files. The good thing is that now you can use the same Images api for that:
Note: You can also serve images stored in Google Cloud Storage. To do this, you need to generate a Blob Key using the Blobstore API create_gs_key() function. You also need to set a default object ACL on the bucket being used that gives your app FULL_CONTROL permissions, so that the image service can add its own ACL to the objects. For information on ACLs and permissions, see the documentation for Google Cloud Storage.
PS. Another great feature I like here, is that you don't have to store different resolutions of your image if you need to serve them in different sizes. You can just add the parameters to the url which is returned by get_serving_url and that will do it. Also you only need to call get_serving_url once, store this url somewhere and use it whenever you need to serve the image. Plus you can reuse the same url for serving the same image in all different sizes.
URL Modifications:
=sXX To resize an image, append =sXX to the end of the image URL, where XX is an integer from 0–1600 representing the new image size in
pixels. 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. For example, if you use =s32 to resize a 1200x1600
image, the resulting image is a 24x32. If that image were 1600x1200,
the resized image would be 32x24 pixels.
=sXX-c To crop and resize an image, append =sXX-c to the end of the image URL, where XX is an integer from 0–1600 representing the new
image size in pixels. 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. If the image is portrait,
the API slices evenly from the top and bottom to make a square. If the
image is landscape, the API slices evenly from the left and right to
make a square. After cropping, the API resizes the image to the
specified size.

Google App Engine (So "Pure Python"): Convert PDF to Image

In Google App Engine, I need to be able to take an uploaded PDF and convert it to an image (or maybe one day a number of tiled images) for storing and serving back out. Is there a library that will read PDF files that is also 100% python (so it can be uploaded with my app)?
From what I've gathered so far...
PIL does not read PDF files, only writes them.
GhostScript is the standard FOSS PDF reader, but I don't believe I'll be able to upload it with my app to GAE since I don't believe it's 100% python.
Is there anything else I might be able to use? Or maybe even a web service that I can call?)
You may want to look into using the GAE Conversion API (not yet fully released). There's a tester signup form here, with a link to further details.
From the doc:
Conversions can be performed in any direction between PDF, HTML, TXT, and image formats, and OCR will be employed if necessary. Note that while PNG, GIF, JPEG, and BMP image formats are supported as input formats, only PNG is available for output.

Text to a PNG on App Engine (Python)

Note: I am cross-posting this from App Engine group because I got no answers there.
As part of my site about Japan, I have a feature where the user can
get a large PNG for use as desktop background that shows the user's
name in Japanese. After switching my site hosting entirely to App
Engine, I removed this particular feature because I could not find any
way to render text to a PNG using the image API.
In other words, how would you go about outputting an unicode string on
top of an image of known dimensions (1024x768 for example), so that
the text will be as large as possible horizontally, and centered
vertically? Is there a way to do this is App Engine, or is there some
external service besides App Engine that could make this easier for
me, that you could recommend (besides running ImageMagick on your own
server)?
Solution #1. Pure Python image library.
You can try to bundle PyPNG with your application. PyPNG is a pure Python library to create PNG images. It depends on zlib module, which is allowed on AppEngine, so PyPNG should work on AppEngine. Just use StringIO objects instead of files and write PNG data to them.
Shamelessly adapting PyPNG example how to make a bitmap PNG image:
import png
from StringIO import StringIO
# bitmap data
s = ['110010010011',
'101011010100',
'110010110101',
'100010010011']
s = map(lambda x: map(int, x), s)
f = StringIO()
w = png.Writer(len(s[0]), len(s), greyscale=True, bitdepth=1)
w.write(f, s)
# binary PNG data
print f.getvalue()
I suspect suboptimal performance, but as far as I know there is no other way to generate images on GAE.
And you still need to figure out how to rasterize text to produce bitmap data. The easiest way, probably, is just to keep bitmaps of all the symbols around (essentially, using a bitmap font).
To render ASCII text with PyPNG take a look at texttopng script.
So, limitations are:
Probably slow (needs to be checked)
Glyph rasterization is to be addressed
Solution #2. Off-site text-to-image rendering.
Google AppEngine does not provide tools to render text as raster images, but Google Charts does. With a proper choice of parameters, the outline text chart just renders simple text to PNG images.
For example, http://chart.apis.google.com/chart?chst=d_text_outline&chld=000000|32|h|FFFFFF|_|Render text to image|with Google Charts.|Some Unicode too:|Здра́вствуйте|こんにちは|नमस्ते|你好|שלו produces this:
Limitations:
You cannot generate images bigger than 300000 pixels
Style and font customizations are limited
Some Unicode scripts are not available
White background only
I ran into this same problem with writing text to an image. The issue at hand is that any imaging libraries used on google app engine must be pure python, which rules out PIL.
PyBMP
PyBMP is a pure-python library that can do simple text rendering. From there you can use google's imaging library to composite the resulting bitmap onto your other pictures. There's some sample code below. The downside is the library lacks nicer features like anti-aliasing and fine control over fonts so the text that it renders looks kind of crappy. It also may or may not handle unicode well.
# Create the image
text_img = bmp.BitMap(300,35,bmp.Color.WHITE)
# bmpfont_Tw_Cen_MT_30 is a generated file using PyBMP's tool
text_img.setFont(bmpfont_Tw_Cen_MT_30.font_data)
text_img.setPenColor( bmp.Color.BLACK )
text_img.drawText(name, 0, 0)
After this you can use google's composite function on text_img.getBitmap() as you would any other image.
External Image Processing
If the text isn't good enough (it wasn't for my project), an alternative solution is to set up an external server on a service like Rackspace purely for image processing. Set up an HTTP handler that does your image processing with PIL, and then returns the resulting image. From there you can either
upload the result straight to your static file hosting server (like s3) or
get the generated-text image result with app engine's urlfetch library and do the rest of your compositing in app engine
Not pretty, but it gets the job done.
It's a bit too late but I was looking for the same. I managed to draw unicode string (here Devanagari) onto an image and save it as a '.png' file by doing the following:
# -*- coding: utf-8 -*-
import Image, ImageDraw, ImageFont
img = Image.new('L', (16,16), 255)
draw = ImageDraw.Draw(img)
text_to_draw = unicode('क','utf-8')
font = ImageFont.truetype('Path/to/font/file',12)
draw.text((2,2), text_to_draw, font = font)
del draw
img.save('image.png')
P.S. got help from other posts on stackoverflow
[Stop press: As comment suggests - this answer doesn't work in Googe App Engine.]
The Python Imaging Library (PIL) can accomplish this.
You can load in the image, draw Unicode text on it with the ImageDraw.text() function.
You may need to call ImageDraw.textsize() a few times with different font sizes to find thelargest font that will fit.
Finally, you can save the .png image to a file (or serve it back directly).
Test with large images if you are running it from within the context of a web-server, to make sure you can allocate sufficient memory to processs large PNG files.
(Have I answered your question appropriately? I don't know if PIL is an option from within the Google App Engine.)

Categories

Resources