Saving a Canvas as an image in UWP

眉间皱痕 提交于 2019-12-24 19:40:29

问题


I found this documentation for exporting and saving a Canvas as a png. It gives the following code:

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
});

In the 'encoder.setPixelData' area, they use an object called 'encoding' to set all the values, but have no explanation of how this object is created in any of the prior steps.

How can I create this 'encoding' object to complete the example?


回答1:


I found a different way to save the canvas, still didn't solve my initial problem

I can turn the canvas into a blob stream and save that to a png file

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
        });
}

Unfortunately it's saving with a transparent background, but maybe there's a way I can make my canvas have a white background.

[edit] ----

So I found a way to answer my original question more directly:

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
        });
}

I've commented out the ability to save as JPG because that's a new problem, but this works for pngs




回答2:


Place your canvas within a Grid with background white and then render it using RenderTargetBitmap. It worked fine for me.

            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();


来源:https://stackoverflow.com/questions/53525526/saving-a-canvas-as-an-image-in-uwp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!