Виктор Ольховский
222 повідомлення
#13 років тому
Есть рисунок представленный в первичном виде: массив пикселей. проще некуда.
если я хочу отобразить скажем уменьшеную вдвое картинку то все просто:
мне надо отображать каждый второй пиксель. если уменьшенную вчетверо - каждый четвертый.
Но! а как добится плавного уменьшения?
как к примеру из картинки шириной в 1000 пикселей получить картинку шириной в 315?
а потом при желании - в 320 к примеру.
по факту ясно - надо подбирать динамические промежутки и брать из них пиксели так, чтобы пройдя тысячу- их набралось 315.
но вот как это реализовать - никак не соображу!
Владимир М.
327 повідомлень
#13 років тому
Самое очевидное метод ближайшего соседа. Недостаток - ступенчатость.
zoom:=size1/size2;
for x:=1 to x_size2 do
for y:=1 to y_size2 do
color2:=color1;


Сложней и лучше - билинейная интерполяция. Недостаток - размытие.

Ещё лучше, но сложней - изучать алгоритмы обработки изображений.
Евгений О.
2989 повідомлень
#13 років тому
Вообще-то intelleks уже ответил.

Цитата:
мне надо отображать каждый второй пиксель. если уменьшенную вчетверо - каждый четвертый.


Это самый не качественный алгоритм.

Посчитать для подобного алгоритма можно например так.

Для 1-го пикселя берем из оригинала для пересчета n1 = round(1000 / 315) пикселей.
Для 2-го пикселя берем из оригинала для пересчета n2 = round((1000 - n1) / (315 - 1)) пикселей.
Для 3-го пикселя берем из оригинала для пересчета n3 = round((1000 - n1 - n2) / (315 - 2)) пикселей.

Или более простой вариант (но и менее точный).
n = наименьшее_целое(1000 / 315)
Для 314 пикселей берем из оригинала по n пикселей, для 315-го - все что осталось.
Виктор Ольховский
222 повідомлення
#13 років тому
Заранее спасибо. чувствую что здесь есть суть. только я не понял СМЫСЛ первичной интерации:
Для 2-го пикселя берем из оригинала для пересчета n2 = round((1000 - n1) / (315 - 1)) пикселей.
что это действие означает то?
Евгений О.
2989 повідомлень
#13 років тому
Цитата ("viktorkoptima"):
что это действие означает то?

Ну хоть немножко улучшить конечную картинку. Берем не 1 пиксель оригинала, а средний цвет и среднюю яркость из преобразуемой группы пикселей оригинала. В целом надо отсчитать прямоугольник в оригинале, который мы уменьшим до 1 пикселя в конечной картинке, и посчитать средний цвет и среднюю яркость этого прямоугольника. Я там только половину расчета написал, например по горизонтали, такое же надо еще сделать по вертикали и получим преобразуемые прямоугольники оригинала.
Виктор Ольховский
222 повідомлення
#13 років тому
Я понимаю. но мне не нужна в данном случае эта качественность. вопрос стоит в другом - как правильно выбирать пиксели чтобы уменьшать плавно- ну описанная поблема в теме?
Евгений О.
2989 повідомлень
#13 років тому
Вас интересут только масштабирование? Ну так intelleks полный цикл расписал для по-пиксельной выборки.
Виктор Ольховский
222 повідомлення
#13 років тому
Я никогда не был знаком с подобными алгоритмами. с рисунками вообще работаю впервые. сбивает напрочь. буду очень благодарен если распишите только машстабирование.
если быть точным: как из рисунка шириной n получить рисунок шириной N (N<n)
Евгений О.
2989 повідомлень
#13 років тому
На каком языке-то? Вообще-то во всех языках есть стандартные функции для масштабирования изображений.
Виктор Ольховский
222 повідомлення
#13 років тому
Да не нужен язык. в двух словах принцип опишите. стандартные не годятся- надо вручную.
Евгений О.
2989 повідомлень
#13 років тому
Ну что-то такое. Только учтите, что это ни к какому конкретному языку не привязано, просто иллюстрация алгоритма.
x1 - ширина оригинала
y1 - высота оригинала
x2 - ширина конечного изображения
y2 - высота конечного изображения

