library - png c++




Как сделать высококачественное масштабирование изображения? (8)

Intel имеет библиотеки IPP, которые обеспечивают высокоскоростные алгоритмы интерполяции, оптимизированные для процессоров семейства Intel. Это очень хорошо, но это не бесплатно. Взгляните на следующую ссылку:

Intel IPP

Я пишу код для масштабирования 32-битного изображения RGBA в C / C ++. Я написал несколько попыток, которые были несколько успешными, но они медленны, а главное качество изображения не приемлемо.

Я сравнил то же изображение, масштабируемое OpenGL (то есть с моей видеокартой) и моей рутиной, и это отличное качество. Я искал Google Code, просматривал исходные деревья всего, что, как я думал, прольет свет (SDL, Allegro, wxWidgets, CxImage, GD, ImageMagick и т. Д.), Но обычно их код либо запутан и разбросан по всему месту, либо пронизан сборщиком и небольшими комментариями или без комментариев. Я также читал несколько статей в Википедии и в других местах, и я просто не нашел ясного объяснения того, что мне нужно. Я понимаю основные понятия интерполяции и выборки, но я изо всех сил пытаюсь получить алгоритм правильно. Я НЕ хочу полагаться на внешнюю библиотеку для одной подпрограммы и должен конвертировать в свой формат изображения и обратно. Кроме того, я хотел бы знать, как это сделать в любом случае. :)

Я видел аналогичный вопрос, заданный перед переполнением стека, но на него не ответили так, но я надеюсь, что есть кто-то, кто может помочь подтолкнуть меня в правильном направлении. Может быть, указать мне на некоторые статьи или псевдокод ... что-нибудь, что поможет мне учиться и делать.

Вот что я ищу:

  1. Нет ассемблера (я пишу очень портативный код для нескольких типов процессоров).
  2. Никаких зависимостей от внешних библиотек.
  3. Я в первую очередь забочусь о масштабировании DOWN, но также должен будет написать процедуру масштабирования позже.
  4. Качество результата и ясность алгоритма наиболее важны (я могу его оптимизировать позже).

Моя процедура по существу принимает следующий вид:

DrawScaled(uint32 *src, uint32 *dst, 
      src_x, src_y, src_w, src_h, 
      dst_x, dst_y, dst_w, dst_h );

Благодаря!

ОБНОВЛЕНИЕ. Чтобы уточнить, мне нужно что-то более продвинутое, чем перепрограммирование коробки для уменьшения масштаба, что слишком сильно размывает изображение. Я подозреваю, что я хочу, это какой-то бикубический (или другой) фильтр, который несколько обращен к бикубическому алгоритму масштабирования (т. Е. Каждый пиксель назначения вычисляется из всех исходных пикселей источника в сочетании с алгоритмом взвешивания, который сохраняет четкость.

пример

Вот пример того, что я получаю от алгоритма wxWidgets BoxResample по сравнению с тем, что я хочу, на растровом изображении 256x256, масштабированном до 55x55.

  • www.free_image_hosting.net/uploads/1a25434e0b.png

И наконец:

  • www.free_image_hosting.net/uploads/eec3065e2f.png

исходное изображение 256x256


В качестве продолжения, Джереми Радд опубликовал эту статью выше. Он реализует фильтрованное изменение размера двух проходов. Источниками являются C #, но это выглядит достаточно ясно, что я могу его портировать, чтобы попробовать. Вчера я нашел очень похожий код C, который было намного сложнее понять (очень плохие имена переменных). Я получил его на работу, но он был очень медленным и не давал хороших результатов, что заставило меня поверить, что в моей адаптации была ошибка. Возможно, мне удастся написать это с нуля с этим в качестве справочной информации, которую я попробую.

Но, учитывая, как работает алгоритм с двумя проходами, я задаюсь вопросом, не существует ли более быстрый способ сделать это, возможно, даже за один проход?


Возможно ли, что OpenGL делает масштабирование в векторном домене? Если это так, нет никакого способа, чтобы какое-либо масштабирование на основе пикселей было рядом с ним по качеству. Это большое преимущество векторных изображений.

Бикубический алгоритм может быть настроен на резкость против артефактов - я пытаюсь найти ссылку, я отредактирую ее, когда буду.

Edit: Это была работа Mitchell-Netravali, о которой я думал, на что ссылается внизу этой ссылки:

http://www.cg.tuwien.ac.at/~theussl/DA/node11.html

Вы также можете рассмотреть вопрос о повторной выборке Ланцоса в качестве альтернативы бикубическому.


Достаточно простой и достойный алгоритм для повторной выборки изображений - это интерполяция Bicubic , только для википедии есть вся информация, необходимая для ее реализации.



Я нашел, что реализация wxWidgets довольно проста для изменения, если требуется. Это все C ++, поэтому проблем с переносимостью там нет. Единственное различие заключается в том, что их реализация работает с неподписанными массивами символов (которые, как мне кажется, является самым простым способом обработки изображений) с байтовым порядком RGB и альфа-компонентом в отдельном массиве.

Если вы ссылаетесь на файл «src / common / image.cpp» в дереве исходных данных wxWidgets, есть функция сэмплирования вниз, которая использует метод выборки в ящике «wxImage :: ResampleBox» и функцию масштабирования вверх, называемую «wxImage :: ResampleBicubic».


Общая статья нашего любимого хозяина: « Улучшение изображения» , обсуждение относительных качеств различных алгоритмов (и ссылка на другую статью CodeProject).


Похоже на то, что вы действительно испытываете трудности с пониманием - это дискретный -> непрерывный -> дискретный поток, задействованный в правильной передискретизации изображения. Хороший технический отчет, который мог бы помочь вам понять, что вам нужно, - это пиксель Алеви Рэя Смита, а не маленький квадрат .





image-scaling