1

Тема: Canvas postprocessing

Привіт всім!

Таке в мене питання. Як краще здійснити пост-обробку намальованого на канвасі зображення?

Наприклад ми малюємо на канвасі текст у заданому користувачем місці.
Після цього все що намальовано ліворуч від центра канвасу залишаєтьсятаким як було, а те що праворуч - вдвічі звужується.

Взагалі таку проблему потрібно розглядати як малювання, а потім обробку намальваного,
чи можна задати якісь правили за якими зображення зразу буде малюватись так як потрібно?

І для обробки зображення такого плану існують якісь бібліотеки, чи потрібно писати свої webgl шейдери?

Буду радий любим порадам :)

2

Re: Canvas postprocessing

там же групування є (я ним не володію)) )

а ще юзають більше ніж один канвас -
на одному прихованому малюють дрібні елементи,
на іншому- те що рідко змінюється,
потім на головний-видимий канвас лишень копіюють

https://blog.clever-games.win/
Це ще не кінець. Це навіть не початок кінця. Але, можливо, це кінець початку.
Зростання мудрості можна точно вимірювати ступенем зменшення злоби.
///// у творчій відпустці. не турбувати /////
Подякували: FakiNyan, Monolith2

3 Востаннє редагувалося sensei (05.12.2017 22:25:12)

Re: Canvas postprocessing

Такс я вернувся і накидав отакий кід
https://jsfiddle.net/sensei228/z6L4cjaa/

Ідейно воно працює так:
Є у нас два сектори канвасу: лівий та правий. На лівому текст має залишатись незмінним, а на правому ставати вдвічі вужчим

Створюємо невидимий канвас який буде 1.5 ширини того, який буде видимим в результаті, бо по іксу [0; 0.5] лишаються незмінними, а [0.5; 1.5] будуть перетворюватись на [0.5; 1]

Текст малюється спершу на невидимому канвасі.
Потім створюємо ще один тимчасовий канвас на який копіюємо вміст сектора з  невидимого канвасу, та використовуючи правильний скейл перемальовуємо його на наш кінцевий канвас і так для обох секторів.


В загальному я зробив те що хотів для початку, але навіть на такому простому прикладі відчутно просідають кадри, тому боюсь прийдеться переписувати на webgl.
Наступне над чим думатиму це як скейлити трикутні, а не квадратні зони

Подякували: 221VOLT1

4

Re: Canvas postprocessing

що то за 0 0.5 1.5 і все інше? ніфіга не пойняв

Говоріть українською! Живіть українською! Відчувайте українською!

5 Востаннє редагувалося sensei (06.12.2017 16:32:35)

Re: Canvas postprocessing

довжину канвасу(1) на якому хочемо побачити результат позначимо 1, тобто це проміжок від 0 до 1

довжину невидимого канвасу(2) який буде в майбутньому скейлитись і малюватись на перший зробимо в 1.5 раз більшою за перший канвас, тобто це в нас проміжок від 0 до 1.5

тобто те що ми намалювали на канвасі (2) в його проміжку [0; 0.5] ідентично перемалюється на той же проміжок канвасу (1)
а те що на проміжку [0.5; 1.5] і має довжину 1, зіскейлиться в два рази, щоб його довжина стала 0.5 та перемалюється на проміжок [0.5; 1] канвасу(1)

шось я трохи туплю і складно пояснюю прості речі  %)

6

Re: Canvas postprocessing

sensei написав:

Такс я вернувся і накидав отакий кід
https://jsfiddle.net/sensei228/z6L4cjaa/

Ідейно воно працює так:
Є у нас два сектори канвасу: лівий та правий. На лівому текст має залишатись незмінним, а на правому ставати вдвічі вужчим

Створюємо невидимий канвас який буде 1.5 ширини того, який буде видимим в результаті, бо по іксу [0; 0.5] лишаються незмінними, а [0.5; 1.5] будуть перетворюватись на [0.5; 1]

Текст малюється спершу на невидимому канвасі.
Потім створюємо ще один тимчасовий канвас на який копіюємо вміст сектора з  невидимого канвасу, та використовуючи правильний скейл перемальовуємо його на наш кінцевий канвас і так для обох секторів.


В загальному я зробив те що хотів для початку, але навіть на такому простому прикладі відчутно просідають кадри, тому боюсь прийдеться переписувати на webgl.
Наступне над чим думатиму це як скейлити трикутні, а не квадратні зони

є така штука як https://github.com/theshock/libcanvas
написана одним js-гуру
приклади http://libcanvas.github.io/
(я не зміг в неї, бо ооп не вмію, можливо вам підійде - швидкодія там ок, автор відповідає на запитання)

https://blog.clever-games.win/
Це ще не кінець. Це навіть не початок кінця. Але, можливо, це кінець початку.
Зростання мудрості можна точно вимірювати ступенем зменшення злоби.
///// у творчій відпустці. не турбувати /////
Подякували: sensei, Monolith2

7

Re: Canvas postprocessing

ніфіга не пойняв

Говоріть українською! Живіть українською! Відчувайте українською!

8

Re: Canvas postprocessing

