Is there a way to avoid the iOS video compression when selecting a video from the gallery with camera.getPicture()?
var options = {
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
mediaType: 1
}
navigator.camera.getPicture(videoGallerySuccess, videoGalleryError, options);
The user has to wait for the video compression to be finished when selecting a video.
I would like to avoid this and instead do my own compression whenever the user has submitted a form for example.
In Cordova Camera Plugin you need to define a quality of the final video/photo. According documentation, default value for all media types is 50. To prevent a loss of resolution (and potentially video processing) set quality to 100.
var options = {
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
mediaType: 1,
quality: 100
}
navigator.camera.getPicture(videoGallerySuccess, videoGalleryError, options);
Related
I am using the cordova-plugin-camera cordova plugin (version 4.0.3), wrapped by the Ionic Native wrapper for Ionic 4 #ionic-native/camera#4. I'm using it to capture a photo (regular or from library), and move it into my app storage area for saving/sending. Things work great on Android. On iOS I continue to get a NOT_FOUND_ERR back when trying to grab the FILE_URI that comes back from the capture.
Below is how I'm capturing the image, which works just fine. The camera launches, I snap (or choose) a photo, and I get a file URI back (file:///var/mobile/Containers/Data/Application/{guid}/tmp/XYZ.jpg). Then something as simple as doing a resolveLocalFilesystemUrl on this resulting file URI will bomb with NOT_FOUND_ERR. Any advice?
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: (isFromLibrary) ? this.camera.PictureSourceType.PHOTOLIBRARY : this.camera.PictureSourceType.CAMERA,
saveToPhotoAlbum: false,
targetWidth: (isForDocScan) ? desiredWidth + 500 : desiredWidth,
targetHeight: (isForDocScan) ? desiredHeight + 500 : desiredHeight
}
let result = null;
try {
result = await this.camera.getPicture(options);
}
catch (err) {
this.loggingService.error('Error getting photo', err);
}
You seem to have some hiccups when using the Camera.DestinationType configs. The below are the outputs when you use FILE_URI and NATIVE_URI
Camera.DestinationType.FILE_URI
'file://' ios
'content://' android
Camera.DestinationType.NATIVE_URI
'assets-library://' ios
'content://' android
Although this is the outputs, this is internally related to your sourceType. What this means is that, if your sourceType is the camera, you should be using FILE_URI as the output is obtained from the temporary storage, while if you are using photogallery, your output needs to be obtained from the library, which is why its recommended you use NATIVE_URI
Im instanciating the AVPlayerItemVideoOutput like so:
let videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: [String(kCVPixelBufferPixelFormatTypeKey): NSNumber(value: kCVPixelFormatType_32BGRA)])
And retrieving the pixelBuffers like this:
#objc func displayLinkDidRefresh(link: CADisplayLink) {
let itemTime = videoOutput.itemTime(forHostTime: CACurrentMediaTime())
if videoOutput.hasNewPixelBuffer(forItemTime: itemTime) {
if let pixelBuffer = videoOutput.copyPixelBuffer(forItemTime: itemTime, itemTimeForDisplay: nil) {
}
}
}
But for some reason CVPixelBufferGetHeight(pixelBuffer) or Width. always return 1280x720 when the video was taken when the iPhone's camera (landscape or portrait) always height=1280 width=720. EVEN if the video is 4k. If I load a square video from instagram or any other video downloaded from the internet (not created directly with the camera app) the width and height are printed correctly when the resolution is less than 720p. But a different resolution, for ex. a 1008x1792 will throw CVPixelBufferGetHeight(pixelBuffer) = 1280
Videos taken with the camera... it always throws a lower res. I tried 4k and 1080 settings (you can change that in iOS Settings > Camera). still.. even in 1080, I get 1280x720 pixel buffers.
I figured out that th UIPickerController I was using was set to default transcode the selected video from library to a Medium setting. in this case it was 1280x720
I ended up changing this properties of the picker
picker.videoQuality = .typeHigh
picker.videoExportPreset = AVAssetExportPresetHighestQuality
Altho the property that actually makes the change is the videoExportPreset the other one I dont know what it does, even tho the Documentation specifies it is for when you record a video OR you pick a video.
uploadImage(filePath: string, camera: boolean = false) {
try {
let options: CameraOptions;
if (camera) {
options = {
quality: 40,
destinationType: this._camera.DestinationType.DATA_URL,
encodingType: this._camera.EncodingType.JPEG,
mediaType: this._camera.MediaType.PICTURE,
correctOrientation: true
}
} else {
options = {
destinationType: this._camera.DestinationType.DATA_URL,
sourceType: this._camera.PictureSourceType.PHOTOLIBRARY,
encodingType: this._camera.EncodingType.JPEG,
mediaType: this._camera.MediaType.PICTURE
}
}
this._camera.getPicture(options).then((imageData) => {
const photo = `data:image/jpeg;base64,${imageData}`;
const fileRef = this._afs.ref(filePath);
const task = fileRef.putString(photo, 'data_url');
task.snapshotChanges().pipe(
finalize(() => {
// execute other actions
fileRef.getDownloadURL().subscribe(url => {
if (url) {
this.fileUploadUrl.next(url);
}
})
let toast = this.toastCtrl.create({
message: 'Image upload successfully',
position: 'bottom',
duration: 3000
});
toast.present();
})
).subscribe();
})
} catch (e) {
console.error(e);
let toast = this.toastCtrl.create({
message: 'Image upload cancelled',
position: 'bottom',
duration: 3000
});
toast.present();
}
}
After a picture a taken (from actual iOS device) sometimes it crashes, sometimes it works fine. If I use the front camera, it always work.
But if I use the back camera, after a picture a selected, it flashes a white screen and then the app restarts. I suspect if it’s something to do with the image size or resolution. Sometimes if I take a very low res picture with the back camera (like in a low light environment), it uploads just fine. I researched a bit online, some people suggest running the app with production mode with --prod flag, but it is not solving it.
I also tried to lower the quality value to a lower number, but that still doesn’t work with the back camera.
I am pretty sure the plugin is added correctly and the privacy settings are also correct otherwise it won't allow me to take pictures.
Yes, you are right. When taking picture using camera with DataURL (i.e Base64). we may face memory issue because of the picture size and quality. You have quality of '40' with is fine. For Width and height you can set around 300px.
The more the image size will increase the size of the image which will impact the memory.
It's not the proper solution for your query, but after wasting my nights on the same I tried to reduce the image and tried to maintain it less than 2mb and it worked quite well.You can reduce the image size by giving the targetWidth and targetHeight. I kept both of them below 500.
const options: CameraOptions = {
quality: 30, // picture quality
destinationType: this.camera.DestinationType.DATA_URL,
sourceType: this.camera.PictureSourceType.CAMERA,
encodingType: this.camera.EncodingType.PNG,
mediaType: this.camera.MediaType.PICTURE,
cameraDirection: this.camera.Direction.FRONT,
allowEdit: true,
correctOrientation :false,
targetWidth: 400,
targetHeight: 400,
}
I am developing an application in phonegap and have functionality of photo capturing using Ipad camera, It works fina and all photo saved properly on server. the only issue was with the fact that they are rotated 90 degree left while saved on server.
Now i tried same thing for photos stored in library and they are upload as it is on server, so i think issue is with ipad photo capturing process. Can anyone help me to found solution for such problem. Is it Ipad normal behaviour or i have mistaken in code ?
I have used below function for photo functionality
//Capture Photo either from camera or IPAD library
function capturePhoto(source){
var deferred = $q.defer();
//When source == 1 than from Photo Library
var cameraOptions = { quality: 70, destinationType: Camera.DestinationType.FILE_URI };
if(source == 1){ cameraOptions = { quality: 70, destinationType: Camera.DestinationType.FILE_URI, sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,targetWidth: 600,targetHeight: 600 }; }
navigator.camera.getPicture( function (imageURI) {
window.resolveLocalFileSystemURI(imageURI, function (fileEntry) {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys) {
fileSys.root.getDirectory("auditPhotos", {create: true, exclusive: false}, function(dir) {
fileEntry.copyTo(dir,generateRandomID()+".jpg",function (entry) {
deferred.resolve(entry.fullPath)
}, null);
}, null);
}, null);
},null);
},
function (message) {
deferred.reject(message);
},
cameraOptions
);
//deferred.resolve(generateRandomID()+".jpg");
return deferred.promise;
}
As you are saving captured image (Using above function) on server in jpg format. JPG & JPEG's have a property of EXIF which store orientation of image. When you captured image through IPAD, this exif data stores camera orientation and other position related things. But this are understood by ipad only and not by browser, that's why image was seen rotated in browser which is the truth. And same image when you viewed in IPAD it was set by IPAD in proper position due to availablity of EXIF.
To solve this problem just save your image in PNG format instead of JPG and all works fine :-)
My friend had a similar problem recently, and while I'm not too sure how to specifically solve your problem, I do know that EXIF data on the image should store something about how it's oriented.
You can try implementing this library to get the EXIF data and rotate the image if needed before the upload: https://code.google.com/p/iphone-exif/
When taking a video in the app the video is not saved to camera roll.
I have set the flag saveToPhotoAlbum: true.
My code
opt = {
limit: 1,
saveToPhotoAlbum: true,
quality: 1
};
navigator.device.capture.captureVideo(
that.captureVideoOnSuccess,
that.onCaptureFail,
opt
);
A similar code works for getPicture with no problems
navigator.camera.getPicture(
that.uploadPhoto,
that.onCaptureFail, {
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
mediaType: Camera.MediaType.PICTURE,
saveToPhotoAlbum: true
}
);
Any idea how to over come this?
Any solution will be welcome - by config, js code, Objective-C
Thanks
Here is my solution (based on https://groups.google.com/forum/#!topic/phonegap/245nKJoqqak)
In plugins/org.apache.cordova.media-capture/src/ios/CDVCapture.m
Method - (CDVPluginResult*)processVideo:(NSString*)moviePath forCallbackId:(NSString*)callbackId
Uncomment the lines under
/* don't need, it should automatically get saved
I don't know why those line are comment out...