使用NSData initWithData的UIImage返回nil

时间:2014-07-02 20:17:41

标签: c++ objective-c string uiimage nsdata

我有一个新问题here由于真正的问题不是在C ++转换中,而是我需要将返回的字符串数据字节转换为CGImageRef。任何人都知道如何做到这一点请转到该链接以回答此问题的后续行为。

谢谢。


行。我没有用protobuf的东西混淆问题,而是简化了我的测试方法,以模拟对protobuf内容的调用。

该测试方法有以下两部分。第1部分使用UIImage并将其转换为std :: string。

  1. 采取UIImage
  2. 从中获取NSData
  3. 将数据转换为unsigned char *
  4. 将unsigned char *填入std :: string
  5. 字符串是我们从protobuf调用中获得的字符串。第2部分从字符串中获取数据并将其转换回NSData格式以填充UIImage。以下是执行此操作的步骤:

    1. 将std :: string转换为char数组
    2. 将char数组转换为const char *
    3. 将char *放入NSData
    4. 返回NSData
    5. - (NSData *)testProcessedImage:(UIImage *)processedImage
      {
          // UIImage to unsigned char *
          CGImageRef imageRef = processedImage.CGImage;
          NSData *data = (NSData *) CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));
          unsigned char *pixels = (unsigned char *)[data bytes];
          unsigned long size = [data length];
      
          // ***************************************************************************
          // This is where we would call transmit and receive the bytes in a std::string
          // ***************************************************************************
      
          // unsigned char * to string
          std::string byteString(pixels, pixels + size);
      
      
          // string to char array to const char *
          char myArray[byteString.size()+1];//as 1 char space for null is also required
          strcpy(myArray, byteString.c_str());
          const char *bytes = (const char *)myArray;
      
          // put byte array back into NSData format
          NSUInteger usize = byteString.length();
          data = [NSData dataWithBytes:(const void *)bytes length:sizeof(unsigned char)*usize];
          NSLog(@"examine data");
      
          return data;
      }
      

      是返回数据的代码:

          NSData *data = [self.messageCommand testProcessedImage:processedImage];
      
          // But when I try to alloc init a UIImage with the data, the image is nil
          UIImage *image = [[UIImage alloc] initWithData:data];
          NSLog(@"examine image");
      

      在尝试使用数据创建UIImage之前,所有内容似乎都按计划进行。使用该数据启动UIImage的Alloc返回nil。必须有某种类型的转换才能使其发挥作用。

3 个答案:

答案 0 :(得分:1)

好的,所以问题很可能是Objective-C,C和C ++数据结构之间的重复转换。总的来说,您需要确保将字符串初始化为字节数组而不是文本C字符串,并且您希望在没有空终止符的情况下返回原始字节。我认为这将正确保存数据:

- (void)onDataReceived:(NSNotification *)note {
    if ([note.name isEqualToString:@"DataReceived"]) {
        NSDictionary *userData = note.userInfo;
        NSData *imageData = [userData objectForKey:@"ImageData"];
 // Note the two-argument string constructor -- this is necessary for non-textual data!
        std::string byteString = std::string(static_cast<const char*>([imageData bytes]), imageData.length);


 // We get the image back as a std::string
        std::string imageStr = [self.message parseMessage:byteString ofSize:byteString.size()];
        NSLog(@"examine imageStr");

 // We get the data from the std::string
        char *imageCStr = new char[imageStr.size()];
        imageStr.copy(imageCStr, imageStr.size());
        NSData *data = [NSData dataWithBytes:imageCStr length:imageStr.size()];
        delete[] imageCStr;

 // But when I try to alloc init a UIImage with the data, the image is nil
        UIImage *image = [[UIImage alloc] initWithData:data];
        NSLog(@"examine image");
    }
}

答案 1 :(得分:1)

我试过了答案。为了摆脱错误,我需要做一些小的改动。此外,我更改了一些变量名称以最大限度地减少混淆。对于UIImage,这仍然是零。

- (void)onObjectReceived:(NSNotification *)note {
    if ([note.name isEqualToString:@"ObjectReceived"]) {
        NSDictionary *userData = note.userInfo;
        NSData *objectData = [userData objectForKey:@"ObjectData"];

        // Added this because bytes is used below.  Or did you mean something else?
        const char *bytes = (const char *)[objectData bytes];

        // Note the two-argument string constructor -- this is necessary for non-textual data!
        std::string byteString = std::string(static_cast<const char*>(bytes), objectData.length);

        // This is an out parameter in the parseMessage method.
        long unsigned int *msgSize = (long unsigned *)malloc(sizeof(long unsigned int));

        // We get the image back as a std::string
        std::string imageStr = [self.message parseMessage:byteString outMsgSize:msgSize];
        NSLog(@"examine imageStr");

        // We get the data from the std::string
        char *imageCStr = new char[imageStr.size()];
        imageStr.copy(imageCStr, imageStr.size());
        NSData *data = [NSData dataWithBytes:imageCStr length:imageStr.size()];
        delete[] imageCStr;

        // But when I try to alloc init a UIImage with the data, the image is nil
        UIImage *image = [[UIImage alloc] initWithData:data];
        NSLog(@"examine image");
    }
}

答案 2 :(得分:0)

我尝试删除其间的所有内容并且有效。这是代码:

- (NSData *)testProcessedImage:(UIImage *)processedImage
{
    // UIImage to unsigned char *
    CGImageRef imageRef = processedImage.CGImage;
    NSData *data1 = (NSData *) CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));

    UIImage *image = [UIImage imageWithCGImage:imageRef];

这告诉我NSData dataWithBytes不起作用,因为我使用的是CGImageRef。我的图像是来自相机的原始数据(不是PNG或JPEG)。

我发现this answer对SO很有帮助。提问者甚至发布了这条评论,&#34;将数据包装在CFData对象中,然后CGDataProviderCreateWithCFData看起来很简单。&#34;

我在SO上发现another answer也很有帮助。它显示了如何使用字符串创建CFDataRef。

有很多有用的信息,但仍然没有找到我需要的信息。我得到另一个问题,并在得到答案时将其引用回来。

谢谢。