iOS : Looping over the pixels of an Image
image-processing, ios, iphone, uiimage
Solution
This works for me (this is using ARC):
- (BOOL) pointInside: (CGPoint) point withEvent: (UIEvent *) event {
CGRect r = CGRectZero ;
r.size =[self size] ;
CGFloat red ;
CGFloat green ;
CGFloat blue ;
CGFloat alpha ;
if (point.x < 0 || point.x > r.size.width || point.y < 0 || point.y > r.size.height) {
return NO ;
}
[inspector colorAt:point red:&red green:&green blue:&blue alpha:&alpha] ;
return alpha > 0.01f ;
}
And here's the magic :)
// CGImageInspection.h
#import <Foundation/Foundation.h>
@interface CGImageInspection : NSObject
+ (CGImageInspection *) imageInspectionWithCGImage: (CGImageRef) imageRef ;
- (void) colorAt: (CGPoint) location
red: (CGFloat *) red
green: (CGFloat *) green
blue: (CGFloat *) blue
alpha: (CGFloat *) alpha ;
@end
And the corresponding implementation:
// CGImageInspection.mm
@interface CGImageInspection ()
- (id) initWithCGImage: (CGImageRef) imageRef ;
@property (assign, nonatomic) CGContextRef context ;
@property (assign, nonatomic) void * pixels ;
@property (assign, nonatomic) NSUInteger bytesPerRow ;
@property (assign, nonatomic) NSUInteger bytesPerPixel ;
@end
@implementation CGImageInspection
@synthesize context ;
@synthesize pixels ;
@synthesize bytesPerRow ;
@synthesize bytesPerPixel ;
- (void) dealloc {
if (self.context) {
::CGContextRelease(self.context) ;
self.context = 0 ;
}
if (self.pixels) {
::free(self.pixels) ;
self.pixels = 0 ;
}
::NSLog(@"CGImageInspection going away") ;
}
+ (CGImageInspection *) imageInspectionWithCGImage: (CGImageRef) imageRef {
return [[CGImageInspection alloc] initWithCGImage:imageRef] ;
}
- (id) initWithCGImage: (CGImageRef) imageRef {
if (self = [super init]) {
size_t pixelsWide = ::CGImageGetWidth(imageRef) ;
size_t pixelsHigh = ::CGImageGetHeight(imageRef) ;
self.bytesPerPixel = 4 ;
self.bytesPerRow = (pixelsWide * self.bytesPerPixel) ;
int bitmapByteCount = (self.bytesPerRow * pixelsHigh) ;
CGColorSpaceRef colorSpace= ::CGColorSpaceCreateDeviceRGB() ;
if (colorSpace == 0) {
return nil ;
}
self.pixels = ::calloc(bitmapByteCount, 1) ;
if (self.pixels == 0) {
::CGColorSpaceRelease(colorSpace) ;
return nil ;
}
self.context = ::CGBitmapContextCreate(
self.pixels
, pixelsWide
, pixelsHigh
, 8 // bits per component
, self.bytesPerRow
, colorSpace
, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big) ;
if (self.context == 0) {
::free(self.pixels) ;
self.pixels = 0 ;
::CGColorSpaceRelease(colorSpace) ;
return nil ;
}
::CGContextDrawImage(context, (CGRect) {{0, 0}, {pixelsWide, pixelsHigh}}, imageRef) ;
::CGColorSpaceRelease(colorSpace) ;
}
return self ;
}
- (void) colorAt: (CGPoint) location
red: (CGFloat *) red
green: (CGFloat *) green
blue: (CGFloat *) blue
alpha: (CGFloat *) alpha {
int yy = (int) location.y ;
int xx = (int) location.x ;
int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel ;
unsigned char * raw = (unsigned char *) self.pixels ;
raw += byteIndex ;
*red = ((CGFloat) (*raw++)) / 255.0f ;
*green = ((CGFloat) (*raw++)) / 255.0f ;
*blue = ((CGFloat) (*raw++)) / 255.0f ;
*alpha = ((CGFloat) (*raw++)) / 255.0f ;
}
@end
Hope this helps.
Problem
I've two images of the same format and size. I would like to loop over the pixels of each image and find the most top left and buttom right difference coordinates. Difference is considered the pixel color of the two pixel with the same coordinates. Can you please provide me a sample code looping through Image pixels and getting its color value ?