Capturing camera/picture data without PhoneGap

This post is more than 2 years old.

Two years later and this blog post is still highly popular. If you like this content, be sure to subscribe to the blog to get the latest updates. You may also want to check out my Apache Cordova book and the JavaScript videos I have available.

As people know, I'm a huge fan of PhoneGap and what it allows me to do with JavaScript, HTML, and CSS. But I think it is crucial to remember that you don't always need PhoneGap. A great example of that is camera access. Did you know that recent mobile browsers support accessing the camera directly from HTML and JavaScript? Let's look at an example.

Over a year ago I wrote a blog post in which I created an application called "Color Thief." This application made use of PhoneGap's Camera API and a third party JavaScript library called Color Thief. I loved this example because it demonstrated how you could combine the extra power that PhoneGap provides along with existing JavaScript libraries.

This morning I watched an excellent Google IO presentation (https://www.youtube.com/watch?v=EPYnGFEcis4&feature=youtube_gdata_player) on Mobile HTML. It was an overview of some of the exciting stuff you can now do with mobile HTML and JavaScript. To be clear, this was all without using wrappers like PhoneGap.

In one of the examples the presenters discussed the new "capture" support for the input/file field type. This is rather simple to implement:

<input type="file" capture="camera" accept="image/*" id="takePictureField">

If supported (recent Android and latest iOS), the user can then use their camera to select a picture. I decided to rebuild my old demo to skip PhoneGap completely and just make use of this feature. Here's the code:

For the most part, this is pretty similar to the last version. I no longer wait for the deviceready event, but instead just listen for the document itself to load. Instead of listening for a button click, I've switched to an input field using type=file. I now listen for the change event, and on that, I see if I have access to a file. If I do, I can then use the URL object to create a pointer to the source and then simply add it to my DOM. After that, Color Thief takes over.

The only tricky part I ran into was that in iOS the URL object is still prefixed. You can see how I get around that in the startup code. To be fair, this isn't 100% backwards compatible, I could add a few checks in here to ensure that things will work and gracefully let people on older phones know they can't use this feature.

But the end result is nearly the exact same functionality in a web page - no PhoneGap, no native code.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by sfdsf posted on 2/28/2016 at 3:06 PM

can you give the required js files?

Comment 2 (In reply to #1) by Raymond Camden posted on 2/28/2016 at 3:51 PM

The code is in the blog entry.

Comment 3 by Vianney DIERS posted on 3/8/2016 at 4:42 PM

Hi, thanks for this article. How can send the taken picture to an default email ?

Comment 4 (In reply to #3) by Raymond Camden posted on 3/8/2016 at 9:06 PM

I don't think you can do that with just a generic web page. You could POST to a server side app that sends it.

Comment 5 (In reply to #4) by Vianney DIERS posted on 3/9/2016 at 1:58 PM

thanks for your answer.

And what about using "href="mailto" ?
Like this :
href="mailto:myemail@mail.com?sub..."Send

Thank you in advance

V

Comment 6 (In reply to #5) by Raymond Camden posted on 3/9/2016 at 2:09 PM

It won't work with an attachment.

Comment 7 by Luis Arturo Aranda Quezada posted on 5/10/2016 at 4:30 PM

Hi, 1st sorry if my eng its not the best...
2nd, how can i take a picture from the camera, but with and added frame, for example, a logo of a band in a corner...

im creating an app for a music band, and i want that inside the app, you may take a picture, but already had a frame like a said, a logo or maybe the signatures of the band...that way the fan may post them on fb or storage it on mobile.

Thanks.

Comment 8 (In reply to #7) by Raymond Camden posted on 5/10/2016 at 5:46 PM

You can do basic image "editing" with canvas, but it isn't going to be trivial. This article may be useful: http://developer.telerik.co...

Comment 9 (In reply to #8) by Luis Arturo Aranda Quezada posted on 5/10/2016 at 5:49 PM

you are gonna hate me LOL but could u send me the html to my email? cause im kinda new in this app developing...and i dont have that eng skills to understand html...
i mean i need the code, simply as i just change some text...

Comment 10 (In reply to #9) by Raymond Camden posted on 5/10/2016 at 5:58 PM

The complete source is in the blog post up above - just copy and paste.

Comment 11 (In reply to #10) by Luis Arturo Aranda Quezada posted on 5/11/2016 at 5:39 PM

already do that...but i want to edit the drops and all things...and i read all the adobe creative image complement....and....i just can figure how or where...i even look for some online DIY option and nothing :/ :(

Comment 12 (In reply to #11) by Raymond Camden posted on 5/11/2016 at 5:44 PM

Not sure how I can help you here. I've pointed out some suggestions, and it is up to you now to try to implement them, and if you run into a specific issue, I can try to help.

Comment 13 (In reply to #12) by Luis Arturo Aranda Quezada posted on 5/11/2016 at 5:47 PM

ok the only thing i would need, its to tell me, where or how change the droplets...

Saludos.
LDG *Luis A. Aranda Q*.
CV y Portafolio <http: luisarandaq.wix.com="" cvdg="">

2016-05-11 12:44 GMT-05:00 Disqus <notifications@disqus.net>:

Comment 14 (In reply to #13) by Raymond Camden posted on 5/11/2016 at 5:53 PM

What are droplets?

Comment 15 (In reply to #14) by Luis Arturo Aranda Quezada posted on 5/11/2016 at 5:55 PM

mmm you know...the drops or props that u drag into the picture...

Saludos.
LDG *Luis A. Aranda Q*.
CV y Portafolio <http: luisarandaq.wix.com="" cvdg="">

2016-05-11 12:53 GMT-05:00 Disqus <notifications@disqus.net>:

Comment 16 (In reply to #15) by Raymond Camden posted on 5/11/2016 at 6:00 PM

Ah... well... I suggest checking out that link I shared then. Good luck!

Comment 17 (In reply to #7) by Philippe Corrèges posted on 5/17/2016 at 10:59 AM

Hi!
Just copied the html in an html file. Opened the file in browser. Nothing occurs with my camera :(. I use Firefox. Is the html supposed to work immediately?

Comment 18 (In reply to #17) by Raymond Camden posted on 5/17/2016 at 1:07 PM

Did you open it via http or file?

Comment 19 (In reply to #18) by Philippe Corrèges posted on 5/17/2016 at 1:45 PM

Http.
I ha inserted all the required js files and now see multiple popus with GAP issue.

Comment 20 (In reply to #19) by Raymond Camden posted on 5/17/2016 at 2:45 PM

What is the GAP issue specifically?

Comment 21 (In reply to #2) by ant_frisby posted on 7/19/2016 at 4:06 PM

Hi Raymond,

Where are the JS files? they don't seem to be in the blog post as you suggest. I tried downloading quantize.js and color-thief.js but I'm getting this error in my console:
Uncaught ReferenceError: createPalette is not defined

Thanks

Anthony

Comment 22 (In reply to #2) by ant_frisby posted on 7/19/2016 at 4:23 PM

This was my solution...

Change this line:
var colorArr = createPalette($("#yourimage"), 5);

to this:
var colorThief = new ColorThief();
var colorArr = colorThief.getPalette($("#yourimage")[0], 5);

Now it works nicely :)

Thanks

PS. nice blog btw

Comment 23 (In reply to #22) by Raymond Camden posted on 7/19/2016 at 6:08 PM

Ah - must be an update. This blog post is quite old now so not surprised. Thanks!

Comment 24 by Andreas Pecka posted on 8/20/2016 at 11:54 AM

Hi, where I can find the relevant .js files?

<script type="text/javascript" charset="utf-8" src="jquery-2.0.0.min.js"></script>
<script type="text/javascript" charset="utf-8" src="quantize.js"></script>
<script type="text/javascript" charset="utf-8" src="color-thief.js"></script>

Comment 25 (In reply to #24) by Raymond Camden posted on 8/20/2016 at 1:36 PM

On the Color Thief project site.

Comment 26 (In reply to #25) by Andreas Pecka posted on 8/21/2016 at 1:58 PM

Hi, thank you, but I googled it with no success, do you have a link for that? That would be great ;-) Thank you in advance!

Comment 27 (In reply to #26) by Raymond Camden posted on 8/22/2016 at 1:11 AM

Oh - it looks like that code is in Color Thief itself now. So most likely you just need *that* code, which is in their site, which I link to in the post.

Comment 28 (In reply to #27) by Erhan Yaşar posted on 11/2/2016 at 3:39 PM

It's not seen as quantize.js anymore. How do u suggest to find or make it work?

Comment 29 (In reply to #28) by Raymond Camden posted on 11/2/2016 at 3:46 PM

Did you check the docs at the ColorThief site?

Comment 30 (In reply to #29) by Erhan Yaşar posted on 11/2/2016 at 4:37 PM

Of course, you may check either https://github.com/lokesh/c...

Comment 31 by octavn posted on 11/8/2016 at 4:35 PM
 < input type="file" capture="camera" accept="image/*"

is now slightly outdated with the boolean variant of the capture attribute being in the HTML Media Capture spec since 2012.

Updated code:

 < input type="file" capture="capture" accept="image/*"

That being said, the capture attribute, in any form, is only respected by Android. iOS still gives you the option to select an existing photo regardless of it's presence.

For more details check out my article on the HTML Media Capture syntax https://addpipe.com/blog/co...

Comment 32 (In reply to #31) by Raymond Camden posted on 11/8/2016 at 4:39 PM

You realize this post is like 3+ years old too, right? ;)

Comment 33 (In reply to #32) by octavn posted on 11/8/2016 at 4:46 PM

Yup, but still seems to be popular for accessing the webcam :)

Comment 34 (In reply to #33) by Raymond Camden posted on 11/8/2016 at 4:49 PM

Fair enough - and obviously if you found it - others will.

Comment 35 by Papia Chowdhury posted on 1/16/2017 at 8:35 AM

Hello Raymond,

Though it is an old post, still I didn't find any comparable post to your one on this topic.
I am not a programmer, but now stuck in an urgent need of changing someone's code for an application to go live. I am successful implementing your code for single image, but I have to do it for more than one image, I mean multiple images. Can you help me with how to do that? I hope I don't sound cocky, but really I do have very little knowledge of writing code. Hope you won't mind guiding me.

Thanks
Papia

Comment 36 (In reply to #35) by Raymond Camden posted on 1/16/2017 at 2:01 PM

Depending on exactly what you are doing, it could be non-trivial. You can add "multiple" to the input field and see if you are allowed to take multiple pictures, but then the JS code has to handle that too. Mine specifically only uses the first image.

It is doable, but not something I could handle properly in a comment. Sorry.

Comment 37 by awebdeveloper posted on 2/26/2017 at 4:27 AM

Doesnt work on android. I am trying this on a emulator (Nexus 5x with Android 6)

I am using

`<input type="file" accept="image/*" capture="capture"/> `

Did you try this on android.

Comment 38 (In reply to #37) by octavn posted on 2/27/2017 at 9:13 AM

I am not sure it will work on emulators. Can the emulator also emulate the webcam or mic?

You should test on a real device. The code is correct.

Comment 39 (In reply to #38) by awebdeveloper posted on 2/27/2017 at 3:26 PM

Tested on a actual phone and it doesn't work

Comment 40 (In reply to #37) by Raymond Camden posted on 2/27/2017 at 3:28 PM

You said it doesn't work - what happens when you click? When you remote debug with Chrome DevTools, what do you see?

Comment 41 (In reply to #40) by awebdeveloper posted on 2/27/2017 at 5:38 PM

I only get the file upload. Not the camera option. Works perfectly on iOS n Mobile web but not Android

Comment 42 (In reply to #41) by Raymond Camden posted on 2/27/2017 at 7:17 PM

Try the updated blog post, https://www.raymondcamden.c.... Note that capture="camera" may be what you need now.

Comment 43 (In reply to #42) by octavn posted on 2/28/2017 at 10:08 AM

Since 5 years ago `capture` became a boolean in the spec https://www.w3.org/TR/2012/... so using `capture="camera"` (string, non boolean) is not guaranteed to work either across browsers and devices.

Comment 44 (In reply to #43) by Raymond Camden posted on 2/28/2017 at 2:12 PM

Ah yeah - I always forget which is which. Either way - maybe the newer post will help him/her.

Comment 45 (In reply to #44) by awebdeveloper posted on 3/1/2017 at 2:18 AM

I tried all 5 on android cordova(moto g3). Your solutions work on mobile web not on android webview.

1. <input type="file" accept="image/*" capture="">
2. <input type="file" accept="image/*" capture="camera">
3. <input type="file" capture="camera">
4. <input type="file" capture="">
5. <input type="file" accept="image/*">

Comment 46 (In reply to #44) by awebdeveloper posted on 3/1/2017 at 2:22 AM

See jcesamobile's comment in this comment to the question http://stackoverflow.com/qu...

Comment 47 (In reply to #45) by Raymond Camden posted on 3/1/2017 at 2:22 AM

Ok - but you realize that this post was about using the camera outside of Cordova - if you are using Cordova just use the plugin.

Comment 48 (In reply to #47) by awebdeveloper posted on 3/1/2017 at 6:56 AM

hmm... it wasnt apparent.

Comment 49 (In reply to #48) by Raymond Camden posted on 3/1/2017 at 12:33 PM

Err... you do see the title of the post, right? :)

Comment 50 (In reply to #49) by awebdeveloper posted on 3/1/2017 at 6:17 PM

Not being disrespectful but the title no were mentioned browser. The reason I got confused is that it says without phonegap. And I thought with that you meant plan web view

Comment 51 by Van Essen posted on 3/26/2017 at 8:55 AM

Hi,
Is there an adaptation to collect the information of a barcode?
I would use my iphone with HTML5 to manage a barcode database.
Thank you!

Comment 52 (In reply to #51) by Raymond Camden posted on 3/26/2017 at 1:08 PM

You can't right now, but it's coming soon in Chrome at least: https://www.chromestatus.co...

Comment 53 by Marina Reznik posted on 7/5/2017 at 7:36 PM

Hi,
how look input for Choose Existing button?
Thank you!

Comment 54 (In reply to #53) by Raymond Camden posted on 7/6/2017 at 1:00 PM

Sorry what?

Comment 55 (In reply to #54) by Marina Reznik posted on 7/6/2017 at 7:37 PM

Oh sorry
I create two buttons as in your demo, one of them should open the camera (take a photo), the second (choose existing) one immediately access the gallery
For the camera button I'm writing, <type ="fille"="" capture="camera " accept="image/*"> , but what should I write for the second button?
What I need to write in order to access the gallery, not to the camera?
Thank you!

Comment 56 (In reply to #55) by Raymond Camden posted on 7/6/2017 at 7:46 PM

A regular input/type=file without the capture/accept stuff should prompt you to select from various locations, which on the iPhone includes the photo library.

Comment 57 (In reply to #56) by Marina Reznik posted on 7/6/2017 at 8:50 PM

I'll try
But if I'm not mistaken, this way opens the bottom menu iPhone to select a file(camera,gallery,Dropbox)
Thank you!

Comment 58 (In reply to #57) by Raymond Camden posted on 7/6/2017 at 10:10 PM

Yeah - that's what it did for me too.

Comment 59 by Vinit Pratap Singh posted on 7/29/2017 at 10:36 AM

How can i open front camera by default, i have to use this on framwork7.

Comment 60 (In reply to #59) by Raymond Camden posted on 7/29/2017 at 1:45 PM

The newer MediaDevices.getUserMedia lets you specify a front facing camera. Start here: https://developer.mozilla.o...