주요 내용으로 건너뛰기

동적 L8 이미지 생성

이 섹션에서는 동적 L8 이미지의 사용 방법과 더불어 팔레트 생성 방법을 중점적으로 설명하겠습니다.

동적 비트맵L8 이미지 형식에 대한 일반 정보를 읽어보십시오.

동적 L8 이미지

동적 L8 비트맵을 생성하는 방법은 다른 동적 비트맵과 비슷하지만 비트맵에 생성할 팔레트의 유형을 지정해야 한다는 점이 다릅니다.

TouchGFX는 다음과 같이 3가지 유형의 팔레트를 지원합니다.

팔레트설명
CLUT_FORMAT_L8_ARGB888832비트(빨간색, 녹색, 파란색, 픽셀 단위 알파 채널에 각각 8비트)
CLUT_FORMAT_L8_RGB88824비트(빨간색, 녹색, 파란색에 각각 8비트, 픽셀 단위 알파 채널 없음)
CLUT_FORMAT_L8_RGB56516비트(빨간색에 5비트, 녹색에 6비트, 파란색에 5비트, 픽셀 단위 알파 채널 없음)

24비트 팔레트를 사용한 동적 L8 이미지 생성

여기서는 24비트 팔레트를 사용하여 100 x100 픽셀 L8 비트맵을 생성합니다.

Screen1View.cpp
BitmapId dynamicBitmap1 = Bitmap::dynamicBitmapCreateL8(100, 100, Bitmap::CLUT_FORMAT_L8_RGB888, 256);

위 호출로 100 x100 L8 비트맵과 24비트 팔레트가 비트맵 캐시에 할당되었습니다. 이 팔레트는 동적 비트맵에 사용할 수 있는 색상이 256가지이지만 이 수치를 원하는 크기로 조정하여 메모리 낭비를 줄일 수 있습니다.

팔레트 액세스

픽셀 바로 뒤에(첫 번째 32비트 주소에서) L8 팔레트 형식을 나타내는 2바이트(저장된 리틀 엔디안), 팔레트의 형식 수를 나타내는 2바이트(저장된 리틀 엔디안), 그리고 실제 팔레트 색상이 순서대로 표시됩니다. 따라서 팔레트 색상은 픽셀에서 4바이트 떨어져 있습니다(32비트 정렬).

다음과 같이 (아직 초기화되지 않은) 팔레트에 대한 포인터를 가져올 수 있습니다.

Screen1View.cpp
//Get a pointer to the bitmap data (pixels and palette)
uint8_t* data = Bitmap::dynamicBitmapGetAddress(dynamicBitmap1);

//1 byte pr pixel, round up to 32-bit
uint32_t byteSize = 100*100;
byteSize = ((byteSize + 3) & ~3);

//Palette size is saved in byte 2 and 3
int palSize = (data[3] << 8) | data[2];

//Palette starts four bytes after the pixels
uint8_t* pal = (data + byteSize + 4);

동적 L8 비트맵 예시

이제 예를 통해서 동적 L8 비트맵을 생성하고 팔레트를 조작하는 방법에 대해 알아보겠습니다. 팔레트 조작은 일반 애플리케이션에서 흔한 작업이 아닙니다. 이 예시는 팔레트에 액세스하여 생성하는 방법을 설명하기 위해서입니다.

먼저 TouchGFX Designer에서 스크린을 생성하여 다음과 같이 배경에 흰색 Box를, 그리고 원하는 위치(예: x=140, y=8)에 이미지를 삽입합니다.

스크린 생성

이제 코드를 생성하고 Screen1View.cpp 파일을 엽니다. 그런 다음 코드를 setupScreen에 삽입하여 비트맵 캐시를 초기화하고 동적 비트맵을 생성해야 합니다.

200*256 픽셀의 비트맵을 생성합니다. 이때 L8 비트맵에서 각 픽셀은 1바이트입니다. 이미지의 각 행을 다른 색상으로 채색합니다. 따라서 첫 행은 색상이 0이고, 마지막 행은 색상이 255입니다.

그런 다음 팔레트에서 색상을 초기화합니다. 팔레트의 시작 주소를 계산하고 256가지 색상의 RGB 값을 설정합니다. 이때 초록색에서 빨간색으로, 다시 빨간색에서 초록색으로 색상을 생성합니다.

Screen1View.cpp
#ifdef SIMULATOR
uint32_t cacheBuffer[320*1024/4]; //simulate PSRAM
uint16_t* psram = (uint16_t*)cacheBuffer;
#else
uint16_t* psram = (uint16_t*)(0xd0000000 + 480*272*2*2); //Address after two 16bit framebuffers
#endif

Screen1View::Screen1View()
{
}

void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();

//Create one dynamic bitmap
Bitmap::setCache(psram, 320*1024, 1); //320Kb cache
const uint16_t palSize = 256;
BitmapId dynamicBitmap1 = Bitmap::dynamicBitmapCreateL8(200, 256, Bitmap::CLUT_FORMAT_L8_RGB888, palSize);
imageDynamic.setBitmap(Bitmap(dynamicBitmap1));

if (dynamicBitmap1 == BITMAP_INVALID)
{
touchgfx_printf("Unable to create dynamic bitmap\n");
}
else
{
uint8_t* data = Bitmap::dynamicBitmapGetAddress(dynamicBitmap1);

uint8_t* pixel = data;
//make colored rows
for (int y = 0; y<256; y++)
{
for (int x = 0; x<200; x++)
{
*pixel++ = y;
}
}

uint32_t byteSize = 200*256;
byteSize = ((byteSize + 3) & ~3);

//Palette starts four bytes after the pixels
uint8_t* pal = (data + byteSize + 4);

//Make palette with 256 colors from green to red to green
for (int i = 0; i < palSize; i++)
{
//BGR
pal[i * 3 + 0] = 0x00;
pal[i * 3 + 1] = 127 * (1 + cosf(i * 6.28f / (palSize - 1)));
pal[i * 3 + 2] = 255 * (sinf(i * 3.14f / (palSize - 1)));
}
}
}

위 작업을 마치면 스크린에 다음과 같이 표시됩니다.

L8 이미지 표시

팔레트 조작

동적 L8 비트맵에 사용할 팔레트에 액세스할 수 있기 때문에 조작도 쉽습니다.

여기서는 인덱스 하나씩 아래로 색상을 순환시켜 모든 프레임에서 이미지를 강제로 다시 드로잉합니다.

Screen1View.cpp
...
void Screen1View::handleTickEvent()
{
//get palette address
uint8_t* data = Bitmap::dynamicBitmapGetAddress(imageDynamic.getBitmap());
uint32_t byteSize = 200*256;
byteSize = ((byteSize + 3) & ~3);
const int palSize = (data[3] << 8) | data[2];
uint8_t* pal = (data + byteSize + 4);

//Cycle palette, copy color 0
int8_t blue = pal[0], green = pal[1], red = pal[2];

//Move palette down, 1->0, 2->1, ...
for (int i = 3; i < palSize * 3; i++)
{
pal[i - 3] = pal[i];
}

//Insert color 0 as color 255
pal[(palSize - 1) * 3 + 0] = blue;
pal[(palSize - 1) * 3 + 1] = green;
pal[(palSize - 1) * 3 + 2] = red;

//Force redraw by invalidating
imageDynamic.invalidate();
}

그러면 동적 비트맵에서 색상이 “위로” 이동합니다.

L8 팔레트의 순환