FakiNyan написав:

ніфіга не пойняв

Кажіть тоді з якого моменту незрозуміло
І гляньте код і приклад, можливо так буде легше


221VOLT написав:

є така штука як https://github.com/theshock/libcanvas

Дякую, подивлюсь чи найду якесь застосування тому

9

Re: Canvas postprocessing

не пойняв, що перемальовується

Говоріть українською! Живіть українською! Відчувайте українською!

10

Re: Canvas postprocessing

https://jsfiddle.net/sensei228/z6L4cjaa/8/
ми спершу малюємо зображення на невидимий канвас, потім застосовуючи потрібні нам перетворення до намальованого зображення перемальовуємо його на видимий канвас
(знизу то той що мав бути невидимим)

11

Re: Canvas postprocessing

а нафіга ви створюєте ще один канвас в коді? tempCanvas

Говоріть українською! Живіть українською! Відчувайте українською!

12

Re: Canvas postprocessing

він використовується безпосередньо для перетворення зображення, в нашому випадку скейлу, щоб канвас з якого ми перемальовуємо залишався незмінним

  tempCanvas.width = canvasSource.width - canvas.width/2;
  sourceImage = ctxSource.getImageData(canvas.width/2, 0, tempCanvas.width, tempCanvas.height);
  ctxTemp.putImageData(sourceImage, 0, 0);
  ctx.save();
  ctx.scale(0.5, 1);
  ctx.drawImage(tempCanvas, canvas.width, 0);
  ctx.restore();

але для лівої частини де зображення не трансформується так, можна було обійтись без нього

13

Re: Canvas postprocessing

ну таке, наче пойняв

Говоріть українською! Живіть українською! Відчувайте українською!

14

Re: Canvas postprocessing

переробив скейлення так як зауважив факінун забравши хитрування з tempCanvas'ом
тепер просідання наче зникли
https://jsfiddle.net/sensei228/z6L4cjaa/9/

function drawScaledText() 
{
  //left part
  ctx.drawImage(canvasSource, 0, 0, canvas.width/2, 
  canvas.height, 0, 0, canvas.width/2, canvas.height);
  
  //right part
  ctx.drawImage(canvasSource, canvas.width/2, 0, canvasSource.width - canvas.width/2, 
  canvas.height, canvas.width/2, 0, canvas.width/2, canvas.height);
}
Подякували: 221VOLT1

15

Re: Canvas postprocessing

https://jsfiddle.net/sensei228/5bvcqxe3/
зробив скейл того що попадає у трикутну зону, та зміщення всього що йде після неї

тепер працюватиму над скейлом у напрямку довільного вектора, тобто не просто зліва направо

Прихований текст
Моя кінцева мета це модифікувати зображення маючи канву поділену на сітку з трикутників, де кожен з них має свій напрям скейлу
Подякували: ostap34PHP, 221VOLT2

16

Re: Canvas postprocessing

https://jsfiddle.net/cxhexdyw/
зробив скейл у напрямку довільного вектора (перпендикуляр до заданої лінії в мому випадку)

моменти які варто виділити:
як заскейлити зображення під довільним кутом
API для роботи з канвасом по замовчуванню дає можливість скейлити зображення тільки відносно координатних осей. Тому нам потрібно перетворити координатну площину таким чином, щоб наш вектор став в рівень з однією з цих осей. Після перетворення ми можемо заскейлити його звичним спочобом по "х" чи "у" (в залежності від того до якої осі ми рівнялись). Після того як скейл змінено нам потрібно повернути координатну площину до початкового її стану, тому застосовуємо протилежні перетворення до тих, які ми робили в першому кроці:

var angle = Math.atan2(line.b.y - line.a.y, line.b.x - line.a.x);//знаходимо кут до осі У

ctx.rotate(angle); //крутимо координатну площину, щоб вектор скейлу став в рівень з віссю У
ctx.scale(1, scale); //скейлимо площину
ctx.rotate(-angle); //повертаємо її на місце

ctx.drawImage(... 

як зафіксувати нерухому точку при перетворенні
це потрібно для того, щоб розмістити в правильному місці заскейлене зображення
Згрубша алгоритм такий:
зсуваємо координатну площину до потрібної точки (в даному прикладі це центр лінії яка є перпендикуляром до напрямного вектора)
потім застосовуємо потрібні нам перетворення (rotate, scale)
і при малюванні зображення початкові його координати задаємо як координати тої самої точки тільки зі знаком "-"

var midX = (line.a.x+line.b.x)/2; 
var midY = (line.a.y+line.b.y)/2;
  
ctx.translate(midX, midY);

ctx.drawImage(canvasSource, 0, 0, canvasSource.width, canvasSource.height, 
  -midX, -midY, canvas.width, canvas.height);

По суті якщо зображення ніяк не вертіти, то зображення намалюєтсья без змін, а якщо змінити rotate, то буде видно що зображення поркутилось не довкола лівого верхнього кута, а довкола заданої точки


сильно допомогла стаття http://codetheory.in/canvas-rotating-an … lar-point/

Подякували: FakiNyan, 221VOLT2