Transparent background turns white - ios

I'm uploading an image with a transparent background to firebase. The background becomes white when I downloaded it somehow. Any idea how to fix this?
Here's my putData function.
let uploadData = imageview.image!.jpegData(compressionQuality: 0.75)
let uploadTask = imagesRef.putData(uploadData!, metadata: nil, completion: { (metadata, error) in
guard let metadata = metadata else {
return
}
And here is the download function.
URLSession.shared.dataTask(with: NSURL(string: imageURL as! String)! as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print("ERROR LOADING IMAGES FROM URL: \(String(describing: error))")
DispatchQueue.main.async {
imageView.image = UIImage()
}
return
}
DispatchQueue.main.async {
if let downloadedImage = UIImage(data: data!) {
imageCache.setObject(downloadedImage, forKey: NSString(string: imageURL!))
imageView.image = downloadedImage
}
}
}).resume()

I'm uploading an image with a transparent background to firebase. The
background becomes white when I downloaded it somehow. Any idea how to
fix this?
You're doing it right, except you're getting getting a JPEG instead of PNG data ;) Remember that JPEG does not support transparent BG.
Hope it helps!

Related

how to do something right after downloading image using SDWebImage?

So, I want to show a message to the user right after an image is downloaded and set in ImageView. I am using SDWebImage. how to do that?
Here is my current code
profilePictureImageView.sd_setImage(with: referenceImage, placeholderImage: UIImage(named: ImageName.defaultProfilePicture))
You can do it like this
profilePictureImageView.sd_setImage(with: referenceImage, placeholderImage: UIImage(named: "cod_logo"), options: [.highPriority]) { (image, error, cashtype, url) in
if image != nil{
// Do something Here after load image
}
print(error) // Your error is here
}
This is pod 'SDWebImage' = '4.0.0' and XCode == 11.3.1
self.userAvatar.sd_setImage(with: URL(string: __user_avatar), placeholderImage: UIImage(named: "UserDefalutAvatar"), options: .progressiveDownload, progress: { (receivedSize, expectedSize, targetURL) in
print("The progress value for the downloading is \(receivedSize)")
}) { (downloadedImage, downloadedError, imageCacheType, downloadedURL) in
if let _downloadedError = downloadedError {
print("Download image encountered error. \(_downloadedError.localizedDescription)")
return
}
if let _downloadedImage = downloadedImage {
print("This is downloaded image, you can do it what you want")
}
}

jpegData() from UIImageView is nil

I'm trying to extract the image data from a UIImageView so I can upload it to Firebase Storage. However, iv.image?.jpegData() is returning nil. I'm using the standard Kingfisher library method to add the image from the URL to the UIImageView.
Here's my code:
let url = URL(string: "https://pbs.twimg.com/profile_images/1229497999392477186/BMXkjVEJ_400x400.jpg")
let iv = UIImageView()
iv.kf.setImage(with: url)
if let png = iv.image?.jpegData(compressionQuality: .leastNormalMagnitude){
filePath.putData(png, metadata: nil){ metadata, error in
print("metadata: \(metadata) |error: \(error)") // doesn't print
}
}
Any idea why iv.image?.jpegData() is nil? I've also tried iv.image?.pngData() and that is also nil.
As
iv.kf.setImage(with: url)
is asynchronous iv.image?.jpegData()/iv.image?.pngData() will be nil until the image is loaded from the server
setImage doesn't change the image property automatically. It has to potentially download the image from the Internet, which takes time.
Luckily, you can know when the download is completed by adding a completionHandler:
iv.kf.setImage(with: url, completionHandler: { result in
guard case .success(let imageResource) = result else {
// an error has occurred!
return
}
if let png = imageResource.image.jpegData(compressionQuality: .leastNormalMagnitude){
filePath.putData(png, metadata: nil){ metadata, error in
print("metadata: \(metadata) |error: \(error)") // doesn't print
}
}
})
As #Sh_Khan has explained you need to wait for the async call to finish. Here's is the fix:
let url = URL(string: "https://pbs.twimg.com/profile_images/1229497999392477186/BMXkjVEJ_400x400.jpg")
let iv = UIImageView()
iv.kf.setImage(with: url) { _ in
if let png = iv.image?.jpegData(compressionQuality: .leastNormalMagnitude){
filePath.putData(png, metadata: nil){ metadata, error in
print("metadata: \(metadata) |error: \(error)")
}
}
}

setImageWith Url completion block swift ios

