【问题标题】:CGBitmapContextCreate returns null; writing rbga pixel array to fileCGBitmapContextCreate 返回 null;将 rbga 像素数组写入文件
【发布时间】:2011-12-14 12:47:40
【问题描述】:

我正在尝试使用here [stackoverflow.com] 找到的代码将 RBGA 像素阵列写入文件,但它失败了。

我将像素信息存储在 32 位整数的一维数组中,因此该方法的第一位(希望)从 32 位整数中获取相关位,将它们存储到字符数组中。

运行时,下面的方法 a) 打印出我们没有创建图像(CGBitmapContextCreateImage(bitmapContext) 返回 NULL),b) 在尝试释放图像时死掉了(RayTracerProject[33126] <Error>: CGBitmapContextCreateImage: invalid context 0x0 ImageIO: <ERROR> CGImageDestinationAddImage image parameter is nil),这是有道理的,因为cgImage一片空白。

方法:

-(void) write{

char* rgba = (char*)malloc(width*height);
for(int i=0; i < width*height; ++i) {
    rgba[4*i] = (char)[Image red:pixels[i]];
    rgba[4*i+1] = (char)[Image green:pixels[i]];
    rgba[4*i+2] = (char)[Image blue:pixels[i]];
    rgba[4*i+3] = (char)[Image alpha:pixels[i]];
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext = CGBitmapContextCreate(
                                                   rgba,
                                                   width,
                                                   height,
                                                   8, // bitsPerComponent
                                                   width, // bytesPerRow
                                                   colorSpace,
                                                   kCGImageAlphaNoneSkipLast);

CFRelease(colorSpace);

CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);

if ( cgImage == NULL ) 
    printf("Couldn't create cgImage correctly"). 

CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("image.png"), kCFURLPOSIXPathStyle, false);

CFStringRef type = kUTTypePNG; // or kUTTypeBMP if you like
CGImageDestinationRef dest = CGImageDestinationCreateWithURL(url, type, 1, 0);

CGImageDestinationAddImage(dest, cgImage, 0);

CFRelease(cgImage);
CFRelease(bitmapContext);
CGImageDestinationFinalize(dest);
free(rgba);
}; 

为了完整起见,我的位移方法:

// Extract the 8-bit red component from a 32bit color integer. 
+(int) red:(int) color{
 return (color >> 16) & 0xff;
};

// Extract the 8-bit green component from a 32bit color integer. 
+(int) green:(int) color{
  return (color >> 8) & 0xff;
};

// Extract the 8-bit blue component from a 32bit color integer. 
+(int) blue:(int) color{
  return (color & 0xff);
};

// Extract the 8-bit alpha component from a 32bit color integer. 
+(int) alpha:(int) color{
  return (color >> 24) & 0xff;
};

根据找到的文档 here [developer.apple.com],CGBitmapContextCreateImage 将返回 A new bitmap context, or NULL if a context could not be created,但无法帮助我理解为什么无法创建上下文。

我做错了什么? [此外,如果有一种更智能的方法可以在 Objective-C 中将像素数组写入文件,那么我不会拘泥于这种特殊的做事方式——这个项目是我几年前做的 Java 项目的一个端口- 我使用了 FileOutputStream,但在 Objective-C 中找不到等价物]。

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    我现在可以使用它 - 发布这个以防其他人有一天发现它有用。

    上面的代码有一些错误 - 例如,在对 CGBitmapContextCreate 的调用中,我没有将 width*4 用于每行的字节数,而我的 rgba 数组比它应该小了 4 倍到过。下面的代码运行,虽然我不知道图像保存到哪里(我将硬编码一个路径,直到我弄清楚)。

    -(void) write{
    
     //printf("First pixel is: %d\n", pixels[0]);
     // RGBA array needs to be 4x pixel array - using 4bytes per int.  
     char* rgba = (char*)malloc(width*height*4);
     //printf("Size of char array: %d\n", width*height*4);
    
     for(int i=0; i < width*height; ++i) {
        rgba[4*i] = (char)[Image red:pixels[i]];
        rgba[4*i+1] = (char)[Image green:pixels[i]];
        rgba[4*i+2] = (char)[Image blue:pixels[i]];
        rgba[4*i+3] = (char)[Image alpha:pixels[i]];
     }
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
     CGContextRef bitmapContext = CGBitmapContextCreate(
                                                       rgba,
                                                       width,
                                                       height,
                                                       8, // bitsPerComponent
                                                       width*4, // bytesPerRow (4x larger then width)
                                                       colorSpace,
                                                       kCGImageAlphaNoneSkipLast);
    
     CFRelease(colorSpace);
    
     CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
    
     /*if ( cgImage == NULL ) 
          printf("Couldn't create cgImage correctly");
      else
          printf("Has been created correctly");
     */
     CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,  CFSTR("image.png"), kCFURLPOSIXPathStyle, false);
    
     CFStringRef type = kUTTypePNG; // or kUTTypeBMP if you like
     CGImageDestinationRef dest = CGImageDestinationCreateWithURL(url, type, 1, 0);
    
     CGImageDestinationAddImage(dest, cgImage, 0);
    
     CFRelease(cgImage);
     CFRelease(bitmapContext);
     CGImageDestinationFinalize(dest);
     free(rgba);
    }; 
    

    【讨论】:

    • 别忘了free(rgba)。这可以在CGBitmapContextCreateImage 之后完成,因为这是一个复制操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多