Поскольку вы знаете, что значения пикселей равны 0-4095, я не могу найти более быстрый способ, чем этот:
new_image= image.point(lambda value: value<<4 | value>>8)
Согласно документации , лямбда-функция будет вызываться не более 4096 раз, независимо от размера вашего изображения.
РЕДАКТИРОВАТЬ: Поскольку функция, заданная для точки , должна иметь форму argument * scale + offset
для в I
изображении, то это лучше всего использовать функцию point
:
new_image= image.point(lambda argument: argument*16)
Максимальное значение выходного пикселя будет 65520.
Второй дубль:
Модифицированная версия вашего собственного решения, использующая itertools
для повышения эффективности:
import itertools as it # for brevity
import operator
def scale_12to16(image):
new_image= image.copy()
new_image.putdata(
it.imap(operator.or_,
it.imap(operator.lshift, image.getdata(), it.repeat(4)),
it.imap(operator.rshift, image.getdata(), it.repeat(8))
)
)
return new_image
Это позволяет избежать ограничения аргумента функции point
.