将图像二进制数据渲染为img或canvas标记 [英] render an image binary data into a img or canvas tag

查看:756
本文介绍了将图像二进制数据渲染为img或canvas标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一条路线用于请求图片,如下所示:

I have a route which I use to request images, something like this:

/api/image

它返回文件数据的正文,如:

it returns the body the file data, something like:

����JFIF��C��C��� ��    
�����+�}Yϭ�F39M>���������>���;��ˋ��uXʽ�w�ڤx\-[2g��k�S���H���m
[�V?[_W����#��v��}6�[��F�F�%����n�...

我要做的是这样的事情:

what I'm trying to do is something like this:

<canvas>

然后我这样做了:

代码:

var canvas = $('canvas');
var blob = new Blob([file], {type: 'image/png'});
var url = URL.createObjectURL(blob);
var img = new Image;
var ctx = canvas.getContext('2d');

$(img).on('load',function(event) {
   ctx.drawImage(img, 0, 0);
   URL.revokeObjectURL(url);
}).each(function(){
     if(this.complete) { $(this).load() }
});
img.src = url;

我还将文件直接附加到图像源属性,如:

I also appended the file directly to the image source attribute like:

img.src ='data:image / png; base64,'+ file

img.src = 'data:image/png;base64,' + file

但它不起作用

我得到的是资源未找到,并且会引发 404 错误:

What I get is that the resource is not found and it throws a 404 error:

> GET blob:http://localhost:3000/2a86de11-b565-4578-8ec1-2c20cbdae739 404 (Not Found)

我有点困惑,我做错了什么?

I'm a bit confused, what am I doing wrong?

编辑:我刚刚这样做了:

edit: i just did this:

var blob = new Blob([file], {type: 'image/png'});
var reader = new FileReader();

reader.onload = function (e) {
  suggestion.img.attr('src', e.target.result);
};
reader.readAsDataURL(blob);

但它不显示图像

推荐答案

嗯,你所展示的顶级数据是二进制的,因此,只需预先设置dataURL的东西就行不通。您需要对二进制数据执行不同的操作,或者发回实际的base64编码数据。

Well, the top data you've shown is binary and as such, just prepending the dataURL stuff wont work. You'll need to either do something different with the binary data or send back actual base64 encoded data instead.

这是一个复合示例。
它显示:

Here's a compound example. It shows:


  • 读取磁盘上的文件

  • 显示它

  • 上传

  • 使用GD创建更改后的副本,除非它是svg

  • 将其发送回浏览器二进制数据

  • 捕获它

  • 将其转换为blob然后再将dataURL

  • 再设置为带有它的图像的src属性。

  • base64编码它,添加dataURL并输出它。

  • 检索异地或交叉协议图像和在画布上绘图而不会污染它。

  • reading of a file on disk
  • displaying it
  • uploading it
  • creating an altered copy with GD unless it's an svg
  • sending it back to the browser as binary data
  • catching it
  • transforming it into a blob and then a dataURL
  • before finally setting the src attribute of an image with it.
  • base64 encoding it, adding the dataURL stuff and outputtting it.
  • retrieving a off-site or cross-protocol image and drawing on a canvas without tainting it.

base64.php

<?php
    // usefull for images without CORS header
    if (isset($_GET['filename']) == true)
    {
        $filename = urldecode( $_GET['filename'] );
        $data = file_get_contents($filename);
        $finfo = new finfo(FILEINFO_MIME);
        $mimeType = $finfo->buffer($data);
        Header("Content-Type: $mimeType");                  // use the currently detected mime-type
        echo $data;
        die;
    }

    if (isset($_FILES['upload']) == true)
    {
        $alterResult = true;

        // GD wont load svgs :(
        if (strcmp(trim($_FILES['upload']['type']),"image/svg+xml") == 0)
            $alterResult = false;

        // expecting a form element with the type of 'file' and the name of 'upload' - accepting 1 file max
        $data = file_get_contents( $_FILES['upload']['tmp_name'] );

        // draw copy of image, invert the colours, guassian blur 5 times, draw inverted,bluury image beside unaltered copy
        if ($alterResult == true)
        {
            $mImage = imagecreatefromstring ($data);
            $output = imagecreatetruecolor(imagesx($mImage) * 2, imagesy($mImage));
            imagesavealpha ( $mImage , true);
            imagesavealpha ( $output , true);
            imagecopy($output, $mImage, 0, 0, 0, 0, imagesx($mImage) - 1, imagesy($mImage) - 1);
            imagefilter($mImage,IMG_FILTER_NEGATE);
            imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
            imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
            imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
            imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
            imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
            imagecopy($output, $mImage, imagesx($mImage), 0, 0, 0, imagesx($mImage) - 1, imagesy($mImage) - 1);
            Header("Content-Type: image/png");
            imagepng($output);
            imagedestroy($mImage);
            imagedestroy($output);
            die;
        }
        // it's an svg, so just return byte-for-byte what we received
        else
        {
            $finfo = new finfo(FILEINFO_MIME);
            $mimeType = $finfo->buffer($data);
            $mimeType = preg_replace("/text\/plain/", "image/svg+xml", $mimeType);  // svgs are wrongly reported as text files
            Header("Content-Type: $mimeType");                  // use the currently detected mime-type
            echo $data;
            die;
        }
    }
?><!doctype html>
<html>
<head>
<script>
function byId(id){return document.getElementById(id)}
function newEl(tag){return document.createElement(tag)}
window.addEventListener('load',onDocLoaded);
function onDocLoaded(evt)
{
    byId('fileInput').addEventListener('change', onFileChosen);

    // cross origin test
    var can = newEl('canvas');
    var ctx = can.getContext('2d');
    var srcImg = byId('crossOrigin');
    can.width = srcImg.naturalWidth;
    can.height = srcImg.naturalHeight;
    ctx.drawImage(srcImg, 0,0);
    document.body.appendChild(can);
    console.log( can.toDataURL() );
}
function ajaxGet(url, onLoad, onError)
{
    var ajax = new XMLHttpRequest();
    ajax.onload = function(evt){onLoad(this);}
    ajax.onerror = function(evt){onError(this);}
    ajax.open("GET", url, true);
    ajax.send();
}
function ajaxGetBinary(url, onLoad, onError)
{
    var ajax = new XMLHttpRequest();
    ajax.responseType = 'arraybuffer';
    ajax.onload = function(evt){onLoad(this);}
    ajax.onerror = function(evt){onError(this);}
    ajax.open("GET", url, true);
    ajax.send();
}
function ajaxPostForm(url, formElem, onLoad, onError)
{
    var ajax = new XMLHttpRequest();
    ajax.open("POST", url, true);
    ajax.responseType = 'arraybuffer';
    ajax.onload = function(evt){onLoad(this);}
    ajax.onerror = function(evt){onError(this);}
    ajax.send( new FormData(formElem) );
}

function onFileChosen(evt)
{
    // just clear the images if no file selected
    if (this.files.length < 1)
    {
        byId('beforeImg').src = '';
        byId('afterImg').src = '';
        return;
    }

    var file = this.files[0];       // used to set the mime-type of the file when we get it back
    /*
        ==========Before upload/download==========
    */
    let fileReader = new FileReader();
    fileReader.onload = function(evt){byId('beforeImg').src=this.result;}
    fileReader.readAsDataURL(file); 

    /*
        ==========After upload/download==========
        send the file to the backend (also this source-file), then the back-end will read the temporary file and output it.
        we catch this binary output and make an image element with it
    */
    ajaxPostForm('<?php echo $_SERVER['PHP_SELF']; ?>', byId('mForm'), onPostOkay, function(){});
    function onPostOkay(ajax)
    {
        let arrayBuffer = ajax.response;
        if (arrayBuffer)
        {
            let byteArray = new Uint8Array(arrayBuffer);
            let blob = new Blob([byteArray], {type: file.type });
            byId('afterImg').src = URL.createObjectURL(blob);
        }
    }
}
</script>
<style>
.panel
{
    display: inline-block;
    padding: 8px;
    border-radius: 8px;
    border: solid 1px black;
    text-align: center;
}
</style>
</head>
<body>
    <!-- RESULT of below: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA......." -->
    <img id='crossOrigin' src='base64.php?filename=https%3A%2F%2Fmy.totalwellbeingdiet.com%2Fimg%2Fcsiro%2Flogos%2Fcsiro.png'/>

    <!-- RESULT of below: "Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported." -->
    <!-- <img id='crossOrigin' src='https://my.totalwellbeingdiet.com/img/csiro/logos/csiro.png'/> -->

    <form id='mForm' method='post' enctype="multipart/form-data">
        <input id='fileInput' type='file' name='upload'/>
    </form>
    <div class='panel'>
        <img id='beforeImg'/><br>
        <strong>Before upload</strong>
    </div>
    <div class='panel'>
        <img id='afterImg'/><br>
        <strong>After upload/mod/download</strong>
    </div>
</body>
</html>

这篇关于将图像二进制数据渲染为img或canvas标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