如何在UIImageView中显示base64图片?

52

我得到了这个Base64编码的gif图片:

R0lGODlhDAAMALMBAP8AAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACH5BAUKAAEALAAAAAAMAAwAQAQZMMhJK7iY4p3nlZ8XgmNlnibXdVqolmhcRQA7

现在我想在我的iPhone应用程序中显示这个Base64字符串。

我可以通过使用WebView来实现这个目标:

aUIWebView.scalesPageToFit = NO;
aUIWebView.opaque = NO;
aUIWebView.backgroundColor = [UIColor clearColor]; 
[aUIWebView loadHTMLString:
  @"<html><body style=""background-color: transparent""><img src=""data:image/png;base64,R0lGODlhDAAMALMBAP8AAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAUKAAEALAAAAAAMAAwAQAQZMMhJK7iY4p3nlZ8XgmNlnibXdVqolmhcRQA7"" /></body></html>"
 baseURL:nil];

使用UIImageView是否可以实现同样的事情?

11个回答

132

你不需要对它进行编码。只需创建一个NSUrl,它知道"data:"-url。

NSURL *url = [NSURL URLWithString:base64String];    
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *ret = [UIImage imageWithData:imageData];

如评论所述,您必须确保在数据前面添加 data:image/png;base64,,否则您的 base64 数据将无效。


10
是的!这真是太棒了!也许值得一提的是,您需要在实际的原始base64字符串前添加"data:image/png;base64,"才能使其正常工作。我从OP发布的WebView/HTML代码中推断出了这一点,但我可以理解有些人可能会忽略这个细节,然后此方法将无法正常工作。 - ipmcc
谢谢ipmcc,我很失望它没能工作,直到我看了你的评论。 - Barlow Tucker
@ipmcc 你说得对,我的base64数据略微超过了2048字节的URL大小限制。谢谢。 - Federico Zancan
在我所有的实验中,NSURL 总是为 nil。 - Cocoanetics
NSURL 对我来说总是为 nil,直到我意识到服务器给了我一个带有大量换行符(\n)的 Base64 字符串。当我去掉它们后,它就可以工作了。 - hordurh
显示剩余2条评论

70

虽然这是一个很老的问题,但在iOS7之后,有一种全新、更简单的方法来实现这个功能。因此,我在这里写下来,以便未来的读者可以使用它。

NSData* data = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
UIImage* image = [UIImage imageWithData:data];

非常易于使用,且不会触及URL的2048字节大小限制。


谢谢。这是我基于你的答案用Swift编写的UIImage扩展。extension UIImage { class func fromBase64(base64: String) -> UIImage? { //如果存在前缀,则删除 let PREFIX = "data:image/png;base64," let dataOnly: String if base64.startsWith(PREFIX) { dataOnly = base64.substringFromIndex(base64.startIndex.advancedBy(PREFIX.length)) } else { dataOnly = base64 } if let data = NSData(base64EncodedString: dataOnly, options: NSDataBase64DecodingOptions.init(rawValue: 0)) { return UIImage(data: data) } return nil } } - webjprgm
干净利落的副本,再加上合理的期望,可以超出URL大小限制。 - YvesLeBorg

16

这段代码将会把一个 base64 编码的字符串显示为图片:

NSString *str = @"data:image/jpg;base64,";
str = [str stringByAppendingString:restauInfo.picture];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];

restauInfo.picture是一个包含base64编码JPG的NSString。

在我的情况下,“restauInfo.picture”的值来自数据库。


我通过masche的帖子和ipmcc的评论弄清楚了这个问题。因此,我决定写一个新的答案,并提供可以直接复制的代码 - 希望这能帮到你。 - Thorsten Niehues

8
你可以按照以下方式进行操作:
(UIImage *)decodeBase64ToImage:(NSString *)strEncodeData {
  NSData *data = [[NSData alloc]initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters];
  return [UIImage imageWithData:data];
}

然后像这样调用:

UIImage *image = [self decodeBase64ToImage:dataString];

4
  1. 将Base64解码为原始二进制数据。这里需要自己完成,你可能会发现NSStringcStringUsingEncoding:方法很有用。
  2. 使用dataWithBytes:length:创建NSData实例。
  3. 使用[UIImage imageWithData:]加载它。

2

Swift 4+

let base64EncodedString = "" // Your Base64 Encoded String
if let imageData = Data(base64Encoded: base64EncodedString) {
                let image = UIImage(data: imageData)
                self.imageView.image = image
            }

2

感谢 porneL

我通过谷歌找到了一个 Base64 脚本: Base64.m

然后我稍微修改了一下,就得到了一个工作的测试代码:

NSString * base64img = @"R0lGODlhDAAMALMBAP8AAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAUKAAEALAAAAAAMAAwAQAQZMMhJK7iY4p3nlZ8XgmNlnibXdVqolmhcRQA7";
base64Data = [base64img dataUsingEncoding:NSASCIIStringEncoding];
base64Bytes = [base64Data bytes];
mutableData = [NSMutableData dataWithCapacity:[base64Data length]];
lentext = [base64Data length];

while( YES ) {
       if( ixtext >= lentext ) break;
       ch = base64Bytes[ixtext++];
       flignore = NO;

       if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A';
       else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26;
       else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52;
    else if( ch == '+' ) ch = 62;
       else if( ch == '=' ) flendtext = YES;
       else if( ch == '/' ) ch = 63;
       else flignore = YES;

       if( ! flignore ) {
        short ctcharsinbuf = 3;
        BOOL flbreak = NO;

        if( flendtext ) {
            if( ! ixinbuf ) break;
            if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1;
            else ctcharsinbuf = 2;
            ixinbuf = 3;
            flbreak = YES;
        }

        inbuf [ixinbuf++] = ch;

        if( ixinbuf == 4 ) {
            ixinbuf = 0;
            outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 );
            outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 );
            outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F );

            for( i = 0; i < ctcharsinbuf; i++ )
                [mutableData appendBytes:&outbuf[i] length:1];
        }

        if( flbreak )  break;
       }
}


//Finally I can access my image data:
aUIImageView.image = [UIImage imageWithData: [NSData dataWithData:mutableData]];

2

Objective-C

NSString *plainString = @"foo";

编码
NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
NSLog(@"%@", base64String);  

解码

NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(@"%@", decodedString); 

选项

NSURL *URL = [NSURL URLWithString:
  [NSString stringWithFormat:@"data:application/octet-stream;base64,%@",
       base64String]];

 return [NSData dataWithContentsOfURL:URL];

Swift

let plainString = "foo"

编码

let plainData = (plainString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
let base64String = plainData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.fromRaw(0)!)
println(base64String) 

解码

let decodedData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions.fromRaw(0)!)
let decodedString = NSString(data: decodedData, encoding: NSUTF8StringEncoding)    
println(decodedString) // foo

1
在我的情况下,这里提出的@Masche的解决方案有效。由于我需要在Swift 2.0中使用它,因此:
let url = NSURL(string: imageString)
let data = NSData.init(contentsOfURL: url!)
let image = UIImage(data: imageData)

1

如果有人正在寻找基于Jonathan M提供的Objective-C答案实现此操作的Swift代码,这里是:

var data = NSData (base64EncodedString: base64String, options: NSDataBase64DecodingOptions(0))
var image = UIImage(data: data!)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接