I'm trying to replicate a function of Instagram where you have your picture and you can add stickers (others images) and then save it.
So on the UIImageView
that holds my picture, I add the sticker (another UIImageView
) to it as a subview, positioned at the center of the parent UIImageView
.
To move the sticker around the picture, I do it using a CGAffineTransform
(I don't move the center of the UIImageView
). I also apply a CGAffineTransform
for rotating and scaling the sticker.
To save the picture with the stickers, I use a CGContext
as following:
extension UIImage {
func merge2(in rect: CGRect, with imageTuples: [(image: UIImage, viewSize: CGSize, transform: CGAffineTransform)]) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
draw(in: CGRect(size: size), blendMode: .normal, alpha: 1)
// Those multiplicators are used to properly scale the transform of each sub image as the parent image (self) might be bigger than its view bounds, same goes for the subviews
let xMultiplicator = size.width / rect.width
let yMultiplicator = size.height / rect.height
for imageTuple in imageTuples {
let size = CGSize(width: imageTuple.viewSize.width * xMultiplicator, height: imageTuple.viewSize.height * yMultiplicator)
let center = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
let areaRect = CGRect(center: center, size: size)
context.saveGState()
let transform = imageTuple.transform
context.translateBy(x: center.x, y: center.y)
context.concatenate(transform)
context.translateBy(x: -center.x, y: -center.y)
// EDITED CODE
context.setBlendMode(.color)
UIColor.subPink.setFill()
context.fill(areaRect)
// EDITED CODE
imageTuple.image.draw(in: areaRect, blendMode: .normal, alpha: 1)
context.restoreGState()
}
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
The rotation inside the transform is taken into account. The scaling inside the transform is taken into account.
But the translation inside the transform seems to no work (there is a tiny translation but it doesn't reflect the real one).
I'm obviously missing something here but can't find out what.
Any idea?
EDIT:
Here are some screenshots of how the sticker looks like on the app and what is the final image saved in the library. As you can see, the rotation and scale (the width/height ratio) of the final image are the same than the one in the app.
The UIImageView
holding the UIImage
has the same ratio than its image.
I also added a background when drawing the sticker to clearly see the bounds of the actual image.
No rotation or scaling:
Rotated and scaled:
EDIT 2:
Here is a test project that reproduces the behaviour described above.