주요 내용으로 건너뛰기

이미지 압축

TouchGFX는 버전 4.22부터 이미지 압축 기능을 지원합니다. 4.22의 경우, L8 이미지 압축으로 지원이 제한되어 있습니다.

이미지 압축은 이미지에 대한 저장 공간 요구 사항을 줄여주는 프로세스입니다. 프로젝트에서 이미지 크기가 줄면 더 작은 플래시를 사용해서 비용을 절감할 수 있습니다. 또한, 프로젝트에서 더 많은 이미지를 사용할 수 있기 때문에 보다 풍부한 UI를 구현하는 것이 가능합니다.

이미지 압축은 일반적으로 무손실 압축과 손실 압축 두 가지 방식이 있습니다. 손실 압축은 이미지의 사소한 세부 사항을 제거해서 압축을 합니다. 크기는 최대한 줄일 수 있지만, 원본 이미지를 정확하게 재현할 수 없는 경우가 많습니다. 무손실 압축은 항상 원본 이미지를 그대로 재현합니다. 또한, 무손실 압축은 일반적으로 이미지의 크기를 줄여줍니다.

그래픽의 경우에 UI 요소를 디자인한 대로 정확히 드로잉해야 하는 경우가 많습니다. 이러한 이유로 TouchGFX는 무손실 압축만 지원하고 있습니다.

이미지 압축은 크기를 줄일 수 있다는 장점이 있지만, 이미지를 프레임 버퍼에 그릴 때 압축을 해제해야 한다는 단점도 있습니다. 압축되지 않은 이미지를 그릴 때와 비교해 이러한 압축 해제를 위해서는 많은 경우에 CPU에서 더 많은 작업이 필요합니다. 그 결과, 성능 저하가 발생할 수 있습니다.

따라서 플래시 공간 감소로 얻는 이점과 CPU 사용량 증가로 인한 단점을 비교해야 합니다.

많은 STM32 마이크로컨트롤러에 존재하는 DMA2D 및 GPU2D(ChromART 및 NeoChrom GPU) 그래픽 가속기는 압축된 이미지를 직접 그릴 수 없다는 점에 유의하십시오. 압축된 이미지는 항상 소프트웨어 렌더링을 사용해 그려집니다.

많은 애플리케이션에서 모든 이미지를 압축하는 것이 아니라, 성능이 손상되지 않고 플래시 공간 감소가 가능한 경우에만 이미지를 압축하도록 권장하고 있습니다.

L8 압축

위에서 언급했듯이 TouchGFX 4.22는 L8 이미지 압축을 지원합니다. L8 비트맵 형식은 최대 256가지 색상이 지원되는 이미지에만 적합합니다. 각 픽셀은 이미지와 함께 저장된 컬러 테이블의 색상을 나타내는 8비트 숫자일 뿐입니다. L8 압축은 픽셀 수만 압축하고, 컬러 테이블은 그대로 둡니다.

아래 이미지를 예로 들어보겠습니다. 이미지가 미터링 애플리케이션에서 배경으로 사용되는 경우입니다.

L8-ARGB8888

이미지는 184 x 184 픽셀입니다. 따라서 픽셀 데이터의 크기는 184 x 184 = 33.856 바이트입니다.

이미지를 압축하면 픽셀 데이터가 5.735 바이트로 줄어듭니다. 컬러 테이블을 포함한 이미지 데이터의 전체 크기는 원본 이미지의 20% 미만입니다. 따라서 압축을 하면 동일한 플래시 공간에 5개의 서로 다른 배경을 가지거나, 플래시 요구 사항을 28.121 바이트로 줄일 수 있습니다.

압축된 L8 이미지는 일반적인 비압축 비트맵처럼 사용됩니다. 예를 들어 TouchGFX Designer 또는 코드에서 프로젝트를 수정하지 않고도 이미지 위젯을 사용해 이미지를 표시할 수 있습니다. 이렇게 하면 압축된 이미지를 매우 쉽게 사용할 수 있습니다.

