3

I didn't like apples image picker so I decided to implement my own. I just finished the stage of getting all the users photos and displaying them in a collection view although I noticed that the difference in image quality is horrible. Here is my code:

import UIKit
import Photos
import PhotosUI
import Foundation

private let reuseIdentifier = "Cell"
var selectedImage = UIImage()

class CollectionVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    
    var imageArray = [UIImage]()
    
    override func viewDidLoad() {
        super.viewDidLoad()

     grapPhotos()
       

        
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        return imageArray.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath)
        let imageView = cell.viewWithTag(1) as! UIImageView
        
        
        cell.layer.cornerRadius = 4
        imageView.image = imageArray[indexPath.row]
    
        
        return cell
    }
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        let selectedImageName = imageArray[indexPath.item]
        print(selectedImageName)
        selectedImage = selectedImageName
        performSegue(withIdentifier: "Custom", sender: self)
    }
    
    func grapPhotos() {
        
        let imgManager = PHImageManager.default()
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = true
        requestOptions.deliveryMode = .highQualityFormat
        
        
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        fetchOptions.predicate = NSPredicate(format: "mediaType = %d || mediaType = %d", PHAssetMediaType.image.rawValue, PHAssetMediaType.video.rawValue)
        
        if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: fetchOptions) {
            
            if fetchResult.count > 0 {
                
                for i in 0..<fetchResult.count {
                    imgManager.requestImage(for: fetchResult.object(at: i), targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: {
                        
                        image, error in
                        
                        
                        self.imageArray.append(image!)
                        
                        
                    })
        
                    
                }
            }
            else {
                self.collectionView?.reloadData()
                print("No Photos")
            }
        }
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        let width = collectionView.frame.width / 3 - 6
        
        
        
        return CGSize(width: width, height: width)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        
        return 6.0
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        
        return 6.0
    }
}

I don't really know much about working with images so if anyone could help me out on displaying higher quality images that would be great.

coder
  • 35
  • 6
  • Why do you use .aspectFill and not .aspectFit ? The former (aspectFill ) will distort the image if its size proportional the the container. – claude31 Sep 01 '20 at 18:01
  • @claude31 since I have the images in a collection view I would like all the images to be the same size – coder Sep 01 '20 at 18:19
  • Yes, but aspectFill may distort them. Is it the problem you get ? – claude31 Sep 01 '20 at 20:27
  • But I look at other apps and they have aspect fill images with high quality. I think it has something to do with the answer @rohanphadte posted – coder Sep 02 '20 at 01:06
  • Does it work with the scale factor ? Normally that will make the image larger but not change the quality. Thanks to report. – claude31 Sep 02 '20 at 06:08
  • @claude31 It actually makes the image larger and have better quality. I have really been struggling on how to have an image with high quality and not zoomed in a ton. – coder Sep 02 '20 at 06:11

2 Answers2

2

This really works))

for index in 0..<fetchResult.count {
        let asset = fetchResult.object(at: index) as PHAsset
        let sizeFactor = UIScreen.main.scale
        let deviceSize = UIScreen.main.nativeBounds.size
        manager.requestImage(for: asset,
                                targetSize: CGSize(width: deviceSize.width * sizeFactor,
                                                   height: deviceSize.height * sizeFactor),
                                contentMode: .aspectFit,
                                options: requestOptions,
                                resultHandler: { (uiimage, info) in
            if let image = uiimage {
                allImages.append(image)
            }
        })
    }

You only need to know ->

let sizeFactor = UIScreen.main.scale
let deviceSize = UIScreen.main.nativeBounds.size
PAULMAX
  • 87
  • 1
  • 11
1

Image quality depends on the phone your viewing on - retina screens require more pixels. You'll need to multiply your targetSize by UIScreen.main.scale.

Try setting targetSize: CGSize(width: 200 * UIScreen.main.scale, height: 200.0 * UIScreen.main.scale) in your imgManager.requestImage function.

For Retina displays, the scale factor may be 3.0 or 2.0 and one point can represented by nine or four pixels, respectively. For standard-resolution displays, the scale factor is 1.0 and one point equals one pixel.

rohanphadte
  • 978
  • 6
  • 19
  • I'm a little confused by what you're saying. I assume you mean one of two things: first off, I have to change the the target size in which case I don't know how to do that. Secondly, it just depends on my phone but then that leads me to the question why does other images on my phone have higher quality? – coder Sep 02 '20 at 01:04
  • Changing target size means changing `targetSize: CGSize(width: 200 * UIScreen.main.scale, height: 200.0 * UIScreen.main.scale)` in the `requestImage` function. I'm not sure what you mean by "why does other images on my phone have higher quality". Are you referring to other images on your phone in apple's image picker or using this collection view that you've made? – rohanphadte Sep 02 '20 at 01:11
  • Quick update I ended up changing the code to: `targetSize: CGSize(width: 150, height: 150 * UIScreen.main.scale * UIScreen.main.scale * UIScreen.main.scale` I seemed to get the highest quality when doing this although this zooms in on the image so I'm wondering how to not do that. – coder Sep 02 '20 at 02:34
  • Why multiply 3 times the height ? – claude31 Sep 02 '20 at 06:42