Drawing into CGImageRef - iphone

I want to create a CGImageRef and draw points to it.
What context to use to create an empty CGImageRef and be able to draw onto it.
CGContextRef or CGBitmapContextRef?
If you can provide code to create an empty CGImageRef image and draw to it I would appreciate.

#define HIRESDEVICE (((int)rintf([[[UIScreen mainScreen] currentMode] size].width/[[UIScreen mainScreen] bounds].size.width )>1))
- (CGImageRef) blerg
{
CGFloat imageScale = (CGFloat)1.0;
CGFloat width = (CGFloat)180.0;
CGFloat height = (CGFloat)180.0;
if ( HIRESDEVICE )
{
imageScale = (CGFloat)2.0;
}
// Create a bitmap graphics context of the given size
//
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, width * imageScale, height * imageScale, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
// Draw ...
//
CGContextSetRGBFillColor(context, (CGFloat)0.0, (CGFloat)0.0, (CGFloat)0.0, (CGFloat)1.0 );
// …
// Get your image
//
CGImageRef cgImage = CGBitmapContextCreateImage(context);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
return cgImage;
}

Related

How to give gradient in irregular shape of image?

I have an PNG image and I want to fill that image with gradient. Is this possible?
Means on the time of touch on iPad that part should be fill with gradient.
Just like in flood fill image fill with simple color(R+G+B).
I want that image fill gradient.
Thanx in advance for help.
And this is my line of code where i am find irregular shape and then fill the color by touch i need to modified it.
- (unsigned char*)rawDataFromImage:(UIImage*)image
{
CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
NSLog(#"w=%d,h=%d",width,height);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = malloc(height * width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
return rawData;
}
If any one having different solution for that so please give me.
I don't want to draw color on image i want to touch and fill on image but with gradient.
-(void)drawRect:(CGRect)rect
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.35, // Start color
1.0, 1.0, 1.0, 0.06 }; // End color
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGRect currentBounds = self.bounds;
CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds));
CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, midCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}

Screenshot shows black image in device - cocos2d-iPhone

