2013-10-07 3 views
1

Я рассмотрел учебники, другие вопросы о стеке и документацию PIL, но я все еще не уверен, как это сделать.Вертикальное увядание изображения с прозрачностью с использованием библиотеки PIL PILO

Я хотел бы начать замирание изображения вертикально примерно на 55% вниз по оси Y и получить изображение полностью прозрачным примерно на 75%. Важно, чтобы я сохранил всю высоту изображения, хотя последние 25% или около того должны быть полностью прозрачными.

Возможно ли это с PIL?

ответ

4

Уверенный, что это выполнимо.

Предположим, что вы начинаете с изображения без прозрачности (потому что в противном случае ваш вопрос неоднозначен).

Шаг 1: Добавить альфа-плоскость. Это всего лишь putalpha, если вы не имеете дело с непланарным изображением, и в этом случае вам нужно сначала преобразовать его в RGB или L.

Шаг 2: Перебрать пиксели, которые вы хотите изменить, используя массив пикселей, возвращенное load (или getpixel и setpixel, если вам приходится иметь дело с древними версиями PIL).

Шаг 3: Нет шага 3. Если вы не посчитаете сохранение изображения. В этом случае, OK, шаг 3 сохраняет изображение.

from PIL import Image 

im = Image.open('bird.jpg') 
im.putalpha(255) 
width, height = im.size 
pixels = im.load() 
for y in range(int(height*.55), int(height*.75)): 
    alpha = 255-int((y - height*.55)/height/.20 * 255) 
    for x in range(width): 
     pixels[x, y] = pixels[x, y][:3] + (alpha,) 
for y in range(y, height): 
    for x in range(width): 
     pixels[x, y] = pixels[x, y][:3] + (0,) 
im.save('birdfade.png') 

Здесь альфа падает линейно от 255 до 0; вы хотите, чтобы он упал по другой кривой, или вы используете RGB16 вместо RGB8, или используете L вместо RGB, вы должны выяснить, как его изменить.


Если вы хотите сделать это быстрее, вы можете использовать NumPy вместо цикла Python для шага 2. Или вы можете обратить шаги 1 и 2-построить альфа-плоскость заранее, и применять все сразу передавая его putalpha вместо 255. Или ... Поскольку это заняло полсекунды на самом большом изображении, с которым я лежал, я не слишком беспокоюсь о производительности, если вам не нужно сделать миллион из них, и вам нужна более быстрая версия.

+0

К сожалению, выиграл» я смогу применить ваш ответ на практике в течение нескольких часов, но выглядит хорошо. Я скоро уточню. Кроме того, я забыл упомянуть о том, что изображения (там будет немало, так что эффективность будет приятной) - все jpeg, но jpeg не поддерживает прозрачность, поэтому его нужно сохранить как png, правильно? – RTF

+0

@RTF: Правильно, вам нужно будет сохранить PNG (или что-то еще, что поддерживает прозрачность). Между тем, сколько «довольно много»? И насколько велики файлы? Проводить дополнительное часовое кодирование и отлаживать что-то более сложное, чтобы сэкономить 10 секунд времени выполнения, не стоит; если это сэкономит вам дополнительные 3 часа работы каждый месяц в течение следующих 3 лет, это совсем другая история ... – abarnert

+0

Может быть несколько сотен изображений, вытащенных из веб-службы по одному, около 400 тыс. 500 тыс. каждый (итоговые png будут быть ~ 1.75mb, намного больше, чем хотелось бы, но у меня нет выбора, если я хочу прозрачность).Как это бывает, каждый запрос изображения требует не менее 1 секунды между запросами, чтобы предотвратить дросселирование, и сейчас я сплю для большей части этого. Поэтому я возьму это, а не возьму другую библиотеку (numpy). – RTF

3

Использование NumPy:

import numpy as np 
import Image 

img = Image.open(FILENAME).convert('RGBA') 
arr = np.array(img) 
alpha = arr[:, :, 3] 
n = len(alpha) 
alpha[:] = np.interp(np.arange(n), [0, 0.55*n, 0.75*n, n], [255, 255, 0, 0])[:,np.newaxis] 
img = Image.fromarray(arr, mode='RGBA') 
img.save('/tmp/out.png') 
+0

Спасибо, но я собираюсь пойти с решением abarnerts без необходимости numpy. Я не против жертвовать приростом производительности, которое принесет numpy, и это означает, что мне не нужно тянуть другую библиотеку. – RTF

+1

Я думаю, вы могли бы сделать это немного проще и быстрее, просто используя numpy, чтобы построить плоскость A, чтобы перейти к 'putalpha'. Из быстрого теста (хотя я получил аргументы, чтобы интерпретировать неправильно, потому что я идиот, поэтому результат был неправильным), .91s для 'setpixel', .36s для' im.load' .06s для вашей версии. 05s для 'putalpha'. – abarnert

0

Вы должны изменить код @abarnert немного, если вы хотите, чтобы исчезнуть образ, который уже был прозрачный фон (detail):

from PIL import Image 

im = Image.open('bird.jpg') 
width, height = im.size 
pixels = im.load() 
for y in range(int(height*.55), int(height*.75)): 
    for x in range(width): 
     alpha = pixels[x, y][3]-int((y - height*.55)/height/.20 * 255) # change made here 
     if alpha <= 0: 
      alpha = 0 
     pixels[x, y] = pixels[x, y][:3] + (alpha,) 
for y in range(y, height): 
    for x in range(width): 
     pixels[x, y] = pixels[x, y][:3] + (0,) 
bg.save('birdfade.png') 
Смежные вопросы