Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Exif orientation unwinding #596

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 2 additions & 6 deletions Examples/Example-Shared/Kitten.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@
#import <Cocoa/Cocoa.h>
#endif

@interface Kitten : NSObject
#import "ImageSource.h"

@property (nonatomic, strong) NSURL *imageURL;
@property (nonatomic, strong) id dominantColor;
@property (nonatomic, assign) CGSize imageSize;

+ (void)fetchKittenForWidth:(CGFloat)width completion:(void (^)(NSArray *kittens))completion;
@interface Kitten : NSObject <ImageSource>

@end
6 changes: 4 additions & 2 deletions Examples/Example-Shared/Kitten.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ - (CGSize)CGSizeValue

#endif


@implementation Kitten
@synthesize imageURL;
@synthesize dominantColor;
@synthesize imageSize;

+ (void)fetchKittenForWidth:(CGFloat)width completion:(void (^)(NSArray *kittens))completion
+ (void)fetchImagesForWidth:(CGFloat)width completion:(void (^)(NSArray *images))completion
{
NSArray *kittenURLs = @[[NSURL URLWithString:@"https://i.pinimg.com/736x/92/5d/5a/925d5ac74db0dcfabc238e1686e31d16.jpg"],
[NSURL URLWithString:@"https://i.pinimg.com/736x/ff/b3/ae/ffb3ae40533b7f9463cf1c04d7ab69d1.jpg"],
Expand Down
8 changes: 8 additions & 0 deletions Examples/Example/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
68B3850B1B5572BF004EB26F /* ProgressiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B3850A1B5572BF004EB26F /* ProgressiveViewController.m */; };
68B3850E1B5577D4004EB26F /* DegradedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B3850D1B5577D4004EB26F /* DegradedViewController.m */; };
9D9328E51C3D4CC200E1F1D3 /* Kitten.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9328E41C3D4CC200E1F1D3 /* Kitten.m */; };
FABFA41B262938420074812A /* Oriented.m in Sources */ = {isa = PBXBuildFile; fileRef = FABFA41A262938420074812A /* Oriented.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -68,6 +69,9 @@
A5DEC9B706184109844D57E2 /* PINRemoteImage.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PINRemoteImage.podspec; path = ../PINRemoteImage.podspec; sourceTree = "<group>"; };
E2B84DF860DF48B5B22537B6 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
F30E394524AE56850067A777 /* PINRemoteImage copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PINRemoteImage copy-Info.plist"; path = "/Users/garrettmoon/code/PINRemoteImage/Examples/Example/PINRemoteImage copy-Info.plist"; sourceTree = "<absolute>"; };
FABFA419262938420074812A /* Oriented.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Oriented.h; sourceTree = "<group>"; };
FABFA41A262938420074812A /* Oriented.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Oriented.m; sourceTree = "<group>"; };
FABFA41D262938590074812A /* ImageSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageSource.h; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -122,8 +126,11 @@
6003F593195388D20070C39A /* PINRemoteImage */ = {
isa = PBXGroup;
children = (
FABFA41D262938590074812A /* ImageSource.h */,
9D9328E31C3D4CC200E1F1D3 /* Kitten.h */,
9D9328E41C3D4CC200E1F1D3 /* Kitten.m */,
FABFA419262938420074812A /* Oriented.h */,
FABFA41A262938420074812A /* Oriented.m */,
6003F59C195388D20070C39A /* PINAppDelegate.h */,
6003F59D195388D20070C39A /* PINAppDelegate.m */,
6003F59F195388D20070C39A /* Main.storyboard */,
Expand Down Expand Up @@ -287,6 +294,7 @@
buildActionMask = 2147483647;
files = (
68B385081B557116004EB26F /* WebPViewController.m in Sources */,
FABFA41B262938420074812A /* Oriented.m in Sources */,
68B3850B1B5572BF004EB26F /* ProgressiveViewController.m in Sources */,
9D9328E51C3D4CC200E1F1D3 /* Kitten.m in Sources */,
6003F59E195388D20070C39A /* PINAppDelegate.m in Sources */,
Expand Down
23 changes: 23 additions & 0 deletions Examples/Example/PINRemoteImage/ImageSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// ImageSource.h
// Example
//
// Created by Alex Quinlivan on 16/04/21.
// Copyright © 2021 Garrett Moon. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@protocol ImageSource <NSObject>

@property (nonatomic, strong) NSURL *imageURL;
@property (nonatomic, strong) id dominantColor;
@property (nonatomic, assign) CGSize imageSize;

+ (void)fetchImagesForWidth:(CGFloat)width completion:(void (^)(NSArray *images))completion;

@end

NS_ASSUME_NONNULL_END
25 changes: 25 additions & 0 deletions Examples/Example/PINRemoteImage/Oriented.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Oriented.h
// Example
//
// Created by Alex Quinlivan on 16/04/21.
// Copyright © 2021 Garrett Moon. All rights reserved.
//

#import <Foundation/Foundation.h>

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif

#import "ImageSource.h"

NS_ASSUME_NONNULL_BEGIN

@interface Oriented : NSObject <ImageSource>

@end

NS_ASSUME_NONNULL_END
130 changes: 130 additions & 0 deletions Examples/Example/PINRemoteImage/Oriented.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//
// Oriented.m
// Example
//
// Created by Alex Quinlivan on 16/04/21.
// Copyright © 2021 Garrett Moon. All rights reserved.
//

#import "Oriented.h"

#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED

@interface NSValue (PINiOSMapping)
+ (NSValue *)valueWithCGSize:(CGSize)size;
- (CGSize)CGSizeValue;
@end

@implementation NSValue (PINiOSMapping)

+ (NSValue *)valueWithCGSize:(CGSize)size
{
return [self valueWithSize:size];
}

- (CGSize)CGSizeValue
{
return self.sizeValue;
}

@end

#endif

@implementation Oriented
@synthesize imageURL;
@synthesize dominantColor;
@synthesize imageSize;

+ (void)fetchImagesForWidth:(CGFloat)width completion:(void (^)(NSArray *images))completion
{
NSArray *orientedURLs = @[[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_0.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_1.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_2.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_3.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_4.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_5.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_6.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_7.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Landscape_8.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_0.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_1.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_2.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_3.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_4.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_5.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_6.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_7.jpg?raw=true"],
[NSURL URLWithString:@"https://github.com/AlexQuinlivan/exif-orientation-examples/blob/master/Portrait_8.jpg?raw=true"],
];

NSArray *orientedSizes = @[[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(450, 300)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
[NSValue valueWithCGSize:CGSizeMake(300, 450)],
];

dispatch_group_t group = dispatch_group_create();
NSMutableArray *orienteds = [[NSMutableArray alloc] init];

CGFloat scale = 1;
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
scale = [[UIScreen mainScreen] scale];
#else
scale = [[NSScreen mainScreen] backingScaleFactor];
#endif
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSInteger count = 0;
for (NSInteger idx = 0; idx < 500; idx++) {
Oriented *oriented = [[Oriented alloc] init];
CGFloat r = (rand() % 255) / 255.0f;
CGFloat g = (rand() % 255) / 255.0f;
CGFloat b = (rand() % 255) / 255.0f;
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
oriented.dominantColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0f];
#else
oriented.dominantColor = [NSColor colorWithRed:r green:g blue:b alpha:1.0f];
#endif

NSUInteger orientedIdx = rand() % 18;

CGSize orientedSize = [orientedSizes[orientedIdx] CGSizeValue];
NSInteger orientedSizeWidth = orientedSize.width;
NSInteger orientedSizeHeight = orientedSize.height;

if (orientedSizeWidth > (width * scale)) {
orientedSizeHeight = ((width * scale) / orientedSizeWidth) * orientedSizeHeight;
orientedSizeWidth = (width * scale);
}

oriented.imageURL = orientedURLs[orientedIdx];
oriented.imageSize = CGSizeMake(orientedSizeWidth / scale, orientedSizeHeight / scale);

dispatch_sync(dispatch_get_main_queue(), ^{
[orienteds addObject:oriented];
});
count++;
}
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
if (completion) {
completion(orienteds);
}
});
}

@end
34 changes: 23 additions & 11 deletions Examples/Example/PINRemoteImage/PINViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
#import <PINRemoteImage/PINImageView+PINRemoteImage.h>
#import <PINRemoteImage/PINRemoteImageCaching.h>

#import "ImageSource.h"
#import "Kitten.h"
#import "Oriented.h"

@interface PINViewController () <UICollectionViewDataSource, UICollectionViewDelegate>

@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) NSMutableArray *kittens;
@property (nonatomic, strong) NSMutableArray *images;

@end

Expand All @@ -40,8 +42,18 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder

- (void)fetchKittenImages
{
[Kitten fetchKittenForWidth:CGRectGetWidth(self.collectionView.frame) completion:^(NSArray *kittens) {
[self.kittens addObjectsFromArray:kittens];
[Kitten fetchImagesForWidth:CGRectGetWidth(self.collectionView.frame) completion:^(NSArray *kittens) {
[self.images removeAllObjects];
[self.images addObjectsFromArray:kittens];
[self.collectionView reloadData];
}];
}

- (void)fetchOrientedImages
{
[Oriented fetchImagesForWidth:CGRectGetWidth(self.collectionView.frame) completion:^(NSArray *oriented) {
[self.images removeAllObjects];
[self.images addObjectsFromArray:oriented];
[self.collectionView reloadData];
}];
}
Expand All @@ -56,16 +68,16 @@ - (void)viewDidLoad
[self.collectionView registerClass:[PINImageCell class] forCellWithReuseIdentifier:NSStringFromClass([PINImageCell class])];
[self.view addSubview:self.collectionView];

self.kittens = [[NSMutableArray alloc] init];
[self fetchKittenImages];
self.images = [[NSMutableArray alloc] init];
[self fetchOrientedImages];
}

- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
Kitten *kitten = [self.kittens objectAtIndex:indexPath.item];
return kitten.imageSize;
id<ImageSource> image = [self.images objectAtIndex:indexPath.item];
return image.imageSize;
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
Expand All @@ -75,18 +87,18 @@ - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.kittens.count;
return self.images.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PINImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([PINImageCell class]) forIndexPath:indexPath];
Kitten *kitten = [self.kittens objectAtIndex:indexPath.item];
cell.backgroundColor = kitten.dominantColor;
id<ImageSource> image = [self.images objectAtIndex:indexPath.item];
cell.backgroundColor = image.dominantColor;
cell.imageView.alpha = 0.0f;
__weak PINImageCell *weakCell = cell;

[cell.imageView pin_setImageFromURL:kitten.imageURL
[cell.imageView pin_setImageFromURL:image.imageURL
completion:^(PINRemoteImageManagerResult *result) {
if (result.requestDuration > 0.25) {
[UIView animateWithDuration:0.3 animations:^{
Expand Down
50 changes: 25 additions & 25 deletions Examples/Example/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
PODS:
- libwebp (1.1.0):
- libwebp/demux (= 1.1.0)
- libwebp/mux (= 1.1.0)
- libwebp/webp (= 1.1.0)
- libwebp/demux (1.1.0):
- libwebp (1.2.0):
- libwebp/demux (= 1.2.0)
- libwebp/mux (= 1.2.0)
- libwebp/webp (= 1.2.0)
- libwebp/demux (1.2.0):
- libwebp/webp
- libwebp/mux (1.1.0):
- libwebp/mux (1.2.0):
- libwebp/demux
- libwebp/webp (1.1.0)
- PINCache (3.0.1-beta.8):
- PINCache/Arc-exception-safe (= 3.0.1-beta.8)
- PINCache/Core (= 3.0.1-beta.8)
- PINCache/Arc-exception-safe (3.0.1-beta.8):
- libwebp/webp (1.2.0)
- PINCache (3.0.3):
- PINCache/Arc-exception-safe (= 3.0.3)
- PINCache/Core (= 3.0.3)
- PINCache/Arc-exception-safe (3.0.3):
- PINCache/Core
- PINCache/Core (3.0.1-beta.8):
- PINOperation (~> 1.1.1)
- PINOperation (1.1.2)
- PINRemoteImage (3.0.0):
- PINRemoteImage/PINCache (= 3.0.0)
- PINRemoteImage/Core (3.0.0):
- PINCache/Core (3.0.3):
- PINOperation (~> 1.2.1)
- PINOperation (1.2.1)
- PINRemoteImage (3.0.3):
- PINRemoteImage/PINCache (= 3.0.3)
- PINRemoteImage/Core (3.0.3):
- PINOperation
- PINRemoteImage/PINCache (3.0.0):
- PINCache (= 3.0.1-beta.8)
- PINRemoteImage/PINCache (3.0.3):
- PINCache (~> 3.0.3)
- PINRemoteImage/Core
- PINRemoteImage/WebP (3.0.0):
- PINRemoteImage/WebP (3.0.3):
- libwebp
- PINRemoteImage/Core

Expand All @@ -43,11 +43,11 @@ EXTERNAL SOURCES:
:path: "../../"

SPEC CHECKSUMS:
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
PINCache: 534fd41d358d828dfdf227a0d327f3673a65e20b
PINOperation: 24b774353ca248fcf87d67b2d61eef42087c125a
PINRemoteImage: e2b89e19fb6e77ffc099f9d9f3b3fe1745e3f9f9
libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0
PINCache: 7a8fc1a691173d21dbddbf86cd515de6efa55086
PINOperation: 00c935935f1e8cf0d1e2d6b542e75b88fc3e5e20
PINRemoteImage: f1295b29f8c5e640e25335a1b2bd9d805171bd01

PODFILE CHECKSUM: 6be36f4931404348fd582ddb8bd0b80c534561ac

COCOAPODS: 1.9.3
COCOAPODS: 1.10.1