NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Zjednodušení aplikace

V předchozím kvízu, Online test znalostí JavaScript, jsme si ověřili nabyté zkušenosti z kurzu.

Jak se ti líbí článek?
Před uložením hodnocení, popiš prosím autorovi, co je špatněZnaků 0 z 50-500
Jak se ti kurz líbí?
Tvé hodnocení kurzuZnaků 0 z 50-500
Aktivity
Avatar
Martin Suchodol:27.7.2023 11:01

Ahoj, dělám editor obrázků, spíše je to takový projekt abych se trochu zlepšil v javascriptu. A mám tam několik metod pro aplikování filtrů konkrétně se jedná o černobílý, sepiový a vintage efekt. Každý z efektů je definovaný samostatně:

function applyGrayscaleEffect() {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  canvas.width = photo.width;
  canvas.height = photo.height;

  ctx.drawImage(photo, 0, 0, canvas.width, canvas.height);

  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  for (let i = 0; i < data.length; i += 4) {
    const red = data[i];
    const green = data[i + 1];
    const blue = data[i + 2];

    const gray = 0.2126 * red + 0.7152 * green + 0.0722 * blue;

    data[i] = gray;
    data[i + 1] = gray;
    data[i + 2] = gray;
  }

  ctx.putImageData(imageData, 0, 0);

  photo.src = canvas.toDataURL();
  resetButton.style.display = 'block';
  isEffectApplied = true;
  isCropSelected = false;
  isCroped = false;
  updateButtons();
  showImageInfoPanel();
}

function applySepiaEffect() {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  canvas.width = photo.width;
  canvas.height = photo.height;

  ctx.drawImage(photo, 0, 0, canvas.width, canvas.height);

  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  for (let i = 0; i < data.length; i += 4) {
    const red = data[i];
    const green = data[i + 1];
    const blue = data[i + 2];

    const sepiaRed = (0.393 * red + 0.769 * green + 0.189 * blue);
    const sepiaGreen = (0.349 * red + 0.686 * green + 0.168 * blue);
    const sepiaBlue = (0.272 * red + 0.534 * green + 0.131 * blue);

    data[i] = sepiaRed;
    data[i + 1] = sepiaGreen;
    data[i + 2] = sepiaBlue;
  }

  ctx.putImageData(imageData, 0, 0);

  photo.src = canvas.toDataURL();
  resetButton.style.display = 'block';
  isEffectApplied = true;
  isCropSelected = false;
  isCroped = false;
  updateButtons();
  showImageInfoPanel();
}

function applyVintageEffect()
{
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  canvas.width = photo.width;
  canvas.height = photo.height;

  ctx.drawImage(photo, 0, 0);

  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  for(let i=0; i < data.length; i += 4) {
    const red = data[i];
    const green = data[i + 4];
    const blue = data[i + 2];

    data[i] = red * 0.9;
    data[i + 1] = green * 0.7;
    data[i + 2] = blue * 0.5;

    data[i] += 30;
    data[i + 1] += 10;
  }

  ctx.putImageData(imageData, 0, 0);

  photo.src = canvas.toDataURL();
  resetButton.style.display = 'block';
  isEffectApplied = true;
  isCropSelected = false;
  isCroped = false;
  updateButtons();
  showImageInfoPanel();
}

Následně pak mám listener který hlídá rozbalovací menu a aplikuje efekt podle toho jaká je vybraná hodnota v rozbalovacím menu.

Aktuálně se pak snažím aplikaci trochu zpřehlednit, a přemýšlím co s metodami na aplikaci efektů, nabízí se zde možnost sjednocení do metody nazvané třeba applyEffect(ef­fect), s tím že o tom jaký efekt se bude aplikovat rozhodne switch. Na jednu stranu by to rozhodně byl dobrý nápad, jelikož každá z metod má hromadu duplicitního kódu. Na druhou stranu takhle oddělené mi to přijd přehlednější ale to je spíš subjektivní pocit.

