Javascript WinJS条形码阅读器问题(图像未加载到画布中)

Javascript WinJS条形码阅读器问题(图像未加载到画布中),javascript,visual-studio-2012,html5-canvas,windows-store-apps,winjs,Javascript,Visual Studio 2012,Html5 Canvas,Windows Store Apps,Winjs,我正在开发一个基于winjs的条形码阅读器应用程序。最初,我将使用camera capture API捕获图像,并将该文件对象传递给canvas元素,并使用ZXing库读取其条形码。但是,传递到画布的图像并没有按如下方式完全渲染。 下面是我的html代码 <body> <p>Decoding test for static images</p> <canvas id="canvasDecode" height="200" width="200">&

我正在开发一个基于winjs的条形码阅读器应用程序。最初,我将使用camera capture API捕获图像,并将该文件对象传递给canvas元素,并使用ZXing库读取其条形码。但是,传递到画布的图像并没有按如下方式完全渲染。 下面是我的html代码

<body>
<p>Decoding test for static images</p>
<canvas id="canvasDecode" height="200" width="200"></canvas>
<h3 id="result"></h3>
<p>Put some content here and leave the text box</p>
<input id="input" class="win-textarea" onchange="generate_barcode()">
<h3 id="content"></h3>
<canvas id="canvasEncode" height="200" width="200"></canvas>
<img class="imageHolder" id="capturedPhoto" alt="image holder" />
</body>

静态图像的解码测试

在此处放置一些内容并保留文本框


当我使用文件选择器API时,同样的代码工作得很好。告诉我哪里出了问题。

我认为您在异步性方面遇到了一些问题。我欢迎您使用对then()的链式调用,但有一个隐藏的问题-在加载映像时,对img.src的赋值会开始一个异步操作。在引发img.onload事件之前,代码将继续运行,因此img.onload对img变量(指向文件URL的指针)的闭包将在映像完全加载之前更改

下面是一些对我有用的代码

(function () {
"use strict";

WinJS.Binding.optimizeBindingReferences = true;

var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;

app.onactivated = function (args) {
    if (args.detail.kind === activation.ActivationKind.launch) {
        if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
            // TODO: This application has been newly launched. Initialize
            // your application here.

            var dialog = new Windows.Media.Capture.CameraCaptureUI();
            var aspectRatio = { width: 1, height: 1 };
            dialog.photoSettings.croppedAspectRatio = aspectRatio;
            dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).then(function (file) {

                if (file) {
                    // draw the image
                    var canvas = document.getElementById('canvasDecode')
                    var ctx = canvas.getContext('2d');
                    var img = new Image;
                    img.onload = function () {
                        canvas.width = img.width;
                        canvas.height = img.height;
                        ctx.drawImage(img, 0, 0, img.width, img.height);
                    }
                    img.src = URL.createObjectURL(file);
                    // open a stream from the image
                    return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
                }
            })
            .then(function (stream) {
                if (stream) {
                    // create a decoder from the image stream
                    return Windows.Graphics.Imaging.BitmapDecoder.createAsync(stream);
                }
            })
            .done(function (decoder) {
                if (decoder) {
                    // get the raw pixel data from the decoder
                    decoder.getPixelDataAsync().then(function (pixelDataProvider) {
                        var rawPixels = pixelDataProvider.detachPixelData();
                        var pixels, format; // Assign these in the below switch block.

                        switch (decoder.bitmapPixelFormat) {
                            case Windows.Graphics.Imaging.BitmapPixelFormat.rgba16:
                                // Allocate a typed array with the raw pixel data
                                var pixelBufferView_U8 = new Uint8Array(rawPixels);

                                // Uint16Array provides a typed view into the raw 8 bit pixel data.
                                pixels = new Uint16Array(pixelBufferView_U8.buffer);
                                if (decoder.bitmapAlphaMode == Windows.Graphics.Imaging.BitmapAlphaMode.straight)
                                    format = ZXing.BitmapFormat.rgba32;
                                else
                                    format = ZXing.BitmapFormat.rgb32;
                                break;

                            case Windows.Graphics.Imaging.BitmapPixelFormat.rgba8:
                                // For 8 bit pixel formats, just use the returned pixel array.
                                pixels = rawPixels;
                                if (decoder.bitmapAlphaMode == Windows.Graphics.Imaging.BitmapAlphaMode.straight)
                                    format = ZXing.BitmapFormat.rgba32;
                                else
                                    format = ZXing.BitmapFormat.rgb32;
                                break;

                            case Windows.Graphics.Imaging.BitmapPixelFormat.bgra8:
                                // For 8 bit pixel formats, just use the returned pixel array.
                                pixels = rawPixels;
                                if (decoder.bitmapAlphaMode == Windows.Graphics.Imaging.BitmapAlphaMode.straight)
                                    format = ZXing.BitmapFormat.bgra32;
                                else
                                    format = ZXing.BitmapFormat.bgr32;
                                break;
                        }
                        // create a barcode reader
                        var reader = new ZXing.BarcodeReader();
                        reader.onresultpointfound = function (resultPoint) {
                            // do something with the resultpoint location
                        }
                        // try to decode the raw pixel data
                        var result = reader.decode(pixels, decoder.pixelWidth, decoder.pixelHeight, format);
                        // show the result
                        if (result) {
                            document.getElementById("result").innerText = result.text;
                        }
                        else {
                            document.getElementById("result").innerText = "no barcode found";
                        }
                    });
                }
            });
        } else {
            // TODO: This application has been reactivated from suspension.
            // Restore application state here.
        }
        args.setPromise(WinJS.UI.processAll());
    }
};

