Как уменьшить изображение pixbuf без потери качества?

У меня есть изображение pixbuf, и я хочу сохранить его в формате PDF с помощью cairo. Поскольку pixbuf слишком велик, я хочу уменьшить его. Я использую scale_simple метод. Но масштабированный результат стал размытым. Ниже скриншот, который я сделал. Реальное изображение находится справа, а слева - изображение из pdf blur

Вы знаете, как уменьшить размер pixbuf без потери качества? Ниже мой пример кода.

from gi.repository import GdkPixbuf, Gdk
import cairo

class gui():
    def __init__(self):
        pix = GdkPixbuf.Pixbuf.new_from_file('tux2.png')
        pix = pix.scale_simple(pix.get_width() / 3, pix.get_height() / 3, GdkPixbuf.InterpType.HYPER)
        ps = cairo.PDFSurface('pix.pdf', 500, 500)
        cr = cairo.Context(ps)
        Gdk.cairo_set_source_pixbuf(cr, pix, 0, 0)
        cr.paint()

if __name__ == '__main__':
    gui()

person user2435611    schedule 03.07.2013    source источник
comment
Когда вы уменьшаете (растровое) изображение, если вы одновременно не увеличиваете его dpi, вы всегда теряете качество. Нет никакого способа обойтись без этого. Изображение 200x200 содержит только 4/9 информации изображения 300x300, и вы не можете выбросить 55% информации без потери качества. Усреднение, размытие, дизеринг и другие методы - это попытки сделать потерю менее заметной; все они имеют очевидные побочные эффекты, но их неиспользование имеет еще более очевидные побочные эффекты.   -  person abarnert    schedule 03.07.2013
comment
Я считаю, что речь идет именно об увеличении dpi, поскольку на выходе получается PDF, по сути векторный формат.   -  person Dima Tisnek    schedule 03.07.2013


Ответы (2)


Вы не должны масштабировать pixbuf вообще.

Вместо этого вы должны масштабировать объект (pixbuf как есть).

Это будет выглядеть примерно так:

cr.save()
cr.scale(scale_xy, scale_xy)
cr.xxx_place_image(...)
cr.restore()
person Dima Tisnek    schedule 03.07.2013
comment
нп. Чтобы добавить предостережение, скажем, ваш пользователь сбросил изображение rgba размером 80Kx80K с 16 битами на канал, что приведет к огромному pdf, в этом случае вы можете предварительно масштабировать растровое изображение :) - person Dima Tisnek; 04.07.2013

А как насчет воссоздания этого конкретного изображения с помощью команд PDF? Это векторный формат, и вы можете создать подобное изображение в svg и импортировать его. Масштабирование изображения - это фатальный процесс потери фактических данных о цвете, поскольку имеет место аппроксимация. Используйте расширенный алгоритм масштабирования, например фильтрацию Ланцоша.

person Mico    schedule 03.07.2013