带有NSData的UIImage initWithData返回nil
UIImage with NSData initWithData returns nil
我有一个新问题!因为真正的问题不是在c++转换,而是我需要将返回的字符串数据字节转换为CGImageRef。如果有人知道怎么做,请去那个链接回答这个问题。
谢谢。
OK。我没有用protobuf的东西来混淆这个问题,而是简化了我的测试方法来模拟对protobuf的调用。
该测试方法完成以下两部分。第1部分获取一个UIImage并将其转换为std::string。
- take a UIImage
- 获取NSData
- 将数据转换为unsigned char *
- 将无符号char *填充到std::string
该字符串是我们将从protobuf调用接收到的字符串。第2部分从字符串中获取数据并将其转换回NSData格式以填充UIImage。以下是执行该操作的步骤:
- 将std::字符串转换为char数组
- 将char数组转换为const char *
- 将char *放入NSData
- 返回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; }
是返回数据时的代码:
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。用那个数据Alloc初始化UIImage返回nil。
好的,所以问题很可能与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");
}
}
我试着回答。为了消除错误,我需要做一些小的修改。此外,我还更改了一些变量名,以尽量减少混淆。这仍然会为UIImage返回nil。
- (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");
}
}
我试着删除中间的一切,它工作。下面是代码:
- (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)。
我在网上找到了这个答案,这很有帮助。询者甚至发表了这样的评论,"看起来很简单包装(数据)在CFData对象,然后CGDataProviderCreateWithCFData。"
我在SO上找到了另一个答案,也很有帮助。它展示了如何使用字符串。
创建CFDataRef。有很多有用的信息在那里,但仍然没有找到我需要的。我要问另一个问题,当我得到答案时,把它引用到这里。谢谢。
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 什么时候在C++中返回常量引用是个好主意
- 你能重载对象变量名本身返回的内容吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何获取std::result_of函数的返回类型
- QueryWorkingSet总是返回false
- (C++)分析树以计算返回错误值的简单算术表达式
- 访问者访问变体并返回不同类型时出错
- 如何返回一个类的两个对象相加的结果
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- lower_bound()返回最后一个元素
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 如何取消对nullptr的屏蔽,返回正确的对象
- 奇怪的结构&GCC&clang(void*返回类型)
- 架构决策:返回std::future还是提供回调
- 当给定包含中文字符的wchar_t数组时,NSString initWithBytes返回nil
- 带有NSData的UIImage initWithData返回nil
- lubridge getGlobal总是返回nil