2025, Oct 22 10:31

Почему PIL getcolors() возвращает None и как это решить

Разбираем, почему PIL getcolors() на больших изображениях возвращает None: порог maxcolors, предел уникальных цветов и как поднять лимит для анализа палитры.

При работе с PIL и анализе палитры изображения многих удивляет, что getcolors() возвращает None. Чаще всего это проявляется на больших или очень детализированных изображениях и может выглядеть как ошибка. Но это не баг — вы упираетесь в встроенный в API порог.

Как воспроизвести проблему

Достаточно такого простого кода:

from PIL import Image
img_src = "path_or_url_to_image"
base_pic = Image.open(img_src)
unique_palette = base_pic.getcolors(maxcolors=100000)

На небольших картинках всё выглядит нормально. На очень большом изображении unique_palette может оказаться None, что поначалу сбивает с толку.

Что происходит на самом деле

Возвращаемое значение getcolors() напрямую зависит от порога, который вы передаёте через параметр maxcolors. Если в изображении уникальных цветов больше этого лимита, getcolors() вернёт None. В одном реальном примере в изображении было 250 203 цвета, поэтому maxcolors=100 000 не хватило и вызов вернул None.

Есть две простые границы, которые помогают ориентироваться. Максимально возможное количество уникальных цветов не может превышать число пикселей в изображении — это ширина, умноженная на высоту. Существует и верхний предел, задаваемый глубиной цвета. Для типичного изображения с глубиной 24 бита на пиксель этот потолок равен 2**24, то есть 16 777 216 возможных цветов. Если пикселей больше, какие‑то цвета неизбежно повторяются.

Как исправить

Такое поведение API заложено намеренно. Если вам нужны данные о цветах и вы понимаете, что изображение может превысить текущий лимит, увеличьте maxcolors настолько, чтобы вызов не завершался досрочно:

from PIL import Image
img_src = "path_or_url_to_image"
base_pic = Image.open(img_src)
color_set = base_pic.getcolors(maxcolors=100000000)

При более высоком пороге getcolors() вернёт список пар «цвет—частота», а не None — даже для очень детализированных или огромных изображений.

Почему это важно

Многие процессы анализа цвета — извлечение палитры, поиск доминирующих оттенков, предварительные проверки перед квантизацией — опираются на getcolors(). Если незаметно упереться в порог и получить None, последующая логика может ломаться самыми неожиданными способами. Понимание связи между фактическим числом уникальных цветов и ограничением maxcolors помогает выбрать подходящий порог и избежать хрупкого поведения на больших ресурсах.

Практические выводы

Если getcolors() возвращает None, это означает, что в изображении больше уникальных цветов, чем указано в вашем maxcolors. Большие изображения легко превышают скромные пороги; в одном случае насчитали 250 203 разных цвета. Абсолютное число уникальных цветов ограничено количеством пикселей и глубиной цвета; для распространённых 24 bpp верхняя граница — 16 777 216. Если сомневаетесь, задайте большее значение maxcolors, чтобы анализ не прерывался преждевременно.

Статья основана на вопросе на StackOverflow от Aadvik и ответе от Aadvik.