带有 NSData initWithData 的 UIImage 返回 nil [英] UIImage with NSData initWithData returns nil

查看:86
本文介绍了带有 NSData initWithData 的 UIImage 返回 nil的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

谢谢.

<小时>

好的.我没有用 protobuf 的东西来混淆问题,而是简化了我的测试方法来模拟对 protobuf 东西进行的调用.

这个测试方法做了以下两部分.第 1 部分采用 UIImage 并将其转换为 std::string.

  1. 获取一个 UIImage
  2. 从中获取 NSData
  3. 将数据转换为无符号字符 *
  4. 将无符号字符 * 填充到 std::string 中

字符串是我们将从 protobuf 调用中接收到的字符串.第 2 部分从字符串中获取数据并将其转换回 NSData 格式以填充 UIImage.以下是执行此操作的步骤:

  1. 将 std::string 转换为字符数组
  2. 将 char 数组转换为 const char *
  3. 将字符 * 放入 NSData
  4. 返回 NSData

<块引用>

- (NSData *)testProcessedImage:(UIImage *)processedImage{//UIImage 到无符号字符 *CGImageRef imageRef = processingImage.CGImage;NSData *data = (NSData *) CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));unsigned char *pixels = (unsigned char *)[数据字节];unsigned long size = [数据长度];//********************************************************************************//这是我们在 std::string 中调用传输和接收字节的地方//********************************************************************************//unsigned char * 到字符串std::string byteString(pixels, pixel + size);//string 到 char 数组到 const char *char myArray[byteString.size()+1];//同样需要1个字符空间为nullstrcpy(myArray, byteString.c_str());const char *bytes = (const char *)myArray;//将字节数组放回 NSData 格式NSUInteger usize = byteString.length();data = [NSData dataWithBytes:(const void *)bytes length:sizeof(unsigned char)*usize];NSLog(@"检查数据");返回数据;}

返回数据时的代码:

 NSData *data = [self.messageCommand testProcessedImage:processedImage];//但是当我尝试使用数据分配初始化 UIImage 时,图像为零UIImage *image = [[UIImage alloc] initWithData:data];NSLog(@"查看图片");

一切似乎都按计划进行,直到我尝试使用数据创建 UIImage.使用该数据初始化 UIImage 的 Alloc 返回 nil.必须有某种类型的转换才能完成这项工作.

解决方案

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

- (void)onDataReceived:(NSNotification *)note {if ([note.name isEqualToString:@"DataReceived"]) {NSDictionary *userData = note.userInfo;NSData *imageData = [userData objectForKey:@"ImageData"];//注意两个参数的字符串构造函数——这是非文本数据所必需的!std::string byteString = std::string(static_cast([imageData bytes]), imageData.length);//我们将图像作为 std::string 返回std::string imageStr = [self.message parseMessage:byteString ofSize:byteString.size()];NSLog(@"检查 imageStr");//我们从 std::string 中获取数据char *imageCStr = new char[imageStr.size()];imageStr.copy(imageCStr, imageStr.size());NSData *data = [NSData dataWithBytes:imageCStr length:imageStr.size()];删除[] imageCStr;//但是当我尝试使用数据分配初始化 UIImage 时,图像为零UIImage *image = [[UIImage alloc] initWithData:data];NSLog(@"查看图片");}}

I have a new question here! As the real problem was not in the C++ conversion but rather that I need to convert the returned string data bytes into a CGImageRef. Anybody know how to do that please go to that link to answer the follow on to this question.

Thank you.


OK. Instead of muddying the question with protobuf stuff, I have simplified my test method to simulate the call that would be made to the protobuf stuff.

This test method does the following two parts. Part 1 takes a UIImage and converts it into a std::string.

  1. take a UIImage
  2. get the NSData from it
  3. convert the data to unsigned char *
  4. stuff the unsigned char * into a std::string

The string is what we would receive from the protobuf call. Part 2 takes the data from the string and converts it back into the NSData format to populate a UIImage. Following are the steps to do that:

  1. convert the std::string to char array
  2. convert the char array to a const char *
  3. put the char * into NSData
  4. return NSData

- (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;
}

The is the code for when the data is returned:

    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");

Everything seems to go as planned until I try to create the UIImage with the data. Alloc initing the UIImage with that data returns nil. There must be some type of conversion that will make this work.

解决方案

OK, so the problem is most likely with the repeated conversions between Objective-C, C and C++ data structures. Overall, you need to make sure to initialize the string as a byte array rather than a textual C string, and you want to get back the raw bytes without a null terminator. I think this will preserve the data correctly:

- (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");
    }
}

这篇关于带有 NSData initWithData 的 UIImage 返回 nil的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