【问题标题】:Python Google App Engine Image objectPython Google App Engine 图片对象
【发布时间】:2012-11-28 10:46:45
【问题描述】:

使用 Python 图像库 PIL 和 Google App Engine Blobstore...

这个:

img = images.Image(blob_key=image)
logging.info(img.size)
self.response.headers['Content-Type'] = 'image/jpeg'
self.response.out.write(img)

有属性错误:

AttributeError: 'Image' object has no attribute 'size'

所以来自谷歌应用引擎的 Image 实例没有大小?

那么这是如何工作的:

img = images.Image(blob_key=image)
img.resize(width, height)
img.im_feeling_lucky()
thumbnail = img.execute_transforms(output_encoding=images.JPEG)
self.response.headers['Content-Type'] = 'image/jpeg'
self.response.out.write(thumbnail)

我错过了什么?

编辑:

修复是使用 get_serving_url 而不是使用我的图像服务器,正如@voscausa 所建议的那样。 由于我的对象是由 jinja2 模板解析的,因此不可能通过 jinja2 创建 Image 对象。 所以最终的解决方案如下:

class Mandelbrot(db.Model):
  image = blobstore.BlobReferenceProperty()

@property
def image_url(self):
  return images.get_serving_url(self.image)

这样我可以将图像 url 解析到我的页面,例如:

<img src=
{% if mandelbrot.image %}
  "{{ mandelbrot.image_url }}" 
{% else %} 
  "./assets/img/preloader.gif"
{% endif %}
/>

【问题讨论】:

  • 再解释一下。没有调整大小的第一种方法不提供有效的图像资源。这是问题,而不是大小。
  • 您的问题确实与 PIL 无关,您应该更改标题。 Google 可能会使用 PIL 来实现其 Image 类,但它是一个完全独立的东西。

标签: python google-app-engine blobstore


【解决方案1】:

我不熟悉 PIL,因为我使用 Google 的另一种解决方案来提供图像和调整图像大小。 Google 可以使用 Google 高性能图像服务为您提供图像。这意味着:

  • 您必须使用 get_serving_url 为 blobstore 中的图像创建一次 serving_url
  • 您可以更改提供的图像的大小。原件没有改变
  • Google 将为您提供几乎免费的图片。您不需要处理程序。您只需支付带宽费用

这是一个例子。您可以更改 =s0,以更改大小。 s0 返回原始大小。

https://lh6.ggpht.com/1HjICy6ju1e2GIg83L0qdliUBmPHUgKV8FP3QGK8Qf2pHVBfwkpO_V38ifAPm-9m20q_3ueZzdRCYQNyDE3pmA695iaLunjE=s0

get_serving_url 文档:https://developers.google.com/appengine/docs/python/images/functions

代码:

class Dynamic(db.Model):          # key : name
    name = db.StringProperty() 
    blob_ref = blobstore.BlobReferenceProperty()
    serving_url = db.LinkProperty()

dyn= Dynamic.get_by_key_name(key_name)
try :       # get url with size = 0
    dyn.serving_url = images.get_serving_url(dyn.blob_ref, size=None, secure_url=True)
except DeadlineExceededError : 
    try :             # sometimes this request fails, retry. This always works fine
        dyn.serving_url = images.get_serving_url(dyn.blob_ref, size=None, secure_url=True)
    except DeadlineExceededError :
        logging.error('Image API get_serving_url deadline error after retry' %(dyn.key().name()))                        
        return None
    dyn.put()

【讨论】:

  • 同意这是最好的方法。谢谢您的回答。但是一个快速的问题。如果您想通过模板获取服务网址?例如:object.image = self._save_to_blobstore_and_get_key(image) 将对象解析为模板时,如何在不首先创建图像对象的情况下检索 url?
  • 我使用了一个引用 blobstore(最后上传的版本)和 serving_url 的数据存储实体。当我创建模板时,我使用这个实体来填充模板并将大小(s=xxx)添加到模板中。我不明白你的代码,所以我编辑了我的答案以添加代码。
  • 是的,您的示例是正确的,尽管您的速度更快!此外,您的示例正在节省资源,但并不总是调用get_serving_url() 另外请参阅我更正的示例
  • 看起来不错。您可以将动态大小 (=sxxx) 添加到模板中,如果未定义大小,您可以添加默认值:=s0 喜欢:{{ mandelbrot.image_url }}=s{{ mandelbrot.size|default('0') }}
  • 请注意:您还可以使用谷歌云存储来存储图像并获取服务 url,而不仅仅是 blobstore。
【解决方案2】:

它看起来像 PIL doesn't implement .size 的 GAE 版本。改用这样的东西:

logging.info((img.width, img.height))

【讨论】:

  • 我的问题@Blender 不是获取尺寸而是提供图像。忽略大小。也仅供参考。
猜你喜欢
  • 2013-09-14
  • 2013-12-25
  • 2013-08-25
  • 1970-01-01
  • 2011-08-25
  • 2015-02-07
  • 2012-05-09
  • 2011-06-17
  • 2012-09-05
相关资源
最近更新 更多