모질라 재단 ‘픽셀 다루기’ 링크

캔버스에서 사용되는 좌표 변수의 의미

캔버스에서 사용되는 좌표 변수의 의미

data 속성은 원시 픽셀 데이터를 보기 위해 액세스할 수 있는 Uint8ClindedArray를 반환합니다. 각 픽셀은 네 개의 1바이트 값(적색, 녹색, 파란색, 알파, 순서대로 “RGBA” 형식)으로 표현됩니다. 각 색상 구성요소는 0 ~ 255 사이의 정수로 표시됩니다. 각 구성요소는 배열 내에서 연속적인 색 바이트 값이 할당되며, 최상단 좌측 픽셀의 빨간색 구성요소는 배열 내의 인덱스 0에 있습니다. 픽셀은 배열 전체에 걸쳐 왼쪽에서 오른쪽으로, 그 다음 아래로 진행합니다.

Uint8ClindedArray 높이 × 너비 × 4바이트를 포함합니다. 배열의 인덱스 번호는 0부터 (높이 × 너비 × 4바이트) – 1까지 의 범위를 가지고 있습니다.

  • 그레이스케일: 각 픽셀에서 RGB 3개를 평균낸 값을 다시 RGB에 배분하면 됩니다. 예를 들어 어떤 픽셀의 R200, G140, B180이라면 이 셋의 평균은 173.33이며 이 값을 다시 배분하면 R 173.33, G 173.33, B 173.33 이 됩니다.
  • 색상 반전(Invert): 각 색상 픽셀의 원래 값을 255에서 빼면 색상이 반전됩니다.
  • 컬러라이즈 : https://stackoverflow.com/questions/7521058/colorize-grayscale-image

 

링크: 직접 가서 해보기

<!DOCTYPE html>
<html lang="ko">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <canvas id="canvas" width="1024" height="768" style="float:left"></canvas>
  <div id="wrapper" style="width:200px;float:left">
    <div id=color></div>
    <button id=grayBtn data-next-state="grayscale">그레이스케일</button>
    <button id=invertBtn>색 반전</button>
    <hr><input type=checkbox id=aaBtn checked><label for=aaBtn>부드럽게 하기</label>
    <canvas id="zoom" width="300" height="227"></canvas>
  </div>

  <script>
    // 컨텍스트 생성 및 받아오기
    var img = new Image();
    img.src = './Hydrangeas.jpg';
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    img.onload = draw;
    var color = document.getElementById('color');
    var originalDataArray = []  // 그레이스케일 기능에서 원래 이미지를 저장하기 위한 배열

    // 이미지 로딩 완료시 실행될 부분
    function draw() {
      ctx.drawImage(img, 0, 0);
      img.style.display = 'none';
      
      // ctx.getImageData(sx, sy, sw, sh);
      var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      var data = imageData.data;

      var invertColor = function() {
        for (var i = 0; i < data.length; i += 4) {
          data[i] = 255 - data[i]
          data[i + 1] = 255 - data[i + 1]
          data[i + 2] = 255 - data[i + 2]
        }
        // ctx.putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
        ctx.putImageData(imageData, 0, 0, 0, 0, 512, 768)
      }

      var grayscale = function(e) {
        var nextState = e.target.getAttribute("data-next-state")
        console.log(nextState)

        if (nextState == "grayscale") {
          for (var i = 0; i < data.length; i += 4) {
            var avg = (data[i] + data[i + 1] + data[i + 2]) / 3;

            // 되돌리기 위해 원래 이미지를 백업
            originalDataArray[i] = data[i]
            originalDataArray[i + 1] = data[i + 1]
            originalDataArray[i + 2] = data[i + 2]

            data[i] = avg; // red
            data[i + 1] = avg; // green
            data[i + 2] = avg; // blue
          }
          e.target.setAttribute("data-next-state", "normal")
          
        } else {
          for (var i = 0; i < data.length; i += 4) {

            data[i] = originalDataArray[i]
            data[i + 1] = originalDataArray[i + 1]
            data[i + 2] = originalDataArray[i + 2]

          }
          e.target.setAttribute("data-next-state", "grayscale")
        }

        ctx.putImageData(imageData, 0, 0);
      };

      // 돋보기 기
      var zoomctx = document.getElementById('zoom').getContext('2d');

      var zoom = function(event) {
        var x = event.layerX;
        var y = event.layerY;

        // ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
        var SPX = 20
        var DPX = 200
        zoomctx.drawImage(canvas,
          Math.min(Math.max(0, x - SPX / 2), img.width - SPX),
          Math.min(Math.max(0, y - SPX / 2), img.height - SPX),
          SPX, SPX,
          0, 0,
          DPX, DPX);
      };

      var smoothbtn = document.getElementById('aaBtn');
      // 기본 옵션은 앤티앨리어싱 적용 상태이므로 해제하기 위한 부분
      var toggleSmoothing = function(event) {
        zoomctx.imageSmoothingEnabled = this.checked;
        zoomctx.mozImageSmoothingEnabled = this.checked;
        zoomctx.webkitImageSmoothingEnabled = this.checked;
        zoomctx.msImageSmoothingEnabled = this.checked;
      };

      // 이벤트 적용
      var invertbtn = document.getElementById('invertBtn');
      invertbtn.addEventListener('click', invertColor);

      var invertbtn = document.getElementById('grayBtn');
      invertbtn.addEventListener('click', grayscale);

      canvas.addEventListener('mousemove', zoom);
      
      smoothbtn.addEventListener('change', toggleSmoothing);
    }


    // 픽셀별 컬러 추출
    function pick(event) {
      var x = event.layerX;
      var y = event.layerY;
      var pixel = ctx.getImageData(x, y, 1, 1);
      var data = pixel.data;
      var rgba = 'rgba(' + data[0] + ', ' + data[1] +
        ', ' + data[2] + ', ' + (data[3] / 255) + ')';
      color.style.background = rgba;
      color.textContent = rgba;
      if (data[0] + data[1] + data[2] < 480) {
        color.style.color = "white";
      } else {
        color.style.color = "black";
      }
    }

    canvas.addEventListener('mousemove', pick);

  </script>
</body>

</html>

 

문의 | 코멘트 또는 yoonbumtae@gmail.com




0개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다