Permalink
Browse files

#283: Added option for converting images to Grayscale

  • Loading branch information...
1 parent e7c02bb commit 92b75bc18be031516dc9bdd662b9f5d4a973d985 @NachoSoto NachoSoto committed Jan 29, 2013
@@ -67,6 +67,8 @@
5376131E155AD0D5005750A4 /* SDWebImagePrefetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 53922D91148C56230056699D /* SDWebImagePrefetcher.h */; settings = {ATTRIBUTES = (Public, ); }; };
5376131F155AD0D5005750A4 /* UIButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 53922D93148C56230056699D /* UIButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
53761320155AD0D5005750A4 /* UIImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 53922D95148C56230056699D /* UIImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 57B7420516B75D52004199BE /* UIImage+Grayscale.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B7420316B75D52004199BE /* UIImage+Grayscale.h */; };
+ 57B7420616B75D52004199BE /* UIImage+Grayscale.m in Sources */ = {isa = PBXBuildFile; fileRef = 57B7420416B75D52004199BE /* UIImage+Grayscale.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -106,6 +108,8 @@
53922D96148C56230056699D /* UIImageView+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+WebCache.m"; path = "SDWebImage/UIImageView+WebCache.m"; sourceTree = SOURCE_ROOT; };
53FB893F14D35D1A0020B787 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
53FB894814D35E9E0020B787 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 57B7420316B75D52004199BE /* UIImage+Grayscale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Grayscale.h"; sourceTree = "<group>"; };
+ 57B7420416B75D52004199BE /* UIImage+Grayscale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Grayscale.m"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -184,6 +188,8 @@
53922D94148C56230056699D /* UIButton+WebCache.m */,
53922D95148C56230056699D /* UIImageView+WebCache.h */,
53922D96148C56230056699D /* UIImageView+WebCache.m */,
+ 57B7420316B75D52004199BE /* UIImage+Grayscale.h */,
+ 57B7420416B75D52004199BE /* UIImage+Grayscale.m */,
);
name = Categories;
sourceTree = "<group>";
@@ -256,6 +262,7 @@
53761320155AD0D5005750A4 /* UIImageView+WebCache.h in Headers */,
530E49E816464C25002868E7 /* SDWebImageOperation.h in Headers */,
530E49EA16464C7C002868E7 /* SDWebImageDownloaderOperation.h in Headers */,
+ 57B7420516B75D52004199BE /* UIImage+Grayscale.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -386,6 +393,7 @@
5376130F155AD0D5005750A4 /* UIImageView+WebCache.m in Sources */,
530E49EC16464C84002868E7 /* SDWebImageDownloaderOperation.m in Sources */,
53406750167780C40042B59E /* SDWebImageCompat.m in Sources */,
+ 57B7420616B75D52004199BE /* UIImage+Grayscale.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -13,7 +13,8 @@
typedef enum
{
SDWebImageDownloaderLowPriority = 1 << 0,
- SDWebImageDownloaderProgressiveDownload = 1 << 1
+ SDWebImageDownloaderProgressiveDownload = 1 << 1,
+ SDWebImageDownloaderGrayscale = 1 << 2
} SDWebImageDownloaderOptions;
extern NSString *const SDWebImageDownloadStartNotification;
@@ -9,6 +9,7 @@
#import "SDWebImageDownloaderOperation.h"
#import "SDWebImageDecoder.h"
#import <ImageIO/ImageIO.h>
+#import "UIImage+Grayscale.h"
@interface SDWebImageDownloaderOperation ()
@@ -276,6 +277,12 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
dispatch_async(self.queue, ^
{
UIImage *image = [UIImage decodedImageWithImage:SDScaledImageForPath(self.request.URL.absoluteString, self.imageData)];
+
+ if (self.options & SDWebImageDownloaderGrayscale)
+ {
+ image = [image grayscaleImage];
+ }
+
dispatch_async(dispatch_get_main_queue(), ^
{
if (CGSizeEqualToSize(image.size, CGSizeZero))
@@ -31,7 +31,11 @@ typedef enum
* This flag enables progressive download, the image is displayed progressively during download as a browser would do.
* By default, the image is only displayed once completely downloaded.
*/
- SDWebImageProgressiveDownload = 1 << 3
+ SDWebImageProgressiveDownload = 1 << 3,
+ /**
+ * By using this flag, the downloaded image will be converted to Grayscale
+ */
+ SDWebImageGrayscale = 1 << 4
} SDWebImageOptions;
typedef void(^SDWebImageCompletedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType);
@@ -100,6 +100,7 @@ - (NSString *)cacheKeyForURL:(NSURL *)url
SDWebImageDownloaderOptions downloaderOptions = 0;
if (options & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority;
if (options & SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload;
+ if (options & SDWebImageGrayscale) downloaderOptions |= SDWebImageDownloaderGrayscale;
__block id<SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished)
{
completedBlock(downloadedImage, error, SDImageCacheTypeNone, finished);
@@ -0,0 +1,15 @@
+//
+// UIImage+Grayscale.h
+// SDWebImage
+//
+// Created by Nacho Soto on 1/28/13.
+// Copyright (c) 2013 Dailymotion. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UIImage (Grayscale)
+
+- (instancetype)grayscaleImage;
+
+@end
@@ -0,0 +1,81 @@
+//
+// UIImage+Grayscale.m
+// SDWebImage
+//
+// Created by Nacho Soto on 1/28/13.
+// Copyright (c) 2013 Dailymotion. All rights reserved.
+//
+
+#import "UIImage+Grayscale.h"
+
+@implementation UIImage (Grayscale)
+
+- (instancetype)grayscaleImage
+{
+ /**
+ * reference: http://stackoverflow.com/a/1300589
+ */
+ const int kRed = 1,
+ kGreen = 2,
+ kBlue = 4;
+
+ const int colors = kGreen | kBlue | kRed;
+ const int m_width = self.size.width,
+ m_height = self.size.height;
+
+ uint32_t *const rgbImage = (uint32_t *)malloc(m_width * m_height * sizeof(uint32_t));
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGContextRef context = CGBitmapContextCreate(rgbImage, m_width, m_height, 8, m_width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
+ CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
+ CGContextSetShouldAntialias(context, NO);
+ CGContextDrawImage(context, CGRectMake(0, 0, m_width, m_height), self.CGImage);
+ CGContextRelease(context);
+ CGColorSpaceRelease(colorSpace);
+
+ // now convert to grayscale
+ uint8_t *const m_imageData = (uint8_t *)calloc(m_width * m_height, sizeof(uint8_t));
+ for (int y = 0; y < m_height; y++)
+ {
+ for (int x = 0; x < m_width; x++)
+ {
+ uint32_t rgbPixel=rgbImage[y*m_width+x];
+ uint32_t sum=0,count=0;
+ if (colors & kRed) {sum += (rgbPixel>>24)&255; count++;}
+ if (colors & kGreen) {sum += (rgbPixel>>16)&255; count++;}
+ if (colors & kBlue) {sum += (rgbPixel>>8)&255; count++;}
+ m_imageData[y*m_width+x]=sum/count;
+ }
+ }
+ free(rgbImage);
+
+ // convert from a gray scale image back into a UIImage
+ uint8_t *const result = (uint8_t *)calloc(m_width * m_height, sizeof(uint8_t));
+
+ // process the image back to rgb
+ for (int i = 0; i < m_height * m_width; i++)
+ {
+ result[i*4]=0;
+ int val=m_imageData[i];
+ result[i*4+1]=val;
+ result[i*4+2]=val;
+ result[i*4+3]=val;
+ }
+
+ // create a UIImage
+ colorSpace = CGColorSpaceCreateDeviceRGB();
+ context = CGBitmapContextCreate(result, m_width, m_height, 8, m_width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
+ CGImageRef image = CGBitmapContextCreateImage(context);
+ CGContextRelease(context);
+ CGColorSpaceRelease(colorSpace);
+ UIImage *resultUIImage = [UIImage imageWithCGImage:image];
+ CGImageRelease(image);
+
+ free(m_imageData);
+
+ // make sure the data will be released by giving it to an autoreleased NSData
+ [NSData dataWithBytesNoCopy:result length:m_width * m_height];
+
+ return resultUIImage;
+}
+
+@end

0 comments on commit 92b75bc

Please sign in to comment.