изменить размер изображения перед загрузкой с помощью фоновой передачи в 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 примера Simple Imaging (http://code.msdn.microsoft.com/windowsapps/Simple-Imaging-Sample-a2dec2b0), в котором показано, как выполнять всевозможные преобразования изображения. Изменение размеров включено туда, так что это будет просто вопрос вырезания частей, которые вам не нужны.

Я обсуждаю все это в моей бесплатной электронной книге Программирование приложений Магазина Windows с помощью 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