[JS] 이미지 모자이크 기능 추측해보기

cgoing·2023년 6월 12일
20
post-thumbnail
post-custom-banner

소개👻

본 포스트에서는 특정 이미지흑백으로 변환하는 로직을 살펴보며, 이러한 프로세스가 어떻게 실제로 활용되는지에 대해 고찰합니다.

이 글을 읽고나면 당신은 이미지에 모자이크 처리하는 방법을 스스로 추측 하실수 있을겁니다.

또한, 이미지, 사운드, 비디오와 같은 다양한 미디어를 수정하고 편집하는 여러 프로그램들 (예: 포토샵, 오토튠)이 어떻게 만들어졌는지에 대한 흥미로운 추측을 통해 더 깊이 있는 이해를 제공하고자 합니다.

이 로직은 JavaScript로 작성되었지만, 특정 언어에 국한된 것이 아닙니다.
JavaScript에 익숙하지 않아도 걱정하지 않아도 됩니다.
본 포스트의 핵심은 언어나 기술적 세부사항보다는 프로그래밍의 근본적인 원리와 논리를 이해하는 데 있습니다. 따라서 백엔드든 프론트엔드든, 어떤 언어를 사용하든 간에 '프로그래머'라는 공통된 관점에서 이 내용을 살펴보시면 됩니다.

🌈RGB

학창시절에 배운 삼원색 이 기억나실 것입니다.

RGB (Red, Green, Blue) 는 빛의 세 가지 기본 색상을 나타냅니다. 이 세 가지 색상의 조합으로 모든 색상을 생성할 수 있습니다.

각각의 색상은 0부터 255 사이의 값을 가집니다. 이 값을 '밝기' 또는 '강도'라고 생각할 수 있습니다.

  • RGB 값이 모두 0인 경우, 색상은 검은색입니다.
  • RGB 값이 모두 255인 경우, 색상은 흰색입니다.
  • RGB 값이 (255,0,0)인 경우, 색상은 빨간색입니다.

개발을 배울 초창기에, 사진을 숫자로 표현할 수 있다는 사실을 알았을 때 정말로 놀랐습니다.

이미지는 픽셀 단위로 크기를 측정할 수 있으며, 각 픽셀은 하나의 RGB 값을 가집니다.

따라서, 이미지는 사실상 2차원 배열로 표현될 수 있습니다
[
[ RGB( 0,24,233 ), RGB( 254,145,6 ), RGB(20,51,60) ... ],
[ RGB( 50,124,23 ), RGB( 40,245,123 ), RGB(150,1,70) ... ],
[ RGB( 65,2,13 ), RGB( 54,245,57 ), RGB(0,151,20) ... ],
...
]

🌗흑백으로 만드는 방법

픽셀의 R, G, B 각 성분이 동일한 값으로 설정되어 있다면 이 색상은 회색조 입니다.

예를 들어, RGB(128, 128, 128)은 중간 톤의 회색을 나타내며, RGB(255, 255, 255)은 흰색을, RGB(0, 0, 0)은 검은색을 나타냅니다.

결국 이미지의 모든 픽셀의 RGB 를 회색조로 변경하게 되면 밝기만 존재하는 흑백 사진이 됩니다.

만약 RGB ( 200, 100, 100 ) 인 색상의 RGB 값의 평균을 구하게 되면

( 200 + 100 + 100 ) / 3 == 133.33333333333334

133 은 0 ~ 255 중에 대충 중간 회색 정도가 예상 되네요

반대로 RGB 의 각 값의 차이를 벌리게 되면 더 선명한 색이 됩니다. ( 선명도 필터)

👨‍💻WEB 에 서 실행 하는 방법

아래 간단한 HTML 파일이 있습니다.

input 의 파일을 변경하게 되면 HtmlCanvasElement 를 통해 이미지의 RGB 값을 배열로 추출하여 변경 하면 됩니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <input type="file" accept="image/*" id="input" />
      <img id="image" style="width:400px;height: 400px; object-fit: cover;"></img>
    </div>
    <script src="app.js"></script>
  </body>
