CGImageRef rotation distorted image - objective-c

Have following code for rotation:
CGFloat angleInRadians = angle * M_PI/180.0;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGRect imgRect = CGRectMake(width, height, width, height);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL,
rotatedRect.size.width,
rotatedRect.size.height,
8,
0,
colorSpace,
(CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
CGContextSetAllowsAntialiasing(bmContext, true);
CGContextSetShouldAntialias(bmContext, true);
CGContextSetInterpolationQuality(bmContext, kCGInterpolationHigh);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(
bmContext,
+(rotatedRect.size.width/2),
+(rotatedRect.size.height/2));
CGContextRotateCTM(bmContext, angleInRadians);
CGContextTranslateCTM(
bmContext,
-(rotatedRect.size.width/2),
-(rotatedRect.size.height/2));
CGContextDrawImage(bmContext, CGRectMake(0, 0, rotatedRect.size.width, rotatedRect.size.height), imgRef);
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
return rotatedImage;
As a result I getting distorted image. What I'm doing wrong here?

.
.
.
CGRect imgRect = CGRectMake(0., 0., width, height); // origin at {0, 0}; not {width, height}
.
.
.
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
CGImageRelease(bmContext); // don't need this anymore
.
.
.
As commented, the origin is at 0.0, 0.0 not at width or height.

Related

How to fix error when save UIImage with SPRectangle on IOS 6.0

This function return a black image. I use the Sparrow Library.
This is my code :
-(UIImage *) saveRectangle:(SPRectangle*)rectangle
{
int numberOfComponents = 8;
int width = rectangle.width;
int height = rectangle.height;
NSInteger bufferLenght = width * height * numberOfComponents;
NSMutableData * buffer= [NSMutableData dataWithLength:bufferLenght];
glPixelStorei(GL_PACK_ALIGNMENT, 4); // force 4 byte alignment
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, [buffer mutableBytes]);
CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, [buffer mutableBytes], bufferLenght, NULL);
CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault, ref, NULL, true, kCGRenderingIntentDefault);
uint32_t* pixels = (uint32_t *)malloc(bufferLenght);
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width*4, CGImageGetColorSpace(iref), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
CGContextTranslateCTM(context, 0.0, height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, width, height), iref);
CGImageRef outputRef = CGBitmapContextCreateImage(context);
free(pixels);
return [UIImage imageWithCGImage:outputRef];
}
The code you show has very little Sparrow code to it (other than the SPRectangle which is very akin to a CGRect). Sounds like you're trying to save a capture of a rectangular area of a Sparrow scene. Sparrow intends to abstract you from the OpenGL implementation details. Are you sure it wouldn't be easier to just use an SPRenderTexture? http://doc.sparrow-framework.org/core/Classes/SPRenderTexture.html
Also be sure you want to return an UIImage and not a SPImage. Hope it helps.

Rotated image should also follow the same pattern without white space

I am Rotating the image by using this code
- (CGImageRef)CGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle
{
CGFloat angleInRadians = angle * (M_PI / 360);
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGRect imgRect = CGRectMake(0, 0, width, height);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL,
rotatedRect.size.width,
rotatedRect.size.height,
8,
0,
colorSpace,
kCGImageAlphaPremultipliedFirst);
CGContextSetAllowsAntialiasing(bmContext, YES);
CGContextSetShouldAntialias(bmContext, YES);
CGContextSetInterpolationQuality(bmContext, kCGInterpolationHigh);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(bmContext,
+(rotatedRect.size.width/2),
+(rotatedRect.size.height/2));
CGContextRotateCTM(bmContext, angleInRadians);
CGContextTranslateCTM(bmContext,
-(rotatedRect.size.width/2),
-(rotatedRect.size.height/2));
CGContextDrawImage(bmContext, CGRectMake(0, 0,
rotatedRect.size.width,
rotatedRect.size.height),
imgRef);
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
CFRelease(bmContext);
// [(id)rotatedImage autorelease];
return rotatedImage;
}
By this i am having the resultant image like this..
those white spaces should not be there and it should follow the same pattern of that size with out that white spaces around..the rotated image....
Please help..Thanks in advance

cylindrical look Gradient in UIView

I want to draw bar with a cylindrical look and with shadow effect(As shown in the below image). Can some one help to define Linear Gradient for below look and feel.
Code:
-(void)drawRect:(CGRect)rect {
//UIview Back color is red or green
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
CGContextRef currentContext = UIGraphicsGetCurrentContext();
size_t num_locations = 4;
CGFloat locations[4] = { 0.0,0.7,0.9,1.0 };
CGFloat components[16] = { 0.0, 0.0, 0.0, 0.01,
0.0, 0.0, 0.0, 0.1,
0.0, 0.0, 0.0, 0.2,
0.0, 0.0, 0.0, 0.5
};
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), currentBounds.size.height);
CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, midCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
Here's a general purpose gradient maker:
CGGradientRef makeGradient2(NSArray *colors, CGFloat *stops)
{
size_t nc = 4;
NSInteger colorSize = nc * sizeof(CGFloat);
CGFloat *theComponents = malloc( [colors count] * colorSize );
CGFloat *compPtr = theComponents;
for (int i=0; i < colors.count; i++){
UIColor *color = [colors objectAtIndex:i];
CGColorRef cgColor = [color CGColor];
const CGFloat *components = CGColorGetComponents(cgColor);
memmove(compPtr, components, colorSize);
compPtr += nc;
}
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents (cs, theComponents, stops, colors.count);
CGColorSpaceRelease(cs);
free(theComponents);
return gradient;
}
call it like (this creates a three part gray gradient with lightest in the middle)
CGFloat stops[] = { 0.0, 0.5, 1.0};
gradient = makeGradient2([NSArray arrayWithObjects:
[UIColor colorWithRed:.2 green:.2 blue:.2 alpha:1.0],
[UIColor colorWithRed:.5 green:.5 blue:.5 alpha:1.0],
[UIColor colorWithRed:.2 green:.2 blue:.2 alpha:1.0],
nil], stops);
and then you can draw with it like (for a left to right gradient):
CGContextDrawLinearGradient(gc, gradient, CGPointMake(0.0, 0.0), CGPointMake(rect.size.width, 0.0), 0);