몇 가지 제한 사항이 있습니다. 압축된 이미지는 이미지의 크기를 조정하거나 이미지를 회전시키는 위젯 또는 캔버스 위젯과 함께 사용할 수 없습니다. 아래 목록을 참조하십시오.

Caution
압축된 이미지를 모든 위젯에서 사용할 수 있는 것은 아닙니다. TouchGFX Designer는 경고 아이콘을 제공합니다.

호환되지 않는 위젯과 함께 압축 이미지 사용.

3가지 알고리즘

TouchGFX는 3가지 압축 알고리즘을 사용합니다. 이미지 변환 프로그램은 사용자가 구성에서 특정 알고리즘을 지정하지 않는 한, 최적의 압축을 제공하는 알고리즘을 선택합니다. 알고리즘은 다음과 같습니다.

  • L4는 각 픽셀을 4비트로 인코딩하고, 최대 16가지 색상이 지원되는 이미지에만 적용할 수 있습니다.
  • RLE는 픽셀의 실행 길이를 인코딩하고, 최대 64가지 색상이 지원되는 이미지에만 적용할 수 있습니다.
  • LZW9은 딕셔너리를 기반으로 인코딩을 수행하고, 모든 L8 이미지에 적용할 수 있습니다.

RLE 알고리즘은 LZW9보다 압축 해제 속도가 훨씬 빠르다는 점에서 이미지 변환 프로그램은 LZW9의 이미지 압축 성능이 약간 더 나은 경우에는 RLE를 선택합니다.

압축 이미지 사용

압축된 이미지는 일반 이미지와 똑같이 사용됩니다. TouchGFX Designer에서 비트맵을 사용하도록 위젯을 구성하거나, 코드에서 비트맵을 할당할 수 있습니다.

L8-ARGB8888 이미지에 대한 압축 구성

Compression 값을 "Auto"로 설정하기만 하면 됩니다. 이미지 변환 프로그램은 최적의 압축을 자동으로 선택하거나, 이미지를 압축할 수 없는 경우에는 어떤 것도 선택하지 않습니다.

위젯에서 압축 이미지 선택

이제는 평소처럼 위젯에 대한 이미지를 선택할 수 있습니다. 압축되지 않은 이미지와 비교해도 이 부분에서는 차이가 없습니다.

코드에서 이미지를 사용할 때도 별다른 차이가 없습니다. 압축된 비트맵은 평소와 같이 BitmapID를 사용하여 참조됩니다.

    image1.setXY(148, 148);
image1.setBitmap(touchgfx::Bitmap(BITMAP_GAUGE_BACKGROUND_ID));

압축된 L8 이미지에 대한 자세한 내용은 여기에서 확인하십시오.

압축 수준

이미지 변환 프로그램이 선택한 압축 알고리즘이 생성된 파일에 기록됩니다. 여기에서 압축 수준을 확인할 수도 있습니다.

위에서 사용한 이미지는 generated/images/src/image_gauge_background.cpp 파일에 생성이 됩니다. 이 파일의 헤더는 다음과 같습니다.

image_gauge_background.cpp (extract)
// 4.22 D0 AN R0 FL8_ARGB8888 U888 N0 SExtFlashSection EExtFlashSection CL8_LZW9

