如何从NSData字符串数据创建CGImageRef(NOT UIImage)

时间:2014-07-22 21:25:13

标签: objective-c uiimage cgimage

如何在没有UIImage的情况下创建新的CGImageRef?我无法使用image.CGImage

我从服务器进程收到base64编码的图像作为std :: string。下面代码的第一部分模拟接收编码的字符串。

- (UIImage *)testChangeImageToBase64String
{
    UIImage *processedImage = [UIImage imageNamed:@"myFile.jpg"];

    // UIImage to unsigned char *
    CGImageRef imageRef = processedImage.CGImage;
    NSData *data = (NSData *) CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));

    // encode data to Base64 NSString
    NSString *base64EncodedDataString = [data base64EncodedStringWithOptions:0];
    // create encoded std::string
    std::string encoded([base64EncodedDataString UTF8String]);


    // ***************************************************************************
    // This is where we call the server method and receive the bytes in a std::string
    std::string received = encoded;
    // ***************************************************************************


    // get Base64 encoded std::string into NSString
    NSString *base64EncodedCstring = [NSString stringWithCString:encoded.c_str() encoding:[NSString defaultCStringEncoding]];

    // NSData from the Base64 encoded std::string
    NSData *nsdataFromBase64String = [[NSData alloc]initWithBase64EncodedString:base64EncodedCstring options:0];

一切都很好!!!! .....直到我尝试填充newImage。


当我获得编码的字符串时,我需要获得CGImageRef以将数据恢复为正确的格式以填充UIImage。 如果数据格式不正确,UIImage将为零。

我需要使用nsdataFromBase64String创建一个新的CGImageRef。

类似的东西:

    CGImageRef base64ImageRef = [newCGImageRefFromString:nsdataFromBase64String];

然后我可以使用imageWithCGImage将数据放入一个新的UIImage。

类似的东西:

    UIImage *imageFromImageRef = [UIImage imageWithCGImage: base64ImageRef];

然后我可以返回UIImage。

    return newImage;
}

请注意,以下行不起作用:

    UIImage *newImage = [[UIImage alloc] initWithData:nsdataFromBase64String];

数据需要格式正确,否则UIImage将为零。因此,我的问题,“如何使用NSData创建CGImageRef?”

1 个答案:

答案 0 :(得分:3)

简短的回答,因为这主要是刚刚超过我在NSChat中提到的内容:

  1. 弄清楚您接收的图像格式及其大小(宽度和高度,以像素为单位)。你在聊天中提到它只是直接的ARGB8数据,所以请记住这一点。如果有的话,我不确定你是如何收到其他信息的。

  2. 使用CGImageCreate,使用你已经知道的图像创建一个新图像(也就是说,你可能知道它的宽度,高度等等 - 如果你不知道,你应该用它来包装它你正在发送的图像)。例如,这个没有人喜欢写的样板:

    // NOTE: have not tested if this even compiles -- consider it pseudocode.
    
    CGImageRef image;
    CFDataRef bridgedData;
    CGDataProviderRef dataProvider;
    CGColorSpaceRef colorSpace;
    CGBitmapInfo infoFlags = kCGImageAlphaFirst; // ARGB
    
    // Get a color space
    colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    // Assuming the decoded data is only pixel data
    bridgedData  = (__bridge CFDataRef)decodedData;
    dataProvider = CGDataProviderCreateWithCFData(bridgedData);
    
    // Given size_t width, height which you should already have somehow
    image = CGImageCreate(
        width, height, /* bpc */ 8, /* bpp */ 32, /* pitch */ width * 4,
        colorSpace, infoFlags,
        dataProvider, /* decode array */ NULL, /* interpolate? */ TRUE,
        kCGRenderingIntentDefault /* adjust intent according to use */
      );
    
    // Release things the image took ownership of.
    CGDataProviderRelease(dataProvider);
    CGColorSpaceRelease(colorSpace);
    

    该代码的写法是保证它是ARGB_8888,数据是正确的,没有任何东西可能返回NULL等。复制/粘贴上面的代码可能会导致半径3英里内的所有内容爆炸。错误处理取决于您(例如,CGColorSpaceCreateWithName可能会返回null)。

  3. 使用CGImage分配UIImage。由于UIImage将拥有/复制CGImage,释放你的CGImageRef(实际上,文档没有说明 UIImage用CGImage做什么,但是你不再使用它了,所以你必须释放你的。)