在UWP中将画布另存为图像

时间:2018-11-28 18:04:50

标签: javascript uwp winjs

我发现this documentation用于将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 :(得分:0)

我找到了另一种保存画布的方法,但仍然没有解决我的最初问题

我可以将画布转换为Blob流并将其保存到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
        });
}

不幸的是,它使用透明背景进行保存,但是也许有一种方法可以使我的画布具有白色背景。

[edit] ----

因此,我找到了一种更直接地回答原始问题的方法:

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的功能,因为这是一个新问题,但这适用于png

答案 1 :(得分:0)

将画布放在背景为白色的网格内,然后使用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();