LOCATION_PRAGMA("ExtFlashSection")
KEEP extern const unsigned char image_gauge_background[] LOCATION_ATTRIBUTE("ExtFlashSection") = {
// 184x184 L8_ARGB8888 pixels. Compression [output/input x 100]: 5735/33856 x 100 = 16.9%
0x00, 0x26, 0x50, 0xa8, 0x60, 0xe1, 0x02, 0x86, 0x0c, 0x1a, 0x36, 0x70,
....

첫 번째 라인의 주석 끝에 압축 수준이 나와 있습니다. 여기에서 Image Converter가 LZW9 알고리즘을 선택했음을 확인할 수 있습니다. 라인 5의 끝을 보면 원본이 33856 바이트인 것과 달리 현재 픽셀 데이터는 5735 바이트라는 것을 알 수 있습니다. 압축 결과는 16.9%입니다(압축 수준은 작을수록 좋음). 주의! 압축에는 색상표가 포함되지 않습니다.

이미지를 비트맵 캐시로 압축 해제

대부분의 경우에 압축된 이미지를 그릴 때가 압축되지 않은 이미지를 그릴 때보다 성능이 떨어집니다. 게다가 서론 부분에서 언급했듯이, STM32 마이크로컨트롤러의 그래픽 가속기(DMA2D 및 GPU2D)는 압축된 이미지를 그릴 수 없습니다. 따라서 압축된 이미지는 항상 소프트웨어에 의해 그려지기 때문에 성능이 저하되고 CPU 부하가 높아집니다.

이러한 이유로 TouchGFX에는 런타임에서 압축 이미지를 RAM의 비트맵 캐시로 압축 해제하는 기능도 포함되어 있습니다.

이미지를 RAM으로 압축 해제하면 그리기 성능은 압축되지 않은 이미지를 사용할 때와 비슷하지만, 가속기가 이미지를 그릴 수 있습니다.

압축을 해제할 수 있으려면 먼저 비트맵 캐시를 설정해야 합니다. 비트맵 캐시 사용에 대한 자세한 내용은 여기에서 확인하십시오.

비트맵 캐시를 설정한 후에는 Bitmap::decompress 함수를 사용해 이미지의 압축을 해제할 수 있습니다. 아래와 같이 전체 코드가 표시됩니다.

// Define an array for the bitmap cache
uint16_t cache[20*1024]; //40 KB cache
// Define an array for the decompression temporary buffer
uint16_t lzwBuffer[1024];

void TemplateView::setupScreen()
{
...
Bitmap::setCache(cache, sizeof(cache));
bool r = Bitmap::decompress(BITMAP_GAUGE_BACKGROUND_ID, lzwBuffer);
image1.setXY(148, 148);
image1.setBitmap(touchgfx::Bitmap(BITMAP_GAUGE_BACKGROUND_ID));
}

비트맵 캐시는 압축되지 않은 이미지를 저장할 수 있을 만큼 충분히 커야 합니다. 이미지는 184 x 184 픽셀에 207가지 ARGB8888 색상이 포함된 컬러 테이블을 더한 것입니다. 따라서 전체 크기는 34.688 바이트가 됩니다.

2048 바이트 버퍼는 LZW9 압축 이미지를 압축 해제하는 동안 압축 해제기에 의해 사용됩니다(딕셔너리 구축 용도로). 압축 해제 후에는 버퍼가 필요하지 않기 때문에 다른 용도로 재사용할 수 있습니다. RLE 및 L4 압축 이미지의 압축 해제에는 버퍼가 필요하지 않습니다.

압축을 해제한 이미지를 더 이상 사용하지 않을 때는 Bitmap::cacheRemoveBitmap 메소드를 사용해 비트맵 캐시에서 이를 제거할 수 있습니다.

제한 사항

압축된 이미지는 이미지의 크기를 조정하거나 이미지를 회전시키는 Widget들 또는 특정 영역을 채우는 Widget들과 함께 사용할 수 없습니다. 이러한 제한을 두는 것은 성능상의 이유 때문입니다. TouchGFX Designer에서는 압축된 이미지를 선택하도록 허용하지 않습니다.

이러한 위젯과 함께 특정 L8 이미지를 사용하려면 이미지 압축을 활성화하지 않는 것이 좋습니다.

압축 이미지를 지원하지 않는 위젯은 다음과 같습니다.

  • TextureMapper
  • ScalableImage
  • 바늘 및 아크용 Gauge
  • 그래프 아래 영역을 채우기 위한 StaticGraph 및 DynamicGraph
  • 손목용 AnalogClock
  • 원, 라인 및 쉐이프
  • CircleProgress 및 LineProgress