Render a single UIImage and rotation has to be applied - objective-c

I have rendered few UIImage objects using CGContextDrawImage. But when i apply rotation to the image, it is not applied and the view disappears.
code here
-(void )renderImage: (ItemView *)array
{
NSArray *selectedImages = self.slideView.selectedView.subviews;
CGSize combinedSize = CGSizeMake(0, 0);
for (int i = 0; i < [selectedImages count]; ++i) {
CGSize sourceSize = [selectedImages[i] size];
NSLog(#"sdfsd %f %f ", sourceSize.width, sourceSize.height);
combinedSize.width = MAX(combinedSize.width, sourceSize.width);
combinedSize.height += sourceSize.height;
}
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
{
CGContextTranslateCTM(context, 0, 768);
CGContextScaleCTM(context, 1,-1);
for (int i = 0; i < [selectedImages count]; ++i) {
UIImageView *imageview = selectedImages[i];
UIImage *sourceImage = imageview.image;
CGContextSaveGState(context);
float radians1 = atan2(imageview.transform.a, imageview.transform.b);
CGFloat angle = [(NSNumber *)[imageview valueForKeyPath:#"layer.transform.rotation.z"] floatValue];
printf("\n radians %f",radians1);
printf("\n angle %f",angle);
CGContextRotateCTM(context, radians(angle));
CGContextDrawImage(context, imageview.frame, imageview.image.CGImage);
CGContextRestoreGState(context);
//CGContextDrawImage(context, imageview.frame, imageview.image);
}
}
UIImage *combinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(combinedImage, nil, nil, nil);
}
Thanks,
Any help would be appreciated

Let's say you have an array of source images:
NSArray *sourceImages = ...;
// each element of sourceImages is a UIImage
Now you want to take the first count images from the array and concatenate them vertically into a new image. Start by figuring out the size of the combined image:
CGSize combinedSize = CGSizeMake(0, 0);
for (int i = 0; i < count; ++i) {
CGSize sourceSize = [sourceImages[i] size];
combinedSize.width = MAX(combinedSize.width, sourceSize.width);
combinedSize.height += sourceSize.height;
}
Next, create a graphics context of that size:
UIGraphicsBeginImageContextWithOptions(combinedSize, NO, 0); {
Now draw each component image into the graphics context at the appropriate position:
CGFloat y = 0;
for (int i = 0; i < count; ++i) {
UIImage *sourceImage = sourceImages[i];
[sourceImage drawAtPoint:CGPointMake(0, y)];
y += sourceImage.size.height;
}
Finally, create the combined image from the context and dispose of the context:
}
UIImage *combinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Read Drawing and Printing Guide for iOS - Drawing and Creating Images for more information.

I cracked the answer . # rob mayoff : Thanks much who helped me out.
code here
//code to render group of images excluding the image which has been selected in a particular view
-(void )renderImage: (ItemView *)selectedItem
{
NSArray *selectedImages = self.slideView.selectedView.subviews;
int selectedItemIndex = [selectedImages indexOfObject:selectedItem];
if(selectedItem.image==nil){
[selectedItem loadImageFromFile];
}
// first set
UIGraphicsBeginImageContextWithOptions(self.slideView.selectedView.frame.size, NO, 0);
for (int i = 0; i < selectedItemIndex; ++i) {
if([selectedImages[i] isKindOfClass:[ItemView class]]){
ItemView *imageview = (ItemView *)selectedImages[i];
CGAffineTransform transform = imageview.transform;
imageview.transform = CGAffineTransformIdentity;
UIImage *image = [[UIImage alloc] initWithContentsOfFile:imageview.filename];
UIImageView *renderImageView = [[UIImageView alloc] initWithImage:image]; //[imageview copy];
renderImageView.frame = imageview.frame;
renderImageView.bounds = imageview.bounds;
imageview.transform = transform;
renderImageView.transform = transform;
renderImageView.center = CGPointMake(imageview.frame.size.width/2,imageview.frame.size.height/2);
UIView *view = [[UIView alloc] initWithFrame:renderImageView.frame];
view.backgroundColor = [UIColor clearColor];
[view addSubview:renderImageView];
[renderImageView release];
[image release];
imageview.image = nil;
UIGraphicsBeginImageContext(imageview.frame.size);
CGContextRef context1 = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context1];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[view release];
[result drawAtPoint:imageview.frame.origin];
}
}
UIImage *combinedImage1 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//UIImageWriteToSavedPhotosAlbum(combinedImage1, nil, nil, nil);
if (groupBgImage1) {
[groupBgImage1 removeFromSuperview];
[groupBgImage1 release];
groupBgImage1 = nil;
}
groupBgImage1 = [[UIImageView alloc] initWithImage:combinedImage1];
[self.slideView.selectedView insertSubview:groupBgImage1 belowSubview:selectedItem ];
// second set
UIGraphicsBeginImageContextWithOptions(self.slideView.selectedView.frame.size, NO, 0);
for (int i = selectedItemIndex+1; i < [selectedImages count]; ++i) {
if([selectedImages[i] isKindOfClass:[ItemView class]]){
ItemView *imageview = (ItemView *)selectedImages[i];
CGAffineTransform transform = imageview.transform;
imageview.transform = CGAffineTransformIdentity;
UIImage *image = [[UIImage alloc] initWithContentsOfFile:imageview.filename];
UIImageView *renderImageView = [[UIImageView alloc] initWithImage:image]; //[imageview copy];
renderImageView.frame = imageview.frame;
renderImageView.bounds = imageview.bounds;
imageview.transform = transform;
renderImageView.transform = transform;
renderImageView.center = CGPointMake(imageview.frame.size.width/2,imageview.frame.size.height/2);
UIView *view = [[UIView alloc] initWithFrame:renderImageView.frame];
view.backgroundColor = [UIColor clearColor];
[view addSubview:renderImageView];
[renderImageView release];
[image release];
imageview.image = nil;
UIGraphicsBeginImageContext(imageview.frame.size);
CGContextRef context1 = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context1];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[view release];
[result drawAtPoint:imageview.frame.origin];
}
}
UIImage *combinedImage2 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(combinedImage2, nil, nil, nil);
if (groupBgImage2) {
[groupBgImage2 removeFromSuperview];
[groupBgImage2 release];
groupBgImage2 = nil;
}
groupBgImage2 = [[UIImageView alloc] initWithImage:combinedImage2];
[self.slideView.selectedView insertSubview:groupBgImage2 aboveSubview:selectedItem ];
}

Related

Image not centered vertically in scrollview

What am I missing? The inner scrollview and the image view fill the entire screen. But somehow my image is not centered. The top left corner of the image starts in the center of the view, but I would like to have the image nicely centered. Also during zooming.
-(void)prepareScrollView
{
for(int i =0;i<[self.layoverPhotoAssets count];i++){
PHAsset *asset = self.layoverPhotoAssets[i];
FMImageZoomViewController *zoomController = [[FMImageZoomViewController alloc] init];
// UIImageView *imageView = [[UIImageView alloc] init];
int x = self.scrollView.frame.size.width * i;
zoomController.view.frame = CGRectMake(x, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
//zoomController.view.frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
[self.scrollView addSubview:zoomController.view];
zoomController.zoomScroller.delegate = self;
zoomController.imageView.tag = 1;
[self.zoomControllers addObject:zoomController];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeFast;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; //I only want the highest possible quality
options.synchronous = NO;
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:zoomController.zoomScroller.frame.size contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *result, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
if(result){
zoomController.imageView.image = result;
zoomController.imageView.backgroundColor = [UIColor redColor];
}
});
}];
//self.scrollView.contentSize= ;
}
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width * [self.layoverPhotoAssets count], 0)];
[self scrollToAsset:self.selectedAsset];
}
Consider:
zoomController.view.frame = CGRectMake(x, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:zoomController.view];
That cannot be right. If zoomController.view is to be a subview of self.scrollView, its frame within self.scrollView is in terms of the bounds of self.scrollView, not the frame of self.scrollView.
Solved it like this:
-(void)prepareScrollView
{
for(int i =0;i<[self.layoverPhotoAssets count];i++){
PHAsset *asset = self.layoverPhotoAssets[i];
FMImageZoomViewController *zoomController = [[FMImageZoomViewController alloc] init];
// UIImageView *imageView = [[UIImageView alloc] init];
int x = self.scrollView.frame.size.width * i;
zoomController.view.frame = CGRectMake(x, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
//zoomController.view.frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
[self.scrollView addSubview:zoomController.view];
zoomController.zoomScroller.delegate = self;
[self.zoomControllers addObject:zoomController];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeExact;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; //I only want the highest possible quality
options.synchronous = NO;
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:zoomController.zoomScroller.bounds.size contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
if(result){
zoomController.imageView = [[UIImageView alloc] initWithImage:result];
zoomController.imageView.frame = zoomController.zoomScroller.bounds;
[zoomController.imageView setContentMode:UIViewContentModeScaleAspectFit];
zoomController.imageView.clipsToBounds = YES;
[zoomController.imageView setCenter: self.scrollView.center];
zoomController.imageView.tag = 1;
[zoomController.zoomScroller addSubview:zoomController.imageView];
// zoomController.imageView.contentMode = UIViewContentModeCenter;
// if (zoomController.imageView.bounds.size.width > result.size.width && zoomController.imageView.bounds.size.height > result.size.height) {
// zoomController.imageView.contentMode = UIViewContentModeScaleAspectFit;
// }
}
});
}];
//self.scrollView.contentSize= ;
}
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width * [self.layoverPhotoAssets count], 0)];
[self scrollToAsset:self.selectedAsset];
}

