2015-05-07 2 views
4

У меня есть изображение в памяти, и я хочу выполнить метод imagemagick convert, используя Python's subprocess. В то время как эта линия хорошо работает с помощью терминала в Ubuntu:Python subprocess: pipe image blob to imagemagick shell command

cat image.png | convert - 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 методами и разными способами записи в stdin.

Лучшая часть, ничего не происходит, но я не получаю реальной ошибки. При печати стандартного вывода я могу видеть ImageMagick помощи на терминале, а затем следующее:

По умолчанию, формат изображения файла `» определяются его волшебной числа. Чтобы указать конкретный формат изображения, предварите имя файла с именем формата изображения и двоеточием (например, ps: изображение) или укажите тип изображения в качестве суффикса имени файла (например, image.ps). Укажите «файл» как '-' для стандартного ввода или вывода. (Нет, нет)

Возможно, здесь есть намек, который я не получаю. Пожалуйста, указывайте мне в правильном направлении, я новичок в Python, но из моего опыта работы с PHP это должно быть очень простой задачей, или я надеюсь.

Edit:

Это решение, которое я в конечном счете используется для обработки 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()) 

ответ

3

Не подпроцессу, что вызывает какие-либо проблемы это то, что вы передаете чтобы ошибочно ошибиться, tostring() действительно передается imagemagick. если вы на самом деле хотели повторить команду Линукса вы можете трубы от одного процесса к другому:

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) 

Когда вы передаете список арг вам не нужны оболочки = True, если вы хотите использовать оболочку = 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) 

Если вы хотите, чтобы написать стандартный ввод с помощью общения вы можете также передать содержимое файла с помощью .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()) 
+0

Это не помогает мне, потому что я хочу передать изображение из памяти * без необходимости создавать физическую копию на диске. Все ваши примеры касаются чтения файла изображения. Попытка передать объект изображения в stdin не работает, ничего не происходит, как я описал в вопросе. – iMoses

+0

Итак, откуда взялось изображение? –

+0

Я использую прокси для чтения изображения через HTTP, и я хочу использовать сам blob для создания оптимизированных версий изображения без необходимости сохранения оригинала на диске. Я знаю, что это не должно быть проблемой при использовании других языков программирования, я понятия не имею, как реализовать его с помощью Python. – iMoses