UIImagePickerView gives portion of image blank while selecting image in editing mode - swift

I am using UIImagePickerView to allow user to select profile image. After selecting image from UIImagePickerView user select portion of image (Square selection box which comes in editing mode) when user choose that image I am uploading it to a server and also storing it to a local machine part of the image comes as a black when I open that image on server as well as on device.
This is how image looks after uploading.
Following code I am using.
func launchImagePicker(){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.navigationBar.isTranslucent = false
imagePicker.navigationBar.barTintColor = UIColor(named:"navigationColor")
imagePicker.navigationBar.tintColor = .white
present(imagePicker, animated: true, completion: {
self.closeSharedWindow()
})
}
following will get call when we cancel picker
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
Here we are getting image from picker and uploading it.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var selectedImageFromPicker: UIImage?
if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage {
selectedImageFromPicker = editedImage
}
else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage {
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker{
profileImageView.image = selectedImage
self.uploadImageToServer(image: selectedImage , userId: (self.user?.userId)!) {
self.dismiss(animated: true, completion: nil)
}
}
}
following function will upload image to server
func uploadImageToServer(image: UIImage,userId: String,completion: #escaping () -> ()){
//,completion: #escaping ([String:Any])->Void
let imgData = UIImageJPEGRepresentation(image, 0.5)!
let parameters = ["userId": userId]
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "profileImage",fileName: "file.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
}
},
to:APPURL.updateProfileImage)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
self.storeProfileImageDetail(image: image)
guard let profileImage = UIImageJPEGRepresentation(image,0.9) else {
print("Error in JPG Representation Image")
return
}
//save image on local
self.saveImageToDisk(image: profileImage)
completion()
}
case .failure(_):
self.view.makeToast("Failed to upload profile image.")
completion()
}
}
}
I am unable to understand what could be wrong any one have idea about this?

Related

How to get filename when using PHPickerViewController for photo

How to get filename when using PHPickerViewController for photo
this is my function code
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true, completion: nil)
for item in results {
item.itemProvider.loadObject(ofClass: UIImage.self) {(image, error) in
if let image = image as? UIImage{
}
}
}
}
Please help, thank you
Hope you van find file name by using this:
item.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.item") { (url, error) in
if error != nil {
print("error \(error!)");
} else {
if let url = url {
let filename = url.lastPathComponent;
print(filename)
}
}
}
You can use this to get file name from UIImagePickerController
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imageURL = info[UIImagePickerControllerReferenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil)
let asset = result.firstObject
print(asset?.value(forKey: "filename"))
}
dismiss(animated: true, completion: nil)
}
The NSItemProvider from PHPickerResult has a suggestedName property that will give you the file name. So from your provided code:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true, completion: nil)
for item in results {
item.itemProvider.loadObject(ofClass: UIImage.self) {(image, error) in
// This will give you the file name
guard let fileName = item.itemProvider.suggestedName else { return }
if let image = image as? UIImage{
}
}
}
}

Upload image to Firebase Storage and show as Profile Image

I need help with uploading image to Firebase Storage. I have a profile menu in my app. When user tap on this menu he/she can see profile with their info and Profile Image. So I made it so you can select a photo from the gallery. But I need to save photo to Firebase Storage and add ref to Firebase Database by uid.
In addition, the user may not have a photo, so it will be nill because nothing in Database. Look at photo and you will understand everything
extension ProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var selectedImage: UIImage?
if let editedImage = info[.editedImage] as? UIImage {
selectedImage = editedImage
self.profileImage.image = selectedImage!
self.savedImage = selectedImage
picker.dismiss(animated: true, completion: nil)
} else if let originalImage = info[.originalImage] as? UIImage {
selectedImage = originalImage
self.profileImage.image = selectedImage!
self.savedImage = selectedImage
picker.dismiss(animated: true, completion: nil)
}
}
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView) )
profileImage.addGestureRecognizer(tapGesture)
profileImage.isUserInteractionEnabled = true
#objc func handleSelectProfileImageView () {
print("Tapped")
let pickerController = UIImagePickerController()
pickerController.delegate = self
present(pickerController, animated: true, completion: nil)
}
So, how to upload and dowload image.
If the user does not have a photo (ref in Database). He will see image from assets.
If the user have photo he will see image from FB.
image
For Uploading to Firebase storage
let imgData: NSData = NSData(data: UIImageJPEGRepresentation((self.img_Photo?.image)!, 0.5)!)
let _:NSData = NSData(data:UIImagePNGRepresentation(((self.img_Photo?.image)!))!)
self.uploadProfileImageToFirebase(data: imgData)
Function for uploading
func uploadProfileImageToFirebase(data:NSData){
let randomPic = randomString(length: 10)
let storageRef = Storage.storage().reference().child("Pictures").child("\(value(forKey: "UserUID") ?? randomPic).jpg")
if data != nil {
storageRef.putData(data as Data, metadata: nil, completion: { (metadata, error) in
if(error != nil){
print(error)
return
}
guard let userID = Auth.auth().currentUser?.uid else {
return
}
// Fetch the download URL
storageRef.downloadURL { url, error in
if let error = error {
// Handle any errors
if(error != nil){
print(error)
return
}
} else {
// Get the download URL for 'images/stars.jpg'
let urlStr:String = (url?.absoluteString) ?? ""
let values = ["photo_url": urlStr]
self.registerUserIntoDatabaseWithUID(uid: userID, values: values as [String : AnyObject])
}
}
})
}
}
func registerUserIntoDatabaseWithUID(uid:String, values:[String:AnyObject]){
let ref = Database.database().reference(fromURL: "https://domain.firebaseio.com/")
let usersReference = ref.child("users").child((Auth.auth().currentUser?.uid)!)
usersReference.updateChildValues(values) { (error, ref) in
if(error != nil){
print(error)
return
}
self.parentVC?.dismiss(animated: true, completion: nil)
}
}