iOS 9.3 UIGraphicsImageRenderer showing nil any other option for this?

I'm want apply feather effect to the image when cropped but want i render the image using UIGraphicsImageRenderer the render is nil(iOS 9.3) is there any other option for rendering the image in iOS 9.3
This is my code:
UIImage* Img = _myimage;
UIImageView * imageview = [[UIImageView alloc]initWithImage:Img];
[imageview setFrame:CGRectMake(0, 0, Img.size.width, Img.size.height)];
UIBezierPath *aPath;
CAShapeLayer *shapeLayer;
aPath = [UIBezierPath bezierPath];
aPath.contractionFactor = 0.8;
NSValue *mvalue = [_pointsarray objectAtIndex:0];
CGPoint mp2 = [mvalue CGPointValue];
[aPath moveToPoint:mp2];
[aPath addBezierThroughPoints:_pointsarray];
[aPath closePath];
aPath.lineWidth = 2;
shapeLayer = [CAShapeLayer new];
shapeLayer.path=aPath.CGPath;
[shapeLayer setFillColor:[UIColor redColor].CGColor];
[shapeLayer fillColor];
//Here the Renderer is nil in iOS 9.3
UIGraphicsImageRenderer * renderer = [[UIGraphicsImageRenderer alloc] initWithSize:Img.size];
UIImage *shapeImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull context)
{
[shapeLayer renderInContext: context.CGContext];
}];
CIImage * shapeCimage = [[CIImage alloc] initWithImage:shapeImage];
CIFilter * gaussianBlurFilter = [CIFilter filterWithName: #"CIGaussianBlur"];
[gaussianBlurFilter setValue:shapeCimage forKey: #"inputImage"];
[gaussianBlurFilter setValue:#8 forKey:#"inputRadius"];
CIImage * blurredCIImage = [gaussianBlurFilter valueForKey:kCIOutputImageKey];
UIImage * blurredImage = [UIImage imageWithCIImage:blurredCIImage];
UIImageView *maskedImageView = [[UIImageView alloc]initWithImage:blurredImage];
maskedImageView.contentMode = UIViewContentModeScaleAspectFit;
maskedImageView.frame = imageview.frame;
imageview.layer.mask=maskedImageView.layer;
[self.view addSubview:imageview];
UIGraphicsImageRenderer is not available in iOS 9. If you need to target this, you can easily write your own like that:
+(instancetype)LT_imageByDrawingOnCanvasOfSize:(CGSize)size usingBlock:(LTImageDrawingContextBlock)block
{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width, size.height), NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
block( context );
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return theImage;
}

Resize cropped image

Have the similar problem as this post:
How to remove the transparent area of an UIImageView after masking?
but solution doesn't help me, in my case I am cropping image to multi parts, and every part has bounds like parent image had, this is cropping function:
- (UIImage*) maskImage:(CALayer *) sourceLayer toAreaInsidePath:(UIBezierPath*) maskPath;
{
return [self compositeImage:sourceLayer onPath:maskPath usingBlendMode:kCGBlendModeSourceIn];
}
- (UIImage*) compositeImage:(CALayer *) layer onPath:(UIBezierPath*) path usingBlendMode:(CGBlendMode) blend;
{
UIGraphicsBeginImageContext([layer frame].size);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *sourceImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsBeginImageContext([layer frame].size);
[path fill];
[sourceImage drawInRect:[layer frame] blendMode:blend alpha:1.0];
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return maskedImage;
}
and how I am using it:
- (PuzzlePart *)calculate:(NSDictionary *) item
{
UIBezierPath *path = [self calculatePath:[item objectForKey:#"figure"]];
UIImageView *iView = [[UIImageView alloc] initWithImage:image];
//iView.contentMode = UIViewContentModeCenter;
UIImage *imagePart = [self maskImage:iView.layer toAreaInsidePath:path];
iView.image = imagePart;
return [[PuzzlePart alloc] initWithParams:imagePart lhckID:lifehackID];
}
- (UIBezierPath *)calculatePath:(NSArray *) points {
UIBezierPath *path = [UIBezierPath bezierPath];
NSDictionary *point = [points objectAtIndex:0];
[path moveToPoint:CGPointMake([point[#"x"] intValue], [point[#"y"] intValue])];
for (int i = 1; i < [points count]; i++) {
point = [points objectAtIndex:i];
[path addLineToPoint:CGPointMake([point[#"x"] intValue], [point[#"y"] intValue])];
}
[path closePath];
return path;
}
and place it:
- (void)placeItems
{
for (PuzzlePart *part in puzzleParts) {
UIImage *imagePart = [part imagePart];
CGRect newRect = [self cropRectForImage:imagePart];
UIImage *image = [self imageWithImage:imagePart convertToSize:newRect.size];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
//imageView.contentMode = UIViewContentModeCenter;
imageView.center = CGPointMake([self getRandomNumberBetween:0 to:self.view.frame.size.width],
[self getRandomNumberBetween:0 to:self.view.frame.size.height]);
[self.view addSubview:imageView];
while ([self viewIntersectsWithAnotherView:self.view chosenView:imageView]) {
viewPositionMovingStep++;
[self placeItem:self.view:imageView];
}
}
[self startCountdown];
}
[self cropRectForImage:imagePart] is the same method from post I marked
and this what I have after:
any ideas? Thank you!

CGRect intersection from child to self

Question
How to achieve an intersection of two sprites, when one is a child of self and the other is a child of a sprite?
As their positions are completely different relevant to the comparisons between each other?
Example; this is ran before each frame to determine whether they intersect
-(void)checkInFOVWithPlayer:(Player *)player andEnemy:(Player *)enemy {
SKNode *node = [player childNodeWithName:player.playersFOVName];
if (CGRectIntersectsRect(node.frame, enemy.frame)) {
// [self playerAimAtEnemy:enemy withPlayer:player];
NSLog(#"inframe");
} else {
NSLog(#" ");
}
}
However, node is a child of player and enemy is a child of self. So how can you check if they intersect?
Here's where they're initialised
float radianAngle = ((fovAngle) / 180.0 * M_PI);
float fovOpposite = atanf(radianAngle) * fovDistance;
SKShapeNode *fov = [SKShapeNode node];
UIBezierPath *fovPath = [[UIBezierPath alloc] init];
[fovPath moveToPoint:CGPointMake(0, 0)];
[fovPath addLineToPoint:CGPointMake(fovOpposite *-1, fovDistance)];
[fovPath addLineToPoint:CGPointMake(fovOpposite, fovDistance)];
[fovPath addLineToPoint:CGPointMake(0, 0)];
fov.path = fovPath.CGPath;
fov.lineWidth = 1.0;
fov.strokeColor = [UIColor clearColor];
fov.antialiased = NO;
fov.fillColor = [UIColor greenColor];
fov.alpha = 0.2;
fov.name = #"playerFOV";
[_playerImage addChild:fov];
and enemy
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"enemyImage" ofType:#"png"];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:bundle];
SKTexture *texture = [SKTexture textureWithImage:image];
_enemy = [Player spriteNodeWithTexture:texture];
_enemy.position = CGPointMake(100, 100);
_enemy.size = CGSizeMake(20, 20);
_enemy.playerAimAngle = [self returnRandomNumberBetween:0 to:360];
_enemy.anchorPoint = CGPointMake(0.5, 0.5);
_enemy.playerHealth = 100;
_enemy.playerIsDead = false;
[self addChild:_enemy];
-(void)checkInFOVWithPlayer:(Player *)player andEnemy:(Player *)enemy {
SKNode *fovNode = [player childNodeWithName:player.playersFOVName];
SKNode *node = [self childNodeWithName:#"enemy"];
CGPoint newPosition = [self convertPoint:node.position toNode:fovNode.parent];
if (CGRectContainsPoint(fovNode.frame, newPosition)) {
[self playerAimAtEnemy:enemy withPlayer:player];
}
}
This has ended up being my solution to the problem, Now however, I must find a way to change the frame of the node so that it is not rectangular.

Render large CATiledLayer into smaller area

I have a CATiledLayer of size 4096 x 4096 which I want to render into a PNG of size 1024 x 1024
this isnt doing it...
-(NSData *)createPNGFormat
{
UIGraphicsBeginImageContext(CGSizeMake(1024, 1024));
tiledLayer.transform = CATransform3DMakeScale(0.25, 0.25, 1.0);
[tiledLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return UIImagePNGRepresentation(image);
}
Any ideas on how to do this?
[First Hack] Brute Force , Render tile by tile. This works (slowly)
-(UIImage *)renderTileX:(NSInteger)xpos tileY:(NSInteger)ypos scale:(CGFloat)ascale
{
CGSize tiledsize = tiledLayer.tileSize;
CGRect tiledframe = tiledLayer.bounds;
CALayer *container = [CALayer layer];
container.frame = CGRectMake(0, 0, tiledsize.width,tiledsize.height);
UIGraphicsBeginImageContext(tiledsize);
[container addSublayer:tiledLayer];
tiledLayer.frame = CGRectMake(-tiledsize.width*xpos,-tiledsize.height*ypos, tiledframe.size.width, tiledframe.size.height);
[container renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[tiledLayer removeFromSuperlayer];
CGFloat fsize = tiledsize.width*ascale;
CGRect apicrect = CGRectMake(0,0,fsize,fsize);
UIGraphicsBeginImageContext(apicrect.size);
[image drawInRect:apicrect];
UIImage *thumb = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return thumb;
}
-(UIImage *)renderTiledLayer
{
UIGraphicsBeginImageContext(CGSizeMake(1024, 1024));
for (NSInteger x = 0 ; x<4; x++) {
for (NSInteger y = 0; y < 4; y++) {
NSLog(#"render %d:%d",x,y);
UIImage *tile = [self renderTileX:x tileY:y scale:0.25];
[tile drawAtPoint:CGPointMake(x*256, y*256)];
}
}
UIImage *fimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return fimage;
}
[Using the Google...] The better way
-(UIImage *)createThumb
{
UIGraphicsBeginImageContext(CGSizeMake(1024, 1024));
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 0.25, 0.25);
[tiledLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *fimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return fimage;
}