1

I have a problem with my code because I'm not clear to crop image using UIBezierPath. I have draw one shape view to move for cropping on one imageview. MyViewController has 2 imageviews and one squareview. There are originalImageView and croppedImageView(the result when cropped). I want to move my squareview to any location for cropping the originalImageView to show in croppedImageView with my shape.

enter image description here

After I move my square Shape on the originalImageView like image below.Then I tap to crop.

enter image description here

But result on croppedImageView showed wrong image like this.

enter image description here

I will detail my code:

In SquareView.m

   #import "SquareView.h"
   #import <QuartzCore/QuartzCore.h>
   @interface SquareView()
   {
         UIBezierPath *aPath;
         UILabel *textLabel;
   }

   @end
   @implementation SquareView

   - (id)initWithFrame:(CGRect)frame
   {
         self = [super initWithFrame:frame];
         if (self) {
               self.backgroundColor = [UIColor clearColor];
               self.opaque = NO;
               CGRect labelRect = CGRectMake(self.frame.size.width/2 - 30, self.frame.size.height/2 - 10, 150, 20);
               textLabel = [[UILabel alloc] initWithFrame:labelRect];
               [textLabel setBackgroundColor:[UIColor clearColor]];
        }
         return self;
   }


   -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
   {
         UITouch *aTouch = [touches anyObject];
         CGPoint location = [aTouch locationInView:self];
         CGPoint previousLocation = [aTouch previousLocationInView:self];
         self.frame = CGRectOffset(self.frame, location.x-previousLocation.x, location.y-    previousLocation.y);
         [textLabel setText:@"Click To Crop"];
         [textLabel setTextColor:[UIColor greenColor]];
         [self addSubview:textLabel];
   }

   -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
   {
         [textLabel removeFromSuperview];
   }


   - (void)drawRect:(CGRect)rect
   {
         aPath = [UIBezierPath bezierPath];
        // Start Point and Draw the lines.
         [aPath moveToPoint:CGPointMake(0,0)];
         [aPath addLineToPoint:CGPointMake(300,0)];
         [aPath addLineToPoint:CGPointMake(300, 300)];
         [aPath addLineToPoint:CGPointMake(0, 300)];
         [aPath closePath];

         //Fill Color and Line Color
         UIColor *colorBg = [UIColor clearColor];
         UIColor *lineColor = [UIColor redColor];
         [aPath setLineWidth:5];
         [lineColor setStroke];
         [aPath stroke];
         [colorBg setFill];
         [aPath fill];

     }
     @end

In MyViewController.m

     -(void)initSquareView
     {
           sqaure = [[SquareView alloc] initWithFrame:CGRectMake(100, 200, 300, 300)];

           tapeGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cropImage:)];
           tapeGesture.numberOfTapsRequired = 1;

           [sqaure addGestureRecognizer:tapeGesture];
           [sqaure addGestureRecognizer:pinchGesture];
           [self.view addSubview:sqaure];
     }

    -(void)cropImage:(UITapGestureRecognizer *)gesture
    {

            [sqaure removeFromSuperview];

            UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0);
            CGContextRef context_ = UIGraphicsGetCurrentContext();

            //(if iOS 7), (else iOS 6)
            if ([self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
               [self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO];
            else
               [self.view.layer renderInContext:context_];
            UIImage *captureImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            CGRect imageRect = CGRectMake(0, 0, sqaure.frame.size.width, sqaure.frame.size.height);
            UIGraphicsBeginImageContextWithOptions(sqaure.bounds.size, NO, 0.0f);
           //Capture as square shape
           //My problem is here 
            UIBezierPath *sqaurepath = [UIBezierPath bezierPath];
            [sqaurepath moveToPoint:CGPointMake(0,0)];
            [sqaurepath addLineToPoint:CGPointMake(300,0)];
            [sqaurepath addLineToPoint:CGPointMake(300, 300)];
            [sqaurepath addLineToPoint:CGPointMake(0, 300)];
            [sqaurepath closePath];
            [sqaurepath addClip];

            [captureImage drawInRect:imageRect];
            UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            [self.captureImageView setContentMode:UIViewContentModeScaleAspectFit];
            [self.captureImageView setImage:croppedImage];
            [self.captureImageView setUserInteractionEnabled:YES];
            [[self.captureImageView layer] setBorderColor:[UIColor redColor].CGColor];
            [[self.captureImageView layer] setBorderWidth:3];;

   }
   @end

Please help me to solve this issue.

Sovannarith
  • 614
  • 1
  • 10
  • 20
  • Why are you drawing the whole view into the context? You should be calculating a rect and drawing that rect from the image into the context. – Wain Dec 16 '13 at 16:20
  • `self.view drawViewHierarchyInRect` and `self.view.layer renderInContext`. This draws the whole view. You just want part of the image... – Wain Dec 16 '13 at 16:25
  • Yes exactly,So how to draw to correspond my image part? Please show me. – Sovannarith Dec 16 '13 at 16:30
  • i think reywenderlich.com have a very nice tutorial for this... – Saad Chaudhry Dec 16 '13 at 17:18

1 Answers1

0

Your captureImage was obtained from entire view's context. Then you draw it into another context with smaller size which equals to the size of your squareView, and then obtain the same image called croppedImage. This is exactly you have on the last screenshot and that's what your mistake is.

I actually didn't work with cropping using bezierPath, but if you need only rectangular-shaped croppings you can use much simplier way to do this: Cropping an UIImage

Community
  • 1
  • 1
Miroslav
  • 546
  • 2
  • 9
  • 22