How to send high quality images to another view using collectionview - swift

My question is really simple. I have a collectionView and I'm sending image from it to another view and showing it. But the problem is that the quality is really bad. I made collectionView from photolibrary using tutorial from youtube. Here's my code how I'm sending image.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCell = collectionView.cellForItem(at: indexPath) as! CollectionViewCell
ujaj = selectedCell.imageView.image
performSegue(withIdentifier: "segue077", sender: self)
}
And my full code:
import UIKit
import Photos
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet public var bandau: UIImageView!
var imageArray = [UIImage]()
override func viewDidLoad() {
grabPhotos()
}
func grabPhotos(){
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat // Quality of images
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count {
imgManager.requestImage(for: fetchResult.object(at: i) as! PHAsset, targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image, error in
self.imageArray.append(image!)
})
}
}
else {
print("You got no photos")
//self.collectionView?.reloadData()
}
}
}
#IBOutlet weak var fakk: UIImageView!
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
let imageView = cell.viewWithTag(1) as! UIImageView
imageView.image = imageArray[indexPath.row]
return cell
}
public var ujaj: UIImage?
#IBAction func kadsasd(_ sender: Any) {
performSegue(withIdentifier: "segue077", sender: self)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCell = collectionView.cellForItem(at: indexPath) as! CollectionViewCell
ujaj = selectedCell.imageView.image
performSegue(withIdentifier: "segue077", sender: self)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width / 3 - 1
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let main = segue.destination as! display
main.image = ujaj
}
Question is how to send FULL quality images? Because now I have 200x200 photos. If I change to higher then automatically my application crashes because of the memory. Maybe it's possible to get a full quality image when user clicks on the cell?

As long as you have your indexPath I suggest you to convert it to Integer and then ask for a photo from library once again. Don't forget to change .targetSize to PHImageManagerMaximumSize also .contentMode to PHImageContentMode.default
In your case:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let index : Int = indexPath.row
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat // Quality of images
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
imgManager.requestImage(for: fetchResult.object(at: index) , targetSize: PHImageManagerMaximumSize, contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: {
image, error in
self.ujaj = image
})
performSegue(withIdentifier: "segue077", sender: self)
}

Related

Why is the image quality so low? (swift)

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.
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
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.

I open a second view that displays a series of images in a collection, Can I press on an image of the collection for use image in the first view?

I open a second view that displays a series of images in a collection, Can I press on an image of the collection for use image in the first view?
//from first ViewController
#IBAction func backgroundButton(_ sender: UIButton) {
}
//SecondViewController
class SecondViewController: UIViewController {
#IBAction func returnHome(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
......
extension SecondViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width/2.5, height: collectionView.frame.width/2)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
cell.data = self.data[indexPath.item]
return cell
}
}
class CustomCell: UICollectionViewCell {
var data: CustomData? {
didSet {
guard let data = data else { return }
bg.image = data.backgroundImage
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
bg.isUserInteractionEnabled = true
bg.addGestureRecognizer(tapGestureRecognizer)
}
}
#objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer) {
let tappedImage = tapGestureRecognizer.view as! UIImageView
self.addSubview(tappedImage)
}
// When I tap on Image in this case addSubview but I want use that image in First View Controller

iOS Collection View Lagging

