ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Html canvas] devicepixelRatio 를 사용해 선명한 이미지 렌더링하기
    Html Canvas 2022. 6. 17. 23:00

    [Html canvas] devicepixelRatio 를 사용해 선명한 이미지 렌더링하기

     

    안녕하세요. gaki 입니다. 오늘은 devicepixelRatio 에 관하여 포스팅해보겠습니다.

    devicepixelRaio 는 물리적 픽셀과 논리적 픽셀의 비율을 나타냅니다.

    그럼 이 devicepixelRatio 가 어떻게 canvas 에 사용되어 선명한 화질을 만들 수 있는 지에 대해 알아보겠습니다.

     

    <개요>

    1. devicepixelRatio 의 정의

    2. canvas 에서 devicepixelRatio 의 사용 이유, 실습


    1. DevicepixelRatio 의 정의

     

    devicePixelRaio 는 앞서 말했듯 물리적 픽셀과 논리적 픽셀의 비율을 나타냅니다.

    물리적 픽셀이란, 디바이스가 실제로 가지고 있는 픽셀이며, 논리적 픽셀은 통상적으로 사용되는 픽셀입니다.

    예를들어 애플 아이폰 S4 가 600px * 320px 이라는 논리적 픽셀을 가지고 있습니다. (이때 사용되는 픽셀은 정형화된 크기를 나타내는 용도) 하지만, 실제로 아이폰 S4 는 사실 1200px * 640px 을 가지고 있습니다.

    즉 다른 회사의 600px * 320px 제품과 애플의 아이폰 S4 를 비교하면 크기는 동일하지만, 사실 애플은 4배나 더 많은 픽셀을 가지고 있기 때문에 이미지를 더 선명하게 표현할 수 있습니다.

     

    devicePixelRatio 는 모든 전자기기마다 천차만별입니다.

     

    그럼 이제 왜 devicePixelRatio 가 html canvas 에서 어떻게 사용되는지, 그리고 사용되는지에 대해서 알아보겠습니다.

     

    2. html canvas 에서 devicepixelRatio 의 사용이유, 실습

     

    canvas / 1000px * 1000px

    위의 그림과 같이 1000 * 1000 의 캔버스를 만들었다고 가정해봅시다.

     

    devicePixelRatio 가 2 맥북 화면에서 위의 캔버스를 보았을때,

    맥북에는 해당 캔버스 영역에 1000 * 1000 개의 픽셀이 아닌, 2000 * 2000 의 픽셀이 존재합니다.

    따라서 1000 * 1000 의 캔버스로 그림을 그리면, 사실 2000 * 2000 개의 픽셀의 이점을 잘 살리지 못할뿐더러 오히려 희미하게 보이는 현상이 발생합니다.

     

    따라서 우리는 1000 * 1000 의 캔버스를 맥북의 물리적 픽셀에 맞춰서 조정해야합니다.

     

    즉, 길이는 1000px * 1000px 인 캔버스이지만, 사실 그안에는 2000 * 2000 의 픽셀이 존재하도록 만들어야 하는 것 입니다.

    이는 css 와 연관됩니다.

     

    css 의 픽셀은 위에서 설명한 logical pixel 을 나타냅니다.

     

    const canvas = document.createElement("canvas");
    
    // css logical pixel
    canvas.style.width = "1000px";
    canvas.style.height = "1000px";

    위의 코드는 css 픽셀을 1000 * 1000 으로 만들어줍니다.

    하지만, 우리의 맥북은 사실 2000 * 2000 픽셀을 가지고 있습니다.

    따라서 캔버스를 더 작은 단위로 쪼개야합니다.

     

    각 칸은 픽셀을 의미

    즉 위의 그림의 형태로 존재하는 캔버스를

     

    아래 처럼 만들어 주어야 합니다. ( 그래야 맥북의 모든 픽셀을 사용해서 선명한 이미지를 만들 수 있습니다.)

     

    위 그림과 아래 그림은 모두 같은 가로세로 길이를 가지지만,(같은 Logical pixel) ( 둘다 css 의 width 는 1000px, height 는 1000px)

    물리적인 픽셀은 다릅니다.

     

    그럼 어떻게 아래처럼 캔버스를 변경시킬 수 있을까요?

     

    const canvas = document.createElement("canvas");
    
    // css logical pixel
    canvas.style.width = "1000px";
    canvas.style.height = "1000px";
    
    
    const devicePixelRatio = window.devicePixelRatio;
    
    canvas.width = 1000 * devicePixelRatio;
    canvas.height = 1000 * devicePixelRatio;

     

    위의 코드와 같이 canvas 속성에 가진 width 와 height 를 조절하면, 캔버스의 css 상의 크기는 변화하지 않고, canvas 내부의 픽셀이 더 잘게 쪼개집니다.

     

    하지만, 이 방법은 한가지 문제가 있습니다.

    바로 좌표가 달라진다는 것입니다.

     

    devicePixelRaio 를 적용하기전, 나는 (1,1) 에 빨간 점을 그리고 싶습니다. 그러면, 위와 같이 그려질 것입니다.

     

    하지만, devicePixelRatio 를 적용한 뒤 (1,1) 에 빨간점을 그리면

     

    위의 그림과 같은 위치에서 점이 찍힙니다. 

     

    즉 pixel 의 가로세로가 2배가 된만큼 좌표도 2배가 되야합니다.

     

    이러한 좌표의 차이로 생기는 문제를 해결하기 위해서 간단히 canvas 를 scale 해서, 좌표를 맞춰주면 됩니다. 

    가령, 맥북의 경우에는 devicePixelRatio 가 2 이므로, canvas 의 context 를 2배 scale 하게되면, 기존의 좌표와 동일하게 사용할 수 있습니다.

     

    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    // css logical pixel
    canvas.style.width = "1000px";
    canvas.style.height = "1000px";
    
    
    const devicePixelRatio = window.devicePixelRatio;
    
    canvas.width = 1000 * devicePixelRatio;
    canvas.height = 1000 * devicePixelRatio;
    ctx.scale(devicePixelRatio, devicePixelRatio);

    위의 코드처럼 context 를 스케일 해주면 좌표를 맞출 수 있습니다.

    'Html Canvas' 카테고리의 다른 글

    오브젝트 풀링 [펌]  (0) 2022.06.22
    [Canvas] Color-picker  (0) 2022.03.04
Designed by Tistory.