Skip to content

Commit

Permalink
Add WebP format support (fix SDWebImage#410)
Browse files Browse the repository at this point in the history
How awesome is that?! =)
  • Loading branch information
Olivier Poitrey committed Jun 7, 2013
1 parent 1dbb79f commit 04fa4c9
Show file tree
Hide file tree
Showing 9 changed files with 381 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "Vendors/libwebp"]
path = Vendors/libwebp
url = http://git.chromium.org/webm/libwebp.git
2 changes: 2 additions & 0 deletions Examples/SDWebImage Demo/MasterViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
action:@selector(flushCache)];
_objects = [NSArray arrayWithObjects:
@"http://assets.sbnation.com/assets/2512203/dogflops.gif",
@"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp",
@"http://www.ioncannon.net/wp-content/uploads/2011/06/test9.webp",
@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.jpg?20120509154705",
@"http://static2.dmcdn.net/static/video/629/228/44822926:jpeg_preview_small.jpg?20120509181018",
@"http://static2.dmcdn.net/static/video/116/367/44763611:jpeg_preview_small.jpg?20120509101749",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ It provides:
- An asynchronous image downloader
- An asynchronous memory + disk image caching with automatic cache expiration handling
- Animated GIF support
- WebP format support
- A background image decompression
- A guarantee that the same URL won't be downloaded several times
- A guarantee that bogus URLs won't be retried again and again
Expand Down
290 changes: 290 additions & 0 deletions SDWebImage.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion SDWebImage/SDWebImageDownloader.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ - (id)init
_downloadQueue = NSOperationQueue.new;
_downloadQueue.maxConcurrentOperationCount = 2;
_URLCallbacks = NSMutableDictionary.new;
_HTTPHeaders = [NSMutableDictionary dictionaryWithObject:@"image/*" forKey:@"Accept"];
_HTTPHeaders = [NSMutableDictionary dictionaryWithObject:@"image/webp,image/*;q=0.8" forKey:@"Accept"];
_barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT);
}
return self;
Expand Down
6 changes: 6 additions & 0 deletions SDWebImage/UIImage+MultiFormat.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "UIImage+MultiFormat.h"
#import "UIImage+GIF.h"
#import "UIImage+WebP.h"

@implementation UIImage (MultiFormat)

Expand All @@ -24,6 +25,11 @@ + (UIImage *)sd_imageWithData:(NSData *)data
image = [[UIImage alloc] initWithData:data];
}

if (!image) // TODO: detect webp signature
{
image = [UIImage sd_imageWithWebPData:data];
}

return image;
}

Expand Down
15 changes: 15 additions & 0 deletions SDWebImage/UIImage+WebP.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// UIImage+WebP.h
// SDWebImage
//
// Created by Olivier Poitrey on 07/06/13.
// Copyright (c) 2013 Dailymotion. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIImage (WebP)

+ (UIImage *)sd_imageWithWebPData:(NSData *)data;

@end
62 changes: 62 additions & 0 deletions SDWebImage/UIImage+WebP.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// UIImage+WebP.m
// SDWebImage
//
// Created by Olivier Poitrey on 07/06/13.
// Copyright (c) 2013 Dailymotion. All rights reserved.
//

#import "UIImage+WebP.h"
#import "webp/decode.h"

// Callback for CGDataProviderRelease
static void FreeImageData(void *info, const void *data, size_t size)
{
free((void *)data);
}

@implementation UIImage (WebP)

+ (UIImage *)sd_imageWithWebPData:(NSData *)data
{
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config))
{
return nil;
}

config.output.colorspace = MODE_rgbA;
config.options.use_threads = 1;

// Decode the WebP image data into a RGBA value array.
if (WebPDecode(data.bytes, data.length, &config) != VP8_STATUS_OK)
{
return nil;
}

int width = config.input.width;
int height = config.input.height;
if (config.options.use_scaling)
{
width = config.options.scaled_width;
height = config.options.scaled_height;
}

// Construct a UIImage from the decoded RGBA value array.
CGDataProviderRef provider =
CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);

UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);

return image;
}

@end
1 change: 1 addition & 0 deletions Vendors/libwebp
Submodule libwebp added at c2113a

0 comments on commit 04fa4c9

Please sign in to comment.