function applyEffect(effectType) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  canvas.width = photo.width;
  canvas.height = photo.height;

  ctx.drawImage(photo, 0, 0, canvas.width, canvas.height);

  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  switch (effectType) {
    case 'grayscale':
      for (let i = 0; i < data.length; i += 4) {
        const red = data[i];
        const green = data[i + 1];
        const blue = data[i + 2];

        const gray = 0.2126 * red + 0.7152 * green + 0.0722 * blue;

        data[i] = gray;
        data[i + 1] = gray;
        data[i + 2] = gray;
      }
      break;
    case 'sepia':
      for (let i = 0; i < data.length; i += 4) {
        const red = data[i];
        const green = data[i + 1];
        const blue = data[i + 2];

        const sepiaRed = (0.393 * red + 0.769 * green + 0.189 * blue);
        const sepiaGreen = (0.349 * red + 0.686 * green + 0.168 * blue);
        const sepiaBlue = (0.272 * red + 0.534 * green + 0.131 * blue);

        data[i] = sepiaRed;
        data[i + 1] = sepiaGreen;
        data[i + 2] = sepiaBlue;
      }
      break;
    case 'vintage':
      for (let i = 0; i < data.length; i += 4) {
        const red = data[i];
        const green = data[i + 1];
        const blue = data[i + 2];

        data[i] = red * 0.9;
        data[i + 1] = green * 0.7;
        data[i + 2] = blue * 0.5;

        data[i] += 30;
        data[i + 1] += 10;
      }
      break;
    default:
      return;
  }

  ctx.putImageData(imageData, 0, 0);
  photo.src = canvas.toDataURL();
  resetButton.style.display = 'block';
  isEffectApplied = true;
  isCropSelected = false;
  isCroped = false;
  updateButtons();
  showImageInfoPanel();
}
 
Odpovědět
27.7.2023 11:01
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:27.7.2023 15:29

Ono, slo by uz do hlavni class zpristupnit data obrazku, ktere pak je predat do funkce, usetris asi 4 radky kodu v kazde funkci. A pak uz tam asi nic navic nezustane.

Funkcemi te muzu zahltit :)
https://mlich.zam.slu.cz/col5.htm
-- Mam tam funkci, ktera vyuziva model YUV, slozku Y ke stanoveni zda ma psat cerne nebo bile na pozadi, aby to bylo dobre citelne.
-- modely RGB, HLS, YUV, YIQ
-- funkci, ktera veme odstin sede a zkusi tvou barvu naladit na stejny odstin, tusim zamenou Y slozky
-- pak tam je algoritmus pocitani z barvy A do B = p/100 * A + (100-p)/100 * B
-- a nekde mam webku s ostrenim
https://mlich.zam.slu.cz/…-lanczos.htm
https://mlich.zam.slu.cz/…polation.htm
-- a pak mam nekde drag-drop, coz je sikovne na kresleni objektu, ze je muzes stale presouvat
https://mlich.zam.slu.cz/…xample5.html
naklikas uzly a muzes je presouvat a propojovat carami
-- a pak je dobry take algoritmus zarovnavani do mrizky, grid, treba po 5 px.

A pak ti muzu popsat zpusob, jak ostrim v Gimpu.

  • layout 1 L1 - clone L2, L3
  • L3 rozmazu gausove
  • provedu spojeni L2 L3 pres efekt extrakce zrnitosti (to vyrobi sedou plochu, kde jsou okraje objektu)
  • a pak provedu spojeni L1 s L2_3 efektem slouceni zrnitosti
  • pripadne predtim L2_3 naklonuji a spojim vsechny klony k L1

Funguje to skvele, kdyz se chces zbavit efektu zamlzeni nebo foceni pres zamlzene sklo. Dokonce to umi vytahnout barvy na cernobile fotce, pokud ji nafotis barevne.

 
Nahoru Odpovědět
27.7.2023 15:29
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:27.7.2023 15:30

Pripadne se da na nektery L2_3 aplikovat nejake dalsi priostreni nez to spojis s L1.
Nevyhodou je, ze to vytahuje zrnitost, takze je vic poznat treba jpeg fragmenty.

 
Nahoru Odpovědět
27.7.2023 15:30
Avatar
JsonKody
Člen
Avatar
JsonKody:1.8.2023 10:59

Nechces to hodit treba na codepen nebo tak?
At to vidim cele.

 
Nahoru Odpovědět
1.8.2023 10:59
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.