其实很简单,整个 RLE 文件就是先为2字节的像素个数(count), 然后是2字节的像素值(RGB565格式)。
稍微需要注意的是由于2字节的像素个数 count, 因为无符号短整型 (unsigned short int), 最多能控制的
总数为 65535( 0xFFFF),所以,如果在压缩处理时取得的同颜色像素的总数大于 0xFFFF,应该要拆分
成多个 0xFFFF 及余数的形式,譬如若有 0x10000 个 0x0FF0,则应该要写成:
0xFFFF, 0x0FF0, 0x0001, 0x0FF0
网上的文章都说的是用 ImageMagick 先转成 raw, 再用谷歌的rgb2565 工具来转。本博嫌这样做麻烦,
写了个工具直接将 png, jpg, bmp 三种格式的图片一步到位转成所需的 rle (RGB565) 格式,另外还写了
个查看结果的验证工具,方便多了。其中转成 rle 的关键代码如下:
/*
传入参数说明:
pimage: RGB 24位格式的图像数组
width: 图像宽度
height: 图像高度
fname: 要保存的文件名, 若为NULL, 将输出到 stdout 即屏幕
返回参数: 1---成功, 0---失败
*/
#define RGB565(r,g,b) ((((uint16_t)((r)&0xF8))>>3) | (((uint16_t)((g)&0xFC))<<3) | (((uint16_t)((b)&0xF8))<<8))
int RGBtoRLE565( unsigned char * pimage, int width, int height, char * fname )
{
FILE * fp = NULL;
unsigned short cnt, val, val2;
unsigned int count, total, tidx=0;
unsigned char r, g, b, * ptr;
if( !pimage || !width || !height ) return 0;
if( fname )
{
fp = fopen( fname, "wb" );
if( !fp ) return 0;
}
total = (width * height);
ptr = pimage;
while( total )
{
count = 1;
r = ptr[2];
g = ptr[1];
b = ptr[0];
val = RGB565( r, g, b );
total--;
ptr += 3;
while( total )
{
val2 = RGB565( ptr[2], ptr[1], ptr[0] );
if( val2 != val ) break;
count++;
total--;
ptr += 3;
}
if( fp )
{
while( count > 0xFFFF )
{
cnt = 0xFFFF;
fwrite( &cnt, sizeof(short), 1, fp );
fwrite( &val, sizeof(short), 1, fp );
count -= 0xFFFF;
}
cnt = (unsigned short)count;
fwrite( &cnt, sizeof(short), 1, fp );
fwrite( &val, sizeof(short), 1, fp );
}
else
{
fprintf( stdout, "%d( 0x%04X ), ", count, val );
if( (tidx & 0x07)==0x07 ) fprintf( stdout, "\n" );
}
tidx++;
}
if( fp )
{
fclose( fp );
}
return 1;
}