Сжатие PNG с помощью PIL и cv2

Я пытаюсь сделать компрессор изображений в моем проекте django. Я хорошо справился с jpg, но у меня было много проблем с png. Для сжатия я использую PIL и cv2, но не могу получить результат лучше, чем 16% сжатия для больших файлов PNG (> 1 МБ). Я попытался объединить обе библиотеки, но это все еще не нововведение. Вот простой код моего взгляда:

(приведенный выше код для сжатия jpg)

elif picture.mode == ('RGBA'):
            if photo.image.size < 1000000:
                colorsloss = picture.convert(mode="P", palette=Image.ADAPTIVE)
                colorsloss.save('media/new/'+name,"PNG",quality=75, optimize=True, bits=8)
            else:
                originalImage = cv.imread(str('/home/andrey/sjimalka'+ photo.image.url))
                cv.imwrite('media/new/'+name, originalImage,[cv.IMWRITE_PNG_COMPRESSION, 9])
                cvcompressed = Image.open('media/new/'+name)
                cvcompressed.convert(mode="RGB")
                cvcompressed.save('media/new/'+name,"PNG",quality=75, optimize=True)

Итак, у меня две большие проблемы: 1) Если у меня изображение небольшого размера (‹1 мб), я использую режим P в Pillow. Он отлично работает, но если я сжимаю изображение с помощью градиента, я могу увидеть некоторые искажения в тех местах, где у меня есть градиент. original  compressed У меня хорошее сжатие (примерно 85%), но пока не знаю, как это исправить.

2) Я не могу получить хорошее сжатие больших файлов png. Моя лучшая цель - 16%, с действительно хорошим качеством, но это все еще не новинка. Мб, я делаю что-то не так, или я должен использовать любую другую библиотеку или технологию, чтобы сделать это лучше. Я хочу получить список 50% сжатия с большими файлами png.

Я уже пробовал использовать pngquant, но их документация была для меня не слишком ясна, и я не могу найти хороших примеров кода.


person Andrej Vilenskij    schedule 01.10.2018    source источник


Ответы (1)


PNG без потерь. Вы не можете отказаться от информации при записи, чтобы уменьшить размер файлов, как в JPEG.

Если вы выберете версию с палитрой, вам понадобится только один байт на пиксель вместо трех, но тогда вы получите только 256 цветов, и градиенты будут выглядеть вздорно.

Кроме того, настройка качества не такая, как для JPEG - она ​​больше похожа на параметр --fast или --best на gzip.

Одна вещь, которую вы можете сделать, если у вас есть большие области прозрачности, как у вас, - это сделать черными все пиксели, которые на 100% прозрачны. Это поможет им лучше сжаться. См. пример здесь.

person Mark Setchell    schedule 02.10.2018
comment
Спасибо за ответ. Я нашел еще одну библиотеку под названием PyPNG. Прямо сейчас я хочу разложить png pic по пикселям и попробовать поработать с массивами пикселей. Наверное, если программно нарисовать картинку на основе входящей, размер будет меньше. Я не уверен, что это может сработать, но сейчас я вижу, что это лучший способ достичь желаемого. - person Andrej Vilenskij; 03.10.2018