将图像二进制数据渲染为img或canvas标记 [英] render an image binary data into a img or canvas tag
问题描述
我有一条路线用于请求图片,如下所示:
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屋!