I am new to swift. I am loading image with url
mainImageView.setImageWith(URL(string: ("https:" + (content?.imagePath)!)), placeholderImage: nil)
print("dimensions after loading \(String(describing: mainImageView.image?.size))")
In case, I print the dimensions of the image as shown above then dimensions come out to be 21*6.5. However, if I wait for sometime and then print the dimensions are 188*109. How do I add a completion block to setImageWith so that I can come to know when image has finished loading?
You can use Sdwebimage for loading the image with completion block https://github.com/rs/SDWebImage
imageView.sd_setImageWithURL(NSURL(string: urlString), completed: {
(image, error, cacheType, url) in
// you can get the image width here...
})
It is happening because URL will always take a time to load image thats why first you got 21*6.5 dimensions and then got real dimensions 188*109.
As best way to prefer 3rd party library SDWebImage that will manage all the thing, You just need to set image URL.
There is method name is
open func sd_setImage(with url: URL!, placeholderImage placeholder: UIImage!, options: SDWebImageOptions = [], completed completedBlock: SDWebImage.SDWebImageCompletionBlock!)
that has completion block so you can manage whatever you want.
Convert image URL into data then Data into UIIamge, Here is a function:
func getImageFromUrl(_ strUrl: String, completionHandler handler: #escaping (_ img: UIImage) -> Void) {
DispatchQueue.global(qos: .background).async {
let url = URL(string: strUrl)
let dataFromUrl = Data(contentsOf: url!)
if dataFromUrl == nil {
return
}
DispatchQueue.main.async(execute: {() -> Void in
handler(UIImage(data: dataFromUrl!))
})
})
}
Use This: -
let imageCache = NSCache<AnyObject, AnyObject>()
typealias CompletionHandler = (_ success:Bool, _ image:UIImage?) -> Void
func loadImageUsingCacheWithUrlString(_ urlString:
String,completionHandler: #escaping CompletionHandler) {
let image = UIImage()
//check cache for image first
if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
image = cachedImage
completionHandler(true, image!)
return
}
if urlString.characters.count == 0 {
completionHandler(false, image)
return
}
//otherwise fire off a new download
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
//download hit an error so lets return out
if error != nil {
print(error ?? "")
completionHandler(false,nil)
return
}
DispatchQueue.main.async(execute: {
if let downloadedImage = UIImage(data: data!) {
image = downloadedImage
imageCache.setObject(downloadedImage, forKey: urlString as AnyObject)
completionHandler(true,image)
}
})
}).resume()
}

How to download and view images from the new Firebase Storage?

I am able to upload images to Firebase Storage but I am having trouble downloading them. This is my code to download images:
let storage = FIRStorage.storage()
let localURL : NSURL! = NSURL(string: "file:///Documents/co.png")
// i also tried let localURL : NSURL! = NSURL.fileURLWithPath("file:///Documents/co.png")
func download() {
let storageRef = storage.referenceForURL("gs://project-5547819591027666607.appspot.com")
let imageRef = storageRef.child("co.png")
let downloadTask = imageRef.writeToFile(localURL) { (URL, error) -> Void in
if (error != nil) {
print(error?.localizedDescription)
}
else {
self.imageView.image = UIImage(data: data!)
}
}
}
I am receiving - Optional("An unknown error occurred, please check the server response.")
Also once I get them downloaded How would I view that image?
For trying to see if the image was downloaded I created a UIImageView and set an outlet for it in storyboard called "imageView" then set the downloaded image to the UIImageView.
self.imageView.image = UIImage(data: data!)
Try
first getting reference to the image you want to download using
let reference = FIRStorage.storage().reference("uploads/sample.jpg")
If you know the size of image is low - like 1-2 mb max . download the image in memory
reference.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
print(error)
} else {
let myImage: UIImage! = UIImage(data: data!)
}
}
This will be the quickest and easy way to download directly from Firebase Storage.
However there are cases when you want the progress blocks and certain other things like caching. In such cases you could use any third party like Alamofire to download the image from the url you get from Firebase Storage.
To get the url do something like this
reference.downloadURLWithCompletion { (URL, error) -> Void in
if (error != nil) {
// Handle any errors
} else {
print(URL)
// download image using NSURLSession or Alamofire
}
}

Async image loading from url inside a UITableView cell - wrong image loading while scrolling

I have a tableView that displays an image in the cell. Most of the time the correct image will be displayed, however occasionally it will display the wrong image (usually if scrolling down the tableView very quickly). I download the images asynchronously.
cell.profImg.getImgFromUrl(link: man.img, contentMode: cell.profImg.contentMode)
And here i do async request:
extension UIImageView {
func getImgFromUrl(link link:String, contentMode mode: UIViewContentMode) {
guard
let url = NSURL(string: link)
else {return}
contentMode = mode
NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
guard
let httpURLResponse = response as? NSHTTPURLResponse where httpURLResponse.statusCode == 200,
let mimeType = response?.MIMEType where mimeType.hasPrefix("image"),
let data = data where error == nil,
let image = UIImage(data: data)
else { return }
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.image = image
}
}).resume()
}
}
I think it's because you do not reset the content of your UIImageView when you start loading you HTTP image. So, when the cell is reused, you display the previously loaded image.
You just have to start your getImgFromUrl by something like self.image = nil (if you want a blank image) or self.image = myPlaceholderImage (if you want a placeholder image during the loading time). Here is how to integrate it in your code:
extension UIImageView {
func getImgFromUrl(link: String, contentMode mode: UIView.ContentMode) {
guard let url = URL(string: link) else { return }
contentMode = mode
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil, let image = UIImage(data: data) else { return }
DispatchQueue.main.async {
self.image = image
}
}).resume()
}
}
But I think you should consider the use of SDWebImage. This library provides a category for UIImageView with support for remote images coming from the web. It will be much more efficient and easier for you.

Resources