我试图使用龙卷风库提供网络摄像头图像,但我发现的唯一方法是先保存图像,然后返回图像名称。
是否有一种方法可以在不保存到磁盘的情况下提供图像?
import tornado.ioloop
import tornado.web
import pygame.camera
import pygame.image
from time import time
from io import StringIO
pygame.camera.init()
cam = pygame.camera.Camera(pygame.camera.list_cameras()[0])
cam.start()
class MainHandler(tornado.web.RequestHandler):
def get(self):
img = cam.get_image()
name = str( round( time() ) )
name = name + '.jpg'
pygame.image.save(img, name)
self.write('<img src="' + name + '">')
application = tornado.web.Application([
(r"/", MainHandler),
(r'/(.*)', tornado.web.StaticFileHandler, {'path': ''})
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
看起来pygame不支持将图像保存到类文件对象,所以您将无法直接使用它。然而,它确实有一个tostring
方法。该文档指出,它允许与其他图像库互操作:
创建一个可以使用' fromstring '方法传输的字符串
所以,你可以使用tostring
将你的图像转换为字符串,然后使用另一个支持将图像写入类文件对象的Python库,并使用其fromstring
方法,
下面是一个使用pillow
作为备选图像库的示例。
import tornado.ioloop
import tornado.web
from PIL import Image
import cStringIO as StringIO
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("<img src='http://localhost:8888/img'>")
class ImgHandler(tornado.web.RequestHandler):
img_name = "bg.jpg"
img = pygame.image.load(img_name)
str_img = pygame.image.tostring(img, "RGB")
size = img.get_size()
fimg = Image.frombytes("RGB", size, str_img, "raw")
fobj = StringIO.StringIO()
fimg.save(fobj, format="png") #jpeg encoder isn't available in my install...
for line in fobj.getvalue():
self.write(line)
self.set_header("Content-type", "image/png")
application = tornado.web.Application([
(r"/", MainHandler),
(r"/img", ImgHandler),
#(r'/(.*)', tornado.web.StaticFileHandler, {'path': ''})
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
localhost:8888
和localhost:8888/img
都将显示图像
是的,您可以在不处理File I/O
的情况下提供图像。我有一个python3
应用程序,通过使用Tornado
我将图像存储在源代码中:
# 1x1 Transparent Pixel in HEX Format
pixel_GIF = [0x47,0x49,0x46,0x38,0x39,0x61,
0x01,0x00,0x01,0x00,0x80,0x00,
0x00,0x00,0x00,0x00,0xff,0xff,
0xff,0x21,0xf9,0x04,0x01,0x00,
0x00,0x00,0x00,0x2c,0x00,0x00,
0x00,0x00,0x01,0x00,0x01,0x00,
0x00,0x02,0x01,0x44,0x00,0x3b]
然后,我使用以下函数将HEX
格式的图像转换为二进制:
def pack_into_binary(data):
"""Convert given data into binary form"""
packed = str()
for datum in data:
packed += struct.pack('B', datum).decode("ISO-8859-1")
return packed
pixel_binary = pack_into_binary(pixel_GIF)
之后,我设置适当的标题,并提供图像:
#1x1 Transparent Tracking Pixel
self.set_header("Content-Length", 42)
self.set_header("Content-Type", "image/gif")
self.set_header("Pragma", "no-cache")
self.set_header("Cache-Control",
"no-store, "
"no-cache=Set-Cookie, "
"proxy-revalidate, "
"max-age=0, "
"post-check=0, pre-check=0"
)
self.set_header("Expires", "Wed, 2 Dec 1837 21:00:12 GMT")
self.write(self.pixel_binary)
不做任何File I/O
.
注意:在您的情况下,如果您有内存中的图像,您可以通过将格式转换为二进制并使用write
方法来提供它。不同的是,你的形象不是预先确定的,不像我。
Edit:查看下面从RGB Surface
到binary
编码的转换示例
from StringIO import StringIO
from PIL import Image
data = pygame.image.tostring(cam.get_image(),"RGB")
img = Image.fromstring('RGBA', (100,200), data) # 100 x 200 example surface
zdata = StringIO()
img.save(zdata, 'JPEG')
self.write(zdata.getvalue())
那么你可以使用Tornado
来服务image
当然!比如:
class ImageHandler(tornado.web.RequestHandler):
def get(self):
img = cam.get_image()
self.set_header('Content-Type', 'image/jpg')
self.write(img.contents)
application = tornado.web.Application([
(r"/image.jpg", ImageHandler),
])
我不知道如何得到图像的内容作为字节,但你得到的想法。