Skip to content
This repository has been archived by the owner on May 3, 2021. It is now read-only.

Commit

Permalink
Add DFCompositeImageDecoder, DFAnimatedImageDecoder, DFWebPImageDecoder
Browse files Browse the repository at this point in the history
  • Loading branch information
kean committed Sep 26, 2015
1 parent 12869c4 commit 2aac084
Show file tree
Hide file tree
Showing 13 changed files with 135 additions and 90 deletions.
10 changes: 8 additions & 2 deletions Demo/DFImageManager.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Demo/Tests/Source/TDFImageFormats.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ @implementation TDFImageFormats
- (void)testThatWebPIsDecoded {
NSData *data = [self _webpImageData];
XCTAssertEqual(data.length, 118042);
XCTAssertTrue([UIImage df_isWebPData:data]);
UIImage *image = [UIImage df_imageWithWebPData:data];
id<DFImageDecoding> decoder = [DFWebPImageDecoder new];
UIImage *image = [decoder imageWithData:data partial:NO];
XCTAssertNotNil(image);
XCTAssertEqual(image.size.width, 768);
XCTAssertEqual(image.size.height, 768);
Expand Down
9 changes: 9 additions & 0 deletions Pod/Source/Core/Processing/DFImageDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@
+ (void)setSharedDecoder:(nullable id<DFImageDecoding>)sharedDecoder;

@end


/*! Composes image decoders.
*/
@interface DFCompositeImageDecoder : NSObject <DFImageDecoding>

- (nonnull instancetype)initWithDecoders:(nonnull NSArray <id<DFImageDecoding>> *)decoders;

@end
57 changes: 33 additions & 24 deletions Pod/Source/Core/Processing/DFImageDecoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,7 @@

@implementation DFImageDecoder

#pragma mark <DFImageDecoding>

- (nullable UIImage *)imageWithData:(nonnull NSData *)data partial:(BOOL)partial {
if (!data.length) {
return nil;
}
#if __has_include("DFImageManagerKit+GIF.h")
if ([DFAnimatedImage isAnimatedGIFData:data]) {
UIImage *image = [DFAnimatedImage animatedImageWithGIFData:data];
if (image) {
return image;
}
}
#endif

#if __has_include("DFImageManagerKit+WebP.h")
if ([UIImage df_isWebPData:data] && !partial) {
UIImage *image = [UIImage df_imageWithWebPData:data];
if (image) {
return image;
}
}
#endif

#if __IPHONE_OS_VERSION_MIN_REQUIRED && !__WATCH_OS_VERSION_MIN_REQUIRED
return [UIImage imageWithData:data scale:[UIScreen mainScreen].scale];
#else
Expand All @@ -57,7 +34,15 @@ - (nullable UIImage *)imageWithData:(nonnull NSData *)data partial:(BOOL)partial
static OSSpinLock _lock = OS_SPINLOCK_INIT;

+ (void)initialize {
[self setSharedDecoder:[DFImageDecoder new]];
NSMutableArray *decoders = [NSMutableArray new];
#if __has_include("DFImageManagerKit+GIF.h")
[decoders addObject:[DFAnimatedImageDecoder new]];
#endif
#if __has_include("DFImageManagerKit+WebP.h")
[decoders addObject:[DFWebPImageDecoder new]];
#endif
[decoders addObject:[DFImageDecoder new]];
[self setSharedDecoder:[[DFCompositeImageDecoder alloc] initWithDecoders:decoders]];
}

+ (nullable id<DFImageDecoding>)sharedDecoder {
Expand All @@ -75,3 +60,27 @@ + (void)setSharedDecoder:(nullable id<DFImageDecoding>)sharedDecoder {
}

@end


@implementation DFCompositeImageDecoder {
NSArray <id<DFImageDecoding>> *_decoders;
}

- (instancetype)initWithDecoders:(NSArray<id<DFImageDecoding>> *)decoders {
if (self = [super init]) {
_decoders = [NSArray arrayWithArray:decoders];
}
return self;
}

- (UIImage *)imageWithData:(NSData *)data partial:(BOOL)partial {
for (id<DFImageDecoding> decoder in _decoders) {
UIImage *image = [decoder imageWithData:data partial:partial];
if (image) {
return image;
}
}
return nil;
}

@end
14 changes: 3 additions & 11 deletions Pod/Source/GIF/DFAnimatedImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,16 @@
#import <UIKit/UIKit.h>
#import <FLAnimatedImage/FLAnimatedImage.h>

/*! The DFAnimatedImage subclasses UIImage and represents a poster image for the underlying animated image. It is a regular UIImage that doesn't override any of the native UIImage behaviours it can be used anywhere where a regular `UIImage` can be used.
/*! The DFAnimatedImage subclasses UIImage and represents a poster image for the underlying animated image. It can be used anywhere where a regular `UIImage` can be used.
*/
@interface DFAnimatedImage : UIImage

/* The animated image that the receiver was initialized with. An `FLAnimatedImage`'s job is to deliver frames in a highly performant way and works in conjunction with `FLAnimatedImageView`.
*/
@property (nonnull, nonatomic, readonly) FLAnimatedImage *animatedImage;

/*! Initializes the DFAnimatedImage with an instance of FLAnimatedImage class.
/*! Initializes the DFAnimatedImage with an instance of FLAnimatedImage class and poster image.
*/
- (nonnull instancetype)initWithAnimatedImage:(nonnull FLAnimatedImage *)animatedImage NS_DESIGNATED_INITIALIZER;

/*! Returns the DFAnimatedImage object with an instance of FLAnimatedImage class created from a given data.
*/
+ (nullable instancetype)animatedImageWithGIFData:(nullable NSData *)data;

/*! Returns YES if the data represents an animated GIF.
*/
+ (BOOL)isAnimatedGIFData:(nullable NSData *)data;
- (nonnull instancetype)initWithAnimatedImage:(nonnull FLAnimatedImage *)animatedImage posterImage:(nonnull CGImageRef)posterImage posterImageScale:(CGFloat)posterImageScale posterImageOrientation:(UIImageOrientation)posterImageOrientation NS_DESIGNATED_INITIALIZER;

@end
21 changes: 2 additions & 19 deletions Pod/Source/GIF/DFAnimatedImage.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,11 @@

@implementation DFAnimatedImage

- (instancetype)initWithAnimatedImage:(FLAnimatedImage *)animatedImage {
if (self = [super initWithCGImage:animatedImage.posterImage.CGImage]) {
- (instancetype)initWithAnimatedImage:(FLAnimatedImage *)animatedImage posterImage:(CGImageRef)posterImage posterImageScale:(CGFloat)posterImageScale posterImageOrientation:(UIImageOrientation)posterImageOrientation {
if (self = [super initWithCGImage:posterImage scale:posterImageScale orientation:posterImageOrientation]) {
_animatedImage = animatedImage;
}
return self;
}

+ (nullable instancetype)animatedImageWithGIFData:(nullable NSData *)data {
FLAnimatedImage *animatedImage = [FLAnimatedImage animatedImageWithGIFData:data];
return animatedImage ? [[DFAnimatedImage alloc] initWithAnimatedImage:animatedImage] : nil;
}

/*! See https://en.wikipedia.org/wiki/List_of_file_signatures
*/
+ (BOOL)isAnimatedGIFData:(nullable NSData *)data {
const NSInteger sigLength = 3;
if (data.length < sigLength) {
return NO;
}
uint8_t sig[sigLength];
[data getBytes:&sig length:sigLength];
return sig[0] == 0x47 && sig[1] == 0x49 && sig[2] == 0x46;
}

@end
9 changes: 9 additions & 0 deletions Pod/Source/GIF/DFAnimatedImageDecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// The MIT License (MIT)
//
// Copyright (c) 2015 Alexander Grebenyuk (github.com/kean).

#import <UIKit/UIKit.h>
#import "DFImageDecoding.h"

@interface DFAnimatedImageDecoder : NSObject <DFImageDecoding>
@end
38 changes: 38 additions & 0 deletions Pod/Source/GIF/DFAnimatedImageDecoder.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// The MIT License (MIT)
//
// Copyright (c) 2015 Alexander Grebenyuk (github.com/kean).

#import "DFAnimatedImageDecoder.h"
#import "DFAnimatedImage.h"

@implementation DFAnimatedImageDecoder

- (UIImage *)imageWithData:(NSData *)data partial:(BOOL)partial {
if (![self _isGIFData:data]) {
return nil;
}
FLAnimatedImage *animatedImage = [FLAnimatedImage animatedImageWithGIFData:data];
if (!animatedImage) {
return nil;
}
UIImage *posterImage = animatedImage.posterImage;
CGImageRef posterImageRef = posterImage.CGImage;
if (!posterImageRef) {
return nil;
}
return [[DFAnimatedImage alloc] initWithAnimatedImage:animatedImage posterImage:posterImageRef posterImageScale:posterImage.scale posterImageOrientation:posterImage.imageOrientation];
}

/*! See https://en.wikipedia.org/wiki/List_of_file_signatures
*/
- (BOOL)_isGIFData:(NSData *)data {
const NSInteger sigLength = 3;
if (data.length < sigLength) {
return NO;
}
uint8_t sig[sigLength];
[data getBytes:&sig length:sigLength];
return sig[0] == 0x47 && sig[1] == 0x49 && sig[2] == 0x46;
}

@end
1 change: 1 addition & 0 deletions Pod/Source/GIF/DFImageManagerKit+GIF.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
// Copyright (c) 2015 Alexander Grebenyuk (github.com/kean).

#import "DFAnimatedImage.h"
#import "DFAnimatedImageDecoder.h"
2 changes: 1 addition & 1 deletion Pod/Source/WebP/DFImageManagerKit+WebP.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
//
// Copyright (c) 2015 Alexander Grebenyuk (github.com/kean).

#import "UIImage+DFImageManagerWebP.h"
#import "DFWebPImageDecoder.h"
9 changes: 9 additions & 0 deletions Pod/Source/WebP/DFWebPImageDecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// The MIT License (MIT)
//
// Copyright (c) 2015 Alexander Grebenyuk (github.com/kean).

#import <UIKit/UIKit.h>
#import "DFImageDecoding.h"

@interface DFWebPImageDecoder : NSObject <DFImageDecoding>
@end
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,22 @@
//
// Copyright (c) 2015 Alexander Grebenyuk (github.com/kean).

#import "UIImage+DFImageManagerWebP.h"
#import "DFWebPImageDecoder.h"
#import <libwebp/webp/decode.h>

@implementation UIImage (DFImageManagerWebP)

+ (BOOL)df_isWebPData:(nullable NSData *)data {
const NSInteger sigLength = 12;
if (data.length < sigLength) {
return NO;
}
uint8_t sig[sigLength];
[data getBytes:&sig length:sigLength];
// RIFF----WEBP
return (sig[0] == 0x52 && sig[1] == 0x49 && sig[2] == 0x46 && sig[3] == 0x46 && sig[8] == 0x57 && sig[9] == 0x45 && sig[10] == 0x42 && sig[11] == 0x50);
}
@implementation DFWebPImageDecoder

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

+ (nullable UIImage *)df_imageWithWebPData:(nullable NSData *)data {
- (UIImage *)imageWithData:(NSData *)data partial:(BOOL)partial {
if (partial) {
return nil;
}
if (![self _isWebPData:data]) {
return nil;
}
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config)) {
return nil;
Expand Down Expand Up @@ -55,4 +50,15 @@ + (nullable UIImage *)df_imageWithWebPData:(nullable NSData *)data {
return image;
}

- (BOOL)_isWebPData:(NSData *)data {
const NSInteger sigLength = 12;
if (data.length < sigLength) {
return NO;
}
uint8_t sig[sigLength];
[data getBytes:&sig length:sigLength];
// RIFF----WEBP
return (sig[0] == 0x52 && sig[1] == 0x49 && sig[2] == 0x46 && sig[3] == 0x46 && sig[8] == 0x57 && sig[9] == 0x45 && sig[10] == 0x42 && sig[11] == 0x50);
}

@end
17 changes: 0 additions & 17 deletions Pod/Source/WebP/UIImage+DFImageManagerWebP.h

This file was deleted.

0 comments on commit 2aac084

Please sign in to comment.