OpenGL接口的基本实现4[转]
目录
绘制图片
void drawImage(int startX, int startY, int w, int h) { //判断是否越界 int left = tmax<int>(startX, 0); int top = tmax<int>(startY, 0); int right = tmin<int>(startX + w, _width); int bottom = tmin<int>(startY + h, _height); for (int x = left; x < right; ++x) { for (int y = top; y < bottom; ++y) { //产生随机颜色值 Rgba color(rand() % 256, rand() % 256, rand() % 256); setPixelEx(x, y, color); } } }
- 使用FreeImage加载图片:
Image* Image::loadFromFile(const char* fileName) { //1 获取图片格式 FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0); if (fifmt == FIF_UNKNOWN) { return 0; } //2 加载图片 FIBITMAP *dib = FreeImage_Load(fifmt, fileName,0); FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib); //! 获取数据指针 FIBITMAP* temp = dib; dib = FreeImage_ConvertTo32Bits(dib); FreeImage_Unload(temp); BYTE* pixels = (BYTE*)FreeImage_GetBits(dib); int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); Image* image = new Image(width,height,pixels); FreeImage_Unload(dib); return image; }
- 封装图像类
class Image { protected: int _width; int _height; uint* _pixel; public: Image(int w, int h, void* data) { if (w == 0 || h == 0 || data == 0) { _width = 0; _height = 0; _pixel = 0; } else { _width = w; _height = h; _pixel = new uint[w * h]; //颜色是RGBA 32bit,采用uint记录 memcpy(_pixel, data, w * h * sizeof(uint)); } } ~Image() { delete[]_pixel; } int width() const { return _width; } int height() const { return _height; } Rgba pixelAt(int x, int y) const { return Rgba(_pixel[y * _width + x]); } public: static Image* loadFromFile(const char*); };
- 【注:】使用共用体提升效率,只用赋值一次
union { struct { unsigned char _b; unsigned char _g; unsigned char _r; unsigned char _a; }; uint _color; }; Rgba4Byte(uint rgba) { _color = rgba; }
去掉不想要的颜色
void Raster::drawImageWidthColorKey( int startX,int startY,const Image* image,Rgba key ) { int left = tmax<int>(startX,0); int top = tmax<int>(startY,0); int right = tmin<int>(startX + image->width(),_width); int bottom = tmin<int>(startY + image->height(),_height); for (int x = left ; x < right ; ++ x) { for (int y = top ; y < bottom ; ++ y) { Rgba color = image->pixelAt(x - left,y - top); if (color != key) { setPixelEx(x,y,color); } } } }
- 图像翻转180度(利用图片一行大小的缓存区,第一行和最后一行交换,依次类推)
int pitch = width*4; BYTE* row = new BYTE[width*4]; for(int j = 0; j < height / 2; j++) { memcpy(row,pixels + j * pitch,pitch ); memcpy(pixels + j * pitch,pixels + (height - j - 1) * pitch,pitch ); memcpy(pixels + (height - j - 1) * pitch,row,pitch ); } delete []row;
Alpha测试
- 通过测试画或者不画
void drawImageAlphaTest(int startX,int startY,const Image* image,byte alpha) { int left = tmax<int>(startX,0); int top = tmax<int>(startY,0); int right = tmin<int>(startX + image->width(),_width); int bottom = tmin<int>(startY + image->height(),_height); for (int x = left ; x < right ; ++ x) { for (int y = top ; y < bottom ; ++ y) { Rgba color = image->pixelAt(x - left,y - top); if (color._a < alpha) { setPixelEx(x,y,color); } } } }
Alpha混合
- 获取当前背景颜色:
inline Rgba getPixel(unsigned x,unsigned y) { return Rgba(_buffer[y * _width + x]); }
void Raster::drawImageAlphaBlend( int startX,int startY,const Image* image,float alpha ) { int left = tmax<int>(startX,0); int top = tmax<int>(startY,0); int right = tmin<int>(startX + image->width(),_width); int bottom = tmin<int>(startY + image->height(),_height); for (int x = left ; x < right ; ++ x) { for (int y = top ; y < bottom ; ++ y) { Rgba srcColor = image->pixelAt(x - left,y - top); Rgba dstColor = getPixel(x,y); Rgba color = colorLerp(dstColor,srcColor,srcColor._a/255.0f * alpha); setPixelEx(x,y,color); } } }
Alpha透明
void drawImageAlpha( int startX,int startY,const Image* image,float alpha ) { int left = tmax<int>(startX,0); int top = tmax<int>(startY,0); int right = tmin<int>(startX + image->width(),_width); int bottom = tmin<int>(startY + image->height(),_height); for (int x = left ; x < right ; ++ x) { for (int y = top ; y < bottom ; ++ y) { Rgba srcColor = image->pixelAt(x - left,y - top); Rgba dstColor = getPixel(x,y); Rgba color = colorLerp(dstColor,srcColor,alpha); setPixelEx(x,y,color); } } }
绘制部分图像至指定区域
void drawImage(int startX,int startY,const Image* image,int x1,int y1,int w,int h) { int left = tmax<int>(startX,0); int top = tmax<int>(startY,0); int right = tmin<int>(startX + w,_width); int bottom = tmin<int>(startY + h,_height); for (int x = left ; x < right ; ++ x) { for (int y = top ; y < bottom ; ++ y) { Rgba srcColor = image->pixelAt(x - left + x1,y - top + y1); setPixelEx(x,y,srcColor); } } }
图像缩放
void drawImageScale(int dstX,int dstY,int dstW,int dstH,const Image* image) { float xScale = (float)image->width()/(float)dstW; float yScale = (float)image->height()/(float)dstH; for (int x = dstX ;x <dstX + dstW ; ++ x ) { for (int y = dstY ;y <dstY + dstH ; ++ y ) { float xx = (x - dstX) * xScale; float yy = (y - dstY) * yScale; Rgba srcColor = image->pixelAt(xx,yy); setPixelEx(x,y,srcColor); } } }