我一直面临着将一个奇怪大小的图像(虽然固定比例)放在GL_QUAD上的任务的挑战(好吧,一个GL_TRIANGLE_STRIP重新设置 - 你得到了点),这对我来说似乎很容易,除了我需要在iOS(4.2+)中执行此操作的部分。无论如何,解决方案都很简单:只需拍摄图像,从中制作纹理,将其映射到正确的顶点,然后就可以了。
正如您可能知道的那样,OpenGL ES纹理要求宽度和高度为2的幂,如2,4,8,......,256,512 ...(不确定这适用于常规OpenGL,但我认为它确实......无论如何,无关紧要)。 由于我必须从Intertubes(实际上是YouTube)下载这些图像,所以我事先无法做任何事情,所以我有这些480x360图像(如果我没记错的话),我必须在三角形条上画它们。幸运的是,我们有纹理映射,它允许我们选择要映射到我们想要的纹理部分,因此明显的解决方案是(可选地向上/缩小)并使用一些遮罩颜色填充源图像,并使用它。 / p>
进入iOS。我从Intertubes获得数据,我很高兴地构建了相应的UIImage,然后我创建了另一个UIImage(是的,我知道,请耐心等待,我稍后会对它进行优化)只是缩小到最接近的2的幂,保留方面,所以让我们说256x192,然后我制作一个位图上下文,把它漆成黑色(或者,重要的是,任何其他颜色,但我想你可以看到为什么我在这种情况下选择黑色),绘制UIImage(a CGImage),并返回使用上述位图上下文构建的UIImage。
我现在是准备在我的GL_TRIANGLE_STRIP上映射的256x256图像的幸福拥有者。除了它不起作用。我尝试了准备好的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;
}
除非您认为它们是问题的核心,否则请不要提及明显的内存管理问题。至于“错误信息”或其他:不,没有这样的事情,整个应用程序只是崩溃。
答案 0 :(得分:1)
好的,现在你可以用大鳟鱼集体击打我的脸。
问题实际上是内存管理,特别是我发布了使用隐式方法(即midImage和texData)创建的对象。隐式创建不会增加保留计数,而显式(alloc + init和friends)则会增加。怎么可能我已经崩溃了?许多。他们够了吗?显然不是。
第二个问题:我在哪里可以找到一个大的帖子,至少1x1m?