преоразмерете изображението преди качване чрез фонов трансфер в winjs

Бих искал да преоразмеря изображение, избрано от галерията на телефона, преди да го кача чрез фоново прехвърляне, досега имам: -

filePicker.pickSingleFileAsync().then(function (file) {
                            uploadSingleFileAsync(uri, file);
                        }).done(null, displayException);

function uploadSingleFileAsync(uri, file) {
                    if (!file) {
                        displayError("Error: No file selected.");
                        return;
                    }
                    return file.getBasicPropertiesAsync().then(function (properties) {
                        if (properties.size > maxUploadFileSize) {
                            displayError("Selected file exceeds max. upload file size (" + (maxUploadFileSize / (1024 * 1024)) +
                                " MB).");
                            return;
                        }
                        var upload = new UploadOperation();
                        //tried this to compress the file but it doesnt work obviously not right for the object
                        //file = file.slice(0, Math.round(file.size / 2));
                        upload.start(uri, file);
                        // Persist the upload operation in the global array.
                        uploadOperations.push(upload);
                    });
                }

а останалите след това качват файла. Опитах се да добавя .slice, но не работи (предполагам, че файлът е по-скоро обект) и не съм сигурен как да компресирам този тип файлов обект. Изглежда не мога да намеря никакви примери или съвети в msdn или във форумите за разработчици на Windows, очевидно мога да преоразмеря снимките, след като са на сървъра, но бих предпочел потребителите да не чакат повече, отколкото трябва, за да качат файловете си.

Трябва ли да запазя изображението, преди да мога да го манипулирам? Всеки съвет ще бъде много оценен!

** РЕДАКТИРАНЕ *

моето качване на singlefileasync сега изглежда така:-

