renderInContext image drawing with specified size - ios

How to draw smaller image than size of context without using CGAffineTransform?
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// center image
CGContextTranslateCTM(context, placement.origin.x, placement.origin.y);
[imageView.layer renderInContext:context];
The problem is that if imageView.image.size is bigger than size it will be drawn centered, but cut at borders (bigger image than drawing area). I want the image to fit, so would like to decrease size of imageView.image.size. Is there any way to achieve this using renderInContext?

Via [imageView.layer renderInContext:context]; you can't change the size (or i didn't find a way). The only option to do so, is to create now image with drawImage (on requested size), allocate new UIImageView and draw its layer.
UIImage *resizedImage = [self createNewImageFrom:currentImage withSize:size];
UIImageView *imageView = [[UIImageView alloc] initWithImage:resizedImage];
// ...
[imageView.layer renderInContext:context];
- (UIImage*)createNewImageFrom:(UIImage*)image withSize:(CGSize)size {
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0.0f, size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), image.CGImage);
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}

Why do you want to do this without transforming the context? It's the exact right tool for the job!
The simplest way here would be to call CGContextScaleCTM to apply a scale factor to the context. That scale factor will effect all drawing to the context, including the call to -renderIntoContext:.

this is version for scaled size, just replace scale with size.width and size.height for any target size.
for UIView:
-(UIImage*)convertViewToImage:(UIView*)v withScale:(float)scale{
//create bitmap context with scaled size
CGSize s = v.bounds.size;
s.width *= scale;
s.height *= scale;
UIGraphicsBeginImageContextWithOptions(s, NO, [UIScreen mainScreen].scale);
//scale CTM to render and resotre CTM
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextScaleCTM(context, scale, scale);
[v.layer renderInContext: context];
CGContextRestoreGState(context);
UIImage*image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
for UIScrollView
-(UIImage*)convertScrollContentToImage:(UIScrollView*)sv withScale:(float)scale{
//create bitmap context with scaled size
CGSize s = sv.contentSize;
s.width *= scale;
s.height *= scale;
UIGraphicsBeginImageContextWithOptions(s, NO, [UIScreen mainScreen].scale);
{
//set scroll.frame.size to contentSize, and contentOffset to 0
CGPoint savedContentOffset = sv.contentOffset;
CGRect savedFrame = sv.frame;
sv.contentOffset = CGPointZero;
sv.frame = CGRectMake(0, 0, sv.contentSize.width, sv.contentSize.height);
//scale CTM to render and resotre CTM
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextScaleCTM(context, scale, scale);
[sv.layer renderInContext: context];
CGContextRestoreGState(context);
//set scroll.frame.size and ContentOffset back
sv.contentOffset = savedContentOffset;
sv.frame = savedFrame;
}
UIImage*image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

Related

Add a semi-transparent layer to UIImage using Core Graphics

I need to take a UIImage and to add a semi-transparent layer in order to produce a new UIImage. I think I'm getting close but something is still wrong. Here's my code:
- (UIImage*) addLayerTo:(UIImage*)source
{
CGSize size = [source size];
UIGraphicsBeginImageContext(size);
CGRect rect = CGRectMake(0, 0, size.width, size.height);
[source drawInRect:rect blendMode:kCGBlendModeNormal alpha:0.18];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 0.2, 0.5, 0.1, 0.18);
CGContextFillRect(context, rect);
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return testImg;
}
You forgot to draw the current image you want to blend with source image in current context.
- (UIImage*) addLayerTo:(UIImage*)source
{
CGSize size = [source size];
UIGraphicsBeginImageContext(size, NO, [UIScreen mainScreen].scale); // Use this image context initialiser instead
CGRect rect = CGRectMake(0, 0, size.width, size.height);
[self drawInRect: rect] // Draw the current image in context
[source drawInRect:rect blendMode:kCGBlendModeNormal alpha:0.18]; // Blend with other image
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 0.2, 0.5, 0.1, 0.18);
CGContextFillRect(context, rect);
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return testImg;
}
- (UIImage*) addLayerTo:(UIImage*)source
{
CGSize size = [source size];
// create context with UIScrean scale
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
// get new context
CGContextRef ctx1 = UIGraphicsGetCurrentContext();
// draw view
CGContextDrawImage(ctx1, CGRectMake(0.0f, 0.0f, size.width, size.height), source.CGImage);
// set fill color
UIColor *fillColor = [UIColor purpleColor];
// fill with it
CGContextSetFillColorWithColor(ctx1, fillColor.CGColor);
CGContextFillRect(ctx1, CGRectMake(0, 0, size.width, size.height));
// create new image
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
// end context
UIGraphicsEndImageContext();
return outputImage;
}

Rotating UIImageView data -