Firebase storage

I tried to upload images into firebase storage, and fyi my app is under firebase phone number Auth registration. And here is my code for uploading images:
#IBAction func addBtnClicked(_ sender: UIButton) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var selectedImageFromPicker: UIImage?
if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage {
selectedImageFromPicker = editedImage
} else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage {
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker {
imageView.image = selectedImage
}
let storageRef = Storage.storage().reference().child("profile_images").child("test01.png")
if let uploadData = UIImagePNGRepresentation(self.imageView.image!) {
storageRef.putData(uploadData, metadata: nil) { (metadata, error) in
if let error = error {
print(error)
return
}
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("canceled picker")
dismiss(animated: true, completion: nil)
}
But every time after I compiled, I got this error code:
User does not have permission to access gs://cal-dev.appspot.com/profile_images/test01.png." UserInfo={object=profile_images/test01.png, ResponseBody={
"error": {
"code": 403,
"message": "Permission denied. Could not perform this operation"
}
Have you given read and write access in your firebase console? It seems that you are not authorized to write data to firebase..

Uploading an image into a Web Service from an ImageView

I'm trying to upload an image taken by the device camera, or selected from the device Gallery, later present it at the screen with an ImageView, and at last upload it to a Rest API. I already have a default image stored in the Rest API and my App is already loading this image, but when I try to change the image I have issues.
This is my code after the Post API call, the data of my JSON:
let defaultServiceResponse = data["defaultServiceResponse"] as! NSDictionary
self.idResponse = defaultServiceResponse["idResponse"] as! Int
let loginModel = LoginModel()
if self.idResponse == 0 {
let userInfo = data["userInfo"] as! NSDictionary
loginModel.imageProfileUrl = userInfo["imageProfileUrl"] as! String
let url = URL(string: loginModel.imageProfileUrl)
let data = try? Data(contentsOf: url!)
self.userImage.image = UIImage(data: data!)!
Then I have a second class where I'm trying to upload the image:
class PhotoViewController: UIViewController, UIImagePickerControllerDelegate,
UINavigationControllerDelegate {
#IBOutlet weak var imagePicked: UIImageView!
#IBAction func openCameraButton(sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera;
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
}
#IBAction func openPhotoLibraryButton(sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary;
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
}
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
imagePicked.image = image
dismiss(animated:true, completion: nil)
}
#IBAction func saveButt(sender: AnyObject) {
let imageData = UIImageJPEGRepresentation(imagePicked.image!, 0.6)
let compressedJPGImage = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(compressedJPGImage!, nil, nil, nil)
let alert = UIAlertView(title: "Wow",
message: "Your image has been saved to Photo Library!",
delegate: nil,
cancelButtonTitle: "Ok")
alert.show()
}
When I tap the openCamara button and openLibrary button it does the correct function each time, but when I choose the photo (either from the Camera or the Gallery) it doesn't appear anything at the ImageView, and the error I receive is: "Creating an image format with an unknown type is an error
"
And I'm not sending back the image into the Rest API because I haven't any idea of how can I do that.
Can somebody help me showing where is the error that is not letting me show the picture at the screen on the ImageView?
And if it's posible can somebody show me the best way to return that image into my Rest API?
#Zita Noriega Estrada
this code will remove your all errors.
func isValidData(_ result: Result<Any>, completion: #escaping (_ : NSDictionary?, _ : Bool?, _ : NSError?) -> Void) {
self.getValidDict(result, completion: {(dict, error) in
var success = false
var errorNew = error
if dict != nil {
success = ((dict?["dataKey"] as AnyObject).boolValue)!
if !success {
errorNew = NSError(domain: "", code: 400, userInfo: [NSLocalizedDescriptionKey: dict?.value(forKey: "messageKey")! as Any])
}
}
completion (dict, success, errorNew)
})
}
func getValidDict(_ result: Result<Any>, completion: #escaping (_ : NSDictionary?, _ : NSError?) -> Void) {
var dict: NSDictionary!
let errorNew = result.error as NSError?
if let json = result.value {
dict = (json as AnyObject).value(forKey: "responseKey") as! NSDictionary
}
completion (dict, errorNew)
}
Use Alamofire to upload image to server.
Try this code:
func uploadImage {
uploadImage(image: image, completion: { (success, error) in
if success! {
} else {
}
})
}
func uploadImage(_ image: UIImage!, completion: #escaping (_ : Bool?, _: NSError?) -> Void) {
let parameters: Parameters = ["image": image]
Alamofire.upload(multipartFormData: {
multipartFormData in
// For Image
for (key, value) in parameters {
if value != nil {
if let imageData = UIImageJPEGRepresentation(value!, 0.5) {
multipartFormData.append(imageData, withName: key, fileName: "file.png", mimeType: "image/png")
}
}
}
}, to: "apiName", method: .post, encodingCompletion: {
encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.response {
[weak self] response in
guard self != nil
else {
return
}
upload.responseJSON(completionHandler: { response in
self?.isValidData(response.result, completion: {(dict, success, error) in
completion (success, error)
})
})
}
case .failure(let encodingError):
print("error:\(encodingError)")
completion (false, encodingError as NSError?)
}
})
}

