locked
How to save a photo captured via the webcam?

    Question

  • I am creating an app that requries the user to capture a picture via the camera app, I would like to save the photo the user captured into a folder. I have been searching high and low for an answer but I have yet to find one. Here is what I have so far 

    linkClickEventHandler: function (eventInfo) { //Launches camera function to capture a picture var captureUI = new Windows.Media.Capture.CameraCaptureUI(); captureUI.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).then(function (capturedItem) { //If the user captured a picture if (capturedItem) { //This is where the capturedItem would be saved } else { document.getElementById("output").innerHTML = "User didn't capture a photo." } }); }

    Any help would be greatly appreciated


    Wednesday, November 14, 2012 1:02 AM

Answers

  • Hi,

    Please refer to the follow code to create a file:

    var localFolder = Windows.Storage.ApplicationData.current.localFolder;  
        localFolder.createFileAsync("myfile.data", Windows.Storage.CreationCollisionOption.replaceExisting)  
            .then(function (file) {  
               return Windows.Storage.FileIO.writeTextAsync(file, jsonText);  
           });


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com
    Microsoft One Code Framework

    • Marked as answer by Song Tian Tuesday, November 20, 2012 9:52 AM
    Wednesday, November 14, 2012 2:51 AM
  • The capturedItem that you get in your completed handler is a StorageFile object that you can then duplicate anywhere else you'd like using the StorageFile.copyAsync method. Here's how I do exactly that in the "HereMyAm" example from Chapter 8 of my free ebook from MSPress, Programming Windows 8 Apps with HTML, CSS, and JavaScript:

        function capturePhoto() {
            //Due to the .bind() call in addEventListener, "this" will be the image element,
            //but we need a copy for the async completed handler below.
            var that = this;
    
            var captureUI = new Windows.Media.Capture.CameraCaptureUI();
    
            //Indicate that we want to capture a PNG that's no bigger than our target element --
            //the UI will automatically show a crop box of this size
            captureUI.photoSettings.format = Windows.Media.Capture.CameraCaptureUIPhotoFormat.png;
            captureUI.photoSettings.croppedSizeInPixels = { width: this.clientWidth, height: this.clientHeight };
    
            //For use across chained promises
            var capturedFile = null;
    
            captureUI.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo)
                .then(function (capturedFileTemp) {
                    //Be sure to check validity of the item returned; could be null if the user canceled.
                    if (!capturedFileTemp) { throw ("no file captured"); }
    
                    //As a demonstration of ms-appdata usage, copy the StorageFile to a folder called HereMyAm
                    //in the appdata/local folder, and use ms-appdata to point to that.
                    //var local = Windows.Storage.ApplicationData.current.localFolder;
    
                    //Use this folder instead to copy to the Pictures Library--be sure to declare that capability in the manifest
                    var pix = Windows.Storage.KnownFolders.picturesLibrary;
    
                    capturedFile = capturedFileTemp;
                    return pix.createFolderAsync(folderName, Windows.Storage.CreationCollisionOption.openIfExists);
                })
                .then(function (myFolder) {
                    //Again, check validity of the result operations
                    if (!myFolder) { throw ("could not create local appdata folder"); }
    
                    //Append file creation time to the filename (should avoid collisions, but need to convert colons)
                    var newName = capturedFile.displayName + " - " + capturedFile.dateCreated.toString().replace(/:/g, "-") + capturedFile.fileType;
                    return capturedFile.copyAsync(myFolder, newName);
                })
                .done(function (newFile) {
                    updateImage(that, newFile);
                },
                function (error) {
                    console.log(error.message);
                });
        }

    You'll see here that I'm creating a subfolder within the picture library (or local appdata, which is in a commented line), but that step isn't necessary--so long as you have the StorageFolder you want, you just pass that to copyAsync. Also note that the 'updateImage' function is just what called URL.createObjectURL and assigns the result to an img element for display and saves the StorageFile in Windows.Storage.AccessCache for future reference.

    .Kraig
    Author, Programming Windows 8 Apps with HTML, CSS, and JavaScript, a free ebook from Microsoft Press


    • Marked as answer by Techn0guy Thursday, November 15, 2012 1:30 AM
    Wednesday, November 14, 2012 5:48 PM