</html>

아래는 canvas 로 Image의 Data 를 출력한 값 입니다.
실제 이미지의 RGB 값을 출력하면 RGB 가 아닌 RGBA 입니다. A 는 투명도 입니다.

이미지의 data의 총 길이는 결국 4의 배수가 되게 됩니다.

//  이미지를 입력받을 input
const input = document.getElementById('input');
/**
 * 버츄얼 캔버스
 * 직접 화면에 보여지지 않고, 원본 이미지를 그린 후, 그 이미지의 RGB 값이 담긴 Array 를 가져와서
 * RGB 를 흑백으로 변환후에, 다시 Base64 형태로 뽑기 위한 용도.
 */
const vCanvase = document.createElement('canvas');
const ctx = vCanvase.getContext('2d');

/** 업로드한 파일을 읽는 용도 */
const reader = new FileReader();

reader.onload = e => {
  const image = new Image();
  image.onload = () => {
    ctx.clearRect(0, 0, vCanvase.width, vCanvase.height); // 기존 버추얼 캔버스를 지움.
    vCanvase.width = image.width;
    vCanvase.height = image.height;
    ctx.drawImage(image, 0, 0); // 인풋으로 들어온 이미지를 버추얼 캔버스에 그림

    const imageData = ctx.getImageData(0, 0, vCanvase.width, vCanvase.height); // 이미지의 정보를 가져옴
    

    for (let i = 0; i < imageData.data.length; i += 4) {
      //  각 필셀별로 평균을 구해 흑색채로 변경

      const avg =
        (imageData.data[i] + imageData.data[i + 1] + imageData.data[i + 2]) / 3; // rgb 의 값 평균
      imageData.data[i] = avg; // R
      imageData.data[i + 1] = avg; // G
      imageData.data[i + 2] = avg; // B
      // A 인 투명도는 그대로~
    }

    ctx.putImageData(imageData, 0, 0); //흑백으로 변환된 이미지를 다시 그림

    const grayscaleDataURL = vCanvase.toDataURL('image/png'); // 이미지를 base64 로 추출

    document.getElementById('image').setAttribute('src', grayscaleDataURL);
  };

  image.src = e.target.result;
};

input.addEventListener('change', e => {
  const file = e.target.files[0];
  reader.readAsDataURL(file);
});

마무리 ( 모자이크 🕶 )

제목에 있던 내용처럼, 이미지에 모자이크 처리 하는 방법에 대해 추측이 되시나요?

가로 100px 세로 100px, 에 해당하는 정사각형 이미지 가 있다고 가정합니다.

이 이미지의 정 가운데 부분을 모자이크 하려면,

해당 이미지의 정 가운데 영역의 px 좌표 를 구합니다.

선택된 영역의 px 값의 x 축 y 축으로 4개씩 묶어서 (위 이미지 기준 파란 사각형 ) 해당 픽셀들의 RGB 값의 평균 색상을 구합니다.

그다음 4개의 Px 에 해당 색상으로 전부 변경하면 되지 않을까? 하는 추측을 할 수 있게 됩니다.

언제 시간나면 구현해서 포스팅 하겠습니다.

RGBA에서의 A 알파 (투명도) 를 통해 포토샵이 어떻게 계층을 나누어 이미지에 스티커를 붙히는지,
음성파일의 주파수를 숫자로 계산하여 특정 주파수는 정확한 '솔' 이라는 음을 내기 때문에 ..... 어떻게 오토튠 이라는게 가능할지,
가끔은 우리가 사용하고있는 다양한 프로그램들을 사용하면서, 어떻게 만들어졌는가 에 대한 고민해보시면 재밌습니다.


추천자료

이미지->이모지로만들기 싸이트 codepan


원본글
아직은 베타여서 좋은내용은 벨로그에도 같은 글을 올리고 있습니다. 놀러오세연~

profile
사랑해
post-custom-banner

0개의 댓글