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

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

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

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

Вот что я ищу:

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

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

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

```

Благодаря!

**UPDATE:** Для уточнения, мне нужно что - то более продвинутое , чем коробка RESAMPLE для разукрупнения , которая размывает изображение слишком много. Я подозреваю , что я хочу , это какое - то бикубический (или другого) фильтра , который противоположен алгоритм бикубического UPSCALING (т.е. каждого пиксел назначения рассчитывается из всех источников способствующих пикселей в сочетании с алгоритмом взвешивания , который держит вещи острой.

пример
------

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

* www.free\_image\_hosting.net/uploads/1a25434e0b.png

И наконец: 

* www.free\_image\_hosting.net/uploads/eec3065e2f.png

оригинал 256x256 изображение

 

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

Идея заключается в том, чтобы принимать равномерно разнесенные выборки из исходного изображения; в вашем случае, 55 из 256, или один из каждых 4.6545. Просто вокруг числа, чтобы получить пиксель выбрать.

 

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

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

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

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

Вы также можете посмотреть в [Ланцоше передискретизацию](http://en.wikipedia.org/wiki/Lanczos_resampling) в качестве альтернативы Bicubic.

 

Довольно простой и достойный алгоритм дискретизации изображения является [бикубическим](http://en.wikipedia.org/wiki/Bicubic_interpolation) , википедией одна имеет всю информацию , вам нужно , чтобы это реализовать.

 

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

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

 

Похоже , что вы на самом деле трудно понять дискретное -> непрерывный -> дискретного поток участвует в правильно передискретизации изображения. Хороший отчет технологий , которые могли бы помочь дать вам представление о том , что это вам нужно , Элви Рея Смита [пиксель *не* маленькой площади](http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf) .

 

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

[Intel IPP](http://www.intel.com/cd/software/products/asmo-na/eng/302910.htm)

 

Родовая статья от нашего любимого хозяина: [Лучше Resizing Image](http://blog.codinghorror.com/better-image-resizing/) , обсуждая относительные качества различных алгоритмов (и ссылки на другую статью CodeProject).

 

Попробуйте использовать **Adobe библиотеки Generic Image** ( <http://opensource.adobe.com/wiki/display/gil/Downloads> ) , если вы хотите что - то готовое , а не только алгоритм.

---

Выписка из: <http://www.catenary.com/howto/enlarge.html#c>

Увеличить или уменьшить - С Исходный код Требует Виктор обработки изображений библиотеки для 32-разрядной Windows, V 5.3 или выше.

```

int enlarge_or_reduce(imgdes *image1)
{
   imgdes timage;
   int dx, dy, rcode, pct = 83; // 83% percent of original size

   // Allocate space for the new image
   dx = (int)(((long)(image1->endx - image1->stx + 1)) * pct / 100);
   dy = (int)(((long)(image1->endy - image1->sty + 1)) * pct / 100);
   if((rcode = allocimage(&timage, dx, dy,
      image1->bmh->biBitCount)) == NO_ERROR) {
      // Resize Image into timage
      if((rcode = resizeex(image1, &timage, 1)) == NO_ERROR) {
         // Success, free source image
         freeimage(image1);
         // Assign timage to image1
         copyimgdes(&timage, image1);
         }
      else // Error in resizing image, release timage memory
         freeimage(&timage);
      }
   return(rcode);
}

```

Этот пример изменяет область изображения и заменяет исходное изображение с новым изображением. 

 

Codeproject статья обсуждения и обмен исходного кода для **масштабирования изображения:**

* [Двупроходное Масштабирование с помощью **фильтров**](http://www.codeproject.com/KB/graphics/2_pass_scaling.aspx)
* [Матрица преобразование изображений в C #, используя **.NET GDI +**](http://www.codeproject.com/KB/GDI-plus/matrix_transformation.aspx)
* [Изменение размера фотографического изображения с **GDI + для .NET**](http://www.codeproject.com/KB/GDI-plus/imageresize.aspx)
* [Быстрое Диадическое Масштабирование изображения с **Хааром Transform**](http://www.codeproject.com/KB/graphics/Dyadic_down_sampling.aspx)

 

В качестве последующих мер, Джереми Радд опубликовал [эту статью](http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx) выше. Он реализует фильтруется двупроходное изменения размера. Источниками являются C # , но это выглядит достаточно ясно , что я могу портировать его , чтобы дать ему попробовать. Вчера , что было гораздо труднее понять (очень плохо имена переменных) я нашел очень похожий код C. Я получил его , чтобы разобраться, из-работы, но это было очень медленно и не дает хорошие результаты , которые привели меня к мысли , что была ошибка в моей адаптации. Я , возможно, лучше удачи писать с нуля с этим в качестве ссылки, которую я буду стараться.

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

 

Посмотрите на [ImageMagick](http://www.imagemagick.org) , которая делает все виды перемасштабирования фильтров.