All replies

  • Hi,

    Please refer to the follow code to create a file:

    var localFolder = Windows.Storage.ApplicationData.current.localFolder;  
        localFolder.createFileAsync("myfile.data", Windows.Storage.CreationCollisionOption.replaceExisting)  
            .then(function (file) {  
               return Windows.Storage.FileIO.writeTextAsync(file, jsonText);  
           });


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com
    Microsoft One Code Framework

    • Marked as answer by Song Tian Tuesday, November 20, 2012 9:52 AM
    Wednesday, November 14, 2012 2:51 AM
  • It is giving me an error that jsonText is undefined what would I have to replace it with?
    Wednesday, November 14, 2012 3:54 AM
  • Hi,

    That just is an example. You should define that before the function.


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com
    Microsoft One Code Framework

    Wednesday, November 14, 2012 6:10 AM
  • The capturedItem that you get in your completed handler is a StorageFile object that you can then duplicate anywhere else you'd like using the StorageFile.copyAsync method. Here's how I do exactly that in the "HereMyAm" example from Chapter 8 of my free ebook from MSPress, Programming Windows 8 Apps with HTML, CSS, and JavaScript:

        function capturePhoto() {
            //Due to the .bind() call in addEventListener, "this" will be the image element,
            //but we need a copy for the async completed handler below.
            var that = this;
    
            var captureUI = new Windows.Media.Capture.CameraCaptureUI();
    
            //Indicate that we want to capture a PNG that's no bigger than our target element --
            //the UI will automatically show a crop box of this size
            captureUI.photoSettings.format = Windows.Media.Capture.CameraCaptureUIPhotoFormat.png;
            captureUI.photoSettings.croppedSizeInPixels = { width: this.clientWidth, height: this.clientHeight };
    
            //For use across chained promises
            var capturedFile = null;
    
            captureUI.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo)
                .then(function (capturedFileTemp) {
                    //Be sure to check validity of the item returned; could be null if the user canceled.
                    if (!capturedFileTemp) { throw ("no file captured"); }
    
                    //As a demonstration of ms-appdata usage, copy the StorageFile to a folder called HereMyAm
                    //in the appdata/local folder, and use ms-appdata to point to that.
                    //var local = Windows.Storage.ApplicationData.current.localFolder;
    
                    //Use this folder instead to copy to the Pictures Library--be sure to declare that capability in the manifest
                    var pix = Windows.Storage.KnownFolders.picturesLibrary;
    
                    capturedFile = capturedFileTemp;
                    return pix.createFolderAsync(folderName, Windows.Storage.CreationCollisionOption.openIfExists);
                })
                .then(function (myFolder) {
                    //Again, check validity of the result operations
                    if (!myFolder) { throw ("could not create local appdata folder"); }
    
                    //Append file creation time to the filename (should avoid collisions, but need to convert colons)
                    var newName = capturedFile.displayName + " - " + capturedFile.dateCreated.toString().replace(/:/g, "-") + capturedFile.fileType;
                    return capturedFile.copyAsync(myFolder, newName);
                })
                .done(function (newFile) {
                    updateImage(that, newFile);
                },
                function (error) {
                    console.log(error.message);
                });
        }

    You'll see here that I'm creating a subfolder within the picture library (or local appdata, which is in a commented line), but that step isn't necessary--so long as you have the StorageFolder you want, you just pass that to copyAsync. Also note that the 'updateImage' function is just what called URL.createObjectURL and assigns the result to an img element for display and saves the StorageFile in Windows.Storage.AccessCache for future reference.

    .Kraig
    Author, Programming Windows 8 Apps with HTML, CSS, and JavaScript, a free ebook from Microsoft Press


    • Marked as answer by Techn0guy Thursday, November 15, 2012 1:30 AM
    Wednesday, November 14, 2012 5:48 PM