Как я генерирую круговые миниатюры с PIL?

left.keys map { k => k -> List(left(k),right(k)) } toMap

Это сжато и будет работать, предполагая, что ваши две карты left и right. Не уверен насчет эффективности.

1125 Но ваш вопрос немного двусмысленный по двум причинам. Вы не указываете

  1. Отношение подтипа между значениями (т. Е. class1, class2),
  2. Что происходит, если карты имеют разные ключи

Для первого случая рассмотрим следующий пример:

val left = Map("foo" ->1, "bar" ->2)
val right = Map("bar" -> 'a', "foo" -> 'b')

Что приводит к

res0: Map[String,List[Int]] = Map(foo -> List(1, 98), bar -> List(2, 97))

Обратите внимание, как Char были преобразованы в Int с из-за иерархии типов scala. В более общем случае, если в вашем примере class1 и class2 не связаны, вы получите обратно List[Any]; это, вероятно, не то, что вы хотели.

Вы можете обойти это, исключив конструктор List из моего ответа; это вернет Tuple с сохранением типа:

res0: Map[String,(Int, Char)] = Map(foo -> (1,b), bar -> (2,a))

Вторая проблема - это то, что происходит, когда у вас есть карты, которые не имеют одинаковых ключей. Это приведет к исключению key not found. Другими словами, вы делаете левое, правое или внутреннее соединение двух карт? Вы можете устранить неоднозначность типа объединения, переключившись на right.keys или right.keySet ++ left.keySet для правого / внутреннего соединения соответственно. В последнем случае обойдется проблема с отсутствующим ключом, но, возможно, это не то, что вам нужно, т. Е. Может быть, вы хотите использовать левое или правое соединение вместо этого. В этом случае вы можете рассмотреть возможность использования метода withDefault из Map, чтобы каждый ключ возвращал значение, например, None, но это требует немного больше работы.

39
задан bool.dev 25 November 2013 в 12:16
поделиться

1 ответ

Самый простой способ сделать это - использовать маски. Создайте черно-белую маску любой формы. И используйте putalpha , чтобы поместить эту форму в качестве альфа-слоя:

from PIL import Image, ImageOps

mask = Image.open('mask.png').convert('L')
im = Image.open('image.png')

output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
output.putalpha(mask)

output.save('output.png')

Вот маска, которую я использовал:

alt text


Если вы хотите, чтобы размер эскиза был переменным, вы можете использовать ImageDraw и нарисуйте маску:

from PIL import Image, ImageOps, ImageDraw

size = (128, 128)
mask = Image.new('L', size, 0)
draw = ImageDraw.Draw(mask) 
draw.ellipse((0, 0) + size, fill=255)

im = Image.open('image.jpg')

output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
output.putalpha(mask)

output.save('output.png')

Если вы хотите вывод в формате GIF, вам нужно использовать функцию вставки вместо putalpha :

from PIL import Image, ImageOps, ImageDraw

size = (128, 128)
mask = Image.new('L', size, 255)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + size, fill=0)

im = Image.open('image.jpg')

output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
output.paste(0, mask=mask)
output.convert('P', palette=Image.ADAPTIVE)

output.save('output.gif', transparency=0)

Обратите внимание, что я внес следующие изменения:

  • Маска теперь перевернутый. был заменен на черный и наоборот.
  • Я конвертирую в «P» с помощью «адаптивной» палитры. В противном случае PIL будет использовать только безопасные для Интернета цвета, и результат будет плохо выглядеть.
  • Я добавляю информацию о прозрачности изображения.

Обратите внимание на : с этим подходом возникает большая проблема. Если изображение GIF содержит черные части, все они также станут прозрачными. Вы можете обойти это, выбрав другой цвет для прозрачности. Я настоятельно рекомендую вам использовать для этого формат PNG. Но если вы не можете, то это лучшее, что вы могли сделать.

71
ответ дан 27 November 2019 в 02:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: