카테고리 없음

위젯이 왜.. 다르게 보이지? 2. 이미지와 devicePixelRatio

ssuncake 2023. 7. 20. 15:26

이전글 위젯이 왜.. 다르게 보이지? 1. 해상도 이해하기

Android OS 와 iOS 는 각각 논리적 픽셀을 사용하고 있고 Flutter도 logical pixel이라는 논리적픽셀을 사용한다.

플러터에서 위젯에 주는 width와 height는 논리적 픽셀값이고 실제로 위젯이 그려지는것은 이 width, height 값과 devicePixelRatio가 곱해진 값으로 화면에 위젯이 그려진다.

2 * 2 공간에서 표현되는 픽셀의 갯수

플러터에서 일반적으로 사용하는 이미지는 래스터 이미지인데...

플러터에서 이미지를 사용하는 위젯을 만들때 어떻게  이미지를 넣어줘야 할까?

이미지의 종류

앱을 만들때 사용하는 이미지는 크게 래스터 이미지벡터이미지 2가지로 구분 할 수 있다.

컴퓨터 과학에서 래스터 그래픽스(Raster graphics) 이미지, 곧 비트맵은 일반적으로 직사각형 격자의 화소, 색의 점을 모니터, 종이 등의 매체에 표시하는 자료 구조이다. 래스터 이미지는 다양한 포맷의 그림 파일로 저장할 수 있다.
비트맵은 화면에 표시되는 그림의 비트 대 비트와 일치하며, 일반적으로 장치 독립 비트맵으로서, 디스플레이의 비디오 메모리의 기억 장치에 쓰이는 포맷과 일치한다. 비트맵은 기술적으로 화소 단위로, 또 화소 당 비트 수 (표시하는 색의 수를 정의하는 색 깊이)로 그림의 가로, 세로에 따라 구분한다.
- 위키백과
벡터 그래픽스(Vector graphics)는 컴퓨터 과학에서 그림을 보여줄 때 수학 방정식을 기반으로 점, 직선, 곡선, 다각형과 같은 물체를 사용하는 것을 말한다. 객체 지향 그래픽스(문화어: 대상지향그라픽스)라고도 한다.
벡터 그래픽스는 사진에서 흔히 쓰이는 화소로 모인 그림을 대표하는 래스터 그래픽스의 대안이다.
- 위키백과

 

플러터에서 래스터 이미지는 Image위젯을 사용하고, 벡터 이미지는 flutter_svg 패키지의 SvgPicture 위젯을 사용하여 구현할 수 있다.

 

여기에서 해상도에 영향을 받는 래스터 이미지는 기기에 따라서 유저가 보기에 다르게(작거나 확대하거나) 표현 될 수 있다.

더보기

래스터이미지를 확대하는경우 이미지보간법을 이용하게 되는데

Image위젯의 경우 fit 옵션으로 확대 방법을 결정하고 filterQuality 옵션에서 처리속도와 품질의 정도를 결정 할 수 있다.

fit 의 기본값은 BoxFit.contain 이고 filterQuality 기본 값은 FilterQuality.low이다. 

보간법은 한계가 있으니 그냥 고해상도 이미지를 사용하자.

 

일반적으로 이미지를 앱에 넣어서 배포 할 때에는 asset폴더에 넣는다.

  assets:
    - asset/

pubspec.yaml에서 위와같이 정의해주고 프로젝트에 asset폴더에 추가한다.

 

위와같이 추가를 해주면 이제 

   Image.asset('assets/sample.png')

이미지 위젯을 이용하여 asset에 있는 이미지를 사용 할 수 있다.

 

래스터 이미지 파일의 형식은 아래와 같은 형식들이 있다.

JPEG (Joint Photographic Experts Group): .jpeg, .jpg
사진에 많이 사용되는 형식으로 손실 압축을 사용하며, 압축률과 이미지 품질을 조정할 수 있습니다.
PNG (Portable Network Graphics): .png
투명 배경을 지원하며, 손실 없는 압축 형식으로 이미지 품질이 보존됩니다. 애니메이션 이미지를 지원하는 APNG 형식도 있습니다.
BMP (Bitmap): .bmp
비압축 이미지 형식으로 이미지 품질이 보존됩니다. 파일 크기가 크기 때문에 주로 사용되지 않습니다.
TIFF (Tagged Image File Format): .tiff, .tif
무손실 또는 손실 압축을 지원하는 이미지 형식으로 고해상도 이미지 저장에 주로 사용됩니다.
WEBP: .webp
구글에서 개발한 이미지 형식으로 손실 또는 무손실 압축을 지원하며, JPEG, PNG, GIF보다 더 작은 파일 크기를 가집니다.

주로 많이쓰는것은 손실압축형식인 .jpg와 투명한 배경을 지원하는 .png이다.

 

100 * 100 의 sample.png를 s22 ultra에 그려보자

 

이미지 자체는 100 * 100 사이즈만큼 잘 그려졌지만 확대가 되서 흐릿하게 보인다.

s22 ultra는 해상도가 높기 때문에 플러터에서 devicePixelRatio를 4.0으로 표시하고 있다.

 

앞에서 얘기했던것처럼 다양한 해상도를 지원하기 위해서는 s22 ultra에서는 4.0x 만큼의 고해상도 이미지가 표시되어야 이미지가 또렷하게 보일것이다. 그럼 코드상에서 일일이 기기상의 devicePixelRatio를 확인하고 그에 맞는 이미지를 가져와야 할까?

 

플러터에서는 iOS처럼 간단한 밀도기반 형식을 따르기 때문에 기기별 해상도에 맞는 이미지를 가져오도록 지원하고 있다.

1.0x 이미지는 그냥 넣고 다른 해상도의 이미지는 각각 배율에 맞게 폴더를 만들어서 넣으면 알아서 그에 맞는 이미지를 가져온다.

 

포토샵으로 한다면 가장 큰 이미지(4.0x)를 만든 후 1.0x, 1.5x, 2.0x, 3.0x, 4.0x 로 내보내기를 할 수 있고

figma를 사용한다면 1.0x를 기준으로 만든 이미지를 Flutter Export를 사용해서 아주 간단하게 내보내기를 할 수 있다. 

위 샘플 이미지는 

100*100 프레임(#)에 텍스트만 넣은 간단한 이미지이다.
Flutter Export를 이용하여 내보내기

Flutter Export는 viewer나 개발자 모드에서는 해당 플러그인을 사용 할 수 없기 때문에 지원 되지 않는다. 디자이너에게 요청하자.

 

플러그인으로 내보내기를 하면 압축파일이 다운로드 되고 압축 해제를 해보면 위와같이 만들어진다.

여러개를 한번에 내보내기 할 수도 있다.

 

각 이미지의 크기는 배율대로 만들어져있다.

1.0x 이미지
3.0x 이미지
4.0x 이미지

확인을 위해서 이미지 이름은 같지만 각 배율만큼의 텍스트를 이미지에 넣어놨다.

 

프로젝트에 만들어진 이미지를 추가하고 다시 돌려보면 아래처럼 고해상도 이미지가 나온다.

 

 

참고 

래스터그래픽스

벡터 그래픽스