ios - iOS 中随机图像的 OpenGL ES 纹理

标签 ios opengl-es textures

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

相关文章:

ios - UIBarButtonItems 选定的颜色在 iOS 7 中不会正确更改

ios - Swift:检查数据类型是否可以转换为 Double

ios - iOS 中的动画和旋转图像

javafx - 使用三角形网格纹理,无需读/写图像文件

java - 如何在OpenGL中给物体添加纹理?

ios - UIWebview 中的空白屏幕

ios - 将字符串显示为带两位小数的数字

ios - 使用 glReadPixels 读取 Tap Point 的值? OpenGL 2.0 iOS

android - 来自 OpenGLRenderer 的 GL 错误 : 0x502

glTexImage2D 的 android 位图像素格式