Skip to content

Commit 4c7560f

Browse files
author
Michael Potter
committed
Demonstrate all image format styles in demo application
1 parent 91c9e38 commit 4c7560f

File tree

11 files changed

+230
-59
lines changed

11 files changed

+230
-59
lines changed

FastImageCache/FICImageCache.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,20 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage);
162162
*/
163163
- (void)deleteImageForEntity:(id <FICEntity>)entity withFormatName:(NSString *)formatName;
164164

165+
///-------------------------------
166+
/// @name Canceling Image Requests
167+
///-------------------------------
168+
169+
/**
170+
Cancels an active request for an image from the image cache.
171+
172+
@param entity The entity that uniquely identifies the source image.
173+
174+
@param formatName The format name that uniquely identifies which image table to look in for the cached image.
175+
176+
@discussion After this method is called, the completion block of the <[FICImageCacheDelegate imageCache:wantsSourceImageForEntity:withFormatName:completionBlock:]> delegate
177+
method for the corresponding entity, if called, does nothing.
178+
*/
165179
- (void)cancelImageRetrievalForEntity:(id <FICEntity>)entity withFormatName:(NSString *)formatName;
166180

167181
///-----------------------------------
@@ -229,9 +243,22 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage);
229243

230244
@optional
231245

246+
/**
247+
This method is called on the delegate when the image cache has received an image retrieval cancellation request.
248+
249+
@param imageCache The image cache that has received the image retrieval cancellation request.
250+
251+
@param entity The entity that uniquely identifies the source image.
252+
253+
@param formatName The format name that uniquely identifies which image table to look in for the cached image.
254+
255+
@discussion When an image retrieval cancellation request is made to the image cache, it removes all of its internal bookkeeping for requests. However, it is still the
256+
delegate's responsibility to cancel whatever logic is it performing to provide a source image to the cache (e.g., a network request).
257+
258+
@see [FICImageCache cancelImageRetrievalForEntity:withFormatName:]
259+
*/
232260
- (void)imageCache:(FICImageCache *)imageCache cancelImageLoadingForEntity:(id <FICEntity>)entity withFormatName:(NSString *)formatName;
233261

234-
235262
/**
236263
This method is called on the delegate to determine whether or not all formats in a family should be processed right now.
237264

FastImageCache/FICImageFormat.h

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,19 @@ typedef NS_OPTIONS(NSUInteger, FICImageFormatDevices) {
1515
FICImageFormatDevicePad = 1 << UIUserInterfaceIdiomPad,
1616
};
1717

18-
/**
19-
`FICImageFormat` acts as a definition for the types of images that are stored in the image cache. Each image format must have a unique name, but multiple formats can belong to the same family.
20-
All images associated with a particular format must have the same image dimentions and opacity preference. You can define the maximum number of entries that an image format can accommodate to
21-
prevent the image cache from consuming too much disk space. Each `<FICImageTable>` managed by the image cache is associated with a single image format.
22-
*/
23-
24-
2518
typedef NS_OPTIONS(NSUInteger, FICImageFormatStyle) {
2619
FICImageFormatStyle32BitBGRA,
2720
FICImageFormatStyle32BitBGR,
2821
FICImageFormatStyle16BitBGR,
2922
FICImageFormatStyle8BitGrayscale,
3023
};
3124

25+
/**
26+
`FICImageFormat` acts as a definition for the types of images that are stored in the image cache. Each image format must have a unique name, but multiple formats can belong to the same family.
27+
All images associated with a particular format must have the same image dimentions and opacity preference. You can define the maximum number of entries that an image format can accommodate to
28+
prevent the image cache from consuming too much disk space. Each `<FICImageTable>` managed by the image cache is associated with a single image format.
29+
*/
30+
3231
@interface FICImageFormat : NSObject <NSCopying>
3332

