CGBitmapContextCreate返回null;将rbga像素数组写入文件

时间:2011-12-14 12:47:40

标签: objective-c

我正在尝试使用找到的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中找不到等价物。

1 个答案:

答案 0 :(得分:3)

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

上面的代码存在一些错误 - 例如,我在调用width*4时没有使用CGBitmapContextCreate作为每行的字节数,而我的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);
};