function uploadSingleFileAsync(uri, file) {
                    if (!file) {
                        displayError("Error: No file selected.");
                        return;
                    }

                    return file.getBasicPropertiesAsync().then(function (properties) {
                        if (properties.size > maxUploadFileSize) {
                            displayError("Selected file exceeds max. upload file size (" + (maxUploadFileSize / (1024 * 1024)) +
                                " MB).");
                            return;
                        }







                        // Exception number constants. These constants are defined using values from winerror.h,
                        // and are compared against error.number in the exception handlers in this scenario.

                        // This file format does not support the requested operation; for example, metadata or thumbnails.
                        var WINCODEC_ERR_UNSUPPORTEDOPERATION = Helpers.convertHResultToNumber(0x88982F81);
                        // This file format does not support the requested property/metadata query.
                        var WINCODEC_ERR_PROPERTYNOTSUPPORTED = Helpers.convertHResultToNumber(0x88982F41);
                        // There is no codec or component that can handle the requested operation; for example, encoding.
                        var WINCODEC_ERR_COMPONENTNOTFOUND = Helpers.convertHResultToNumber(0x88982F50);
                        // Keep objects in-scope across the lifetime of the scenario.
                        var FileToken = "";
                        var DisplayWidthNonScaled = 0;
                        var DisplayHeightNonScaled = 0;
                        var ScaleFactor = 0;
                        var UserRotation = 0;
                        var ExifOrientation = 0;
                        var DisableExifOrientation = false;

                        // Namespace and API aliases
                        var FutureAccess = Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList;
                        var LocalSettings = Windows.Storage.ApplicationData.current.localSettings.values;

                        //FileToken = FutureAccess.add(file);
                        FileToken = Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList.add(file);

                        id("myImage").src = window.URL.createObjectURL(file, { oneTimeOnly: true });
                        id("myImage").alt = file.name;

                        // Use BitmapDecoder to attempt to read EXIF orientation and image dimensions.
                        return loadSaveFileAsync(file)


                        function resetPersistedState() {
                            LocalSettings.remove("scenario2FileToken");
                            LocalSettings.remove("scenario2Scale");
                            LocalSettings.remove("scenario2Rotation");
                        }
                        function resetSessionState() {
                            // Variables width and height reflect rotation but not the scale factor.
                            FileToken = "";
                            DisplayWidthNonScaled = 0;
                            DisplayHeightNonScaled = 0;
                            ScaleFactor = 1;
                            UserRotation = Windows.Storage.FileProperties.PhotoOrientation.normal;
                            ExifOrientation = Windows.Storage.FileProperties.PhotoOrientation.normal;
                            DisableExifOrientation = false;

                        }




                        function loadSaveFileAsync(file) {
    // Keep data in-scope across multiple asynchronous methods.
    var inputStream;
    var outputStream;
    var encoderId;
    var pixels;
    var pixelFormat;
    var alphaMode;
    var dpiX;
    var dpiY;
    var outputFilename;
    var ScaleFactor = 0.5;

    new WinJS.Promise(function (comp, err, prog) { comp(); }).then(function () {
        // On Windows Phone, this call must be done within a WinJS Promise to correctly
        // handle exceptions, for example if the file is read-only.
        return FutureAccess.getFileAsync(FileToken);

    }).then(function (inputFile) {
        return inputFile.openAsync(Windows.Storage.FileAccessMode.read);
    }).then(function (stream) {
        inputStream = stream;
        return Windows.Graphics.Imaging.BitmapDecoder.createAsync(inputStream);
    }).then(function (decoder) {
        var transform = new Windows.Graphics.Imaging.BitmapTransform();

        // Scaling occurs before flip/rotation, therefore use the original dimensions
        // (no orientation applied) as parameters for scaling.
        // Dimensions are rounded down by BitmapEncoder to the nearest integer.
        transform.scaledHeight = decoder.pixelHeight * ScaleFactor;
        transform.scaledWidth = decoder.pixelWidth * ScaleFactor;
        transform.rotation = Helpers.convertToBitmapRotation(UserRotation);

        // Fant is a relatively high quality interpolation mode.
        transform.interpolationMode = Windows.Graphics.Imaging.BitmapInterpolationMode.fant;

        // The BitmapDecoder indicates what pixel format and alpha mode best match the
        // natively stored image data. This can provide a performance and/or quality gain.
        pixelFormat = decoder.bitmapPixelFormat;
        alphaMode = decoder.bitmapAlphaMode;
        dpiX = decoder.dpiX;
        dpiY = decoder.dpiY;

        // Get pixel data from the decoder. We apply the user-requested transforms on the
        // decoded pixels to take advantage of potential optimizations in the decoder.
        return decoder.getPixelDataAsync(
            pixelFormat,
            alphaMode,
            transform,
            Windows.Graphics.Imaging.ExifOrientationMode.respectExifOrientation,
            Windows.Graphics.Imaging.ColorManagementMode.colorManageToSRgb
            );
    }).then(function (pixelProvider) {
        pixels = pixelProvider.detachPixelData();

        // The destination file was passed as an argument to loadSaveFileAsync().
        outputFilename = file.name;
        switch (file.fileType) {
            case ".jpg":
                encoderId = Windows.Graphics.Imaging.BitmapEncoder.jpegEncoderId;
                break;
            case ".bmp":
                encoderId = Windows.Graphics.Imaging.BitmapEncoder.bmpEncoderId;
                break;
            case ".png":
            default:
                encoderId = Windows.Graphics.Imaging.BitmapEncoder.pngEncoderId;
                break;
        }

        return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
    }).then(function (stream) {
        outputStream = stream;

        // BitmapEncoder expects an empty output stream; the user may have selected a
        // pre-existing file.
        outputStream.size = 0;
        return Windows.Graphics.Imaging.BitmapEncoder.createAsync(encoderId, outputStream);
    }).then(function (encoder) {
        // Write the pixel data onto the encoder. Note that we can't simply use the
        // BitmapTransform.ScaledWidth and ScaledHeight members as the user may have
        // requested a rotation (which is applied after scaling).
        encoder.setPixelData(
            pixelFormat,
            alphaMode,
            DisplayWidthNonScaled * ScaleFactor,
            DisplayHeightNonScaled * ScaleFactor,
            dpiX,
            dpiY,
            pixels
            );

        return encoder.flushAsync();
    }).then(function () {
        WinJS.log && WinJS.log("Successfully saved a copy: " + outputFilename, "sample", "status");
    }, function (error) {
        WinJS.log && WinJS.log("Failed to update file: " + error.message, "sample", "error");
        resetSessionState();
        resetPersistedState();
    }).then(function () {
        // Finally, close each stream to release any locks.
        inputStream && inputStream.close();
        outputStream && outputStream.close();
    }).then(function () {
        var upload = new UploadOperation();
        upload.start(uri, file);
        // Persist the upload operation in the global array.
        uploadOperations.push(upload);

    });
}

Но получавам грешка, когато стигна до този ред return
file.openAsync(Windows.Storage.FileAccessMode.readWrite); казвайки, че нямам достъп за писане? Как да получа достъп за писане или да го преместя, за да мога да имам достъп за писане?


person user3249516    schedule 14.08.2014    source източник


Отговори (1)


За да преоразмерите изображение, можете да използвате API за кодиране на изображение в WinRT, а именно този в Windows.Graphics.Imaging. Предлагам ви да разгледате сценарий 2 от примера за просто изображение (http://code.msdn.microsoft.com/windowsapps/Simple-Imaging-Sample-a2dec2b0), който показва как да правите всички видове трансформации върху изображение. Промяната на размерите е включена там, така че ще бъде просто въпрос на изрязване на частите, които не ви трябват.

Имам дискусия за всичко това в моята безплатна електронна книга, Програмиране на приложения от Windows Store с HTML, CSS и JavaScript, 2-ро издание , в глава 13, раздел „Манипулиране и кодиране на изображения“. Там се опитвам да отделя основните стъпки в процеса в нещо малко по-лесно смилаемо и предоставям допълнителна проба.

Процесът на кодиране може да изглежда доста ангажиращ (много верижни обещания), но е доста ясен и е точно това, което една имейл програма би направила, за да намали размера на прикачените изображения, например. Във всеки случай трябва да получите друг StorageFile с по-малко изображение, което след това можете да предадете на програмата за качване. Бих препоръчал да използвате вашите данни от временното приложение за такива файлове и не забравяйте да ги изчистите, когато качването приключи.

person Kraig Brockschmidt - MSFT    schedule 03.09.2014
comment
благодаря Опитах този пример и дори това ми дава грешката:- SCRIPT16389: Изключението е на път да бъде уловено от кода на библиотеката на JavaScript на ред 485, колона 13 в ms-appx://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/ js/Scenario2_ImageTransforms.js 0x80004005 - Грешка по време на изпълнение на JavaScript: Неуточнена грешка Файл: Scenario2_ImageTransforms.js, Ред: 485, Колона: 13, когато се опитвате да запазите отново изображението на реда, който казва: - return FutureAccess.getFileAsync(FileToken); Мисля, че може да е грешка при тип достъп само за четене - person user3249516; 04.09.2014
comment
Това е странно. Нещата на FutureAccess обаче са само за запазване на разрешения за файла за по-късни сесии. Това не е необходимо, ако записвате в appdata, където имате присъщи разрешения за начало. - person Kraig Brockschmidt - MSFT; 04.09.2014