首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:优化内存中的图像(StringIO & POpen与jpegoptim)

Python:优化内存中的图像(StringIO & POpen与jpegoptim)
EN

Stack Overflow用户
提问于 2015-02-25 03:59:51
回答 2查看 593关注 0票数 1

我试图使用各种库的STDIN版本(本例中的jpegoptim),在不接触磁盘的情况下压缩图像。

此代码不返回优化的(jpegoptim压缩的)映像。

有人能帮助或解释为什么StringIO.StringIO()对象对Popen()的这种用法不返回图像的优化版本吗?如果我将文件保存到磁盘,它就能正常工作。

代码语言:javascript
复制
import sys
import urllib2 as urllib
import StringIO

from subprocess import Popen, PIPE, STDOUT
fp = urllib.urlopen('http://www.path.to/unoptimized.jpg')
out_im2 = StringIO.StringIO(fp.read()) # StringIO Image
print "Image Size: %s" % format(sys.getsizeof(out_im2.getvalue()))
subp = Popen(["/usr/bin/jpegoptim", "-"], shell=True, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
image_str = subp.communicate(input=out_im2.getvalue())[0]
out_im2.write(image_str)

##This should be a different size if it worked! It's not
print "Compressed JPG: %s" % format(sys.getsizeof(out_im2.getvalue()))
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-25 04:36:06

这是因为您正在写入相同的输入缓冲区。创建一个新的StringIO()。

StringIO缓冲区最初扩展到第一个未压缩的jpeg的大小。然后用新的较短的字符串缓冲区从0开始写入该缓冲区,但它不会自动截断缓冲区或任何东西。StringIO缓冲区仍然是相同的大小,实际上,所有的尾随数据都将遗留在原始图像的垃圾上。

代码语言:javascript
复制
In [1]: import StringIO

In [2]: out = StringIO.StringIO("abcdefg")

In [3]: out.getvalue()
Out[3]: 'abcdefg'

In [4]: out.write("123")

In [5]: out.getvalue()
Out[5]: '123defg'
票数 2
EN

Stack Overflow用户

发布于 2015-02-25 16:26:32

有几个问题:

  1. StringIO()缓冲区pointed out by @doog abides的不正确覆盖问题
  2. 使用len而不是sys.getsizeof()。后者返回内存中不等于字节字符串中字节数的内部表示的大小。
  3. together

您可以将套接字作为stdin传递给某些系统上的子进程:

代码语言:javascript
复制
import socket
from urllib2 import urlopen
from subprocess import check_output

saved = socket._fileobject.default_bufsize
socket._fileobject.default_bufsize = 0  # hack to disable buffering
try:
    fp = urlopen('http://www.path.to/unoptimized.jpg')
finally:
    socket._fileobject.default_bufsize = saved # restore back

# urlopen() has read http headers; subprocess can read the body now
image_bytes = check_output(["/usr/bin/jpegoptim", "-"], stdin=fp) 
fp.close()

# use `image_bytes` bytestring here..

stderr不是为了避免隐藏错误而设置的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28710874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档