0

I have a cropped image (mainImage) that I allow users to draw on top of using their fingers. The red zig-zag on screen A. shows the finger drawn portion. Right now, using the code below, the newly drawn image context (red zig-zag) is shoved into the same bounds as the cropped image and I end up with a distorted zig-zag (screenshot B.). You can see how the red zig-zag has been shoved into the bounds of the cropped (mainImage).

What I am trying to achieve is an image that combines the two contexts from mainImage and drawImage without distorting the proportions of either photo. So that only the portions of the red zig-zag that overlap the mainImage will be drawn in the new context as in screenshot C.(photoshopped image of the results I would like). Right now, the commitDrawingWithOpacity: method results with screenshot B. and I would like the results of screenshot C.

I've tried CGContextClipToRect, CGContextClipToMask, and also tried creating a new rect for the draw image, among other things but so far no success. I've been stuck on this issue for almost a month now (self taught) and it is one of the very last things I need to do before I can submit my app to apple. So any help would be GREATLY appreciated. Here's a link to the code I am using https://github.com/dblapps/DAScratchPad

Here's the size of each:

drawImage.size = (width=320, height=568) // iPhone 5 screen size

mainImage.size = (width=260, height=800) // size of cropped image

my imageView is set to aspect fit ratio.

- (void) commitDrawingWithOpacity:(CGFloat)opacity {
    UIGraphicsBeginImageContext(mainImage.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextScaleCTM(ctx, 1.0f, -1.0f);
    CGContextTranslateCTM(ctx, 0.0f, -mainImage.size.height);

    CGRect rect = CGRectMake(0.0f, 0.0f, mainImage.size.width, mainImage.size.height);

    if (mainImage != nil) {
        CGContextDrawImage(ctx, rect, mainImage.CGImage);
    }

    CGContextSetAlpha(ctx, opacity);
    CGContextDrawImage(ctx, rect, drawImage.CGImage);
    mainImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    self.layer.contents = (id)mainImage.CGImage;
    drawLayer.contents = nil;
    drawImage = nil;
}

Using the function AVMakeRectWithAspectRatioInsideRect I have been able to get the correct size ratio for my mainImage but still have had no luck with getting anything to work right.

enter image description here

Below is a photoshopped screenshot of the results I am trying to achieve. Screenshot B (above) is what I am getting with my current code.

enter image description here

Jared Gross
  • 649
  • 3
  • 9
  • 23

2 Answers2

0

You are drawing the drawImage using the proportions of the mainImage hence why it's is being distorted. You should keep the proportions of the drawImage and just position it correctly. Here's a potential starting point for you to tweak - it's hard to tell exactly what you are trying to achieve from your question:

CGRect drawImageRect = (CGRect){
  .origin = {
    .x = -((drawImage.size.width - mainImage.size.width)   / 2),
    .y = -((drawImage.size.height - mainImage.size.height) / 2),
  },
  .size = drawImage.size,
};

This rect uses the original size and then adjusts the origin of where the image is drawn

Paul.s
  • 38,494
  • 5
  • 70
  • 88
  • Thanks! been at it trying to tweak what you provided but the drawImage is displaced every time . I updated my question and added a new screenshot of what I am trying to achieve. When I use the code you provided I get a negative number for y coordinate.. My mainImage.size.height is 800 and the drawImage.size.height is only 568 and feel like that is part of my problem but have no idea how to begin. – Jared Gross Mar 24 '14 at 00:02
  • I may have gotten the subtraction the wrong way round. As the width of the `drawImage` is greater than `mainImage` you should expect it to have a negative `x`. As the height of `drawImage` is smaller it should indeed be positive. – Paul.s Mar 24 '14 at 00:27
  • I understand. But as it stands, the drawImage height is 568 and the mainImage height is 800.. but the image has not been cropped by height at all. The equation would return an integer value for y when in fact y should be 0 because the image was only cropped for width. does that make sense? – Jared Gross Mar 24 '14 at 00:49
  • If the image is 800 tall then is the top or bottom off of the screen? – Paul.s Mar 24 '14 at 00:53
  • No, it is in an imageView with aspectFit ratio. sorry, should have made that clear. So I believe my problem is that I am unable to get an accurate origin point for the mainImage because the mainImage default size before cropping is (600 x 800), which is larger than the drawImage size (aka screen size) so the proportions and origins do not correspond with each other from the beginning – Jared Gross Mar 24 '14 at 00:57
  • You would make your life easier if you know the actual size of the image. You can calculate this yourself of with an AVFoundation function. [AVMakeRectWithAspectRatioInsideRect](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVFoundation_Functions/Reference/reference.html#//apple_ref/doc/uid/TP40009540) – Paul.s Mar 24 '14 at 01:04
  • Thanks, that did help with getting the correct size for the mainImage. Now I've been plugging the new AVRect in and seeing what it does in place of my mainImage.size instances but can't seem to reach the right configuration to align everything still. – Jared Gross Mar 24 '14 at 03:04
0

For me, I need to utilize both functions: AVMakeRectWithAspectRatioInsideRect & CGImageCreateWithImageInRect to get the desired results. My problem was the aspect ratio difference between my mainImage and the drawImage. So AVMakeRectWithAspectRatioInsideRect gave me a new rectangle with the correct size ratio and origin points for my mainImage. After that, I used CGImageCreateWithImageInRect to lay the [drawImage CGImage] into the new rectangle and Presto! My drawImage and mainImage create a new context with the exact same aspect ratio. No more distortion or skewing of images. Working code is posted below.

- (void) commitDrawingWithOpacity:(CGFloat)opacity {

    CGRect drawRect = AVMakeRectWithAspectRatioInsideRect(mainImage.size, self.frame);

    UIGraphicsBeginImageContext(mainImage.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextScaleCTM(ctx, 1.0f, -1.0f);
    CGContextTranslateCTM(ctx, 0.0f, -mainImage.size.height);

    CGRect rect = CGRectMake(0.0f, 0.0f, mainImage.size.width, mainImage.size.height);

    if (mainImage != nil) {
        CGContextDrawImage(ctx, rect, mainImage.CGImage);
    }

    CGImageRef imageRef = CGImageCreateWithImageInRect([drawImage CGImage], drawRect);

    CGContextSetAlpha(ctx, opacity);
    CGContextDrawImage(ctx, rect, imageRef);

    mainImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    self.layer.contents = (id)mainImage.CGImage;
    drawLayer.contents = nil;
    drawImage = nil;
}
Jared Gross
  • 649
  • 3
  • 9
  • 23