使用Javascript:作为Uint8Array存储到画布元件而不数据URI渲染PNG([remo

2019-07-05 21:49发布

我试图使存储在一个javascript PNG图像Uint8Array 。 我最初试图代码为以下几点:

var imgByteStr = String.fromCharCode.apply(null, this.imgBytes);

var pageImg = new Image();
pageImg.onload = function(e) {

    // Draw onto the canvas
    canvasContext.drawImage(pageImg, 0, 0);

};

// Attempt to generate the Data URI from the binary
// 3rd-party library adds toBase64() as a string function
pageImg.src="data:image/png;base64,"+encodeURIComponent(imgByteStr.toBase64());

然而,我发现,由于某种原因,在onload函数从来没有运行(我不得不在Chrome设置断点,它根本不会打)。 我发现,如果我将src设置为网址,而不是数据URI,它工作正常。 然而,由于一些限制,我不能直接引用图像的URL,即它必须从加载UInt8Array

此外,为了事情变得复杂的是,这些图像可以在尺寸上兆字节。 从我已阅读,也有与尝试使用数据URI非常大的图像的兼容性问题。 正因为如此,我非常犹豫,利用它们。

现在的问题,因此,这是我怎么使这个字节数组作为PNG到画布背景下,而无需使用数据URI或直接引用该图片的网址?


我一直在使用类似下面的直接处理图像数据使用也试过putImageData功能。 请记住,我没有100%了解此功能

var imgdata = canvasContext.createImageData(this.baseHeight, this.baseWidth);
var imgdatalen = imgdata.data.length;
for(var i=0; i<imgdatalen; i++) {
    imgdata.data[i] = _this.imgBytes[i];
}
canvasContext.putImageData(imgdata, 0, 0);

它是从一个博客,其标签我有自闭解除,所以道歉的灵感没有给出适当的。


此外,虽然慢慢这个东西骂个不停,我遇到了Chrome的错误SECURITY_ERR: DOM Exception 18 。 结果是,一旦图像被加载inot使用的drawImage画布,它不能在没有某些附加的解决方法进行检索。 一个Chromium博客博文的主题是特别有用

Answer 1:

如果您在内存中的数据PNG(我认为这是你描述),那么你可以从它创建的图像。 在HTML它会是什么样子:

 <img src="data:image/png;base64,KSjs9JdldhAlisflAkshf==" />

在JavaScript中,你可以做同样的:

var image = document.createElement('img');
    image.src = 'data:image/png;base64,' + base64Data;

请注意,您可以更改MIME类型,如果你没有PNG数据。

然后,您可以绘制image上使用您的画布context.drawImage(image, 0, 0)或类似的。

所以这一难题的其余部分是你的内容编码Uint8Array到基地64个数据。

var array = new Uint8Array(),
    base64Data = btoa(String.fromCharCode.apply(null, array));

该功能btoa不标准,所以一些浏览器可能不支持它。 然而似乎大多数人 。 否则,你可能会发现一些代码,我使用很有帮助。

我没有测试过任何这喽!



Answer 2:

如果你已经有了一个UInt8Array,你应该考虑使用BlobcreateObjectURL ; createObjectURL分配一个特殊的URL,可以让浏览器,就好像是一个文件被加载外部访问二进制数据的内部产生斑点。

凡有支持 , createObjectURL是巨大的数据URI的一个很好的替代。 您可能还需要退回到使用在Opera,IE <10数据的URI,和所有,但最新版本的移动浏览器。

var myArray; //= your data in a UInt8Array
var blob = new Blob([myArray], {'type': 'image/png'});
var url = URL.createObjectURL(blob); //possibly `webkitURL` or another vendor prefix for old browsers.


Answer 3:

全部工作实例:(保存为.html文件和打开)

1:创建Uint8Array。

2:与调试图案填充。

3:粘贴它页面上canvas元素。

输出谨象下面这样:

<!DOCTYPE HTML >
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> U8A_TO_CANVAS </title>
    <meta name   ="author" 
          content="John Mark Isaac Madison">
    <!-- EMAIL: J4M4I5M7@HOTMAIL.com           -->
</head>
<body>
<canvas id="CANVAS_ID" 
         width ="512" 
         height="512">
</canvas>
<script>

var com     =  4 ; //:4 components( RGBA )
var wid     = 512;
var hig     = 512;
var tot_com = wid*hig*com;//:total#components
var u8a     = new Uint8Array( tot_com );

DrawDebugPattern  ( u8a , wid, hig              );
Uint8ArrayToCanvas( u8a , wid, hig, "CANVAS_ID" );

function Uint8ArrayToCanvas( 
    u8a, //:uint8Array
    wid, //:width__of_u8a_data_in_pixels
    hig, //:height_of_u8a_data_in_pixels
    nam, //:name_id_of_canvas_on_dom
){

    //:Get Canvas:
    var can = document.getElementById( nam );
    if(!can){ throw "[FailedToGetCanvas]"; }

    //:Get Canvas's 2D Context:
    var ctx = can.getContext("2d");
    if(!ctx){ throw "[FailedToGetContext]"; }

    //:Use U8A to create image data object:    
    var UAC = new Uint8ClampedArray( u8a,wid,hig);
    var DAT = new ImageData(UAC, wid, hig);

    //:Paste Data Into Canvas:     
    var ORG_X = 0;                         
    var ORG_Y = 0;                         
    ctx.putImageData( DAT, ORG_X, ORG_Y );  
}

function DrawDebugPattern(u8a,wid,hig){

    var com     = 4      ; //:RGBA==4components.
    var tot_pix = wid*hig;//:total#pixels

    //:Calculate point in center of canvas:
    var cen_x = wid/2;
    var cen_y = hig/2;

    //:Define a circle's radius:
    var rad_c = Math.min(wid,hig) / 2;

    //:Make a pattern on array:
    var d   = 0; //:d_is_for_distance
    var ci  = 0; //:Component_Index
    var pi  = 0; //:Pixel_Index
    var px  = 0; //:Pixel_X_Coord
    var py  = 0; //:Pixel_Y_Coord
    for( pi = 0; pi < tot_pix; pi++ ){

        //:Calculate index of first component
        //:of current pixel:
        ci = pi * com;

        //:Index_To_XY_Formula:
        px =  pi    % wid ;
        py = (pi-px)/ wid ;

        //:Decide if pixel is inside circle:
        var dx = (cen_x-px); //:delta_x
        var dy = (cen_y-py); //:delta_y
        d=Math.sqrt( (dx*dx)+(dy*dy) );
        if( d < rad_c ){
            //:INSIDE_CIRCLE:
            u8a[ ci + 0 ] = 0  ; //:Red
            u8a[ ci + 1 ] = 255; //:Green
            u8a[ ci + 2 ] = 0  ; //:Blue
            u8a[ ci + 3 ] = 255; //:Alpha
        }else{
            //:OUTSIDE_CIRCLE:
            u8a[ ci + 0 ] = 0  ; //:Red
            u8a[ ci + 1 ] = 0  ; //:Green
            u8a[ ci + 2 ] = 64 ; //:Blue
            u8a[ ci + 3 ] = 255; //:Alpha
        }

    }
}
</script>
</body>
<!-- In IE: Script cannot be outside of body.  -->
</html>


文章来源: Javascript: Render PNG stored as Uint8Array onto Canvas element without Data URI