RGB格式是OpenGL常用的格式,经常要绑定到材质中去。
下面简单说说这种格式。并给出读取这种格式的代码。希望对大家有所帮助。
¨ RGB1、RGB4、RGB8都是调色板类型的RGB格式,在描述这些媒体类型的格式细节时,通常会在BITMAPINFOHEADER数据结构后面跟着一个调色板(定义一系列颜色)。它们的图像数据并不是真正的颜色值,而是当前像素颜色值在调色板中的索引。以RGB1(2色位图)为例,比如它的调色板中定义的两种颜色值依次为0x000000(黑色)和0xFFFFFF(白色),那么图像数据001101010111…(每个像素用1位表示)表示对应各像素的颜色为:黑黑白白黑白黑白黑白白白…。
¨ RGB565使用16位表示一个像素,这16位中的5位用于R,6位用于G,5位用于B。程序中通常使用一个字(WORD,一个字等于两个字节)来操作一个像素。当读出一个像素后,这个字的各个位意义如下:
高字节 低字节
R R R R R G G G G G G B B B B B
可以组合使用屏蔽字和移位操作来得到RGB各分量的值:
#define RGB565_MASK_RED 0xF800
#define RGB565_MASK_GREEN 0x07E0
#define RGB565_MASK_BLUE 0x001F
R = (wPixel & RGB565_MASK_RED) >> 11; // 取值范围0-31
G = (wPixel & RGB565_MASK_GREEN) >> 5; // 取值范围0-63
B = wPixel & RGB565_MASK_BLUE; // 取值范围0-31
¨ RGB555是另一种16位的RGB格式,RGB分量都用5位表示(剩下的1位不用)。使用一个字读出一个像素后,这个字的各个位意义如下:
高字节 低字节
X R R R R G G G G G B B B B B (X表示不用,可以忽略)
可以组合使用屏蔽字和移位操作来得到RGB各分量的值:
#define RGB555_MASK_RED 0x7C00
#define RGB555_MASK_GREEN 0x03E0
#define RGB555_MASK_BLUE 0x001F
R = (wPixel & RGB555_MASK_RED) >> 10; // 取值范围0-31
G = (wPixel & RGB555_MASK_GREEN) >> 5; // 取值范围0-31
B = wPixel & RGB555_MASK_BLUE; // 取值范围0-31
¨ RGB24使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。注意在内存中RGB各分量的排列顺序为:BGR BGR BGR…。通常可以使用RGBTRIPLE数据结构来操作一个像素,它的定义为:
typedef struct tagRGBTRIPLE {
BYTE rgbtBlue; // 蓝色分量
BYTE rgbtGreen; // 绿色分量
BYTE rgbtRed; // 红色分量
} RGBTRIPLE;
¨ RGB32使用32位来表示一个像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是带Alpha通道的RGB32。)注意在内存中RGB各分量的排列顺序为:BGRA BGRA BGRA…。通常可以使用RGBQUAD数据结构来操作一个像素,它的定义为:
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 蓝色分量
BYTE rgbGreen; // 绿色分量
BYTE rgbRed; // 红色分量
BYTE rgbReserved; // 保留字节(用作Alpha通道或忽略)
} RGBQUAD;
具体代码:
typedef struct _ImageRec { //定义图像格式
unsigned short imagic;
unsigned short type;
unsigned short dim;
unsigned short xsize, ysize, zsize;
unsigned int min, max;
unsigned int wasteBytes;
char name[80];
unsigned long colorMap;
FILE *file;
unsigned char *tmp, *tmpR, *tmpG, *tmpB;
unsigned long rleEnd;
unsigned int *rowStart;
int *rowSize;
} ImageRec
ImageRec *ImageOpen(const char *fileName) //打开文件
{
union {
int testWord;
char testByte[4];
} endianTest;
ImageRec *image;
int swapFlag;
int x;
endianTest.testWord = 1;
if (endianTest.testByte[0] == 1) {
swapFlag = 1;
} else {
swapFlag = 0;
}
image = (ImageRec *)malloc(sizeof(ImageRec));
if (image == NULL) {
fprintf(stderr, "Out of memory!/n");
exit(1);
}
if ((image->file = fopen(fileName, "rb")) == NULL) {
perror(fileName);
exit(1);
}
fread(image, 1, 12, image->file);
if (swapFlag) {
ConvertShort(&image->imagic, 6);
}
image->tmp = (unsigned char *)malloc(image->xsize*256);
image->tmpR = (unsigned char *)malloc(image->xsize*256);
image->tmpG = (unsigned char *)malloc(image->xsize*256);
image->tmpB = (unsigned char *)malloc(image->xsize*256);
if (image->tmp == NULL || image->tmpR == NULL || image->tmpG == NULL ||
image->tmpB == NULL) {
fprintf(stderr, "Out of memory!/n");
exit(1);
}
if ((image->type & 0xFF00) == 0x0100) {
x = image->ysize * image->zsize * sizeof(unsigned);
image->rowStart = (unsigned *)malloc(x);
image->rowSize = (int *)malloc(x);
if (image->rowStart == NULL || image->rowSize == NULL) {
fprintf(stderr, "Out of memory!/n");
exit(1);
}
image->rleEnd = 512 + (2 * x);
fseek(image->file, 512, SEEK_SET);
fread(image->rowStart, 1, x, image->file);
fread(image->rowSize, 1, x, image->file);
if (swapFlag) {
ConvertLong(image->rowStart, x/(int)sizeof(unsigned));
ConvertLong((unsigned *)image->rowSize, x/(int)sizeof(int));
}
} else {
image->rowStart = NULL;
image->rowSize = NULL;
}
return image;
}
ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) {
unsigned char *iPtr, *oPtr, pixel;
int count;
if ((image->type & 0xFF00) == 0x0100) {
fseek(image->file, (long)image->rowStart[y+z*image->ysize], SEEK_SET);
fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
image->file);
iPtr = image->tmp;
oPtr = buf;
for (;;) {
pixel = *iPtr++;
count = (int)(pixel & 0x7F);
if (!count) {
return;
}
if (pixel & 0x80) {
while (count--) {
*oPtr++ = *iPtr++;
}
} else {
pixel = *iPtr++;
while (count--) {
*oPtr++ = pixel;
}
}
}
} else {
fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
SEEK_SET);
fread(buf, 1, image->xsize, image->file);
}
}
Read_texture(char *name, int *width, int *height, int *components) {
unsigned *base, *lptr;
unsigned char *rbuf, *gbuf, *bbuf, *abuf;
ImageRec *image;
int y;
image = ImageOpen(name);
if(!image)
return NULL;
(*width)=image->xsize;
(*height)=image->ysize;
(*components)=image->zsize;
base = (unsigned *)malloc(image->xsize*image->ysize*sizeof(unsigned));
rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
if(!base || !rbuf || !gbuf || !bbuf)
return NULL;
lptr = base;
for(y=0; y<image->ysize; y++) {
if(image->zsize>=4) {
ImageGetRow(image,rbuf,y,0);
ImageGetRow(image,gbuf,y,1);
ImageGetRow(image,bbuf,y,2);
ImageGetRow(image,abuf,y,3);
rgbatorgba(rbuf,gbuf,bbuf,abuf,(unsigned char *)lptr,image->xsize);
lptr += image->xsize;
} else if(image->zsize==3) {
ImageGetRow(image,rbuf,y,0);
ImageGetRow(image,gbuf,y,1);
ImageGetRow(image,bbuf,y,2);
rgbtorgba(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize);
lptr += image->xsize;
} else if(image->zsize==2) {
ImageGetRow(image,rbuf,y,0);
ImageGetRow(image,abuf,y,1);
latorgba(rbuf,abuf,(unsigned char *)lptr,image->xsize);
lptr += image->xsize;
} else {
ImageGetRow(image,rbuf,y,0);
bwtorgba(rbuf,(unsigned char *)lptr,image->xsize);
lptr += image->xsize;
}
}
free(rbuf);
free(gbuf);
free(bbuf);
free(abuf);
return (unsigned *) base;
}