I rotate image upside down but how to flip it horizontally

i load image from camera roll, but this image is upside down. so i wrote method to rotate it.
CGImageRef imageRef = [image CGImage];
float width = CGImageGetWidth(imageRef);
float height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
Byte *rawData = malloc(height * width * 4);
Byte bytesPerPixel = 4;
int bytesPerRow = bytesPerPixel * width;
Byte bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
int byteIndex = 0;
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
Byte *rawData2 = malloc(height * width * 4);
for (int i = 0 ; i < width * height ; i++) {
int index = (width * height) * 4;
rawData2[byteIndex + 0] = rawData[index - byteIndex + 0];
rawData2[byteIndex + 1] = rawData[index - byteIndex + 1];
rawData2[byteIndex + 2] = rawData[index - byteIndex + 2];
rawData2[byteIndex + 3] = rawData[index - byteIndex + 3];
byteIndex += 4;
}
CGContextRef ctx = CGBitmapContextCreate(rawData2, CGImageGetWidth( imageRef ), CGImageGetHeight( imageRef ), 8, CGImageGetBytesPerRow( imageRef ), CGImageGetColorSpace( imageRef ),kCGImageAlphaPremultipliedLast );
imageRef = CGBitmapContextCreateImage (ctx);
image = [UIImage imageWithCGImage:imageRef];
CGContextRelease(context);
return image;
it's ok, but now i must flip it horizontally, and i don't know how can i do this. i try to do this second day.
thank you for help
Have you tried this:
imageView.transform = CGAffineTransformMakeScale(-1, 1);
?
You can also do the rotation by using a transformation:
imageView.transform = CGAffineTransformMakeRotation(M_PI);
You can concat the two transformation in one like this:
imageView.transform = CGAffineTransformRotation(CGAffineTransformMakeScale(-1, 1), M_PI);
If you want to make your own UIImage object, rather than manipulating views and transformations, I would still suggest you to use the approach described above to make the view draw the image as you like, then convert your UIView content into an UIImage object:
UIGraphicsBeginImageContext(rect.size);
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Existing implementation of cropImage:to:andScaleTo: and straightenAndScaleImage()?

I'm writing code to use UIImagePickerController. Corey previously posted some nice sample code on SO related to cropping and scaling. However, it doesn't have implementations of cropImage:to:andScaleTo: nor straightenAndScaleImage().
Here's how they're used:
newImage = [self cropImage:originalImage to:croppingRect andScaleTo:scaledImageSize];
...
UIImage *rotatedImage = straightenAndScaleImage([editInfo objectForKey:UIImagePickerControllerOriginalImage], scaleSize);
Since I'm sure someone must be using something very similar to Corey's sample code, there's probably an existing implementation of these two functions. Would someone like to share?
If you check the post you linked to, you'll see a link to the apple dev forums where I got some of this code, here are the methods you are asking about. Note: I may have made some changes relating to data types, but I can't quite remember. It should be trivial for you to adjust if needed.
- (UIImage *)cropImage:(UIImage *)image to:(CGRect)cropRect andScaleTo:(CGSize)size {
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef subImage = CGImageCreateWithImageInRect([image CGImage], cropRect);
CGRect myRect = CGRectMake(0.0f, 0.0f, size.width, size.height);
CGContextScaleCTM(context, 1.0f, -1.0f);
CGContextTranslateCTM(context, 0.0f, -size.height);
CGContextDrawImage(context, myRect, subImage);
UIImage* croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(subImage);
return croppedImage;
}
UIImage *straightenAndScaleImage(UIImage *image, int maxDimension) {
CGImageRef img = [image CGImage];
CGFloat width = CGImageGetWidth(img);
CGFloat height = CGImageGetHeight(img);
CGRect bounds = CGRectMake(0, 0, width, height);
CGSize size = bounds.size;
if (width > maxDimension || height > maxDimension) {
CGFloat ratio = width/height;
if (ratio > 1.0f) {
size.width = maxDimension;
size.height = size.width / ratio;
}
else {
size.height = maxDimension;
size.width = size.height * ratio;
}
}
CGFloat scale = size.width/width;
CGAffineTransform transform = orientationTransformForImage(image, &size);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Flip
UIImageOrientation orientation = [image imageOrientation];
if (orientation == UIImageOrientationRight || orientation == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scale, scale);
CGContextTranslateCTM(context, -height, 0);
}else {
CGContextScaleCTM(context, scale, -scale);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, bounds, img);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}