Swift - Alamofire - upload file from photolibrary

I'm trying to implement an upload from my photo-library with Alamofire:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else {
return
}
let documentDirectory: NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as NSString
let imageName = "temp"
let imagePath = documentDirectory.appendingPathComponent(imageName)
if let data = UIImageJPEGRepresentation(image, 80) {
do {
try data.write(to: URL(fileURLWithPath: imagePath), options: .atomic)
} catch let error {
print(error)
}
}
Alamofire.upload(.POST, "\(self.app_url)/user/upload", multipartFormData: { formData in
let filePath = NSURL(fileURLWithPath: image)
formData.appendBodyPart(fileURL: filePath, name: "upload")
formData.appendBodyPart(data: "Alamofire".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name: "test")
}, encodingCompletion: { encodingResult in
switch encodingResult {
case .Success:
print("SUCCESS")
case .Failure(let error):
print(error)
}
})
self.dismiss(animated: true, completion: nil)
}
And it prints:
Ambiguous reference to member 'upload(_:to:method:headers:)'
Can anybody explain me how to resolve this issue?
Thanks and Greetings!
In Swift 3 and Alamofire 4
Here is the Full Implementation of how to upload using Alamofire
Add the Following to your ViewController Class:
UIImagePickerControllerDelegate and UINavigationControllerDelegate
Create A Button:
First Create a button and implement the Following method in it for picker view
#IBAction func btnSelectProfileImageClicked(_ sender: Any) {
let ImagePicker = UIImagePickerController()
ImagePicker.delegate = self
ImagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
self.present(ImagePicker, animated: true, completion: nil)
}
Then Implement the following UIPicker Methods:
func imagePickerController( _ picker: UIImagePickerController,didFinishPickingMediaWithInfo info:[String : Any] )
{Imgprofile.image = info[UIImagePickerControllerOriginalImage] as? UIImage
self.dismiss(animated: true, completion: nil)}
Make Another Button Which Passes the data to URL using Alamofire and Give an #IBAction outlet to it to it :
Enter Following Data to it
#IBAction func btnUpdateProfileSelected(_ sender: Any) {
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(UIImageJPEGRepresentation(self.Imgprofile.image!, 1)!, withName: "Prescription", fileName: "Profile_Image.jpeg", mimeType: "image/jpeg")
}, to:" Your URL Here where You want to Upload")
{ (result) in
switch result {
case .success(let upload, _, _):
print(result)
upload.uploadProgress(closure: { (progress) in
print(progress)
})
upload.responseJSON { response in
//print response.result
print(response);
}
case .failure(let encodingError):
print(encodingError);
}
}
}
Thats all
Hope This helps
For Full sample code or any doubts please comment. I will provide you
the sample code for this. Which Includes the Fetching as well as
upload data using Alamofire.
Thanks