iOS中随机图像的OpenGL ES纹理

时间:2011-07-27 18:05:37

标签: ios opengl-es textures

我一直面临着将一个奇怪大小的图像(虽然固定比例)放在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;
}

除非您认为它们是问题的核心,否则请不要提及明显的内存管理问题。至于“错误信息”或其他:不,没有这样的事情,整个应用程序只是崩溃。

1 个答案:

答案 0 :(得分:1)

好的,现在你可以用大鳟鱼集体击打我的脸。

问题实际上是内存管理,特别是我发布了使用隐式方法(即midImage和texData)创建的对象。隐式创建不会增加保留计数,而显式(alloc + init和friends)则会增加。怎么可能我已经崩溃了?许多。他们够了吗?显然不是。

第二个问题:我在哪里可以找到一个大的帖子,至少1x1m?