Below code generates screenshot in my Game which works fine in Simulator but when i check in device,it shows black image.
here is my code to generate screenshot .
CCDirector *director = (CCDirector *) [CCDirector sharedDirector];
screenshootimage = [director screenshotUIImage];
appDelegate.screenshootimage = [Utility getImageFromView];
imgsprite = [CCSprite spriteWithCGImage:screenshootimage.CGImage key:#"s"];
- (UIImage*) screenshotUIImage
{
CGSize displaySize = [self displaySizeInPixels];
CGSize winSize = [self winSizeInPixels];
//Create buffer for pixels
GLuint bufferLength = displaySize.width * displaySize.height * 4;
GLubyte* buffer = (GLubyte*)malloc(bufferLength);
//Read Pixels from OpenGL
glReadPixels(0, 0, displaySize.width, displaySize.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
//Make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL);
//Configure image
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * displaySize.width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(displaySize.width, displaySize.height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
uint32_t* pixels = (uint32_t*)malloc(bufferLength);
CGContextRef context = CGBitmapContextCreate(pixels, winSize.width, winSize.height, 8, winSize.width * 4, CGImageGetColorSpace(iref), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextTranslateCTM(context, 0, displaySize.height);
CGContextScaleCTM(context, 1.0f, -1.0f);
switch (deviceOrientation_)
{
case CCDeviceOrientationPortrait: break;
case CCDeviceOrientationPortraitUpsideDown:
CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(180));
CGContextTranslateCTM(context, -displaySize.width, -displaySize.height);
break;
case CCDeviceOrientationLandscapeLeft:
CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(-90));
CGContextTranslateCTM(context, -displaySize.height, 0);
break;
case CCDeviceOrientationLandscapeRight:
CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(90));
CGContextTranslateCTM(context, displaySize.height-displaySize.width, -displaySize.height);
break;
}
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, displaySize.width, displaySize.height), iref);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage *outputImage = [[[UIImage alloc] initWithCGImage:imageRef] autorelease];
//Dealloc
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGImageRelease(iref);
CGColorSpaceRelease(colorSpaceRef);
CGContextRelease(context);
free(buffer);
free(pixels);
return outputImage;
}
+ (UIImage*)getImageFromView
{
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
//CGSize imageSize = [[UIScreen mainScreen] bounds].size;
CGSize newImageSize = [[UIScreen mainScreen] bounds].size;
CGSize imageSize = CGSizeMake(newImageSize.height, newImageSize.width);
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO,1.0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].y, [window center].x);
CGContextRotateCTM( context, degreesToRadian( -90 ) ) ;
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-imageSize.height *[[window layer] anchorPoint].y,
-imageSize.width *[[window layer] anchorPoint].x);
// Render the layer hierarchy to the current context
[[window layer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
any help ?!
NOTE: It also works fine in iPad Device, only problem is with iPhone Device.

Change brightness on a greyscale image with transparent background

I use a function to change brightness of a picture (without use openGL), which works well.
I use another function to convert my image in grayscale, which works well too.
But when i combine them, when i apply my brightness function on the grayscale image, i got some stripes on the image, and when the background is transparent (alpha 0) it is replaced by a black background. Do you any have any idea?
Please find below my grayscale function and the brightness function as well :
// ## Brightness without OpenGL call
+(UIImage *) changeImageBrightness:(UIImage *)aInputImage withFactor:(float)aFactor
{
CGImageRef img=aInputImage.CGImage;
CFDataRef dataref = CGDataProviderCopyData(
CGImageGetDataProvider(aInputImage.CGImage));
int length=CFDataGetLength(dataref);
UInt8 *data=(UInt8 *)CFDataGetBytePtr(dataref);
// Perform operation on pixels
for(int index=0;index<length;index+=4) {
// Go For BRIGHTNESS
for(int i=0;i<3;i++) {
if(data[index+i]+aFactor<0) {
data[index+i]=0;
} else {
if(data[index+i]+aFactor>255) {
data[index+i]=255;
} else {
data[index+i]+=aFactor;
}
}
}
}
// .. Take image attributes
size_t width=CGImageGetWidth(img);
size_t height=CGImageGetHeight(img);
size_t bitsPerComponent=CGImageGetBitsPerComponent(img);
size_t bitsPerPixel=CGImageGetBitsPerPixel(img);
size_t bytesPerRow=CGImageGetBytesPerRow(img);
// .. Do the pixel manupulation
CGColorSpaceRef colorspace=CGImageGetColorSpace(img);
CGBitmapInfo bitmapInfo=CGImageGetBitmapInfo(img);
CFDataRef newData=CFDataCreate(NULL,data,length);
CGDataProviderRef provider=CGDataProviderCreateWithCFData(newData);
// .. Get the Image out of this raw data
CGImageRef newImg = CGImageCreate(width, height, bitsPerComponent,
bitsPerPixel, bytesPerRow, colorspace, bitmapInfo, provider,
NULL, true, kCGRenderingIntentDefault);
// .. Prepare the image from raw data
UIImage* rawImage = [[UIImage alloc] initWithCGImage:newImg];
// .. done with all,so release the references
CFRelease(newData);
CGImageRelease(newImg);
CGDataProviderRelease(provider);
CFRelease(dataref);
// return rawImage.CGImage;
UIImage *imageApresFiltreEtRotationCGI = [UIImage
imageWithCGImage:rawImage.CGImage];
return imageApresFiltreEtRotationCGI;
}
+ (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]);
/* changes start here */
// Create bitmap image info from pixel data in current context
CGImageRef grayImage = CGBitmapContextCreateImage(context);
// release the colorspace and graphics context
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
// make a new alpha-only graphics context
context = CGBitmapContextCreate(nil, image.size.width,
image.size.height, 8, 0, nil, kCGImageAlphaOnly);
// draw image into context with no colorspace
CGContextDrawImage(context, imageRect, [image CGImage]);
// create alpha bitmap mask from current context
CGImageRef mask = CGBitmapContextCreateImage(context);
// release graphics context
CGContextRelease(context);
// make UIImage from grayscale image with alpha mask
UIImage *grayScaleImage = [UIImage imageWithCGImage:
CGImageCreateWithMask(grayImage, mask) scale:image.scale
orientation:image.imageOrientation];
// release the CG images
CGImageRelease(grayImage);
CGImageRelease(mask);
// return the new grayscale image
return grayScaleImage;
/* changes end here */
}
Here is the picture i got.
The background behind the baby was transparent before i made the grey/scale and light transformation.

iOS How to perform rotation on a cgimage efficiently (up to 125 frames)?

