I’m using GLPaint example for my Paint app , I needed to take a screenshot of OpenGL ES [CAEAGLLayer] rendered content. I am using function:
-(UIImage *)snapUIImage
{
int s = 2;
const int w = self.frame.size.width;
const int h = self.frame.size.height;
const NSInteger myDataLength = w * h * 4 * s * s;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, w*s, h*s, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y < h*s; y++)
{
memcpy( buffer2 + (h*s - 1 - y) * w * 4 * s, buffer + (y * 4 * w * s), w * 4 * s );
}
free(buffer); // work with the flipped buffer, so get rid of the original one.
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * w * s;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(w*s, h*s, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [ UIImage imageWithCGImage:imageRef scale:s orientation:UIImageOrientationUp ];
CGImageRelease( imageRef );
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
// buffer2 will be destroyed once myImage is autoreleased.
return myImage;
}
-(void)captureToPhotoAlbum {
UIImage *image = [self snapUIImage];
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
}
Above code is working I am getting the image but it is not a high resolution [Retina display] image.Please help.
Thanks in advance.
Working code solution
- (UIImage*) getGLScreenshot
{
int myWidth = self.frame.size.width*2;
int myHeight = self.frame.size.height*2;
int myY = 0;
int myX = 0;
int bufferLength = (myWidth*myHeight*4);
//unsigned char buffer[bufferLength];
unsigned char* buffer =(unsigned char*)malloc(bufferLength);
glReadPixels(myX, myY, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL);
CGImageRef iref = CGImageCreate(myWidth,myHeight,8,32,myWidth*4,CGColorSpaceCreateDeviceRGB(),
kCGBitmapByteOrderDefault,ref,NULL, true, kCGRenderingIntentDefault);
uint32_t* pixels = (uint32_t *)malloc(bufferLength);
CGContextRef context = CGBitmapContextCreate(pixels, myWidth, myHeight, 8, myWidth*4, CGImageGetColorSpace(iref),
kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
CGContextTranslateCTM(context, 0.0, myHeight);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, myWidth, myHeight), iref);
CGImageRef outputRef = CGBitmapContextCreateImage(context);
UIImage *image = nil;
if(regardOrientation) {
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (deviceOrientation == UIDeviceOrientationPortraitUpsideDown) {
image = [UIImage imageWithCGImage:outputRef scale:1 orientation:UIImageOrientationDown];
} else if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
image = [UIImage imageWithCGImage:outputRef scale:1 orientation:UIImageOrientationLeft];
} else if (deviceOrientation == UIDeviceOrientationLandscapeRight) {
image = [UIImage imageWithCGImage:outputRef scale:1 orientation:UIImageOrientationRight];
} else {
image = [UIImage imageWithCGImage:outputRef scale:1 orientation:UIImageOrientationUp];
}
} else {
image = [UIImage imageWithCGImage:outputRef scale:1 orientation:UIImageOrientationUp];
}
image = [UIImage imageWithCGImage:outputRef scale:1 orientation:UIImageOrientationUp];
CGImageRelease(iref);
CGImageRelease(outputRef);
CGContextRelease(context);
CGDataProviderRelease(ref);
free(buffer);
free(pixels);
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
return image;
}
Related
I am using the following code to take a screenshot of the pixels in a GLView. The problem is, it returns a completely black UIImage. This code is being called in LineDrawer.m which is the heart of the GLView code - so it is being called from the right .m file. How can I save the actual screenshot and not a black image?
- (UIImage*) getGLScreenshot {
NSLog(#"1");
float scale = 0.0;
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
{
// scale value should be 1.0 on 3G and 3GS, and 2.0 on iPhone 4.
scale = [[UIScreen mainScreen] scale];
}
// these are swapped since the screen is rotatey
float h = 768 * scale;
float w = 924 * scale;
NSInteger myDataLength = w * h * 4;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y <h; y++)
{
for(int x = 0; x <w * 4; x++)
{
buffer2[(((int)h-1) - y) * (int)w * 4 + x] = buffer[y * 4 * (int)w + x];
}
}
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * w;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(w, h, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
return myImage;
}
- (void)saveGLScreenshotToPhotosAlbum {
UIImageWriteToSavedPhotosAlbum([self getGLScreenshot], nil, nil, nil);
}
I had to do something similar in the Sparrow Framework a while back, you should be able to pull the parts you need out of the code in this forum reply:
http://forum.sparrow-framework.org/topic/spdisplayobjectscreenshot
EDIT: Also this post http://forum.sparrow-framework.org/topic/taking-screenshots
Change your drawable properties
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGB565,
kEAGLDrawablePropertyColorFormat, nil];
kEAGLDrawablePropertyRetainedBacking to YES
Try this I went through a lot of things and finally found a solution.
-(UIImage*)renderImg{
GLint backingWidth = 0;
GLint backingHeight = 0;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
GLubyte *buffer = (GLubyte *) malloc(backingWidth * backingHeight * 4);
GLubyte *buffer2 = (GLubyte *) malloc(backingWidth * backingHeight * 4);
glReadPixels(0, 0, backingWidth, backingHeight, GL_RGBA, GL_UNSIGNED_BYTE,
(GLvoid *)buffer);
for (int y=0; y<backingHeight; y++) {
for (int x=0; x<backingWidth*4; x++) {
buffer2[y * 4 * backingWidth + x] =
buffer[(backingHeight - y - 1) * backingWidth * 4 + x];
}
}
free(buffer);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2,
backingWidth * backingHeight * 4,
myProviderReleaseData);
// set up for CGImage creation
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * backingWidth;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
// Use this to retain alpha
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(backingWidth, backingHeight,
bitsPerComponent, bitsPerPixel,
bytesPerRow, colorSpaceRef,
bitmapInfo, provider,
NULL, NO,
renderingIntent);
// this contains our final image.
UIImage *newUIImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);
return newUIImage;
}
I think it should work perfectly.
I have a problem with cropping image using OpenCV library on a real iPhone.
I have an image with selected area and I'd like to apply a perspective transform on the image with this area. This works fine on the simulator but on the iphone the new image isn't map to rectangle and the new image has also blue color.
Here is my code :
+ (IplImage *)CreateIplImageFromUIImage:(UIImage *)image {
// Getting CGImage from UIImage
CGImageRef imageRef = image.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Creating temporal IplImage for drawing
IplImage *iplimage = cvCreateImage(
cvSize(image.size.width,image.size.height), IPL_DEPTH_8U, 4
);
// Creating CGContext for temporal IplImage
CGContextRef contextRef = CGBitmapContextCreate(
iplimage->imageData, iplimage->width, iplimage->height,
iplimage->depth, iplimage->widthStep,
colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault
);
// Drawing CGImage to CGContext
CGContextDrawImage(
contextRef,
CGRectMake(0, 0, image.size.width, image.size.height),
imageRef
);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
// Creating result IplImage
IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, 3);
cvCvtColor(iplimage, ret, CV_RGBA2BGR);
cvReleaseImage(&iplimage);
return ret;
}
+ (UIImage *)UIImageFromIplImage:(IplImage *)img {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Creating result IplImage
IplImage *image = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 4);
cvCvtColor(img, image, CV_BGR2RGBA);
// Allocating the buffer for CGImage
NSData *data =
[NSData dataWithBytes:image->imageData length:image->imageSize];
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((CFDataRef)data);
// Creating CGImage from chunk of IplImage
CGImageRef imageRef = CGImageCreate(
image->width, image->height,
image->depth, image->depth * image->nChannels, image->widthStep,
colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault,
provider, NULL, false, kCGRenderingIntentDefault
);
// Getting UIImage from CGImage
UIImage *ret = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return ret;
}
+ (UIImage *)perspectiveTransform: (UIImage*) originalImage :(CGFloat) h :(CGFloat) w :(CGPoint) point1 :(CGPoint) point2 :(CGPoint) point3 :(CGPoint) point4
{
CvPoint2D32f srcQuad[4];
srcQuad[0].x = point1.x;
srcQuad[0].y = point1.y;
srcQuad[1].x = point2.x;
srcQuad[1].y = point2.y;
srcQuad[2].x = point3.x;
srcQuad[2].y = point3.y;
srcQuad[3].x = point4.x;
srcQuad[3].y = point4.y;
IplImage *src = [self CreateIplImageFromUIImage:originalImage];
IplImage *dst = cvCreateImage(cvGetSize(src),
src->depth,
src->nChannels);
cvZero(dst);
CGFloat width = src->width;
CGFloat height = src->height;
CvMat* mmat = cvCreateMat(3, 3, CV_32FC1);
CvPoint2D32f *c1 = (CvPoint2D32f *)malloc(4 * sizeof(CvPoint2D32f));
CvPoint2D32f *c2 = (CvPoint2D32f *)malloc(4 * sizeof(CvPoint2D32f));
c1[0].x = round((width/w)*srcQuad[0].x); c1[0].y = round((height/h)*srcQuad[0].y);
c1[1].x = round((width/w)*srcQuad[1].x); c1[1].y = round((height/h)*srcQuad[1].y);
c1[2].x = round((width/w)*srcQuad[2].x); c1[2].y = round((height/h)*srcQuad[2].y);
c1[3].x = round((width/w)*srcQuad[3].x); c1[3].y = round((height/h)*srcQuad[3].y);
c2[0].x = 0; c2[0].y = 0;
c2[1].x = width - 1; c2[1].y = 0;
c2[2].x = 0; c2[2].y = height - 1;
c2[3].x = width - 1; c2[3].y = height - 1;
mmat = cvGetPerspectiveTransform(c1, c2, mmat);
free(c1);
free(c2);
cvWarpPerspective(src, dst, mmat, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
cvReleaseImage(&src);
cvReleaseMat(&mmat);
UIImage *newImage = [self UIImageFromIplImage:dst];
cvReleaseImage(&dst);
return newImage;
}
Thanks for your help !
Is there a way to apply brightness to uiimages. For example I have a UIImageview and inside that i have a uiimage. I want to manipulate its brightness with a help of UISlider without using GlImageprocessing.
Please help me to solve this problem and please don't suggest me about GlImageprocessing. I want to do it without using GlImageprocessing.
here is the code:-
CGImageRef inImage = currentImage.CGImage;
CFDataRef ref = CGDataProviderCopyData(CGImageGetDataProvider(inImage));
UInt8 * buf = (UInt8 *) CFDataGetBytePtr(ref);
int length = CFDataGetLength(ref);
float value2 = (1+slider.value-0.5);
NSLog(#"%i",value);
for(int i=0; i<length; i+=4)
{
int r = i;
int g = i+1;
int b = i+2;
int red = buf[r];
int green = buf[g];
int blue = buf[b];
buf[r] = SAFECOLOR(red*value2);
buf[g] = SAFECOLOR(green*value2);
buf[b] = SAFECOLOR(blue*value2);
}
CGContextRef ctx = CGBitmapContextCreate(buf,
CGImageGetWidth(inImage),
CGImageGetHeight(inImage),
CGImageGetBitsPerComponent(inImage),
CGImageGetBytesPerRow(inImage),
CGImageGetColorSpace(inImage),
CGImageGetAlphaInfo(inImage));
CGImageRef img = CGBitmapContextCreateImage(ctx);
[photoEditView setImage:[UIImage imageWithCGImage:img]];
CFRelease(ref);
CGContextRelease(ctx);
CGImageRelease(img);
define this at the top:-
#define SAFECOLOR(color) MIN(255,MAX(0,color))
Have a look at Apple's demo app GLImageProcessing
, it's really fast:
Open Gl to UIImage Create
-(UIImage *) glToUIImage {
NSInteger myDataLength = 320 * 480 * 4;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y <480; y++)
{
for(int x = 0; x <320 * 4; x++)
{
buffer2[(479 - y) * 320 * 4 + x] = buffer[y * 4 * 320 + x];
}
}
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(
NULL, buffer2, myDataLength, NULL);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * 320;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGImageAlphaNone;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
//UIImageWriteToSavedPhotosAlbum(myImage,nil,nil,nil);
[[NSUserDefaults standardUserDefaults] setObject:UIImageJPEGRepresentation(myImage,1) forKey:#"image"];
return myImage;
}
Similar questions must have been asked many times but this one is a tad different.
I am manipulating pixels of a image loaded in ImageView control from the photo library using the pixel values read from another image (rocks.jpg) .
Below is the code for the same:--
CGContextRef ctx;
CGImageRef imageRef = [self.workingImage CGImage];
UIImage* image2 = [UIImage imageNamed:#"rocks.jpg"];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorSpaceRef colorSpace2 = CGColorSpaceCreateDeviceRGB();
CGColorSpaceRef colorSpace3 = CGColorSpaceCreateDeviceRGB();
CGImageRef cgimage2 = image2.CGImage;
NSUInteger width2 = CGImageGetWidth(cgimage2);
NSUInteger height2 = CGImageGetHeight(cgimage2);
struct pixel* pixels = (struct pixel*) calloc(1, width * height * sizeof(struct pixel));
struct pixel* pixels2 = (struct pixel*) calloc(1, width2 * height2 * sizeof(struct pixel));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
NSUInteger bpr2 = bytesPerPixel * width2;
//size_t bpp2 = CGImageGetBitsPerPixel(cgimage2);
NSUInteger bpc2 = 8;
CGContextRef context = CGBitmapContextCreate(pixels, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRef context2 = CGBitmapContextCreate(pixels2, width2, height2, bpc2, bpr2, colorSpace2,kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace2);
CGContextDrawImage(context2, CGRectMake(0, 0, width2, height2),cgimage2);
NSUInteger numberOfPixels = width*height;
while (numberOfPixels > 0)
{
if(pixels->g == 250)
{
pixels->r = pixels2->r;
pixels->g = pixels2->g;
pixels->b = pixels2->b;
pixels->a = pixels2->a;
// pixels->r = 0;
// pixels->g = 0;
// pixels->b = 0;
}
pixels++;
pixels2++;
numberOfPixels--;
}
ctx = CGBitmapContextCreate(pixels,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpace3,
kCGImageAlphaPremultipliedLast|kCGBitmapByteOrder32Big );
if (ctx == NULL)
{
NSLog(#"The context is null");
}
CGColorSpaceRelease(colorSpace3);
CGImageRef img2 = nil;
if (ctx != nil)
{
img2 = CGBitmapContextCreateImage (ctx);
}
//CGContextDrawImage(ctx, CGRectMake(0, 0, width, height), rawImage.CGImage );
UIImage* rawImage = [UIImage imageWithCGImage:img2];
CGContextRelease(context);
CGContextRelease(context2);
CGContextRelease(ctx);
//self.workingImage = rawImage;
//[self.imageView setImage:self.workingImage];
//[imageView setImage:rawImage];
imageView.image = rawImage;
if (pixels != NULL)
{
pixels = NULL;
free(pixels);
}
if (pixels2 != NULL)
{
pixels2 = NULL;
free(pixels2);
}
The problem is that though I can read the pixel values and also manipulate them but the end result is that the second image(rocks.jpg) gets loaded in the view instead of the manipulated image being loaded.
Can someone help me out on this.??
Thanks in advance.
I want to create an app in which i want to do some image processing. So I would like to know if there is any open-source image processing library available? also I would like to create a filter like this one Glamour Filter any help regarding this would be very much appreciated. If someone already have a source code to create sepia,black and white rotate scale code than please send. Thanks
Here is the code for sepia image
-(UIImage*)makeSepiaScale:(UIImage*)image
{
CGImageRef cgImage = [image CGImage];
CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
CFDataRef bitmapData = CGDataProviderCopyData(provider);
UInt8* data = (UInt8*)CFDataGetBytePtr(bitmapData);
int width = image.size.width;
int height = image.size.height;
NSInteger myDataLength = width * height * 4;
for (int i = 0; i < myDataLength; i+=4)
{
UInt8 r_pixel = data[i];
UInt8 g_pixel = data[i+1];
UInt8 b_pixel = data[i+2];
int outputRed = (r_pixel * .393) + (g_pixel *.769) + (b_pixel * .189);
int outputGreen = (r_pixel * .349) + (g_pixel *.686) + (b_pixel * .168);
int outputBlue = (r_pixel * .272) + (g_pixel *.534) + (b_pixel * .131);
if(outputRed>255)outputRed=255;
if(outputGreen>255)outputGreen=255;
if(outputBlue>255)outputBlue=255;
data[i] = outputRed;
data[i+1] = outputGreen;
data[i+2] = outputBlue;
}
CGDataProviderRef provider2 = CGDataProviderCreateWithData(NULL, data, myDataLength, NULL);
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider2, NULL, NO, renderingIntent);
CGColorSpaceRelease(colorSpaceRef); // YOU CAN RELEASE THIS NOW
CGDataProviderRelease(provider2); // YOU CAN RELEASE THIS NOW
CFRelease(bitmapData);
UIImage *sepiaImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef); // YOU CAN RELEASE THIS NOW
return sepiaImage;
}
Here is the code for Black & White effect
- (UIImage*) createGrayCopy:(UIImage*) source {
int width = source.size.width;
int height = source.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate (nil, width,
height,
8, // bits per component
0,
colorSpace,
kCGImageAlphaNone);
CGColorSpaceRelease(colorSpace);
if (context == NULL) {
return nil;
}
CGContextDrawImage(context,
CGRectMake(0, 0, width, height), source.CGImage);
UIImage *grayImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
CGContextRelease(context);
return grayImage;
}
Search for OpenCV