[removed] Render PNG stored as Uint8Array onto Canvas element without Data URI

后端 未结 3 1506
面向向阳花
面向向阳花 2020-12-29 04:51

I\'m trying to render a PNG image that is stored in a javascript Uint8Array. The code that I originally tried was the following:

var imgByteStr         


        
相关标签:
3条回答
  • 2020-12-29 04:57

    Full Working Example: (save as .html file and open)

    1: Creates Uint8Array.

    2: Fills it with debug pattern.

    3: Pastes it to canvas element on page.

    Output should like like below:

    <!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>
    
    0 讨论(0)
  • 2020-12-29 04:58

    If you already have a UInt8Array, you should consider using Blob and createObjectURL; createObjectURL allocates a special URL that allows the browser to access an internally created blob of binary data as though it were a file being loaded externally.

    Where it is supported, createObjectURL is an excellent alternative to huge data URIs. You may still need to fall back to use of data URIs in Opera, IE<10, and all but the most recent versions of mobile browsers.

    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.
    
    0 讨论(0)
  • 2020-12-29 05:02

    If you have the PNG data in memory (which I think is what you're describing) then you can create an image from it. In HTML it would look like:

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

    In JavaScript you can do the same:

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

    Note that you can change the MIME type if you don't have PNG data.

    You could then draw the image onto your canvas using context.drawImage(image, 0, 0) or similar.

    So the remaining part of the puzzle is to encode the contents of your Uint8Array into Base 64 data.

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

    The function btoa isn't standard, so some browsers might not support it. However it seems that most do. Otherwise you might find some code I use helpful.

    I haven't tested any of this myself!

    0 讨论(0)
提交回复
热议问题