I was developing a application that changes color image to gray image. However, some how the picture comes out wrong. I dont know what is wrong with the code. maybe the parameter that i put in is wrong please help.
UIImage *c = [UIImage imageNamed:@"downRed.png"];
CGImageRef cRef = CGImageRetain(c.CGImage);
NSData* pixelData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(cRef));
size_t w = CGImageGetWidth(cRef);
size_t h = CGImageGetHeight(cRef);
unsigned char* pixelBytes = (unsigned char *)[pixelData bytes];
unsigned char* greyPixelData = (unsigned char*) malloc(w*h);
for (int y = 0; y < h; y++) {
for(int x = 0; x < w; x++){
int iter = 4*(w*y+x);
int red = pixe lBytes[iter];
int green = pixelBytes[iter+1];
int blue = pixelBytes[iter+2];
greyPixelData[w*y+x] = (unsigned char)(red*0.3 + green*0.59+ blue*0.11);
int value = greyPixelData[w*y+x];
}
}
CFDataRef imgData = CFDataCreate(NULL, greyPixelData, w*h);
CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData(imgData);
size_t width = CGImageGetWidth(cRef);
size_t height = CGImageGetHeight(cRef);
size_t bitsPerComponent = 8;
size_t bitsPerPixel = 8;
size_t bytesPerRow = CGImageGetWidth(cRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGBitmapInfo info = kCGImageAlphaNone;
CGFloat *decode = NULL;
BOOL shouldInteroplate = NO;
CGColorRenderingIntent intent = kCGRenderingIntentDefault;
CGDataProviderRelease(imgDataProvider);
CGImageRef throughCGImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, info, imgDataProvider, decode, shouldInteroplate, intent);
UIImage* newImage = [UIImage imageWithCGImage:throughCGImage];
CGImageRelease(throughCGImage);
newImageView.image = newImage;
If someone wants to gray scale images that contain transparent parts the solution offered by digipeople will have a black mask around it. Use this instead to leave the transparent as it is.
- (UIImage *)imageToGreyImage:(UIImage *)image {
// Create image rectangle with current image width/height
CGFloat actualWidth = image.size.width;
CGFloat actualHeight = image.size.height;
CGRect imageRect = CGRectMake(0, 0, actualWidth, actualHeight);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(nil, actualWidth, actualHeight, 8, 0, colorSpace, kCGImageAlphaNone);
CGContextDrawImage(context, imageRect, [image CGImage]);
CGImageRef grayImage = CGBitmapContextCreateImage(context);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
context = CGBitmapContextCreate(nil, actualWidth, actualHeight, 8, 0, nil, kCGImageAlphaOnly);
CGContextDrawImage(context, imageRect, [image CGImage]);
CGImageRef mask = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *grayScaleImage = [UIImage imageWithCGImage:CGImageCreateWithMask(grayImage, mask) scale:image.scale orientation:image.imageOrientation];
CGImageRelease(grayImage);
CGImageRelease(mask);
// Return the new grayscale image
return grayScaleImage;
}
Just use this:
- (UIImage *)convertImageToGrayScale:(UIImage *)image
{
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
// Grayscale color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// Create bitmap content with current image size and grayscale colorspace
CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, [image CGImage]);
// Create bitmap image info from pixel data in current context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
// Create a new UIImage object
UIImage *newImage = [UIImage imageWithCGImage:imageRef];
// Release colorspace, context and bitmap information
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CFRelease(imageRef);
// Return the new grayscale image
return newImage;
}
Swift version, tested and working 100%:
func imageToGreyImage(image: UIImage) -> UIImage {
// Create image rectangle with current image width/height
var actualWidth = image.size.width;
var actualHeight = image.size.height;
var imageRect = CGRectMake(0, 0, actualWidth, actualHeight);
var colorSpace = CGColorSpaceCreateDeviceGray();
var bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.None.rawValue)
var context = CGBitmapContextCreate(nil, Int(actualWidth), Int(actualHeight), 8, 0, colorSpace, bitmapInfo);
CGContextDrawImage(context, imageRect, image.CGImage);
var grayImage = CGBitmapContextCreateImage(context);
bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.Only.rawValue)
context = CGBitmapContextCreate(nil, Int(actualWidth), Int(actualHeight), 8, 0, nil, bitmapInfo);
CGContextDrawImage(context, imageRect, image.CGImage);
var mask = CGBitmapContextCreateImage(context);
var grayScaleImage = UIImage(CGImage: CGImageCreateWithMask(grayImage, mask), scale: image.scale, orientation: image.imageOrientation)
// Return the new grayscale image
return grayScaleImage!;
}
And if u want no alpha just delete the following line:
bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.Only.rawValue)