NickLion писал(а): ↑22.06.2014 11:19
Вот код сваял. Там Qt для проверки, что всё норм, но там легко поменять для нужного формата.
scaleNearestNeighbour — по методу ближайшего, как для сжатия (пиксели выпадают), так и растяжения (квадратиками)
scaleBilinear — билинейный (учтены ограничения по выходу за диапазон, поэтому немного страшно выглядит и 4 раза расчёт производится. Данный методы нормально работает на растяжение, а на сжатие только чуть меньше 1 нормально работает (где-то до 0.75), а меньше начинает пропускать пиксели как и ближайший сосед, там надо немного по-другому делать.
.width() — ширина изображения
.height() — высота
.scanLine(i) — адрес строки i изображения
И да, методы расчитаны толко на 32-х битные изображения!
Благодарю Вас NickLion, попробую прикрутить.
Сегодня полночи просидел в инете, пытался понять теорию. С методом ближайшего соседа разобрался, это совсем просто, а вот с билинейной и бикубической интерполяцией беда. Не пойму я принципа как их расчитывают.
Задача заключается в нахождении яркости в точке V.
Сначала находится яркость в точке V5 с учетом линейной интерполяции между точками V1 и V4; затем в точке V6 с учетом интерполяции между точками V2 и V3. Затем производится интерполяция между точками V5 и V6 для нахождения яркости в точке V.

V5=V1*(1-Ex) +V4*Ex
V6=V2*(1-Ex) +V3*Ex
V = V5*(1-Ey) +V6*Ey
Ex, EyО{0:1}
Мне все здесь понятно, кроме одного, почему интервал {0:1}, ведь расстояние между соседними пикселями всегда = 1, они же рядом, откуда беруться дробные числа.
Вот простой пример, есть два пикселя, между ними нужно вставить третий. Я думаю что цвет среднего (вставляемого) пикселя должен быть: (пиксель №1 + пиксель №2) : 2 = пиксель №3
(200 + 100) : 2 = 150, т.е. среднее значение, это то или нет, если то, то откуда здесь взяться интервалу {0:1}
Или вот Билинейная интерполяция:

Четыре красные точки представляют собой известные значения функции. Значение в зеленой точке должно быть интерполировано.
Пример билинейной интерполяции в единичном квадрате. Значения вершин составляют 0, 1, 1 и 0.5. Опять единичный квадрат, почему единичный, не догоняю.
Ниже приведен пример программы билинейной интерполяции изображения, написанный на C99 (на C89 компилироваться не будет!) (стырено с википедии(ц))
Входные параметры:
a - указатель на массив пикселей изображения, которое необходимо увеличить (уменьшить)
Нумерация элементов [0..old_h-1, 0..old_w-1]
oldw - старая ширина изображения
oldh - старая высота изображения
Выходные параметры:
b - указатель на массив пикселей ресемплированного изображения
Нумерация элементов [0..new_h-1, 0..new_w-1]
neww - новая ширина изображения
newh - новая высота изображения
Код: Выделить всё
#include <stdio.h>
#include <math.h>
#include <sys/types.h>
void resample(int oldw, int oldh, int neww, int newh, u_int a[oldh][oldw], u_int b[newh][neww])
{
int i, j;
int h, w;
float t;
float u;
float tmp;
float d1, d2, d3, d4;
u_int p1, p2, p3, p4; /* Окрестные пикселы */
u_char red, green, blue;
for (j = 0; j < newh; j++) {
tmp = (float) (j) / (float) (newh - 1) * (oldh - 1);
h = (int) floor(tmp);
if (h < 0) {
h = 0;
} else {
if (h >= oldh - 1) {
h = oldh - 2;
}
}
u = tmp - h;
for (i = 0; i < neww; i++) {
tmp = (float) (i) / (float) (neww - 1) * (oldw - 1);
w = (int) floor(tmp);
if (w < 0) {
w = 0;
} else {
if (w >= oldw - 1) {
w = oldw - 2;
}
}
t = tmp - w;
/* Коэффициенты */
d1 = (1 - t) * (1 - u);
d2 = t * (1 - u);
d3 = t * u;
d4 = (1 - t) * u;
/* Окрестные пиксели: a[i][j] */
p1 = a[h][w];
p2 = a[h][w + 1];
p3 = a[h + 1][w + 1];
p4 = a[h + 1][w];
/* Компоненты */
blue = (u_char) p1 *d1 + (u_char) p2 *d2 + (u_char) p3 *d3 + (u_char) p4 *d4;
green = (u_char) (p1 >> 8) * d1 + (u_char) (p2 >> 8) * d2 + (u_char) (p3 >> 8) * d3 + (u_char) (p4 >> 8) * d4;
red = (u_char) (p1 >> 16) * d1 + (u_char) (p2 >> 16) * d2 + (u_char) (p3 >> 16) * d3 + (u_char) (p4 >> 16) * d4;
/* Новый пиксел из R G B */
b[j][i] = ((u_int32_t) red << 16) | ((u_int32_t) green << 8) | (blue);
}
Пытался по тупому вставить, компилируется, но не работает,
a - указатель на массив пикселей изображения, которое необходимо увеличить (уменьшить)
b - указатель на массив пикселей ресемплированного изображения
Я передаю в качестве аргумента int *a и int *b, то есть два массива, один с загруженным изображением, второй пустой
Код: Выделить всё
int *img = img_read_jpeg("/usr/share/wallpapers/wallpaper.jpg"); // размер 1280х1018, функция возвращает int *imge, на мой взгляд это указатель на массив пикселей типа int, (int r, g, b), или я туплю?
int *img_new = calloc(1920 * 1080, 4); // выделяю память под массив, куда будет выход данных
// вызываю функцию
resample(1280, 1018, 1920, 1080, img, img_new);
Компилируется, с предупреждениями:
Код: Выделить всё
foxy.c:445:3: warning: passing argument 5 of ‘resample’ from incompatible pointer type [enabled by default]
resample(1280, 1018, 1920, 1080, img, img_new);
foxy.c:327:6: note: expected ‘u_int (*)[(sizetype)(oldw)]’ but argument is of type ‘int *’
void resample(int oldw, int oldh, int neww, int newh, u_int a[oldh][oldw], u_int b[newh][neww])
foxy.c:445:3: warning: passing argument 6 of ‘resample’ from incompatible pointer type [enabled by default]
resample(1280, 1018, 1920, 1080, img, img_new);
foxy.c:327:6: note: expected ‘u_int (*)[(sizetype)(neww)]’ but argument is of type ‘u_int *’
void resample(int oldw, int oldh, int neww, int newh, u_int a[oldh][oldw], u_int b[newh][neww])
Понимаю, что проблема с не соответствием типов int vs u_int или что то вроде этого, что не так, где косяк (мой конечно). Не люблю я все эти типы u_int и прочие, то ли дело в асме BYTE, WORD, DWORD, QWORD и все, а больше ничего и не надо, удобно, понятно, просто, а в сях столько типов, мозг клинит, не говоря уже про срр и прочие ЯВУ.