У меня новый вопрос Вот! Поскольку настоящая проблема была не в преобразовании C ++, а в том, что мне нужно преобразовать возвращенные байты строковых данных в CGImageRef. Кто-нибудь знает, как это сделать, перейдите по этой ссылке, чтобы ответить на этот вопрос.
Спасибо.
ХОРОШО. Вместо того, чтобы путать вопрос с материалом protobuf, я упростил мой метод тестирования, чтобы имитировать вызов, который будет сделан для материала Protobuf.
Этот метод испытаний состоит из следующих двух частей. Часть 1 берет UIImage и преобразует его в std :: string.
Строка — это то, что мы получили бы от вызова protobuf. Часть 2 берет данные из строки и преобразует их обратно в формат NSData для заполнения UIImage. Ниже приведены шаги для этого:
- (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 с этими данными, возвращает ноль. Должен быть какой-то тип конверсии, который сделает эту работу.
Итак, проблема, скорее всего, связана с повторными преобразованиями между структурами данных 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.
- (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».
я нашел другой ответ на ТАК, что также было полезно. Он показывает, как создать CFDataRef, используя строку.
Там много полезной информации, но я не могу найти то, что мне нужно. Я собираюсь задать еще один вопрос и ссылаться на него здесь, когда получу ответ.
Спасибо.