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;
}
Related
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;
}
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.
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;
}
I used the very simple way.
I create a bitmap based image context and draw the image scaled.
But I always get empty images.
- (UIImage *)resizeImage:(UIImage *)image to:(CGSize)newSize
{
UIGraphicsBeginImageContextWithOptions(newSize, NO, 1.0);
[image drawInRect:CGRectMake(0.0, 0.0, newSize.width, newSize.height)];
UIImage * scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
Any hint where was wrong?
I try to change the coordinate system. It still does not work.
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, newSize.height);
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
I'm working on an App which works with gestureRecognizer. With gestures it is possible to select an UIImage (such as rectangle.png) and it is possible with a UIPopoverView to change the color of that image by selecting a color for the selected image.
This image lay in a UIImageView and I think the best solution is to mask that image and set a colored image with the dame size and frame instead.
Is it the right way? How can I optimize my approach?
Which could be the best practice for this requirement?
(UIImage *)maskImage:(UIColor *)maskColor
{
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToMask(context, rect, self.CGImage);
CGContextSetFillColorWithColor(context, maskColor.CGColor);
CGContextFillRect(context, rect);
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return smallImage;
}