Python 子进程 : pipe an image blob to imagemagick shell command

标签 python image shell imagemagick subprocess

我在内存中有一个图像,我希望使用 Python 的 subprocess 执行 imagemagick 的 convert 方法。虽然这条线在 Ubuntu 的终端上运行良好:

cat image.png |转换 - new_image.jpg

这段代码不能使用 Python:

jpgfile = Image.open('image.png');
proc = Popen(['convert', '-', 'new_image.jpg'], stdin=PIPE, shell=True)
print proc.communicate(jpgfile.tostring())

我也试过在不使用 PIL 的情况下将图像作为常规文件读取,我试过在 subprocess 方法和写入标准输入的不同方法之间切换。

最棒的是,什么也没有发生,但我没有收到真正的错误。打印标准输出时,我可以在终端上看到 imagemagick 帮助,然后是以下内容:

By default, the image format of `file' is determined by its magic number. To specify a particular image format, precede the filename with an image format name and a colon (i.e. ps:image) or specify the image type as the filename suffix (i.e. image.ps). Specify 'file' as '-' for standard input or output. (None, None)

也许这里有一个我没有得到的提示。 请给我指出正确的方向,我是 Python 的新手,但根据我使用 PHP 的经验,这应该是一项非常容易的任务,我希望如此。

编辑:

这是我最终在不保存临时文件的情况下处理 PIL 图像对象的解决方案。希望它能帮助别人。 (在示例中我正在从本地驱动器读取文件,但我的想法是从远程位置读取图像)

out = StringIO()
jpgfile = Image.open('image.png')
jpgfile.save(out, 'png', quality=100);
out.seek(0);
proc = Popen(['convert', '-', 'image_new.jpg'], stdin=PIPE)
proc.communicate(out.read())

最佳答案

导致任何问题的不是子进程,而是您传递给 imagemagick 的内容不正确,tostring() 确实传递给了 imagemagick。如果你真的想复制 linux 命令,你可以从一个进程通过管道传输到另一个进程:

from subprocess import Popen,PIPE
proc = Popen(['cat', 'image.jpg'], stdout=PIPE)

p2 = Popen(['convert', '-', 'new_image.jpg'],stdin=proc.stdout)

proc.stdout.close()
out,err = proc.communicate()

print(out)

当你传递一个参数列表时,你不需要 shell=True,如果你想使用 shell=True,你将传递一个字符串:

from subprocess import check_call
check_call('cat image.jpg | convert - new_image.jpg',shell=True)

通常我会避免 shell=True。这answer概述了 shell=True 的具体作用。

您还可以将文件对象传递给标准输入:

with open('image.jpg') as jpgfile:
    proc = Popen(['convert', "-", 'new_image.jpg'], stdin=jpgfile)

out, err = proc.communicate()

print(out)

但由于代码成功运行时没有输出,您可以使用 check_call,如果存在非零退出状态,您可以捕获并采取适当的操作,这将引发 CalledProcessError:

from subprocess import check_call, CalledProcessError


with open('image.jpg') as jpgfile:
    try:
        check_call(['convert', "-", 'new_image.jpg'], stdin=jpgfile)
    except CalledProcessError as e:
        print(e.message)

如果您想使用 communicate 写入标准输入,您也可以使用 .read 传递文件内容:

with  open('image.jpg') as jpgfile:
     proc = Popen(['convert', '-', 'new_image.jpg'], stdin=PIPE)
     proc.communicate(jpgfile.read())

如果您不想将图像存储在磁盘上,请使用 tempfile:

import tempfile
import requests

r = requests.get("http://www.reptileknowledge.com/images/ball-python.jpg")
out = tempfile.TemporaryFile()
out.write(r.content)
out.seek(0)

from subprocess import check_call
check_call(['convert',"-", 'new_image.jpg'], stdin=out)

使用 CStringIo.StringIO对象:

import requests

r = requests.get("http://www.reptileknowledge.com/images/ball-python.jpg")
out = cStringIO.StringIO(r.content)

from subprocess import check_call,Popen,PIPE
p = Popen(['convert',"-", 'new_image.jpg'], stdin=PIPE)

p.communicate(out.read())

关于Python 子进程 : pipe an image blob to imagemagick shell command,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30105904/

相关文章:

python - Pandas 虫? : Mean of an grouped-by int64 column stays as int64 in some circumstances

C Win32 : save . 来自 HBITMAP 的 bmp 图像

html - 如何根据浏览器宽度保持图像大小

css - 为 CSS Sprite 中包含的小图像设置动画是否与仅为该图像设置动画一样高效?

linux - 查找目录中的文件数

python - 如何将多个数组写入一个excel文件中?

python - 是否可以访问在标准输入中传递给 python 的 python 脚本的源代码?

python - 在 Google App Engine 上的 Mysql 中插入行后获取 ID

php - 从 PHP 调用的 shell 脚本问题

bash - 运行在 bash 中存储为字符串的 PSQL 查询