app.oncheckpoint = function (args) {
    // TODO: This application is about to be suspended. Save any state
    // that needs to persist across suspensions here. You might use the
    // WinJS.Application.sessionState object, which is automatically
    // saved and restored across suspension. If you need to complete an
    // asynchronous operation before your application is suspended, call
    // args.setPromise().
};

app.start();
})();

function generate_barcode() {
// get the content which the user puts into the textbox
var content = document.getElementById("input").value;

// create the barcode writer and set some options
var writer = new ZXing.BarcodeWriter();
writer.options = new ZXing.Common.EncodingOptions();
writer.options.height = 200;
writer.options.width = 200;
writer.format = ZXing.BarcodeFormat.qr_CODE;

// encode the content to a byte array with 4 byte per pixel as BGRA
var imagePixelData = writer.write(content);

// draw the pixel data to the canvas
var ctx = document.getElementById('canvasEncode').getContext('2d');
var imageData = ctx.createImageData(imagePixelData.width, imagePixelData.heigth);
var pixel = imagePixelData.pixel
for (var index = 0; index < pixel.length; index++) {
    imageData.data[index] = pixel[index];
}
ctx.putImageData(imageData, 0, 0);
}
然后我将文件解码/条形码读取功能移到了一个新功能

// Inside handler for app.activated ...
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 1, height: 1 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo)
    .then(function (file) {
            // draw the image
            var canvas = document.getElementById('canvasDecode')
            var ctx = canvas.getContext('2d');
            var img = new Image;
            img.onload = function () {
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0, img.width, img.height);

                // open a stream from the image
                decodePic(file);
            }
            img.onerror = function (err) {
                WinJS.log && WinJS.log("Error loading image");
            }
            img.src = URL.createObjectURL(file);

    });

我希望这有帮助

非常感谢您对确切的问题给出详细的看法。按预期工作。:)
function decodePic(file) {
    file.openAsync(Windows.Storage.FileAccessMode.readWrite)
    .then(function (stream) {
        if (stream) {
            // create a decoder from the image stream
            return Windows.Graphics.Imaging.BitmapDecoder.createAsync(stream);
        }
    })
    .done(function (decoder) {
        if (decoder) {
            // get the raw pixel data from the decoder
            decoder.getPixelDataAsync().then(function (pixelDataProvider) {
                // YOUR BARCODE READING CODE HERE.
            });
        }
    });
}