我一直面临将一个奇怪大小的图像(虽然具有固定比例)放在 GL_QUAD(好吧,GL_TRIANGLE_STRIP resem - 你明白了)上的任务,起初对我来说这似乎相当容易,除了我需要在 iOS (4.2+) 中执行此操作的部分。无论如何,解决方案非常简单:只需拍摄图像,从中制作纹理,将其映射到正确的顶点,就可以了。
您可能很清楚,OpenGL ES 纹理要求宽度和高度为 2 的幂,例如 2、4、8、...、256、512...(不确定这是否适用于常规OpenGL,但我认为它确实......无论如何,没关系)。 因为我必须从 Intertubes(实际上是 YouTube)下载这些图像,所以我不能事先做任何事情,所以我有这些 480x360 图像(如果我没记错的话),我必须将它们涂在我的三角形条上。幸运的是,我们有纹理映射,它允许我们选择要映射到我们想要的位置的纹理部分,所以显而易见的解决方案是(可选地放大/缩小)并用一些哑光颜色填充源图像,并接受它。
进入 iOS。我从 Intertubes 获取数据,我愉快地构建了相应的 UIImage,然后我制作了另一个 UIImage(是的,我知道,请耐心等待,我稍后会对其进行优化)只是按比例缩小到最接近的 2 的幂次方宽度,保留纵横比,假设是 256x192,然后我制作一个位图上下文,将其涂成黑色(或者,重要的是,涂成任何其他颜色,但我想你可以明白为什么我在这种情况下选择黑色),绘制 UIImage(a CGImage),并返回使用上述位图上下文构建的 UIImage。
我现在很高兴拥有一张 256x256 图像,可以映射到我的 GL_TRIANGLE_STRIP 上。除了它不起作用。我尝试使用准备好的 512x512 图像,它完美地工作。我在此处粘贴的代码不包括从 YouTube 检索图像,我只是将其保存在本地以排除网络问题。另外,我没有包括 GL 代码,因为它显然可以正常工作。
- (void)viewDidLoad {
images = [[NSMutableArray alloc] init];
//NSURL *url = [NSURL URLWithString:@"http://i.ytimg.com/vi/d2wVgzXWE9Y/0.jpg"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"opengl_texture" ofType:@"jpg"];
NSData *texData = [NSData dataWithContentsOfFile:path];
UIImage *rawImage = [[UIImage alloc] initWithData:texData];
float newWidth = (float)(1 << (int)floor(log2f(rawImage.size.width)));
// Scale means the scale of the current image relative to the resulting image.
float scale = rawImage.size.width / newWidth;
UIImage *midImage = [UIImage imageWithCGImage:[rawImage CGImage] scale:scale orientation:UIImageOrientationUp];
NSLog(@"%f %f %f", midImage.size.width, midImage.size.height, scale);
[rawImage release];
UIImage *image = [self padImage:midImage withColor:[UIColor redColor]];
NSLog(@"%f %f", image.size.width, image.size.height);
[images addObject:image];
textures = malloc(sizeof(GLuint));
glGenTextures(1, textures);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetWidth(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc(width * height * 4);
CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, 4*width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( context, 0, height - height );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
[midImage release];
[image release];
[texData release];
}
- (UIImage *)padImage:(UIImage *)image withColor:(UIColor *)color {
CGFloat size = round(image.size.width);
NSLog(@"%f", size);
CGContextRef bContext = [self createBitmapContextOfSize:CGSizeMake(size, size)];
CGContextSetFillColorWithColor(bContext, [color CGColor]);
CGContextFillRect(bContext, CGRectMake(0, 0, size, size));
CGContextDrawImage(bContext, CGRectMake(0, 0, size, size), [image CGImage]);
UIImage *result = [UIImage imageWithCGImage:CGBitmapContextCreateImage(bContext)];
CGContextRelease(bContext);
return result;
}
- (CGContextRef) createBitmapContextOfSize:(CGSize) size {
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
int bitmapByteCount;
int bitmapBytesPerRow;
bitmapBytesPerRow = (size.width * 4);
bitmapByteCount = (bitmapBytesPerRow * size.height);
colorSpace = CGColorSpaceCreateDeviceRGB();
bitmapData = malloc( bitmapByteCount );
if (bitmapData == NULL) {
fprintf (stderr, "Memory not allocated!");
return NULL;
}
context = CGBitmapContextCreate (bitmapData,
size.width,
size.height,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
CGContextSetAllowsAntialiasing (context,NO);
if (context== NULL) {
free (bitmapData);
fprintf (stderr, "Context not created!");
return NULL;
}
CGColorSpaceRelease( colorSpace );
return context;
}
请不要提及明显的内存管理问题,除非您认为它们是问题的核心。至于“错误消息”之类的:不,没有这样的东西,整个应用程序崩溃了。
最佳答案
好的,现在你们可以集体用一条大鳟鱼打我的脸了。
问题实际上是内存管理,特别是我释放了使用隐式方法创建的对象(即 midImage 和 texData)。隐式创建不会增加保留计数,而显式(alloc+init 和 friend )会。有多少次我已经崩溃了?很多。他们够了吗?显然不是。
第二个问题:在哪里可以找到大的便利贴,至少 1x1 米?
关于ios - iOS 中随机图像的 OpenGL ES 纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6849071/