javascript - WinJS 条形码读取器问题(图像未在 Canvas 中加载)

标签 javascript visual-studio-2012 html5-canvas windows-store-apps winjs

正在开发基于 winjs 的条形码读取器应用程序。最初,我将使用相机捕获 API 捕获图像,并将该文件对象传递给 Canvas 元素并使用 ZXing 库读取其条形码。但是传递到 Canvas 的图像并未完全渲染,如下所示。 enter image description here 以下是我的 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>

以下是我的 JavaScript 代码

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

当我使用文件选择器 API 时,相同的代码运行良好。让我知道我错在哪里。

最佳答案

我认为您在这里遇到了一些异步问题。我赞赏您使用对 then() 的链式调用,但存在一个隐藏的问题 - 对 img.src 的分配在加载图像时开始异步操作。在引发 img.onload 事件之前,您的代码将继续运行,因此 img.onload 所触及的 img 变量(指向文件 URL 的指针)的闭包会在图像完全加载之前发生变化。

这是一些对我有用的代码。

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

希望这会有所帮助!

关于javascript - WinJS 条形码读取器问题(图像未在 Canvas 中加载),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21061748/

相关文章:

c++ - 重建项目而不停止调试

javascript - HTML5 Canvas 抗锯齿?

javascript - ngSrc 更改时 Angular 指令 : rescale images, 更新

javascript - 单击图像添加到 HTML5 Canvas 路径

javascript - 当文本变得可见时,在滚动期间更改图像

Firefox 扩展中的 Javascript 正则表达式

visual-studio-2012 - 如何在 Visual Studio 2012 中结合 Entity Framework 和 SQL Compact?

c# - 更改后 Visual Studio 2012 不再编译

javascript:检查是否存在多个特定对象属性(也在coffeescript中)

javascript - $http.post 奇怪的行为