Resize transparent image (UIImage) without getting black background - ios

I tried to resize my UIImage which contains transparent image using next solution but it returns image without transparency, instead that transparent area become black color
extension UIImage{
func resizeImageWith(newSize: CGSize) -> UIImage {
let horizontalRatio = newSize.width / size.width
let verticalRatio = newSize.height / size.height
let ratio = max(horizontalRatio, verticalRatio)
let newSize = CGSize(width: size.width * ratio, height: size.height * ratio)
UIGraphicsBeginImageContextWithOptions(newSize, true, 0)
draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}

You are setting the opaque property to true. If you would like it to be transparent you need to set it to false:
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
Note that UIGraphicsBeginImageContextWithOptions returns an optional image so you should change your return type also and you can use defer to end your context after returning the result:
extension UIImage {
func resizeImageWith(newSize: CGSize) -> UIImage? {
let horizontalRatio = newSize.width / size.width
let verticalRatio = newSize.height / size.height
let ratio = max(horizontalRatio, verticalRatio)
let newSize = CGSize(width: size.width * ratio, height: size.height * ratio)
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
defer { UIGraphicsEndImageContext() }
draw(in: CGRect(origin: .zero, size: newSize))
return UIGraphicsGetImageFromCurrentImageContext()
}
}

Related

White line appears on image when image is converted to data using jpegData?

When I convert UIImage to data using jpegData compression it will add a thin line on top of the image, why is that so?
Also I'm using this func for resizing image.
After resizing Im converting to jpegData.
func resizeImage(image: UIImage, targetSize: CGSize , percentage:Double) -> UIImage {
let size = image.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, percentage)
// UIGraphicsBeginImageContextWithOptions(newSize , false , )
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
let image = resizeImage.jpegData(compressionQuality: 0.60)!

UIImage resizing scale

I have an image like this:
and I'd like to resize this image to a specific width: let's say 200px where the height should also get calculated. (So the image should keep its width-to-height scale)
This was all I get so far:
extension UIImage {
func resize(newSize1: CGSize) -> UIImage {
let size = self.size
let widthRatio = newSize1.width / size.width
let heightRatio = newSize1.height / size.height
var newSize2: CGSize
if(widthRatio > heightRatio) {
newSize2 = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize2 = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
let rect = CGRect(x: 0, y: 0, width: newSize2.width, height: newSize2.height)
UIGraphicsBeginImageContextWithOptions(newSize2, false, 1.0)
self.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage2!
}
}
But the function takes a CGSize size parameter (width AND height) but I just want to get a function that takes the width parameter.
How to edit my code to solve my problem?
Any help would be very appreciated :)
Note: The UIImage should get a smaller resolution (less pixels), not the Image View itself!
For Swift 4 And Swift 3 use below UIImage extension for resizing image. It's calculated height according to given width.
extension UIImage {
func resized(toWidth width: CGFloat) -> UIImage? {
let canvasSize = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale)
defer { UIGraphicsEndImageContext() }
draw(in: CGRect(origin: .zero, size: canvasSize))
return UIGraphicsGetImageFromCurrentImageContext()
}
}
You can calculate the desired height based on your width and aspect ratio of the image. The same can be applied to the height parameters. Here is a sample of the extension of the UIImage.
extension UIImage {
func resize(width: CGFloat) -> UIImage {
let height = (width/self.size.width)*self.size.height
return self.resize(size: CGSize(width: width, height: height))
}
func resize(height: CGFloat) -> UIImage {
let width = (height/self.size.height)*self.size.width
return self.resize(size: CGSize(width: width, height: height))
}
func resize(size: CGSize) -> UIImage {
let widthRatio = size.width/self.size.width
let heightRatio = size.height/self.size.height
var updateSize = size
if(widthRatio > heightRatio) {
updateSize = CGSize(width:self.size.width*heightRatio, height:self.size.height*heightRatio)
} else if heightRatio > widthRatio {
updateSize = CGSize(width:self.size.width*widthRatio, height:self.size.height*widthRatio)
}
UIGraphicsBeginImageContextWithOptions(updateSize, false, UIScreen.main.scale)
self.draw(in: CGRect(origin: .zero, size: updateSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
Based on the solution from #deoKasuhal I developed the following approach to scale an image so that the bigger size (width or height) don't exceeds a defined maximum size, defined by the parameter 'base'.
Example: if the original size is width = 4000 and height = 3000 and the parameter 'base' is set to 200 the returned image has the size 200 x 150 (or vice versa if height is bigger than width):
extension UIImage {
func resize(toBase base: CGFloat) -> UIImage {
guard base > 0 else {
return self
}
let widthRatio = base / max(self.size.width, 1)
let heightRatio = base / max(self.size.height, 1)
var updateSize = CGSize()
if (widthRatio > heightRatio) {
updateSize = CGSize(width:self.size.width * heightRatio, height:self.size.height * heightRatio)
} else {
updateSize = CGSize(width:self.size.width * widthRatio, height:self.size.height * widthRatio)
}
UIGraphicsBeginImageContextWithOptions(updateSize, false, UIScreen.main.scale)
self.draw(in: CGRect(origin: .zero, size: updateSize))
if let newImage = UIGraphicsGetImageFromCurrentImageContext() {
UIGraphicsEndImageContext()
return newImage
} else {
UIGraphicsEndImageContext()
return self
}
}
}

Resizing the image to Aspect Fit

I am trying to resize images using the following popular code and it is resizing the image but it is resizing the image as Scale to Fill, I would like to resize them as Aspect Fit. How do I do that?
func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) {
let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
UIGraphicsBeginImageContextWithOptions(newSize, true, 0)
let context = UIGraphicsGetCurrentContext()
// Set the quality level to use when rescaling
context!.interpolationQuality = CGInterpolationQuality.default
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height )
context!.concatenate(flipVertical)
// Draw into the context; this scales the image
context?.draw(image.cgImage!, in: CGRect(x: 0.0,y: 0.0, width: newRect.width, height: newRect.height))
let newImageRef = context!.makeImage()! as CGImage
let newImage = UIImage(cgImage: newImageRef)
// Get the resized image from the context and a UIImage
UIGraphicsEndImageContext()
return newImage
}
I have already set the content mode of image to Aspect Fit but still it is not working.
This is how I called the above code in my collection view controller
cell.imageView.image = UIImage(named: dogImages[indexPath.row])?.resizeImage(image: UIImage(named: dogImages[indexPath.row])
I manually selected my image in storyboard and set its content mode to apsect fit
Did you tried setting the newSize in aspect ratio of original Image size. If you want width fix calculate the height as per width and if you want height fix then calculate width as per height
Calculate height when width is fix:
let fixedWidth: CGFloat = 200
let newHeight = fixedWidth * image.size.height / image.size.width
let convertedImage = resizeImage(image: image, newSize: CGSize(width: fixedWidth, height: newHeight))
Calculate width when height is fix:
let fixedheight: CGFloat = 200
let newWidth = fixedheight * image.size.width / image.size.height
let convertedImage = resizeImage(image: image, newSize: CGSize(width: newWidth, height: fixedheight))
You can use this resized image with aspect fit ratio.
also check the answer: https://stackoverflow.com/a/8858464/2677551, that may help
func scaleImageAspectFit(newSize: CGSize) -> UIImage? {
var scaledImageRect: CGRect = CGRect.zero
let aspectWidth: CGFloat = newSize.width / size.width
let aspectHeight: CGFloat = newSize.height / size.height
let aspectRatio: CGFloat = min(aspectWidth, aspectHeight)
scaledImageRect.size.width = size.width * aspectRatio
scaledImageRect.size.height = size.height * aspectRatio
scaledImageRect.origin.x = (newSize.width - scaledImageRect.size.width) / 2.0
scaledImageRect.origin.y = (newSize.height - scaledImageRect.size.height) / 2.0
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
if UIGraphicsGetCurrentContext() != nil {
draw(in: scaledImageRect)
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return scaledImage
}
return nil
}
Usage :
let resizedImage = oldImage.scaleImageAspectFit(newSize: CGSize(width: nexSize.width, height: nexSize.height))

iOS: Get displayed image size in pixels

In my app, I'm displaying an image of a rectangle from the assets library. The image is 100x100 pixels. I'm only using the 1x slot for this asset.
I want to display this image at 300x300 pixels. Doing this using points is quite simple but I can't figure out how to get UIImageView to set the size in pixels.
Alternatively, if I can't set the size in pixels to display, I'd like to get the size in pixels that the image is being displayed.
I have tried using .scale on the UIImageView and UIImage instances, but it's always 1. Even though I have set constraints to 150 and 300.
To get size in pixels of UIImageView:
let widthInPixels = imageView.frame.width * UIScreen.mainScreen().scale
let heightInPixels = imageView.frame.height * UIScreen.mainScreen().scale
To get size in pixels of UIImage:
let widthInPixels = image.size.width * image.scale
let heightInPixels = image.size.height * image.scale
Swift 5
Take a Look here
// This extension to save ImageView as UImage
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
// this extension to resize image
extension UIImage {
func resizeImage(targetSize: CGSize) -> UIImage {
let size = self.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
let newSize = widthRatio > heightRatio ? CGSize(width: size.width * heightRatio, height: size.height * heightRatio) : CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
self.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
// This extension will display image with 300X300 pixels
extension UIImage {
func Size300X300() -> UIImage? {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
let image = imageView.asImage()
let newImage = image.resizeImage(targetSize: CGSize(width:300, height: 300))
return newImage
}
}
let image = YOURIMAGE.Size300X300()
imageView.image = image!

Swift: How to Optimize the code I wrote to resize an image after cropping?

Here's the code I wrote to resize an image after cropping. I find that I rebuild a CGImageRef to resize the cropped image. I guess there must be a way to optimize it. So how?
let imgRef: CGImageRef = CGImageCreateWithImageInRect(img.CGImage, rect)!
let croppedImg = UIImage(CGImage: imgRef, scale: 1, orientation: .Up)
let imgSize = CGSize(width: Conf.Size.avatarSize.width, height: Conf.Size.avatarSize.width)
UIGraphicsBeginImageContextWithOptions(imgSize, false, 1.0)
croppedImg.drawInRect(CGRect(origin: CGPointZero, size: imgSize))
let savingImgContext = UIGraphicsGetCurrentContext()
UIGraphicsEndImageContext()
if let savingImgRef: CGImageRef = CGBitmapContextCreateImage(savingImgContext) {
let savingImg = UIImage(CGImage: savingImgRef, scale: 1, orientation: .Up)
UIImageWriteToSavedPhotosAlbum(savingImg, nil, nil, nil)
}
Here's a function I use to resize images. Hopefully it is what you are looking for.
func ResizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
let size = image.size
let widthRatio = targetSize.width / image.size.width
let heightRatio = targetSize.height / image.size.height
// Figure out orientation
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}

Resources