【问题标题】:Reading binary image data from a web service into UIImage将 Web 服务中的二进制图像数据读入 UIImage
【发布时间】:2010-03-02 04:55:22
【问题描述】:

我正在我的 iPhone 应用程序中使用网络服务。 Web 服务方法返回一个包含多个字段(例如 ID、描述等)的响应。这些字段之一包含我需要在我的 iPhone 应用程序中转换为 UIImage 的二进制图像数据。

我正在使用 NSXMLParser 成功地从 XML 响应中提取数据。在 XMLParser 的 parser:foundCharacters: 选择器中,它给出了一个 NSString* 指向每个字段中的字符串。由于这是一个字符串,所以当我遇到图像字段时,我会这样做来读取图像数据:

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

但是在这一行之后,img 变量仍然是“nil”。似乎来自 XML 字符串的数据与转换不兼容。我在这里做错了什么? (我能够将其他字段读入我的变量,但不能将这个图像数据字段读入)

提前谢谢..

【问题讨论】:

    标签: iphone web-services binary-data


    【解决方案1】:

    按照 fbrereto 的回答,我设法使用此链接上的代码示例将字符串转换为 NSData:http://www.cocoadev.com/index.pl?BaseSixtyFour(滚动到 MiloBird 用户的代码示例)。现在我可以成功构建图像了。

    它使用objective-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
    

    谢谢大家!

    【讨论】:

    • 我遇到了和你一样的问题。我很高兴找到您的答案,但我并不真正理解代码以及我应该如何使用它。我有一个从 Web 服务解析的字符串 currentElementValue,我想将其转换为 nsdata,以便进一步转换为图像。你能给我一些建议吗?谢谢。
    • 这个答案可能已经很晚了。但是您可以使用示例中提供的方法并像这样调用它: NSData *data = [NSData dataWithBase64EncodedString:currentElementValue]; UIImage *img = [UIImage imageWithData:data];
    【解决方案2】:

    NSString 的诀窍在于它包含的数据相关联的隐式编码。但是,您收到的图像可能是无法正确转换的格式,因为它要么是二进制数据,要么是二进制数据的某种无损编码(例如 base64)。因此,诀窍是确保您根本不让NSString 执行任何编码转换,否则您的图像数据将被损坏。我不会使用dataUsingEncoding:,而是尝试使用更像getBytes:maxLength:usedLength:encoding:options:range:remainingRange 的API。虽然比dataUsingEncoding: 更复杂,但我认为它会为您提供从 NSString 获取数据所需的灵活性,仅此而已。

    【讨论】:

    • 感谢您的宝贵意见,但话又说回来,我需要知道字符串中的字节数。我怎么知道? [string length][string lengthOfBytesUsingEncoding] 都涉及字符编码。如果我能知道字节长度,我也许可以使用 [string getCString] 来获取原始字节。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    相关资源
    最近更新 更多