Draw border around content of UIImageView
Asked Answered
M

3

15

I've a UIImageView with a image with is a car with a transparent background:

enter image description here

And I want to draw a border around the car:

enter image description here

How can I reach this effect?

At the moment, I've tested CoreGraphics in this way, but without good results:

    // load the image
    UIImage *img = carImage;

    UIGraphicsBeginImageContext(img.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [[UIColor redColor] setFill];
    CGContextTranslateCTM(context, 0, img.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGRect rect = CGRectMake(0, 0, img.size.width * 1.1, img.size.height*1.1);
    CGContextDrawImage(context, rect, img.CGImage);

    CGContextClipToMask(context, rect, img.CGImage);
    CGContextAddRect(context, rect);
    CGContextDrawPath(context,kCGPathFill);

    // generate a new UIImage from the graphics context we drew onto
    UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

Any help? Thanks.

Meunier answered 12/9, 2014 at 11:38 Comment(0)
L
17

Here's what I did:

I did it in Swift just to check it in playgrounds, think you can translate it to Objective-C easily:

import UIKit

func drawOutlie(#image:UIImage, color:UIColor) -> UIImage
{
  var newImageKoef:CGFloat = 1.08
  
  var outlinedImageRect = CGRect(x: 0.0, y: 0.0, width: image.size.width * newImageKoef, height: image.size.height * newImageKoef)
  
  var imageRect = CGRect(x: image.size.width * (newImageKoef - 1) * 0.5, y: image.size.height * (newImageKoef - 1) * 0.5, width: image.size.width, height: image.size.height)
  
  UIGraphicsBeginImageContextWithOptions(outlinedImageRect.size, false, newImageKoef)
  
  image.drawInRect(outlinedImageRect)
  
  var context = UIGraphicsGetCurrentContext()
  CGContextSetBlendMode(context, kCGBlendModeSourceIn)
  
  CGContextSetFillColorWithColor(context, color.CGColor)
  CGContextFillRect(context, outlinedImageRect)
  image.drawInRect(imageRect)
  
  var newImage = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  
  return newImage
  
}

var imageIn = UIImage(named: "158jM")

var imageOut = drawOutlie(image: imageIn, UIColor.redColor())

So how does it work?

  1. We create clean context (aka canvas) with a bit bigger size then original image (for outline)
  2. We draw our image on whole canvas
  3. We fill that image with color
  4. We draw smaller image on top

You can change outline size changing this property : var newImageKoef:CGFloat = 1.08

Here's a result that I had in playgrounds

image description here

Swift 5:

extension UIImage {
    
    func drawOutline(imageKeof: CGFloat = 0.2, color: UIColor = .white)-> UIImage? {
        let outlinedImageRect = CGRect(x: 0.0, y: 0.0, width: size.width * imageKeof, height: size.height * imageKeof)
        let imageRect = CGRect(x: self.size.width * (imageKeof - 1) * 0.5, y: self.size.height * (imageKeof - 1) * 0.5, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(outlinedImageRect.size, false, imageKeof)
        draw(in: outlinedImageRect)
        let context = UIGraphicsGetCurrentContext()
        context!.setBlendMode(.sourceIn)
        context!.setFillColor(color.cgColor)
        context!.fill(outlinedImageRect)
        draw(in: imageRect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
}
Lycopodium answered 12/9, 2014 at 12:45 Comment(4)
I'm having trouble getting the same exact result with this line of code. I've converted to Swift 5. The border is not aligned to the image.Masto
bad solution, Since it's drawing the same image with scaling, which results in inhomogeneous strokeObtest
This solution is perfect, https://mcmap.net/q/719094/-how-to-add-colored-border-to-uiimage-in-swiftObtest
This did not create an equal border around all parts of the image.Epos
P
6

haawa answer for Swift 5

extension UIImage {
    func drawOutlie(imageKeof: CGFloat = 1.01, color: UIColor) -> UIImage? {

        let outlinedImageRect = CGRect(x: 0.0, y: 0.0,
                                   width: size.width * imageKeof,
                                   height: size.height * imageKeof)

        let imageRect = CGRect(x: size.width * (imageKeof - 1) * 0.5,
                           y: size.height * (imageKeof - 1) * 0.5,
                           width: size.width,
                           height: size.height)

        UIGraphicsBeginImageContextWithOptions(outlinedImageRect.size, false, imageKeof)

        draw(in: outlinedImageRect)

        guard let context = UIGraphicsGetCurrentContext() else {return nil}
        context.setBlendMode(.sourceIn)
        context.setFillColor(color.cgColor)
        context.fill(outlinedImageRect)
        draw(in: imageRect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }
}
Phlox answered 19/1, 2020 at 6:13 Comment(0)
B
1

This approach is a little bit different but more simple.

imageView.layer.shadowColor = UIColor.red.cgColor
imageView.layer.shadowOffset = CGSize(width: 0, height: 0)
imageView.layer.shadowOpacity = 1
imageView.layer.shadowRadius = 10.0
imageView.clipsToBounds = false
Bracing answered 17/2, 2021 at 9:58 Comment(1)
This is not the solution OP asked for.Boarer

© 2022 - 2024 — McMap. All rights reserved.