Чтение двоичных данных изображения из веб-службы в UIImage - PullRequest
4 голосов
/ 02 марта 2010

Я использую веб-сервис в своем приложении для iPhone. Метод веб-службы возвращает ответ, имеющий несколько полей (например, ID, описание и т. Д.). Одно из этих полей содержит двоичные данные изображения, которые мне нужно преобразовать в UIImage в моем приложении для iPhone.

Я успешно использую NSXMLParser для извлечения данных из XML-ответа. В селекторе parser:foundCharacters: XMLParser он дает NSString*, указывающий на строку в каждом поле. Поскольку это строка, это то, что я делаю для чтения данных изображения, когда сталкиваюсь с полем изображения:

UIImage *img = [[UIImage alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]];

Но переменная img все еще "nil" после этой строки. Похоже, данные из строки XML не совместимы с преобразованием. Что я здесь не так делаю? (Я могу читать другие поля в мои переменные, но не это поле данных изображения)

Заранее спасибо ..

Ответы [ 2 ]

5 голосов
/ 04 марта 2010

После ответа fbrereto мне удалось преобразовать строку в NSData, используя пример кода по этой ссылке: http://www.cocoadev.com/index.pl?BaseSixtyFour (выделите пример кода пользователем MiloBird). Теперь я могу успешно построить изображение.

Он использует категории target-c для добавления селектора + (id)dataWithBase64EncodedString:(NSString *)string; в класс NSData. Вот необходимый пример кода, который я извлек по приведенной выше ссылке:

//MBBase64.h

@interface NSData (MBBase64)

+ (id)dataWithBase64EncodedString:(NSString *)string;     //  Padding '=' characters are optional. Whitespace is ignored.

@end


//MBBase64.m

static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

@implementation NSData (MBBase64)

+ (id)dataWithBase64EncodedString:(NSString *)string;
{
    if (string == nil)
        [NSException raise:NSInvalidArgumentException format:nil];
    if ([string length] == 0)
        return [NSData data];

    static char *decodingTable = NULL;
    if (decodingTable == NULL)
    {
        decodingTable = malloc(256);
        if (decodingTable == NULL)
            return nil;
        memset(decodingTable, CHAR_MAX, 256);
        NSUInteger i;
        for (i = 0; i < 64; i++)
            decodingTable[(short)encodingTable[i]] = i;
    }

    const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
    if (characters == NULL)     //  Not an ASCII string!
        return nil;
    char *bytes = malloc((([string length] + 3) / 4) * 3);
    if (bytes == NULL)
        return nil;
    NSUInteger length = 0;

    NSUInteger i = 0;
    while (YES)
    {
        char buffer[4];
        short bufferLength;
        for (bufferLength = 0; bufferLength < 4; i++)
        {
            if (characters[i] == '\0')
                break;
            if (isspace(characters[i]) || characters[i] == '=')
                continue;
            buffer[bufferLength] = decodingTable[(short)characters[i]];
            if (buffer[bufferLength++] == CHAR_MAX)      //  Illegal character!
            {
                free(bytes);
                return nil;
            }
        }

        if (bufferLength == 0)
            break;
        if (bufferLength == 1)      //  At least two characters are needed to produce one byte!
        {
            free(bytes);
            return nil;
        }

        //  Decode the characters in the buffer to bytes.
        bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
        if (bufferLength > 2)
            bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
        if (bufferLength > 3)
            bytes[length++] = (buffer[2] << 6) | buffer[3];
    }

    realloc(bytes, length);
    return [NSData dataWithBytesNoCopy:bytes length:length];
}

@end

Спасибо всем!

1 голос
/ 02 марта 2010

Уловка с NSString заключается в том, что существует неявное кодирование, связанное с данными, которые оно содержит. Однако изображение, которое вы получаете, вероятно, имеет формат, который не будет преобразован должным образом, поскольку это либо двоичные данные, либо некоторое кодирование двоичных данных без потерь (например, base64). Хитрость заключается в том, чтобы вы не позволяли NSString вообще выполнять какие-либо преобразования кодировки, иначе ваши данные изображения будут повреждены. Вместо использования dataUsingEncoding: я бы попробовал API больше похожий на getBytes:maxLength:usedLength:encoding:options:range:remainingRange. Хотя он сложнее, чем dataUsingEncoding:, я думаю, он даст вам гибкость, необходимую для получения только данных из строки NSSt и ничего более.

...