OpenGL ES 图片到纹理读取方式
2019-06-13 本文已影响0人
如意神王
1.使用CoreGraphics
//从图片中加载纹理
- (GLuint)setupTexture:(NSString *)fileName {
//1、将 UIImage 转换为 CGImageRef
CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
//判断图片是否获取成功
if (!spriteImage) {
NSLog(@"Failed to load image %@", fileName);
exit(1);
}
//2、读取图片的大小,宽和高
size_t width = CGImageGetWidth(spriteImage);
size_t height = CGImageGetHeight(spriteImage);
//3.获取图片字节数 宽*高*4(RGBA)
GLubyte * spriteData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
//4.创建上下文
/*
参数1:data,指向要渲染的绘制图像的内存地址
参数2:width,bitmap的宽度,单位为像素
参数3:height,bitmap的高度,单位为像素
参数4:bitPerComponent,内存中像素的每个组件的位数,比如32位RGBA,就设置为8
参数5:bytesPerRow,bitmap的没一行的内存所占的比特数
参数6:colorSpace,bitmap上使用的颜色空间 kCGImageAlphaPremultipliedLast:RGBA
*/
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4,CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
//5、在CGContextRef上--> 将图片绘制出来
/*
CGContextDrawImage 使用的是Core Graphics框架,坐标系与UIKit 不一样。UIKit框架的原点在屏幕的左上角,Core Graphics框架的原点在屏幕的左下角。
CGContextDrawImage
参数1:绘图上下文
参数2:rect坐标
参数3:绘制的图片
*/
CGRect rect = CGRectMake(0, 0, width, height);
// 图片正向-否则绘制出来的图片上下是反的
CGContextTranslateCTM(spriteContext, 0, rect.size.height);
CGContextScaleCTM(spriteContext, 1.0, -1.0);
//6.使用默认方式绘制
CGContextDrawImage(spriteContext, rect, spriteImage);
//7、画图完毕就释放上下文
CGContextRelease(spriteContext);
//8、绑定纹理到默认的纹理ID(
glBindTexture(GL_TEXTURE_2D, 0);
//9.设置纹理属性
/*
参数1:纹理维度
参数2:线性过滤、为s,t坐标设置模式
参数3:wrapMode,环绕模式
*/
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
float fw = width, fh = height;
//10.载入纹理2D数据
/*
参数1:纹理模式,GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
参数2:加载的层次,一般设置为0
参数3:纹理的颜色值GL_RGBA
参数4:宽
参数5:高
参数6:border,边界宽度
参数7:format
参数8:type
参数9:纹理数据
*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
//11.释放spriteData
free(spriteData);
return 0;
}
2.不使用CoreGraphics
- (GLuint)setupTextureNoneUsingCoreGraphics:(NSString *)fileName {
CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
//判断图片是否获取成功
if (!spriteImage) {
NSLog(@"Failed to load image %@", fileName);
exit(1);
}
//2、读取图片的大小,宽和高
size_t width = CGImageGetWidth(spriteImage);
size_t height = CGImageGetHeight(spriteImage);
GLubyte *imageData = NULL;
CFDataRef dataFromImageDataProvider = NULL;
dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(spriteImage));
imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);
//8、绑定纹理到默认的纹理ID(
glBindTexture(GL_TEXTURE_2D, 0);
//9.设置纹理属性
/*
参数1:纹理维度
参数2:线性过滤、为s,t坐标设置模式
参数3:wrapMode,环绕模式
*/
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
float fw = width, fh = height;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
if (dataFromImageDataProvider) {
CFRelease(dataFromImageDataProvider);
}
return 0;
}
3.动态判断是否使用CoreGraphics
shouldRedrawUsingCoreGraphics == YES 还有一种情况是图片尺寸大于屏幕的时候,下面没有实现,自行查阅GPUImage
- (void)setUpTextureWithImageName:(NSString *)imageName andIsGenerateMipmap:(BOOL)isCreate{
// 默认不使用CoreGraphics
BOOL shouldRedrawUsingCoreGraphics = NO;
//1、将 UIImage 转换为 CGImageRef
CGImageRef newImageSource = [UIImage imageNamed:imageName].CGImage;
if (CGImageGetBytesPerRow(newImageSource) != CGImageGetWidth(newImageSource) * 4 || CGImageGetBitsPerPixel(newImageSource) != 32 ||
CGImageGetBitsPerComponent(newImageSource) != 8)
{
shouldRedrawUsingCoreGraphics = YES;
} else {
/* Check that the bitmap pixel format is compatible with GL */
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(newImageSource);
if ((bitmapInfo & kCGBitmapFloatComponents) != 0) {
/* We don't support float components for use directly in GL */
shouldRedrawUsingCoreGraphics = YES;
} else {
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
if (byteOrderInfo == kCGBitmapByteOrder32Little) {
/* Little endian, for alpha-first we can use this bitmap directly in GL */
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
if (alphaInfo != kCGImageAlphaPremultipliedFirst && alphaInfo != kCGImageAlphaFirst &&
alphaInfo != kCGImageAlphaNoneSkipFirst) {
shouldRedrawUsingCoreGraphics = YES;
}
} else if (byteOrderInfo == kCGBitmapByteOrderDefault || byteOrderInfo == kCGBitmapByteOrder32Big) {
/* Big endian, for alpha-last we can use this bitmap directly in GL */
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
if (alphaInfo != kCGImageAlphaPremultipliedLast && alphaInfo != kCGImageAlphaLast &&
alphaInfo != kCGImageAlphaNoneSkipLast) {
shouldRedrawUsingCoreGraphics = YES;
}
}
}
}
if (isCreate) {
shouldRedrawUsingCoreGraphics = YES;
}
if (shouldRedrawUsingCoreGraphics) {
[self setupTexture:imageName];
} else {
[self setupTextureNoneUsingCoreGraphics:imageName];
}
}
4.OpenGL ES 渲染图片自适应
纹理坐标是不变的,相对改变顶点坐标
1.默认渲染区域
2.基于UIView(layer)比例 屏幕内按照图片尺寸最大限度渲染
3.基于图片比例 按照图片比例采集渲染
GLuint fillMode = 2;
CGImageRef spriteImage = [UIImage imageNamed:@"kunkun.jpg"].CGImage;
//判断图片是否获取成功
if (!spriteImage) {
NSLog(@"Failed to load image");
exit(1);
}
//2、读取图片的大小,宽和高
GLfloat width = CGImageGetWidth(spriteImage);
GLfloat height = CGImageGetHeight(spriteImage);
CGSize inputImageSize = CGSizeMake(width, height);
CGFloat heightScaling = 0.0, widthScaling = 0.0;
CGSize currentViewSize = self.bounds.size;
CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(inputImageSize, self.layer.bounds);
switch(fillMode)
{
case 1:
{
widthScaling = 1.0;
heightScaling = 1.0;
};
break;
case 2:
{
widthScaling = insetRect.size.width / currentViewSize.width;
heightScaling = insetRect.size.height / currentViewSize.height;
}; break;
case 3:
{
widthScaling = currentViewSize.height / insetRect.size.height;
heightScaling = currentViewSize.width / insetRect.size.width;
};
break;
}
NSLog(@"widthScaling == %lf", widthScaling);
NSLog(@"heightScaling == %lf", heightScaling);
//动态调整顶点数组
GLfloat attrArr[] =
{
-widthScaling, -heightScaling, 0.0f, 0.0f, 0.0f,
widthScaling, -heightScaling, 0.0f, 1.0f, 0.0f,
-widthScaling, heightScaling, 0.0f, 0.0f, 1.0f,
widthScaling, heightScaling, 0.0f, 1.0f, 1.0f,
};