Hi in my iOS application I want to rotate the UIImage data in 90 Degrees.
I used the below code for 180 degree rotation - and it works fine.
- (UIImage*)upsideDownBunny:(UIImage *)img {
CGSize imgSize = [img size];
UIGraphicsBeginImageContext(imgSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imgSize.width, -imgSize.height);
[img drawInRect:CGRectMake(0, 0, imgSize.width, imgSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
But when I try to rotate in 90 degree it is not working - please correct me
- (UIImage *)upsideDownBunny:(UIImage *)img {
CGSize imgSize = [img size];
UIGraphicsBeginImageContext(imgSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, -imgSize.width, -imgSize.height);
[img drawInRect:CGRectMake(0, 0, imgSize.width, imgSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Try this...
UIImage * LandscapeImage = [UIImage imageNamed: imgname];
UIImage * PortraitImage = [[UIImage alloc] initWithCGImage: LandscapeImage.CGImage
scale: 1.0
orientation: UIImageOrientationLeft];
hope this helps you!
Try this
- (UIImage *)upsideDownBunny:(UIImage *)image {
// Rotate in degrees
CGFloat degrees = M_PI_2;
// Calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
CGAffineTransform transform = CGAffineTransformMakeRotation(degrees);
rotatedViewBox.transform = transform;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create image context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image.
CGContextTranslateCTM(context, rotatedSize.width * 0.5f, rotatedSize.height * 0.5f);
// Rotate the image context
CGContextRotateCTM(context, degrees);
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(-image.size.width * 0.5f, -image.size.height * 0.5f, image.size.width, image.size.height), [image CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
The problem is your context is being rotated around (0,0) which is the top left corner and after 90 degrees rotate it will go out of bounds. So you need to move the origin of the context to middle.

Apply a transform in CGContextRef for drawInRect

In the code below I'm adding a small image to a large image. I need to be able to apply a transform to the small image. Right now something weird is going on, for example if I pass in a transform of CGAffineTransformMakeRotation(M_PI_2), the newImage is not rotated in place but rather drawn somewhere off screen. How can I fix this?
+ (UIImage*)addToImage:(UIImage *)baseImage newImage:(UIImage*)newImage atPoint:(CGPoint)point transform:(CGAffineTransform)transform {
UIGraphicsBeginImageContextWithOptions(baseImage.size, NO, 1);
CGContextRef context = UIGraphicsGetCurrentContext();
[baseImage drawInRect:CGRectMake(0, 0, baseImage.size.width, baseImage.size.height)];
CGRect newRect = CGRectMake(point.x,
point.y,
newImage.size.width,
newImage.size.height);
CGContextConcatCTM(context, transform);
[newImage drawInRect:newRect];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
Note that I only want to apply the transform to newImage, not baseImage.
Seems like you just forgot to translate the origin of the context before and after the rotation. Here, try this:
- (UIImage*)addToImage:(UIImage *)baseImage newImage:(UIImage*)newImage atPoint:(CGPoint)point transform:(CGAffineTransform)transform {
UIGraphicsBeginImageContextWithOptions(baseImage.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect baseRect = CGRectMake(0, 0, baseImage.size.width, baseImage.size.height);
[baseImage drawInRect:baseRect];
CGRect newRect = CGRectMake(point.x, point.y, newImage.size.width, newImage.size.height);
CGContextTranslateCTM(context, point.x, point.y);
CGContextConcatCTM(context, transform);
CGContextTranslateCTM(context, -point.x, -point.y);
[newImage drawInRect:newRect];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
EDIT:
If you want to rotate the image around its center, add the halves of the image's sides to the corresponding translation values:
float xTranslation = point.x+newRect.size.width/2;
float yTranslation = point.y+newRect.size.height/2;
CGContextTranslateCTM(context, xTranslation, yTranslation);
CGContextConcatCTM(context, transform);
CGContextTranslateCTM(context, -xTranslation, -yTranslation);

CGAffineTransformMakeRotation scales image

I have a UIImageView and I am applying a rotation transform using CGAffineTransformMakeRotation. This does not only rotate the image but scales it as well.
What is the correct way to rotate a UIImageView and retain the size/scale of the image?
I tried setting
self.image.contentMode = UIViewContentModeCenter;
self.image.autoresizingMask = UIViewAutoresizingNone;
and it doesn't seem to help.
try the below method
-(UIImage*)rotateImage:(UIImage*)img forAngle:(CGFloat)radian {
UIView *rotatedViewBox = [[UIView alloc]initWithFrame:CGRectMake(0, 0, img.size.width, img.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(radian);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, rotatedSize.width, rotatedSize.height);
CGContextRotateCTM(context, radian);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(-img.size.width, -img.size.height, img.size.width, img.size.height), img.CGImage);
UIImage *returnImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return returnImg;
}

Scale down a UIImage

How does one scale down a UIImage equally on both dimensions by half?
I have a UIImage that is double the size of the UIImageView and would like it to be the same size, without using any of the content modes for filling or scaling etc.
Just make yourself a new image (expressed as a category method of UIImage) :
- (UIImage*)scaleToSize:(CGSize)size {
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0.0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}

Resources