UIImage с NSData initWithData возвращает ноль

У меня новый вопрос Вот! Поскольку настоящая проблема была не в преобразовании C ++, а в том, что мне нужно преобразовать возвращенные байты строковых данных в CGImageRef. Кто-нибудь знает, как это сделать, перейдите по этой ссылке, чтобы ответить на этот вопрос.

Спасибо.


ХОРОШО. Вместо того, чтобы путать вопрос с материалом protobuf, я упростил мой метод тестирования, чтобы имитировать вызов, который будет сделан для материала Protobuf.

Этот метод испытаний состоит из следующих двух частей. Часть 1 берет UIImage и преобразует его в std :: string.

  1. взять UIImage
  2. получить NSData от него
  3. преобразовать данные в unsigned char *
  4. положить без знака char * в std :: string

Строка — это то, что мы получили бы от вызова protobuf. Часть 2 берет данные из строки и преобразует их обратно в формат NSData для заполнения UIImage. Ниже приведены шаги для этого:

  1. преобразовать std :: string в массив char
  2. преобразовать массив char в const char *
  3. положить символ * в NSData
  4. вернуть 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 с этими данными, возвращает ноль. Должен быть какой-то тип конверсии, который сделает эту работу.

-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

Другие решения

Я попробовал ответ. Были некоторые незначительные изменения, которые мне нужно было сделать, чтобы избавиться от ошибок. Кроме того, я изменил некоторые имена переменных, чтобы минимизировать путаницу. Это все еще возвращает ноль для 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");
}
}
1

Я попытался удалить все промежуточное, и это сработало. Вот код:

- (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, используя строку.

Там много полезной информации, но я не могу найти то, что мне нужно. Я собираюсь задать еще один вопрос и ссылаться на него здесь, когда получу ответ.

Спасибо.

0
По вопросам рекламы [email protected]