I have two images, let's call them image A and image B. I'm trying to rotate and scale image A and to draw it on top of image B at specific location.
I use the function and method below to :
1. rotate and scale my image
2. Draw Image A into Image B at a specific location.
This code works fine but is rather slow, is there a way to improve it?
Function to rotate and scale :
CGImageRef rotateAndScaleImageCreate(const CGImageRef cgImage, const CGFloat radians,const CGFloat scalefactor){
CGImageRef rotatedImageRef = NULL;
const CGFloat originalWidth = CGImageGetWidth(cgImage)*scalefactor;
const CGFloat originalHeight = CGImageGetHeight(cgImage)*scalefactor;
const CGRect imgRect = (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = originalWidth, .size.height = originalHeight};
const CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, CGAffineTransformMakeRotation(radians));
/// Create an ARGB bitmap context
CGContextRef bmContext = NYXImageCreateARGBBitmapContext(rotatedRect.size.width, rotatedRect.size.height, 0);
if (!bmContext)
return nil;
/// Rotation happen here
CGContextTranslateCTM(bmContext, +(rotatedRect.size.width * 0.5f), +(rotatedRect.size.height * 0.5f));
CGContextRotateCTM(bmContext, radians);
/// Draw the image in the bitmap context
CGContextDrawImage(bmContext, (CGRect){.origin.x = -originalWidth * 0.5f, .origin.y = -originalHeight * 0.5f, .size.width = originalWidth, .size.height = originalHeight}, cgImage);
/// Create an image object from the context
rotatedImageRef = CGBitmapContextCreateImage(bmContext);
/// Cleanup
//CGImageRelease(rotatedImageRef);
CGContextRelease(bmContext);
return rotatedImageRef;
}
Method to draw image at specific location within another image:
-(UIImage*) PositionImage:(CGImageRef)image backgroundImage:(CGImageRef)backgroundImage atPointX:(float)X pointY:(float)Y withScale:(float)scale andRotation:(float)rotation{
//////////////////////////////////////////
CGLayerRef layer;
CGImageRef resultImage;
CGContextRef context, layerContext;
void *bitmapData;
CGColorSpaceRef colorSpace;
CGSize canvasSize;
int bitmapByteCount;
int bitmapBytesPerRow;
//Get the background image
//UIImage * backgroundImg = [UIImage imageNamed:#"Mask-Inverted.png"];
//Initialize the canvas size!
canvasSize = CGSizeMake(480,640);//[backgroundImg size];
//
bitmapBytesPerRow = (canvasSize.width * 4);
bitmapByteCount = (bitmapBytesPerRow * canvasSize.height);
//Create the color space
colorSpace = CGColorSpaceCreateDeviceRGB();
bitmapData = malloc( bitmapByteCount );
//Check the the buffer is alloc'd
if( bitmapData == NULL ){
NSLog(#"Buffer could not be alloc'd");
}
//Create the context
context = CGBitmapContextCreate(bitmapData, canvasSize.width, canvasSize.height, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
if( context == NULL ){
NSLog(#"Context could not be created");
}
///Create the Layer
layer = CGLayerCreateWithContext(context, canvasSize, NULL);
if( layer == NULL ){
NSLog(#"Layer could not be created");
}
///Create the layer Context
layerContext = CGLayerGetContext(layer);
if( layerContext == NULL){
NSLog(#"No Layer context");
}
//Draw the image background into the bitmap context
CGContextDrawImage(context, CGRectMake(0.0f,0.0f,480,640),backgroundImage);
//Rotate and Scale Image
CGImageRef rotatedImage =rotateAndScaleImageCreate(image,rotation,scale);
//Draw a image on the layer
CGContextDrawImage(layerContext,CGRectMake(0,0,CGImageGetWidth(rotatedImage),CGImageGetHeight(rotatedImage)),rotatedImage);
CGImageRelease(rotatedImage);
//Draw the layer in the context at the coordinate
CGContextDrawLayerAtPoint( context, CGPointMake(X-CGImageGetWidth(rotatedImage)*0.5f, Y-CGImageGetHeight(rotatedImage)*0.5f), layer);
CGLayerRelease(layer);
//Get the result image
resultImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
//Cleanup
free(bitmapData);
CGColorSpaceRelease(colorSpace);
//Create UIImage
UIImage *imageReturned = [UIImage imageWithCGImage:resultImage];
CGImageRelease(resultImage);
return imageReturned;
}
If you're creating lots of images at the same time, reuse the same CGContext. Also, don't create a new rotated image; rotate the image within the existing context.
Basically, you should only have to create a CGContext once, no matter how many images you end up making with it. That should speed things up significantly.

iphone taking grayscale screenshot?

I'm wondering if there is a SIMPLE way to take a Grayscale screenshot, i know i can take color screenshot like this:
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *data = UIImagePNGRepresentation(image);
now what i need to add in these lines of code to make the UIImage Grayscaled? thank you for reading.
Just convert your image to gray scale.
Read this post. Good luck.
Here is the method:d
#pragma mark -
#pragma mark Grayscale
- (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;
}
Based on Cam's code with the ability to deal with the scale for Retina displays.
- (UIImage *) toGrayscale
{
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale);
int width = imageRect.size.width;
int height = imageRect.size.height;
// the pixels will be painted to this array
uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t));
// clear the pixels so any transparency is preserved
memset(pixels, 0, width * height * sizeof(uint32_t));
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// create a context with RGBA pixels
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
// paint the bitmap to our context which will fill in the pixels array
CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x];
// convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];
// set the pixels to gray
rgbaPixel[RED] = gray;
rgbaPixel[GREEN] = gray;
rgbaPixel[BLUE] = gray;
}
}
// create a new CGImageRef from our context with the modified pixels
CGImageRef image = CGBitmapContextCreateImage(context);
// we're done with the context, color space, and pixels
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixels);
// make a new UIImage to return
UIImage *resultUIImage = [UIImage imageWithCGImage:image
scale:self.scale
orientation:UIImageOrientationUp];
// we're done with image now too
CGImageRelease(image);
return resultUIImage;
}