Transforming UIImage (rotate, translate, scale) and then crop to constant size

  • Hello all.

    I have an app which the user can transform an image (rotate,
    translate, scale), On top of this image is an image has, so mostly the
    user fits in the mask the portion of the image that he wants.

    Then I need to compose an image based on what is inside the mask.
    Problem is that the composed image must have 900wX567h px, the mast is
    1/3 of those dimensions.

    So this is what i do.

    For the transformation I'm using gesture recognizers.
    when I want to compose the image this is are the steps I'm doing

    UIGraphicsBeginImageContext(size)  //size is a CGSize with 900x567
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetAllowsAntialiasing(ctx, YES);
    CGContextSetShouldAntialias(ctx, YES);
    CGContextConcatCTM(ctx, _imageView.transform);

    [_imageView.image
    drawAtPoint:CGPointMake(-_image.size.width/2,-_image.size.height/2)];

    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();

    So I get an image, with the right size, but what is in the image is
    completely different of what was inside the mask when the user edited.

    I have tried scaling the context and translating it, but nothing. I
    have close results but mostly the position and scale are wrong.

    I would appreciate any help you can provide me in this matter, as I
    dunno what I'm missing...

    Thanks in advance

    Gustavo
  • On May 24, 2012, at 12:19 AM, Gustavo Adolfo Pizano wrote:

    > For the transformation I'm using gesture recognizers.
    > when I want to compose the image this is are the steps I'm doing
    >
    > UIGraphicsBeginImageContext(size)  //size is a CGSize with 900x567
    > CGContextRef ctx = UIGraphicsGetCurrentContext();
    > CGContextSetAllowsAntialiasing(ctx, YES);
    > CGContextSetShouldAntialias(ctx, YES);
    > CGContextConcatCTM(ctx, _imageView.transform);

    The image view's transform is going to be with respect to the center of the image view, but you are translating the context with respect to its origin. You need to translate to the center of the context before you apply this transform.

    > [_imageView.image
    > drawAtPoint:CGPointMake(-_image.size.width/2,-_image.size.height/2)];
    >
    > UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    > UIGraphicsEndImageContext();

    As a general comment, you really shouldn't use your _imageView as a data model object (that is, as a container for the transform and image) as it unnecessarily locks you into using the UIImageView as the "truth". Consider for example if you wanted to use a placeholder image in your UI - you would need to somehow communicate the real image to this code via a UIImageView. Instead from an architecture POV you should should model this as an image and a transform, and the UIImageView and this code just happen to share these two components.
    --
    David Duncan
  • On May 25, 2012, at 1:07 AM, Gustavo Adolfo Pizano wrote:

    > sorry clicked wrong button and send before finishing the email.
    >
    > so, after this
    >> UIGraphicsBeginImageContext(size)  //size is a CGSize with 900x567
    >> CGContextRef ctx = UIGraphicsGetCurrentContext();
    >> CGContextSetAllowsAntialiasing(ctx, YES);
    >> CGContextSetShouldAntialias(ctx, YES);
    >> CGContextTranslateCTM(ctx, size.width/2, size.height/2);  //this
    >> will translate my context to the center of the context
    >> CGContextConcatCTM(ctx, _imageView.transform);
    >>
    > I don't quite understand the comment of using the image view's imageā€¦
    > should I then have a UIView with the imageView inside, and transform
    > the UIView instead, then draw the imageView's at the center of it?

    In a Model-View-Controller design pattern views exist to display information from the model (as provided by the controller), or to obtain data from the user (via the controller to be stored in the model). By storing the model in the view, you are basically violating the pattern's precepts.

    A mundane consequence of doing this would occur if you presented a modal view controller (such as the UIImagePickerController) and subsequently your application received a memory warning. At some point you would attempt to assign the image to the image view, but it is likely that the image view would no longer be the correct one to use. Additionally the transform on the image view that will soon be shown to the user is likely to be the wrong transform (probably identity). This would occur because when you present a modal view controller and a memory warning arrives, the view controller typically discards its views, and thus any data those views contained, on the assumption that your view controller can simply reconfigure those views as necessary later.

    > Now I'm little off on the scale matter also, I have seen many post how
    > to get the scale of a UIImageVIew, but somehow nothing seems to work.
    > :(, because I need to have the final image at that given size, but
    > enclosing what was bellow the "mask", and always the final image its
    > too zoomed.  :(.

    I'm not exactly certain what you are trying to do (mostly because I think you've elided the code that shows that) but the basic premise is "translate to your rotation origin, rotate, then translate back to the image origin". Usually the rotation origin is specified in terms of the image, but thats not always the case (and I'm not sure if it is in yours).

    Also be certain to keep discussions like this on list, as there may be many others that may have useful knowledge to impart.

    > Thanks again for your reply.
    >
    > G.
    >
    >
    > On Fri, May 25, 2012 at 10:02 AM, Gustavo Adolfo Pizano
    > <gustavxcodepicora...> wrote:
    >> Hello Duncan.
    >>
    >> Thx for reply.
    >> So if I understood properly
    >>
    >> Translating the context's center.
    >>
    >> iVar: UIImage * originalImage;
    >>
    >> ....
    >> ....
    >> UIGraphicsBeginImageContext(size)  //size is a CGSize with 900x567
    >> CGContextRef ctx = UIGraphicsGetCurrentContext();
    >> CGContextSetAllowsAntialiasing(ctx, YES);
    >> CGContextSetShouldAntialias(ctx, YES);
    >> CGContextTranslateCTM(ctx, size.width/2, size.height/2);  //this
    >> will translate my context to the center of the context
    >> CGContextConcatCTM(ctx, _imageView.transform);
    >>
    >>
    >>
    >>
    >>
    >>
    >> On Thu, May 24, 2012 at 6:49 PM, David Duncan <david.duncan...> wrote:
    >>> On May 24, 2012, at 12:19 AM, Gustavo Adolfo Pizano wrote:
    >>>
    >>>> For the transformation I'm using gesture recognizers.
    >>>> when I want to compose the image this is are the steps I'm doing
    >>>>
    >>>> UIGraphicsBeginImageContext(size)  //size is a CGSize with 900x567
    >>>> CGContextRef ctx = UIGraphicsGetCurrentContext();
    >>>> CGContextSetAllowsAntialiasing(ctx, YES);
    >>>> CGContextSetShouldAntialias(ctx, YES);
    >>>> CGContextConcatCTM(ctx, _imageView.transform);
    >>>
    >>> The image view's transform is going to be with respect to the center of the image view, but you are translating the context with respect to its origin. You need to translate to the center of the context before you apply this transform.
    >>>
    >>>> [_imageView.image
    >>>> drawAtPoint:CGPointMake(-_image.size.width/2,-_image.size.height/2)];
    >>>>
    >>>> UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    >>>> UIGraphicsEndImageContext();
    >>>
    >>>
    >>> As a general comment, you really shouldn't use your _imageView as a data model object (that is, as a container for the transform and image) as it unnecessarily locks you into using the UIImageView as the "truth". Consider for example if you wanted to use a placeholder image in your UI - you would need to somehow communicate the real image to this code via a UIImageView. Instead from an architecture POV you should should model this as an image and a transform, and the UIImageView and this code just happen to share these two components.
    >>> --
    >>> David Duncan
    >>>

    --
    David Duncan
previous month may 2012 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today