zoomX = ближайшее_меньшее_целое(x1 / x2);
zoomY = ближайшее_меньшее_целое(y1 / y2);
x3 = 0; //координата x в конечном изображении
y3 = 0; //координата y в конечном изображении
цикл_по_горизонтали от x = 0 до x1 шаг zoomX
начало
цикл_по_вертикали от y = 0 до y1 шаг zoomY
начало
p = читаем_пиксель_из_оригинала(x, y);
//xчто-то делаем, если надо
записываем_пиксель_в_конечное_изображение(x3, y3, p);
y3 = y3 + 1;
конец
x3 = x3 + 1;
конец
Виктор Ольховский
222 повідомлення
#13 років тому
//xчто-то делаем, если надо
а КОГДА надо?

Хотя смысл я понял. но как то уж очень просто. то есть шаг - дробный а потом округляем. думаете - получится?

Понимаете этот алгоритм по моему мало чем будет отличатся от моего! ведь дробные обращения (раз дробный шаг) к пикселям не будут учитыватся. значит - будут отбрасыватся. значит по сути считаем что шаг целый.
и получается сканируем и показываем каждый третий пиксель или каждый чертвертый или каждый пятый. при большом изображении ШАГ машстабирования получается очень БОЛЬШИМ. понимаете?
то есть к примеру шаг 1 - изображение полная копия оригинала.
шаг -2 - изображение УЖЕ В ДВА РАЗА МЕНЬШЕ.
а если шаг 1.5 то сначала возьет 1 пиксель. потом третий. потом четвертый. хм.. надо попробовать.
Евгений О.
2989 повідомлень
#13 років тому
Цитата ("viktorkoptima"):
у вас в алгоритме записи ПАРАМЕТР zoomX вообще не фигурирует)

Это почему же? >>> цикл_по_горизонтали от x = 0 до x1 шаг zoomX
Цитата ("viktorkoptima"):
а КОГДА надо?

Ну это, вдруг понадобится как-то пересчитать это пиксель, ну например по цвету.
Цитата ("viktorkoptima"):
критерий записи и выборки.

И что это за критерий? 2 цикла обеспечивают выборку из оригинала в том количестве, сколько требуется конечному изображению, и равномерно распределены по оригиналу. Что еще надо?
Евгений О.
2989 повідомлень
#13 років тому
Цитата ("viktorkoptima"):
и получается сканируем и показываем каждый третий пиксель или каждый чертвертый или каждый пятый. при большом изображении ШАГ машстабирования получается очень БОЛЬШИМ.

Да. Самый простой вариант исключения этого я вам раньше предложил - не копирование пикселей, а пересчет области из оригинала.
Виктор Ольховский
222 повідомлення
#13 років тому
Да нет. я же там дальше рассуждаю. к примеру взять шаг 1.2 - получится - потому что будет "попадать" в целые пиксели и брать их. и уже чем при шаге 2. надо вобщем- пробовать.
Евгений О.
2989 повідомлень
#13 років тому
viktorkoptima, оно будет работать, только при дробных значения может выпадать правый и нижний край оригинала. Чтобы это исключить надо использовать более сложный расчет координат. Что-то вроде такого, как я раньше писал.
Для 1-го пикселя берем из оригинала для пересчета n1 = round(1000 / 315) пикселей.
Для 2-го пикселя берем из оригинала для пересчета n2 = round((1000 - n1) / (315 - 1)) пикселей.
Для 3-го пикселя берем из оригинала для пересчета n3 = round((1000 - n1 - n2) / (315 - 2)) пикселей.
В этом случае за счет округления к ближайшему целому шаг будет плавать, ну например 1 3 5 8 10 12 15 17 19 22 и т.д. Так можно захватить оригинал более точно.
Тимур Ч.
300 повідомлень
#13 років тому