利用windows自带的gdi+库,可以很方便地读取一般格式的图片,例如bmp,jpg和png。下面这段代码作为opengl贴纹理的第一步,首先读取图片其次转换成opengl支持的像素格式(从ARGB或RGB转换成RGBA)。可惜gdi+不支持tga,所以对于这种格式的图片,还得另外写代码去处理。
#include <Windows.h>
#include <GdiPlus.h>
#pragma comment (lib, "gdiplus.lib")
#define CUR_LINE ((bitmapHeight - 1 - y) * stride)
#define CUR_POS (y * bitmapWidth + x)
unsigned char * loadNormalFormat (const wstring & path)
{
// 启动GDI+
Gdiplus::GdiplusStartupInput gdipSIn;
unsigned long gdipToken;
Gdiplus::GdiplusStartup (&gdipToken, &gdipSIn, NULL);
// 加载图像文件
Gdiplus::Bitmap * pBitmap = new Gdiplus::Bitmap (path.c_str ());
// 获得图像高宽
unsigned int bitmapWidth = pBitmap->GetWidth ();
unsigned int bitmapHeight = pBitmap->GetHeight ();
if (bitmapWidth <= 0 || bitmapHeight <= 0) {
delete pBitmap;
// 结束GDI+
Gdiplus::GdiplusShutdown (gdipToken);
return NULL;
}
// 获取图像元数据构造GlImage
Gdiplus::Rect bitmapArea (0, 0, bitmapWidth, bitmapHeight);
Gdiplus::BitmapData bitmapData;
pBitmap->LockBits (&bitmapArea, Gdiplus::ImageLockModeRead,
pBitmap->GetPixelFormat (), &bitmapData);
const BYTE * imageData = (BYTE *)bitmapData.Scan0;
int stride = bitmapData.Stride;
unsigned char * glImageData = NULL;
if (imageData != 0) {
unsigned char * glImageData =
new unsigned char[bitmapWidth * bitmapHeight * 4];
const int destR = 0, destG = 1, destB = 2, destA = 3;
int srcR, srcG, srcB, srcA, bytesPerPixel;
// 根据像素格式设置初始值
switch (bitmapData.PixelFormat)
{
case PixelFormat24bppRGB:
srcR = 2; srcG = 1; srcB = 0; bytesPerPixel = 3;
break;
case PixelFormat32bppARGB:
srcA = 3; srcR = 2; srcG = 1; srcB = 0; bytesPerPixel = 4;
break;
default: // 图片的像素格式不支持
delete [] glImageData;
pBitmap->UnlockBits (&bitmapData);
delete pBitmap;
// 结束GDI+
Gdiplus::GdiplusShutdown (gdipToken);
return NULL;
}
// 复制及转换图像数据
for (unsigned int y = 0; y < bitmapHeight; ++y) {
for (unsigned int x = 0; x < bitmapWidth; ++x) {
glImageData[CUR_POS * 4 + destR] =
imageData[CUR_LINE + x * bytesPerPixel + srcR];
glImageData[CUR_POS * 4 + destG] =
imageData[CUR_LINE + x * bytesPerPixel + srcG];
glImageData[CUR_POS * 4 + destB] =
imageData[CUR_LINE + x * bytesPerPixel + srcB];
if (bytesPerPixel == 4)
glImageData[CUR_POS * 4 + destA] =
imageData[CUR_LINE + x * bytesPerPixel + srcA];
else
glImageData[CUR_POS * 4 + destA] = 255;
}
}
}
pBitmap->UnlockBits (&bitmapData);
delete pBitmap;
// 结束GDI+
Gdiplus::GdiplusShutdown (gdipToken);
return glImageData;
}