thaliproject / postcardapp

A sample app to demonstrate how to build Thali applications
MIT License
22 stars 5 forks source link

HTML5 camera capture #105

Closed deadlyfingers closed 8 years ago

deadlyfingers commented 8 years ago

Implement HTML5 capture photo instead using file upload for desktop. Possibly even a Cordova camera replacement on mobile - demos "write once, works everywhere".

deadlyfingers commented 8 years ago

Two methods to get camera in HTML5:

  1. Media Capture Stream (getUserMedia)
  2. Media Capture (File input)

But only File input method is supported by mobile browsers - http://mobilehtml5.org/

So Google Chrome & Firefox only support Media Capture Stream (getUserMedia) but it won't work with Safari / iOS. Related posts: http://stackoverflow.com/questions/7725203/access-iphones-camera-from-uiwebview-using-html-5 http://stackoverflow.com/questions/21015847/how-to-make-getusermedia-work-on-all-browsers

@yaron Media Capture seems to be the only option to use for getting still images with HTML5. It's actually pretty easy to implement and have got it working in an iPhone POC but the trick will be can we mask the nasty default file upload web interface with our nice camera icon button and image preview!

deadlyfingers commented 8 years ago

iOS results: Capturing portrait images come back in landscape - may have to rotate the canvas... (doesn't respect orientation at which the photo was taken)

<input type="file" accept="image/*" capture="camera">
<input type="file" accept="audio/*" capture="microphone">
<input type="file" accept="video/*" capture="camcorder">

^ Also tested the 'video' option which works quite well, but I didn't like the 'audio' option as the native UI still allows you to take a photo for some reason.

Android results: No option to take a photo with Camera, only options to pick an image from Drive, Images, Downloads, Gallery, Photos. (tested with Android L on Sony Xperia and Moto G) Also added the Camera permissions to the AndroidManifest.xml:

    <uses-permission android:name="android.permission.CAMERA" />
yaron commented 8 years ago

@yaronyg I think he means you.

deadlyfingers commented 8 years ago

^ yes indeed! ;)

Using getUserMedia for Android with Chrome error:

Refused to load the image 'android-webview-video-poster: because it violates the following Content Security Policy "default-src". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

Appending img-src * android-webview-video-poster: data:; fixes this error.

Also added permissions:

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.RECORD_VIDEO" />

If you get a black screen then try basic video options:

var options = { audio: false, video: true };
deadlyfingers commented 8 years ago

NB: In order to save as image as attachment in PouchDB the "data:image/jpeg;base64" tag needs to be stripped from imageData. (Otherwise you will get error 500 when trying to save)

deadlyfingers commented 8 years ago

Got this working with Postcard app, but need to see if I can detect orientation of shots captured on iOS Camera and also shots loaded from Camera Roll. But looks like I need to read the EXIF info to get orientation - https://github.com/exif-js/exif-js

Test images: https://github.com/recurser/exif-orientation-examples

Related posts: http://stackoverflow.com/questions/16336158/wrong-orientation-when-image-captured-by-html5-file-api-on-ios-6-0 http://stackoverflow.com/questions/19463126/how-to-draw-photo-with-correct-orientation-in-canvas-after-capture-photo-by-usin http://stackoverflow.com/questions/7584794/accessing-jpeg-exif-rotation-data-in-javascript-on-the-client-side http://stackoverflow.com/questions/20600800/js-client-side-exif-orientation-rotate-and-mirror-jpeg-images

I imagine it best to resize image down using scale then do transform.

deadlyfingers commented 8 years ago

Getting a lot of NSLayoutConstraint garbage atm in WKWebView when capturing image using file input / changing orientation...

2016-01-11 16:04:19.047 PostCardApp[4881:1753109] the behavior of the UICollectionViewFlowLayout is not defined because:
2016-01-11 16:04:19.047 PostCardApp[4881:1753109] the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
2016-01-11 16:04:19.049 PostCardApp[4881:1753109] The relevant UICollectionViewFlowLayout instance is <_UIAlertControllerCollectionViewFlowLayout: 0x1530d7980>, and it is attached to <UICollectionView: 0x150fef200; frame = (0 44; 10 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x1530d84f0>; animations = { bounds.origin=<CASpringAnimation: 0x1530e5200>; bounds.size=<CASpringAnimation: 0x1530e52f0>; position=<CASpringAnimation: 0x1530e53f0>; }; layer = <CALayer: 0x1530d7ed0>; contentOffset: {0, 0}; contentSize: {0, 0}> collection view layout: <_UIAlertControllerCollectionViewFlowLayout: 0x1530d7980>.
2016-01-11 16:04:19.049 PostCardApp[4881:1753109] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
2016-01-11 16:04:19.910 PostCardApp[4881:1753109] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x1530dab20 UILabel:0x1530d6f00.width == UIView:0x1530d41e0.width - 32>",
    "<NSLayoutConstraint:0x1530da390 UIView:0x1530d41e0.width == UIView:0x1530d3fa0.width>",
    "<NSLayoutConstraint:0x14fd0ff20 H:[UIView:0x1530d3fa0(30)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1530dab20 UILabel:0x1530d6f00.width == UIView:0x1530d41e0.width - 32>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-01-11 16:04:24.213 PostCardApp[4881:1753109] Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.

Will only use this file input image method for Desktop and revert to Cordova Camera for Android and iOS using postMessage event from iframe.

yaronyg commented 8 years ago

BTW, do tell me that you aren't saving the data to pouch as Base64? It should be raw binary.

deadlyfingers commented 8 years ago

@yaronyg Cordova was returning Base64 string so I was working with that. But will create an issue for that!