1

Here is code that prepares-for a segue, and then unwinds from that segue.

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "toTossImageVC" {
        let dvc = segue.destination as! TossImageViewController
        dvc.displayedImage = tossPhoto2.image
    }
}

@IBAction func unwindToTossVC(unwindSegue: UIStoryboardSegue) {

    let dvc = unwindSegue.source as! TossImageViewController
    self.tossPhoto2.image = dvc.displayedImage
}

As can be seen, I am passing an image to the destination VC in the prepare for, and then I am retrieving an updated version of that image (the user can tag the image in the destination VC) in the unwind method.

self.tossPhoto2 is a UIImage object and its contentMode is set to scaleToFill in Interface Builder. My problem is that when I do the unwind and assign tossPhoto2's image to dvc.displayedImage, it gets horribly shrunk. Before segueing and tagging the image:

BeforePhotoFine

Then, when we return to this VC after tagging the photo with labels, here's the horribly shrunk photo after:

AfterPhotoShrunk

After searching StackOverflow and other places for a couple of hours, the best suggestion to solving the problem was to set contentMode to .scaleAspectFit but that didn't work (and I want to keep this as scaleToFill anyway as defined in Interface Builder).

Any ideas why this is happening and how I can fix this? Here's the code in TossImageViewController if it helps, but I don't see how I might be inadvertently shrinking the image. This could allows the user to add tags (implemented as UILabels) onto the image.

class TossImageViewController: UIViewController, UINavigationControllerDelegate, UIGestureRecognizerDelegate {
@IBOutlet var tossImage: UIImageView!
var displayedImage: UIImage!
let ac = UIAlertController(title: "Select Toss Type", message: nil, preferredStyle: .actionSheet)
var selectedTossType = String()
var touchPoint: CGPoint!


override func viewDidLoad() {
    super.viewDidLoad()
    tossImage.image = displayedImage

    self.tabBarController?.tabBar.isHidden = true

    let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
    self.view.addGestureRecognizer(gestureRecognizer)

    // Set up the action sheet picker
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    ac.addAction(cancelAction)
    let trashAction = UIAlertAction(title: "Trash", style: .destructive, handler: {(action) -> Void in
        self.selectedTossType = "Trash"
        // Write the selected toss type where the tap happened
        self.displayedImage = self.textToImage(drawText: self.selectedTossType as NSString, inImage: self.displayedImage, atPoint: self.touchPoint, labelWidth: 80)
        print("Trash tag")
    })
    ac.addAction(trashAction)
    let sinkAction = UIAlertAction(title: "Sink Disposal", style: .destructive, handler: {(action) -> Void in
        self.selectedTossType = "Sink Disposal"
        // Write the selected toss type where the tap happened
        self.displayedImage = self.textToImage(drawText: self.selectedTossType as NSString, inImage: self.displayedImage, atPoint: self.touchPoint, labelWidth: 120)
    })
    ac.addAction(sinkAction)
    let saveAction = UIAlertAction(title: "Save for Later", style: .destructive, handler: {(action) -> Void in
        self.selectedTossType = "Save for Later"
        // Write the selected toss type where the tap happened
        self.displayedImage = self.textToImage(drawText: self.selectedTossType as NSString, inImage: self.displayedImage, atPoint: self.touchPoint, labelWidth: 140)
    })
    ac.addAction(saveAction)
    let animalAction = UIAlertAction(title: "Animal", style: .destructive, handler: {(action) -> Void in
        self.selectedTossType = "Animal"
        // Write the selected toss type where the tap happened
        self.displayedImage = self.textToImage(drawText: self.selectedTossType as NSString, inImage: self.displayedImage, atPoint: self.touchPoint, labelWidth: 80)
    })
    ac.addAction(animalAction)
    let sharingAction = UIAlertAction(title: "Sharing", style: .destructive, handler: {(action) -> Void in
        self.selectedTossType = "Sharing"
        // Write the selected toss type where the tap happened
        self.displayedImage = self.textToImage(drawText: self.selectedTossType as NSString, inImage: self.displayedImage, atPoint: self.touchPoint, labelWidth: 80)
    })
    ac.addAction(sharingAction)
    let compostAction = UIAlertAction(title: "Compost", style: .destructive, handler: {(action) -> Void in
        self.selectedTossType = "Compost"
        // Write the selected toss type where the tap happened
        self.displayedImage = self.textToImage(drawText: self.selectedTossType as NSString, inImage: self.displayedImage, atPoint: self.touchPoint, labelWidth: 80)
    })
    ac.addAction(compostAction)

}

override func viewWillDisappear(_ animated: Bool) {
    self.tabBarController?.tabBar.isHidden = false
}

@IBAction func cancel(_ sender: Any) {
    navigationController!.popViewController(animated: true)
}

func textToImage(drawText text: NSString, inImage image: UIImage, atPoint point: CGPoint, labelWidth: CGFloat) -> UIImage {

    let label = UILabel(frame: CGRect(x: (point.x - labelWidth/2), y: point.y, width: labelWidth, height: 20))
    label.textColor = .red
    label.shadowColor = .yellow
    label.text = text as String
    label.textAlignment = .center
    self.view.addSubview(label)

    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(image.size, false, scale)
    view.layer.render(in: UIGraphicsGetCurrentContext()!)
    let taggedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return taggedImage!
}
Yorma
  • 80
  • 9
  • 1
    The `contentMode` does *not* change the image - it simply changes the way it is **displayed**. I'm guessing that something in `TossImageViewController` is modifying the image and, without you doing so intentionally, is creating a *small* version, and then returning that. – DonMag Aug 08 '17 at 17:48
  • Understand on contentMode. Per your tip, I inspected image.size throughout the execution of this issue (between both VCs) and it never changes: 3000 wide by 2002 high. Still digging for an answer. I can share the code in TossImageViewController if that helps. – Yorma Aug 08 '17 at 20:03

1 Answers1

0

OK - it looks like this is the problem...

You have a UIImageView in your TossImageViewController - I don't know its size, but let's say it's 300x300. You set its .image = displayedImage. So far, so good... you see your image scaled to fit on the screen.

Next, after user interaction, you call textToImage(...) and I'm guessing you are trying to draw the text onto the original image? If so, that's not what's happening.

Instead, you are adding a UILabel to self.view, creating a Graphics Context of 3000 x 2002, and then returning UIGraphicsGetImageFromCurrentImageContext() ... but that image is the current view - which is perhaps 750 x 1334 and sitting in the upper-left corner of the Context.

What you need to do is, either:

a) create a 3000 x 2002 UIView, add the image in a UIImageView as a subview of that view, then add the UILabel (sized relative to the big image) as another subview. Then get the image from that context. Or...

b) use the Context and image drawInRect and string drawInRect functions.

This post has some discussion and solutions (both Obj-C and Swift): How to write text on image in Objective-C (iOS)?

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • Thank you! This got me over the hump -- I ended up following the discussion in the link you provided and I'm now (very close) to getting the exact behavior I'm looking for. I really appreciate it! – Yorma Aug 08 '17 at 23:34
  • DonMag - In following the code in the SO post you linked to, I can get things working without shrinking the image, all good there. But now the text isn't showing up where the user taps, as I describe in this post: https://stackoverflow.com/questions/45580224/swift-3-nsstring-drawin-rect-withattributes-text-not-being-drawn-at-ex. Any thoughts on why that is happening? – Yorma Aug 16 '17 at 17:45