3433
///------------------------------
@@ -61,17 +60,21 @@ typedef NS_OPTIONS(NSUInteger, FICImageFormatStyle) {
6160
@property (nonatomic, assign) CGSize imageSize;
6261

6362
/**
64-
The size, in pixels, of the images stored in the image table created by this format. This takes into account the screen scale.
63+
A bitmask of type `<FICImageFormatStyle>` that defines the style of the image format.
64+
65+
`FICImageFormatStyle` has the following values:
66+
67+
- `FICImageFormatStyle32BitBGRA`: Full-color image format with alpha channel. 8 bits per color component, and 8 bits for the alpha channel.
68+
- `FICImageFormatStyle32BitBGR`: Full-color image format with no alpha channel. 8 bits per color component. The remaining 8 bits are unused.
69+
- `FICImageFormatStyle16BitBGR`: Reduced-color image format with no alpha channel. 5 bits per color component. The remaining bit is unused.
70+
- `FICImageFormatStyle8BitGrayscale`: Grayscale-only image format with no alpha channel.
71+
72+
If you are storing images without an alpha component (e.g., JPEG images), then you should use the `FICImageFormatStyle32BitBGR` style for performance reasons. If you are storing very small images or images
73+
without a great deal of color complexity, the `FICImageFormatStyle16BitBGR` style may be sufficient and uses less disk space than the 32-bit styles use. For grayscale-only image formats, the
74+
`FICImageFormatStyle8BitGrayscale` style is sufficient and further reduces disk space usage.
6575
*/
66-
@property (nonatomic, assign, readonly) CGSize pixelSize;
67-
6876
@property (nonatomic, assign) FICImageFormatStyle style;
6977

70-
@property (nonatomic, readonly) CGBitmapInfo bitmapInfo;
71-
@property (nonatomic, readonly) NSInteger bytesPerPixel;
72-
@property (nonatomic, readonly) NSInteger bitsPerComponent;
73-
@property (nonatomic, readonly) BOOL isGrayscale;
74-
7578
/**
7679
The maximum number of entries that an image table can contain for this image format.
7780
@@ -86,6 +89,31 @@ typedef NS_OPTIONS(NSUInteger, FICImageFormatStyle) {
8689
*/
8790
@property (nonatomic, assign) FICImageFormatDevices devices;
8891

92+
/**
93+
The size, in pixels, of the images stored in the image table created by this format. This takes into account the screen scale.
94+
*/
95+
@property (nonatomic, assign, readonly) CGSize pixelSize;
96+
97+
/**
98+
The bitmap info associated with the images created with this image format.
99+
*/
100+
@property (nonatomic, assign, readonly) CGBitmapInfo bitmapInfo;
101+
102+
/**
103+
The number of bytes each pixel of an image created with this image format occupies.
104+
*/
105+
@property (nonatomic, assign, readonly) NSInteger bytesPerPixel;
106+
107+
/**
108+
The number of bits each pixel component (e.g., blue, green, red color channels) uses for images created with this image format.
109+
*/
110+
@property (nonatomic, assign, readonly) NSInteger bitsPerComponent;
111+
112+
/**
113+
Whether or not the the images represented by this image format are grayscale.
114+
*/
115+
@property (nonatomic, assign, readonly) BOOL isGrayscale;
116+
89117
/**
90118
The dictionary representation of this image format.
91119
@@ -106,7 +134,7 @@ typedef NS_OPTIONS(NSUInteger, FICImageFormatStyle) {
106134
107135
@param imageSize The size, in points, of the images stored in the image table created by this format.
108136
109-
@param isOpaque Whether or not the image table's backing bitmap data provider is opaque.
137+
@param style The style of the image format. See the `<style>` property description for more information.
110138
111139
@param maximumCount The maximum number of entries that an image table can contain for this image format.
112140

FastImageCacheDemo/Classes/FICDAppDelegate.m

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,40 @@ @implementation FICDAppDelegate
2626
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
2727
NSMutableArray *mutableImageFormats = [NSMutableArray array];
2828

29-
// Square image format
29+
// Square image formats...
3030
NSInteger squareImageFormatMaximumCount = 400;
3131
FICImageFormatDevices squareImageFormatDevices = FICImageFormatDevicePhone | FICImageFormatDevicePad;
3232

33-
FICImageFormat *squareImageFormat = [FICImageFormat formatWithName:FICDPhotoSquareImageFormatName family:FICDPhotoImageFormatFamily imageSize:FICDPhotoSquareImageSize style:FICImageFormatStyle32BitBGRA
33+
// ...32-bit BGR
34+
FICImageFormat *squareImageFormat32BitBGRA = [FICImageFormat formatWithName:FICDPhotoSquareImage32BitBGRAFormatName family:FICDPhotoImageFormatFamily imageSize:FICDPhotoSquareImageSize style:FICImageFormatStyle32BitBGRA
3435
maximumCount:squareImageFormatMaximumCount devices:squareImageFormatDevices];
3536

36-
[mutableImageFormats addObject:squareImageFormat];
37+
[mutableImageFormats addObject:squareImageFormat32BitBGRA];
38+
39+
// ...32-bit BGR
40+
FICImageFormat *squareImageFormat32BitBGR = [FICImageFormat formatWithName:FICDPhotoSquareImage32BitBGRFormatName family:FICDPhotoImageFormatFamily imageSize:FICDPhotoSquareImageSize style:FICImageFormatStyle32BitBGR
41+
maximumCount:squareImageFormatMaximumCount devices:squareImageFormatDevices];
42+
43+
[mutableImageFormats addObject:squareImageFormat32BitBGR];
44+
45+
// ...16-bit BGR
46+
FICImageFormat *squareImageFormat16BitBGR = [FICImageFormat formatWithName:FICDPhotoSquareImage16BitBGRFormatName family:FICDPhotoImageFormatFamily imageSize:FICDPhotoSquareImageSize style:FICImageFormatStyle16BitBGR
47+
maximumCount:squareImageFormatMaximumCount devices:squareImageFormatDevices];
48+
49+
[mutableImageFormats addObject:squareImageFormat16BitBGR];
50+
51+
// ...8-bit Grayscale
52+
FICImageFormat *squareImageFormat8BitGrayscale = [FICImageFormat formatWithName:FICDPhotoSquareImage8BitGrayscaleFormatName family:FICDPhotoImageFormatFamily imageSize:FICDPhotoSquareImageSize style:FICImageFormatStyle8BitGrayscale
53+
maximumCount:squareImageFormatMaximumCount devices:squareImageFormatDevices];
54+
55+
[mutableImageFormats addObject:squareImageFormat8BitGrayscale];
3756

3857
if ([UIViewController instancesRespondToSelector:@selector(preferredStatusBarStyle)]) {
3958
// Pixel image format
4059
NSInteger pixelImageFormatMaximumCount = 1000;
4160
FICImageFormatDevices pixelImageFormatDevices = FICImageFormatDevicePhone | FICImageFormatDevicePad;
4261

43-
FICImageFormat *pixelImageFormat = [FICImageFormat formatWithName:FICDPhotoPixelImageFormatName family:FICDPhotoImageFormatFamily imageSize:FICDPhotoPixelImageSize style:FICImageFormatStyle32BitBGRA
62+
FICImageFormat *pixelImageFormat = [FICImageFormat formatWithName:FICDPhotoPixelImageFormatName family:FICDPhotoImageFormatFamily imageSize:FICDPhotoPixelImageSize style:FICImageFormatStyle32BitBGR
4463
maximumCount:pixelImageFormatMaximumCount devices:pixelImageFormatDevices];
4564

4665
[mutableImageFormats addObject:pixelImageFormat];

FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
@property (nonatomic, assign, readonly, getter = isDisplayingPhoto) BOOL displayingPhoto;
2020

21-
- (void)showFullscreenPhoto:(FICDPhoto *)photo withThumbnailImageView:(UIImageView *)thumbnailImageView;
21+
- (void)showFullscreenPhoto:(FICDPhoto *)photo forImageFormatName:(NSString *)imageFormatName withThumbnailImageView:(UIImageView *)thumbnailImageView;
2222
- (void)hideFullscreenPhoto;
2323

2424
@end

FastImageCacheDemo/Classes/FICDFullscreenPhotoDisplayController.m

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#import "FICDFullscreenPhotoDisplayController.h"
1010
#import "FICDPhoto.h"
1111

12+
#import <CoreImage/CoreImage.h>
13+
1214
#pragma mark Class Extension
1315

1416
@interface FICDFullscreenPhotoDisplayController () <UIGestureRecognizerDelegate> {
@@ -30,6 +32,8 @@ @interface FICDFullscreenPhotoDisplayController () <UIGestureRecognizerDelegate>
3032
FICDPhoto *_photo;
3133

3234
UITapGestureRecognizer *_tapGestureRecognizer;
35+
36+
CIContext* _CoreImageContext;
3337
}
3438

3539
@end
@@ -90,6 +94,8 @@ - (id)init {
9094

9195
_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapGestureRecognizerStateDidChange)];
9296
[_fullscreenView addGestureRecognizer:_tapGestureRecognizer];
97+
98+
_CoreImageContext = [CIContext contextWithOptions:nil];
9399
}
94100

95101
return self;
@@ -101,7 +107,7 @@ - (void)dealloc {
101107

102108
#pragma mark - Showing and Hiding a Fullscreen Photo
103109

104-
- (void)showFullscreenPhoto:(FICDPhoto *)photo withThumbnailImageView:(UIImageView *)thumbnailImageView {
110+
- (void)showFullscreenPhoto:(FICDPhoto *)photo forImageFormatName:(NSString *)imageFormatName withThumbnailImageView:(UIImageView *)thumbnailImageView {
105111
// Stash away the photo
106112
_photo = photo;
107113

@@ -128,6 +134,20 @@ - (void)showFullscreenPhoto:(FICDPhoto *)photo withThumbnailImageView:(UIImageVi
128134

129135
// Configure the source image view
130136
UIImage *sourceImage = [photo sourceImage];
137+
138+
// Desaturate the source image with Core Image if the image format name is FICDPhotoSquareImage8BitGrayscaleFormatName
139+
if ([imageFormatName isEqualToString:FICDPhotoSquareImage8BitGrayscaleFormatName]) {
140+
CIFilter *colorControlsFilter = [CIFilter filterWithName:@"CIColorControls"];
141+
[colorControlsFilter setValue:[CIImage imageWithCGImage:[sourceImage CGImage]] forKey:kCIInputImageKey];
142+
[colorControlsFilter setValue:[NSNumber numberWithFloat:0] forKey:@"inputSaturation"];
143+
144+
CIImage *outputCIImage = [colorControlsFilter outputImage];
145+
CGImageRef outputImageRef = [_CoreImageContext createCGImage:outputCIImage fromRect:[outputCIImage extent]];
146+
sourceImage = [UIImage imageWithCGImage:outputImageRef];
147+
148+
CGImageRelease(outputImageRef);
149+
}
150+
131151
[_sourceImageView setImage:sourceImage];
132152
[_sourceImageView setFrame:convertedThumbnailImageViewFrame];
133153
[_sourceImageView setAlpha:0];

FastImageCacheDemo/Classes/FICDPhoto.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010

1111
extern NSString *const FICDPhotoImageFormatFamily;
1212

13-
extern NSString *const FICDPhotoSquareImageFormatName;
13+
extern NSString *const FICDPhotoSquareImage32BitBGRAFormatName;
14+
extern NSString *const FICDPhotoSquareImage32BitBGRFormatName;
15+
extern NSString *const FICDPhotoSquareImage16BitBGRFormatName;
16+
extern NSString *const FICDPhotoSquareImage8BitGrayscaleFormatName;
1417
extern NSString *const FICDPhotoPixelImageFormatName;
1518

1619
extern CGSize const FICDPhotoSquareImageSize;

FastImageCacheDemo/Classes/FICDPhoto.m

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313

1414
NSString *const FICDPhotoImageFormatFamily = @"FICDPhotoImageFormatFamily";
1515

16-
NSString *const FICDPhotoSquareImageFormatName = @"FICDPhotoSquareImageFormatName";
16+
NSString *const FICDPhotoSquareImage32BitBGRAFormatName = @"FICDPhotoSquareImage32BitBGRAFormatName";
17+
NSString *const FICDPhotoSquareImage32BitBGRFormatName = @"FICDPhotoSquareImage32BitBGRFormatName";
18+
NSString *const FICDPhotoSquareImage16BitBGRFormatName = @"FICDPhotoSquareImage16BitBGRFormatName";
19+
NSString *const FICDPhotoSquareImage8BitGrayscaleFormatName = @"FICDPhotoSquareImage8BitGrayscaleFormatName";
1720
NSString *const FICDPhotoPixelImageFormatName = @"FICDPhotoPixelImageFormatName";
1821

1922
CGSize const FICDPhotoSquareImageSize = {75, 75};
@@ -188,9 +191,22 @@ - (FICEntityImageDrawingBlock)drawingBlockForImage:(UIImage *)image withFormatNa
188191
contextBounds.size = contextSize;
189192
CGContextClearRect(contextRef, contextBounds);
190193

191-
if ([formatName isEqualToString:FICDPhotoSquareImageFormatName]) {
194+
if ([formatName isEqualToString:FICDPhotoPixelImageFormatName]) {
195+
UIImage *statusBarImage = _FICDStatusBarImageFromImage(image);
196+
CGContextSetInterpolationQuality(contextRef, kCGInterpolationMedium);
197+
198+
UIGraphicsPushContext(contextRef);
199+
[statusBarImage drawInRect:contextBounds];
200+
UIGraphicsPopContext();
201+
} else {
202+
if ([formatName isEqualToString:FICDPhotoSquareImage32BitBGRAFormatName] == NO) {
203+
// Fill with white for image formats that are opaque
204+
CGContextSetFillColorWithColor(contextRef, [[UIColor whiteColor] CGColor]);
205+
CGContextFillRect(contextRef, contextBounds);
206+
}
207+
192208
UIImage *squareImage = _FICDSquareImageFromImage(image);
193-
209+
194210
// Clip to a rounded rect
195211
CGPathRef path = _FICDCreateRoundedRectPath(contextBounds, 12);
196212
CGContextAddPath(contextRef, path);
@@ -200,13 +216,6 @@ - (FICEntityImageDrawingBlock)drawingBlockForImage:(UIImage *)image withFormatNa
200216
UIGraphicsPushContext(contextRef);
201217
[squareImage drawInRect:contextBounds];
202218
UIGraphicsPopContext();
203-
} else if ([formatName isEqualToString:FICDPhotoPixelImageFormatName]) {
204-
UIImage *statusBarImage = _FICDStatusBarImageFromImage(image);
205-
CGContextSetInterpolationQuality(contextRef, kCGInterpolationMedium);
206-
207-
UIGraphicsPushContext(contextRef);
208-
[statusBarImage drawInRect:contextBounds];
209-
UIGraphicsPopContext();
210219
}
211220
};
212221

FastImageCacheDemo/Classes/FICDPhotosTableViewCell.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
@property (nonatomic, weak) id <FICDPhotosTableViewCellDelegate> delegate;
1616
@property (nonatomic, assign) BOOL usesImageTable;
1717
@property (nonatomic, copy) NSArray *photos;
18+
@property (nonatomic, copy) NSString *imageFormatName;
1819

1920
+ (NSString *)reuseIdentifier;
2021
+ (NSInteger)photosPerRow;

FastImageCacheDemo/Classes/FICDPhotosTableViewCell.m

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515

1616
@interface FICDPhotosTableViewCell () <UIGestureRecognizerDelegate> {
1717
__weak id <FICDPhotosTableViewCellDelegate> _delegate;
18-
18+
BOOL _usesImageTable;
1919
NSArray *_photos;
20+
NSString *_imageFormatName;
21+
2022
NSMutableArray *_imageViews;
21-
BOOL _usesImageTable;
2223
UITapGestureRecognizer *_tapGestureRecognizer;
2324
}
2425

@@ -29,8 +30,9 @@ @interface FICDPhotosTableViewCell () <UIGestureRecognizerDelegate> {
2930
@implementation FICDPhotosTableViewCell
3031

3132
@synthesize delegate = _delegate;
32-
@synthesize photos = _photos;
3333
@synthesize usesImageTable = _usesImageTable;
34+
@synthesize photos = _photos;
35+
@synthesize imageFormatName = _imageFormatName;
3436

3537
#pragma mark - Property Accessors
3638

@@ -61,7 +63,7 @@ - (void)setPhotos:(NSArray *)photos {
6163
UIImageView *imageView = [_imageViews objectAtIndex:i];
6264

6365
if (_usesImageTable) {
64-
[[FICImageCache sharedImageCache] retrieveImageForEntity:photo withFormatName:FICDPhotoSquareImageFormatName completionBlock:^(id<FICEntity> entity, NSString *formatName, UIImage *image) {
66+
[[FICImageCache sharedImageCache] retrieveImageForEntity:photo withFormatName:_imageFormatName completionBlock:^(id<FICEntity> entity, NSString *formatName, UIImage *image) {
6567
// This completion block may be called much later. We should check to make sure this cell hasn't been reused for different photos before displaying the image that has loaded.
6668
if (photos == [self photos]) {
6769
[imageView setImage:image];

0 commit comments

Comments
 (0)