Сохранение холста как изображения в UWP - PullRequest
0 голосов
/ 28 ноября 2018

Я нашел эту документацию для экспорта и сохранения Canvas в виде png.Он дает следующий код:

var Imaging = Windows.Graphics.Imaging;
var picker = new Windows.Storage.Pickers.FileSavePicker();
picker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
picker.fileTypeChoices.insert("PNG file", [".png"]);
var imgData, fileStream = null;
picker.pickSaveFileAsync().then(function (file) {            
    if (file) {
        return file.openAsync(Windows.Storage.FileAccessMode.readWrite);                
    } else {
        return WinJS.Promise.wrapError("No file selected");
    }
}).then(function (stream) {
    fileStream = stream;
    var canvas = document.getElementById("canvas1");            
    var ctx = canvas.getContext("2d");
    imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);

    return Imaging.BitmapEncoder.createAsync(Imaging.BitmapEncoder.pngEncoderId, stream);
}).then(function (encoder) {
    //Set the pixel data--assume "encoding" object has options from elsewhere
    encoder.setPixelData(encoding.pixelFormat, encoding.alphaMode,
        encoding.width, encoding.height, encoding.dpiX, encoding.dpiY,
        new Uint8Array(imgData.data));
    //Go do the encoding
    return encoder.flushAsync();
}).done(function () {
    //Make sure to do this at the end
    fileStream.close();  
}, function () {
    //Empty error handler (do nothing if the user canceled the picker
});

В области «encoder.setPixelData» они используют объект «encoding» для установки всех значений, но не имеют объяснения того, как этот объект создается в любомпредыдущих шагов.

Как я могу создать этот объект 'кодирования' для завершения примера?

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Поместите ваш холст в сетку с белым фоном, а затем визуализируйте его, используя RenderTargetBitmap.Это работало нормально для меня.

            RenderTargetBitmap rtb = new RenderTargetBitmap();
            await rtb.RenderAsync("Your Grid containing canvas goes here");    
            var pixelBuffer = await rtb.GetPixelsAsync();
            var pixels = pixelBuffer.ToArray();
            var displayInformation = DisplayInformation.GetForCurrentView();
            FileSavePicker savePicker = new FileSavePicker();
            savePicker.FileTypeChoices.Add("png", new List<string>() { ".png" });
            savePicker.SuggestedFileName = "PNG File";
            StorageFile file = await savePicker.PickSaveFileAsync();
0 голосов
/ 29 ноября 2018

Я нашел другой способ сохранить холст, но до сих пор не решил свою первоначальную проблему

Я могу превратить холст в поток больших двоичных объектов и сохранить его в png-файле

function saveCanvasAsImage(canvasElement) {
    var picker = new Windows.Storage.Pickers.FileSavePicker();
    picker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
    picker.fileTypeChoices.insert("PNG file", [".png"]);

    var input, output = null;
    var blob = canvasElement.msToBlob();

    return picker.pickSaveFileAsync()
        .then(function (file) {
            if (file) {
                return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
            } else {
                return WinJS.Promise.wrapError("No file selected");
            }
        })
        .then(function (op) {
            output = op;
            input = blob.msDetachStream();

            return Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output);
        })
        .then(function() {
            return output.flushAsync();
        })
        .done(function() {
            input.close();
            output.close();
        }, function(e) {
            // handle error here
        });
}

К сожалению, это сохранение с прозрачным фоном, но, возможно, я могу сделать так, чтобы у моего холста был белый фон.

[править] ----

Так что я нашел способОтветьте на мой первоначальный вопрос более прямо:

function saveCanvasAsImage(canvasElement) {
    var Imaging = Windows.Graphics.Imaging;
    var picker = new Windows.Storage.Pickers.FileSavePicker();
    picker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
    // picker.fileTypeChoices.insert("JPEG file", [".jpg"]);
    picker.fileTypeChoices.insert("PNG file", [".png"]);
    var fileStream, decoder, encoding, pixels = null;


    var encoderIds = {
        '.png': Imaging.BitmapEncoder.pngEncoderId,
        '.jpg': Imaging.BitmapEncoder.jpegEncoderId
    }

    var encoderId = encoderIds['.jpg'];

    var blob = canvasElement.msToBlob();

    return Imaging.BitmapDecoder.createAsync(Imaging.BitmapDecoder.pngDecoderId,
            blob.msDetachStream())
        .then(function (dc) {
            decoder = dc;

            return picker.pickSaveFileAsync();
        }).then(function (file) {
            if (file) {
                encoderId = encoderIds[file.fileType];
                return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
            } else {
                return WinJS.Promise.wrapError("No file selected");
            }
        }).then(function(stream) {
            fileStream = stream;

            var transform = new Windows.Graphics.Imaging.BitmapTransform();

            return decoder.getPixelDataAsync(
                decoder.bitmapPixelFormat,
                decoder.bitmapAlphaMode,
                transform,
                Windows.Graphics.Imaging.ExifOrientationMode.respectExifOrientation,
                Windows.Graphics.Imaging.ColorManagementMode.colorManageToSRgb
            );

        }).then(function (pixelProvider) {

            pixels = pixelProvider.detachPixelData();

            return Imaging.BitmapEncoder.createAsync(encoderId, fileStream);
        }).then(function (encoder) {
            encoding = decoder;
            //Set the pixel data--assume "encoding" object has options from elsewhere
            encoder.setPixelData(encoding.bitmapPixelFormat, encoding.bitmapAlphaMode,
                encoding.pixelWidth, encoding.pixelHeight, encoding.dpiX, encoding.dpiY,
                pixels);
            //Go do the encoding
            return encoder.flushAsync();
        }).done(function () {
            //Make sure to do this at the end
            fileStream.close();
        }, function () {
            //Empty error handler (do nothing if the user canceled the picker
        });
}

Я прокомментировал возможность сохранения в формате JPG, потому что это новая проблема, но это работает для pngs

...