在OpenGL读取RGB格式的文件

时间:2022-09-10 17:15:17

RGB格式是OpenGL常用的格式,经常要绑定到材质中去。

下面简单说说这种格式。并给出读取这种格式的代码。希望对大家有所帮助。

¨ RGB1RGB4RGB8都是调色板类型的RGB格式,在描述这些媒体类型的格式细节时,通常会在BITMAPINFOHEADER数据结构后面跟着一个调色板(定义一系列颜色)。它们的图像数据并不是真正的颜色值,而是当前像素颜色值在调色板中的索引。以RGB12色位图)为例,比如它的调色板中定义的两种颜色值依次为0x000000(黑色)和0xFFFFFF(白色),那么图像数据001101010111…(每个像素用1位表示)表示对应各像素的颜色为:黑黑白白黑白黑白黑白白白…。

  ¨ RGB565
使用16位表示一个像素,这16位中的5位用于R6位用于G5位用于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;
}