Cordova Plugin Crop dont work on iOS?

Hello guys im facing the Problem that after i take a picture cordova crop doesnt get called or opened. On iOS it works. Is that a known issue? Or do i have to enable any settings for that?

Did i miss something in this code?
I got that code from a tutorial:

 takeThePhoto(pictureSourceType): Promise<any> {
    return Camera.getPicture({
        destinationType: Camera.DestinationType.FILE_URI,
        mediaType: Camera.MediaType.ALLMEDIA,
        sourceType: pictureSourceType,
        targetWidth: 720,
        encodingType: Camera.EncodingType.JPEG,
        correctOrientation: true
    }).then((fileUri) => {
        // Crop Image, on android this returns something like, '/storage/emulated/0/Android/...'
        // Only giving an android example as ionic-native camera has built in cropping ability
        if (this.platform.is('ios')) {
          return fileUri
        } else if (this.platform.is('android')) {
          // Modify fileUri format, may not always be necessary
          fileUri = 'file://' + fileUri;

          /* Using cordova-plugin-crop starts here */
          return Crop.crop(fileUri, { quality: 100 });
        }
      })

Try this

takeThePhoto(pictureSourceType): Promise<any> {
	return new Promise((result, reject) => {
		Camera.getPicture({
			destinationType: Camera.DestinationType.FILE_URI,
			mediaType: Camera.MediaType.ALLMEDIA,
			sourceType: pictureSourceType,
			targetWidth: 720,
			encodingType: Camera.EncodingType.JPEG,
			correctOrientation: true
		}).then(
			fileUri => {
				// Crop Image, on android this returns something like, '/storage/emulated/0/Android/...'
				// Only giving an android example as ionic-native camera has built in cropping ability
				if (this.platform.is('ios')) {
					resolve(fileUri);
				} else if (this.platform.is('android')) {
					// Modify fileUri format, may not always be necessary
					fileUri = 'file://' + fileUri;
					
					/* Using cordova-plugin-crop starts here */
					resolve(Crop.crop(fileUri, { quality: 100 }));
				} else {
					reject("Unsupported device");
				}
			},
			err => {
				alert(JSON.stringify(err));
				reject(err);
			}
		)
	});
}

Does the error alert occur?

Didnt work. I tried something like this:

    if (this.platform.is('ios')) {
      /* Using cordova-plugin-crop starts here */
      return Crop.crop(fileUri, { quality: 100 });
      //return fileUri
    } else if (this.platform.is('android')) {
      // Modify fileUri format, may not always be necessary
      fileUri = 'file://' + fileUri;

      /* Using cordova-plugin-crop starts here */
      return Crop.crop(fileUri, { quality: 100 });
    }

And it didnt work either it ignores this line:

if (this.platform.is('ios')) {
  /* Using cordova-plugin-crop starts here */
  return Crop.crop(fileUri, { quality: 100 });
  //return fileUri

Try using what I put and add alerts before each reject/resolve, with different texts so we can see where it enters. If none of them pop up on the device, I think it’s safe to assume that it’s throwing an error and never making it there. If so, check the console when running from X Code and see if anything odd shows up.

Yeah ill try but if this line:
resolve(Crop.crop(fileUri, { quality: 100 }));
is missing in this:

if (this.platform.is('ios')) {
  return Crop.crop(fileUri, { quality: 100 });

Crop Plugin will never called? In your code it only returns the fileuri?

Yeah just change that to

resolve(Crop.crop(fileUri, { quality: 100 }));

Assuming I understood that right

im getting “Cant find name reslove”

Can you paste the whole thing?

this is how it looks atm all the other code worked like a charm but as i said only the ios crop didnt work

takeThePhoto(pictureSourceType): Promise<any> {
        return new Promise((result, reject) => {
        Camera.getPicture({
        destinationType: Camera.DestinationType.FILE_URI,
        mediaType: Camera.MediaType.ALLMEDIA,
        sourceType: pictureSourceType,
        targetWidth: 720,
        encodingType: Camera.EncodingType.JPEG,
        correctOrientation: true
    }).then((fileUri) => {
        // Crop Image, on android this returns something like, '/storage/emulated/0/Android/...'
        // Only giving an android example as ionic-native camera has built in cropping ability
        if (this.platform.is('ios')) {
          /* Using cordova-plugin-crop starts here */
          return reslove(Crop.crop(fileUri, { quality: 100 }));
          
          //return fileUri
        } else if (this.platform.is('android')) {
          // Modify fileUri format, may not always be necessary
          fileUri = 'file://' + fileUri;

          /* Using cordova-plugin-crop starts here */
          return reslove(Crop.crop(fileUri, { quality: 100 }));
        }
      })
      .then((path) => {
        // path looks like 'file:///storage/emulated/0/Android/data/com.foo.bar/cache/1477008080626-cropped.jpg?1477008106566'
        //alert('Cropped Image Path!: ' + path);
        this.loading = this.loadingCtrl.create({ content: 'Uploading Image...'});
        this.loading.present();
        return this.toBase64(path).then((base64Img) => {
          this.postdataimage.base64img = base64Img;
           this.http.post('http://service-lukas-reineleimage.php', this.postdataimage).subscribe((rsp) => {
              this.changed = rsp.text();
              if(this.changed == "notchanged")
              {
                //bildwurdenichtgeändert
              } 
              else 
              {
                this.postdataimage.profilepiclink = this.changed;
                NativeStorage.setItem('loginprofilepicture',  this.changed)
                .then(() => console.log('Stored Login Data!'), error => console.error('Error storing Data', error));
                this._zone.run(() => {
                  this.loadData();
                }); 
              }
              this.loading.dismiss();
            });
        });
      })
  }
}

   toBase64(url: string) {
        return new Promise<string>(function (resolve) {
            var xhr = new XMLHttpRequest();
            xhr.responseType = 'blob';
            xhr.onload = function () {
                var reader = new FileReader();
                reader.onloadend = function () {
                    resolve(reader.result);
                }
                reader.readAsDataURL(xhr.response);
            };
            xhr.open('GET', url);
            xhr.send();
        });
    }
  1. Don’t return the resolve/rejects
  2. resolve, not reslove
  3. return new Promise((resolve, reject) => { ... } (this one needs a return)

You’re changing too much :wink:

Where are you using takeThePhoto() - can you show that code too please? :slight_smile:

  presentActionSheet() {
    let actionSheet = this.actionSheetCtrl.create({
      title: 'Choose...',
      buttons: [
        {
          text: 'Camera',
          handler: () => {
            this.takePhoto();
            console.log('Camera clicked');
          }
        },{
          text: 'Gallery',
          handler: () => {
            this.pickImage();
            console.log('Gallery clicked');
          }
        },{
          text: 'Cancel',
          role: 'cancel',
          handler: () => {
            console.log('Cancel clicked');
          }
        }
      ]
    });
    actionSheet.present();
  }

  takePhoto() {
      this.takeThePhoto(Camera.PictureSourceType.CAMERA);
  }

  pickImage() {
        this.takeThePhoto(Camera.PictureSourceType.SAVEDPHOTOALBUM);
  }

Right, so there was more… There’s a lot of unhandled errors here. Did it over, try debugging from here

takeThePhoto(pictureSourceType): Promise<any> {
	return Camera.getPicture(
		{
			destinationType: Camera.DestinationType.FILE_URI,
			mediaType: Camera.MediaType.ALLMEDIA,
			sourceType: pictureSourceType,
			targetWidth: 720,
			encodingType: Camera.EncodingType.JPEG,
			correctOrientation: true
		}
	).then(
		fileUri => {
			if (this.platform.is('android')) {
				fileUri = 'file://' + fileUri;
			}
			return Crop.crop(fileUri, { quality: 100 });
		},
		err => {
			alert(JSON.stringify(err));
			// failed to get picture
		}
	).then(
		path => {
			this.loading = this.loadingCtrl.create({ content: 'Uploading Image...'});
			this.loading.present();

			return this.toBase64(path).then((base64Img) => {
				this.postdataimage.base64img = base64Img;
				this.http.post('http://service-lukas-reineleimage.php', this.postdataimage).subscribe(
					rsp => {
						this.changed = rsp.text();

						if(this.changed == "notchanged") {
							// not changed
						} else {
							this.postdataimage.profilepiclink = this.changed;
							NativeStorage.setItem('loginprofilepicture', this.changed).then(
								() => {
									console.log('Stored Login Data!');
								},
								error => {
									console.error('Error storing Data', error);
								}
							);
							this._zone.run(() => {
								this.loadData();
							});
						}
						this.loading.dismiss();
					},
					err => {
						alert(JSON.stringify(err));
						// failed to call backend
					}
				);
			});
		},
		err => {
			alert(JSON.stringify(err));
			// failed to crop picture
		}
	);
}

Personally I’d split all of this into several functions, so it’s easier to read.

1 Like

So this Code works perfect on android after taking a picture it opens the plugin crop where i can crop the image. The image gets stored on the local storage. From there i take it und convert it into base64 and send it to my php file where it get stored into a FTP server.

 presentActionSheet() {
    let actionSheet = this.actionSheetCtrl.create({
      title: 'Choose...',
      buttons: [
        {
          text: 'Camera',
          handler: () => {
            this.takePhoto();
            console.log('Camera clicked');
          }
        },{
          text: 'Gallery',
          handler: () => {
            this.pickImage();
            console.log('Gallery clicked');
          }
        },{
          text: 'Cancel',
          role: 'cancel',
          handler: () => {
            console.log('Cancel clicked');
          }
        }
      ]
    });
    actionSheet.present();
  }

  takePhoto() {
      this.takeThePhoto(Camera.PictureSourceType.CAMERA);
  }

  pickImage() {
        this.takeThePhoto(Camera.PictureSourceType.SAVEDPHOTOALBUM);
  }

takeThePhoto(pictureSourceType): Promise<any> {
        return new Promise((result, reject) => {
        Camera.getPicture({
        destinationType: Camera.DestinationType.FILE_URI,
        mediaType: Camera.MediaType.ALLMEDIA,
        sourceType: pictureSourceType,
        targetWidth: 720,
        encodingType: Camera.EncodingType.JPEG,
        correctOrientation: true
    }).then((fileUri) => {
        // Crop Image, on android this returns something like, '/storage/emulated/0/Android/...'
        // Only giving an android example as ionic-native camera has built in cropping ability
        if (this.platform.is('ios')) {
          /* Using cordova-plugin-crop starts here */
          return reslove(Crop.crop(fileUri, { quality: 100 }));
          
          //return fileUri
        } else if (this.platform.is('android')) {
          // Modify fileUri format, may not always be necessary
          fileUri = 'file://' + fileUri;

          /* Using cordova-plugin-crop starts here */
          return reslove(Crop.crop(fileUri, { quality: 100 }));
        }
      })
      .then((path) => {
        // path looks like 'file:///storage/emulated/0/Android/data/com.foo.bar/cache/1477008080626-cropped.jpg?1477008106566'
        //alert('Cropped Image Path!: ' + path);
        this.loading = this.loadingCtrl.create({ content: 'Uploading Image...'});
        this.loading.present();
        return this.toBase64(path).then((base64Img) => {
          this.postdataimage.base64img = base64Img;
           this.http.post('http://service-lukas-reineleimage.php', this.postdataimage).subscribe((rsp) => {
              this.changed = rsp.text();
              if(this.changed == "notchanged")
              {
                //bildwurdenichtgeändert
              } 
              else 
              {
                this.postdataimage.profilepiclink = this.changed;
                NativeStorage.setItem('loginprofilepicture',  this.changed)
                .then(() => console.log('Stored Login Data!'), error => console.error('Error storing Data', error));
                this._zone.run(() => {
                  this.loadData();
                }); 
              }
              this.loading.dismiss();
            });
        });
      })
  }
}

   toBase64(url: string) {
        return new Promise<string>(function (resolve) {
            var xhr = new XMLHttpRequest();
            xhr.responseType = 'blob';
            xhr.onload = function () {
                var reader = new FileReader();
                reader.onloadend = function () {
                    resolve(reader.result);
                }
                reader.readAsDataURL(xhr.response);
            };
            xhr.open('GET', url);
            xhr.send();
        });
    }

But as i said on iOS Crop doesnt get called because i only returned the file uri first like this:

if (this.platform.is('ios')) {
  return fileUri

When im insert here the Crop Plugin so, if its a iOS Device, it should open Crop like it works on Android:

if (this.platform.is('ios')) {
  return Crop.crop(fileUri, { quality: 100 });

But the Problem here is that the exactly same code works on Android but on iOS it does nothing.
On iOS it skips this step and upload the picture without Cropping first.

This Code works without any Errors on Android thats why i didnt handle Errors yet.

Ok it works perfect now with this line of code:

 takeThePhoto(pictureSourceType): Promise<any> {
        return Camera.getPicture({
        destinationType: Camera.DestinationType.FILE_URI,
        mediaType: Camera.MediaType.ALLMEDIA,
        sourceType: pictureSourceType,
        targetWidth: 720,
        encodingType: Camera.EncodingType.JPEG,
        correctOrientation: true
    }).then((fileUri) => {
         if (this.platform.is('android')) {
          // Modify fileUri format, may not always be necessary
          fileUri = 'file://' + fileUri;
          }
          /* Using cordova-plugin-crop starts here */
          return Crop.crop(fileUri, { quality: 100 });
      },
      err => {
			    alert(JSON.stringify(err));
			// failed to get picture
		    }
      )

i dont know why but this got skipped on ios:

if (this.platform.is('ios')) {
  return Crop.crop(fileUri, { quality: 100 });

But thanks for your code it works perfect now. Crop get called and all works without bugs!
Thank you very much you saved me years of debugging :smiley:

1 Like