본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Html 캔버스

HTML 캔버스에서 이미지 왜곡하기(canvas image warp, distorted)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2024. 1. 31.

 

캔버스에서 이미지를 왜곡하는 방법을 간단히 소개 합니다.

이미지를 왜곡하기 위해서는 "워핑(warping)" 이라는 방법이 필요한데, 영상과 관련된 기술에서 이미지 워핑(image warping)이라는 이름으로 이미 범용적으로 사용되는 기술 입니다.

해당 기능을 구현하기 위해서는 2가지의 접근법이 필요 합니다.

 

1. 위치 변환 함수를 통해 위치를 변환한다.
2. 위치 변환 함수를 이용해서 실제로 픽셀을 옮긴다.

 

먼저 캔버스에 이미지를 로딩 합니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>CANVAS</title>
  </head>
  <body>
    <canvas id="canvas0" style="border: 1px solid orange"></canvas>
    <canvas id="canvas1" style="border: 1px solid green"></canvas>
  </body>
</html>
<script>
  const canvas0 = document.getElementById("canvas0");
  const ctx0 = canvas0.getContext("2d");

  const canvas1 = document.getElementById("canvas1");
  const ctx = canvas1.getContext("2d");
  const image = new Image();
  image.src =
    "https://cdn.pixabay.com/photo/2024/01/18/00/36/boat-8515980_1280.jpg";
  image.crossOrigin = "Anonymous";

  image.onload = () => {
    ctx0.drawImage(image, 0, 0, canvas1.width, canvas1.height);
    ctx.drawImage(image, 0, 0, canvas1.width, canvas1.height);
  };
</script>

 

canvas0 아이디는 원본 이미지를 표현할 캔버스이며, canvas1 아이디는 왜곡할 캔버스 이미지 입니다.

위 코드를 실행하면 간단한 사진을 볼 수 있습니다.

짜잔~

 

이미지를 왜곡하기 위해서는 캔버스에 사용된 이미지 데이터를 가져와서 각 구간별로 색상값을 조정해 주어야 합니다.

이에 사용된 계산식은 아래와 같습니다.

  const warpPosition = (x, y) => {
    return { x: x + Math.sin(y / 10) * 30, y: y }; //왜곡 정도 결정
  };

 

 

위 코드는 y축 좌표값을 기반으로 x좌표 값을 왜곡하는 코드 입니다.

해당 코드에 나와있는 곱하기30 부분의 값을 늘이거나 줄여서 왜곡 정도를 조정할 수 있습니다.

위 함수를 이제 적용하려면 캔버스에서 사용된 이미지 데이터를 가져와서 배열로 변환한 뒤에, 해당 배열의 rgb값을 x, y 를 가진 2차원 배열에서 1차원 배열로 변환하고 rgba 값 만큼 곱하기를 해 주는 수식이 필요 합니다.

  //이미지 왜곡
  const warpImage = (context, width, height) => {
    const imageData = context.getImageData(0, 0, width, height);
    const data = imageData.data;

    //데이터 배열을 생성
    const warpedData = new Uint8ClampedArray(data.length);

    // 각 픽셀에 대해
    for (let y = 0; y < height; y++) {
      for (let x = 0; x < width; x++) {
        // 원본 위치를 변환
        const orig =
          x > 50 && y > 50 && x < 250 && y < 250 //왜곡할 범위를 지정
            ? warpPosition(x, y)  //아까 그 함수
            : { x, y };  //원본 좌표

        // 원본 위치의 색상을 가져옵니다.
        const origX = Math.floor(orig.x);
        const origY = Math.floor(orig.y);
        //4개의 값(RGBA)을 가지므로, 최종 인덱스를 계산할 때 4를 곱함
        if (origX >= 0 && origX < width && origY >= 0 && origY < height) {
          const origIndex = (origY * width + origX) * 4; //2차원 이미지 픽셀 배열을 1차원 배열로 변환
          const r = data[origIndex];
          const g = data[origIndex + 1];
          const b = data[origIndex + 2];
          const index = (y * width + x) * 4;
          warpedData[index] = r;
          warpedData[index + 1] = g;
          warpedData[index + 2] = b;
          warpedData[index + 3] = 255;
        }
      }
    }
    // 왜곡된 이미지 데이터를 반환합니다.
    return new ImageData(warpedData, width, height);
  };

 

이를 실제 적용해 보면 아래처럼 사진이 뭉개진 모습을 볼 수 있습니다.

지정된 범위의 픽셀값이 왜곡되어 있습니다!

 

간단하게 구현해 본 캔버스를 활용한 이미지 왜곡 방법 이였습니다.

위 코드에 사용된 계산식은 "이미지 워프" 와 관련된 다양한 레퍼런스에서 참고하였습니다.

* 이곳저곳 많이 들여다 보느라 계산식 출처가 어디인지 까먹었습니다..ㅠ

 

궁금한점 또는 틀린부분은 언제든 연락 주세요! 😁

 

반응형

'Html 캔버스' 카테고리의 다른 글

리액트 환경에서의 캔버스 (React Html canvas)  (0) 2022.06.03
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글