In my App I am using a CollectionView to display some Images. When I start scrolling performance is quite poor and big lags occur. I tried utilising an Image cache so the Images are not reloaded every time the cell appears. I have also tried removing the rounded edges and utilising layer.shouldRasterize. Nothing seems to help. The Images are in the Assets of the App.
let imageCache = NSCache<AnyObject, AnyObject>()
...
class MainMenuController: UIViewController, UICollectionViewDataSource, UICollectionViewDataSourcePrefetching, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionView: UICollectionView!
let reuseIdentifier = "cell"
override func viewDidLoad() {
super.viewDidLoad()
....
}
//Collection View
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MainMenuCell
cell.titleLabel.text = self.items[indexPath.item].getName()
cell.titleLabel.textColor = ColorInterface.sharedInstance.ultra_textcolor
if let imageFromCache = imageCache.object(forKey: items[indexPath.item].getKey() as AnyObject) as? UIImage {
cell.imageView.image = imageFromCache
}
else
{
let imageToCache = UIImage(named: items[indexPath.item].getImage())!
imageCache.setObject(imageToCache, forKey: items[indexPath.item].getKey() as AnyObject)
cell.imageView.image = imageToCache
}
cell.layer.cornerRadius = 7
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let totalHeight: CGFloat = (collectionView.frame.width / 2)
let totalWidth: CGFloat = (collectionView.frame.width / 2)
return CGSize(width: ceil(totalWidth - 5),height: ceil(totalHeight - 5))
}
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
for index in indexPaths
{
if imageCache.object(forKey: items[index.item].getKey() as AnyObject) == nil
{
let imageToCache = UIImage(named: items[index.item].getImage())!
imageCache.setObject(imageToCache, forKey: items[index.item].getKey() as AnyObject)
}
}
}
}
After I scrolled to the bottom once everything is silky smooth which originally lead me to believing it is the loading of the images which is causing problems. What am I doing wrong here ?

how to play video in swift 3 Xcode 8.2.1

I have displayed all local videos in Collection view as image.
but now when i click on cell it should play.
my code for displaying in collection view cell is given below
import UIKit
import Photos
import AVFoundation
import AVKit
class VideoViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var imageArrray = [UIImage]()
// var playerController = AVPlayerViewController()
// var player:AVPlayer?
// var tempVideoFetchresult = PHFetchResult<AnyObject>()
override func viewDidLoad() {
//super.viewDidLoad()
grabVideos()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func grabVideos()
{
let imgManager = PHImageManager.default()
let requestOtions = PHImageRequestOptions()
requestOtions.isSynchronous = true
requestOtions.deliveryMode = .highQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions)
{
// tempVideoFetchresult = fetchResult as! PHFetchResult<AnyObject>
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: requestOtions, resultHandler: {
image, error in
self.imageArrray.append(image!)
})
}
}else{
print("You got no photos")
self.collectionView?.reloadData()
}
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArrray.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! videoCollectionViewCell
cell.videoImageView.image = imageArrray[indexPath.row]
//let imageView = cell.viewWithTag(1) as! UIImageView
// let imageView = cell.contentView.viewWithTag(1) as! UIImageView
// imageView.image = imageArrray[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width/3 - 1
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//play video
// self.player = AVPlayer(playerItem: <#T##AVPlayerItem?#>)
}
}
i got answer
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let imgManager = PHImageManager.default()
let requestOtions = PHVideoRequestOptions()
requestOtions.deliveryMode = .highQualityFormat
imgManager.requestPlayerItem(forVideo: tempVideoFetchresult.object(at: indexPath.row) as! PHAsset, options: requestOtions, resultHandler: {
avplayeritem, error in
self.player = AVPlayer(playerItem: avplayeritem)
self.playerController.player = self.player
})
// self.player = AVPlayer(playerItem: <#T##AVPlayerItem?#>)
self.present(self.playerController,animated: true,completion: {
self.playerController.player?.play()
})
}

CollectionView return the same images twice

When I request the images and load them to my collection View, the request return low resolution images and high resolution images at the same time.
As you can see the same images are returned twice with low and hight resolution in my collectionView.
Code:
var imageArray = [UIImage]()
let imgManager = PHImageManager.default()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
grabPhoto()
}
func grabPhoto(){
let imageSize = CGSize(width: 800, height: 800)
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) as? PHFetchResult {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count {
imgManager.requestImage(for: fetchResult.object(at: i), targetSize: imageSize, contentMode: .aspectFill , options: nil, resultHandler: { (image, error) in
self.imageArray.append(image!)
self.photoImageView.image = self.imageArray.first
self.collectionView.reloadData()
print("Result Size Is \(image?.size)")
})
}
}
} else {
print("you got no Photos!")
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UploadPhotoCell", for: indexPath)
let imageView = cell.viewWithTag(1) as! UIImageView
imageView.image = imageArray[indexPath.row]
return cell
}