Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript中Base64编码图像的同步加载_Javascript_Image_Base64_Webgl - Fatal编程技术网

Javascript中Base64编码图像的同步加载

Javascript中Base64编码图像的同步加载,javascript,image,base64,webgl,Javascript,Image,Base64,Webgl,我有一组大约200个base64编码的PNG(全部来自一个共享的JSON文件),我希望直接作为WebGL纹理加载到循环中,而不必求助于回调/事件处理程序(以简化代码和减少事件处理开销)。有没有办法用Javascript实现这一点 我知道加载base64编码图像的规范方法是通过数据URI。但是,似乎设置图像对象的src属性并不会实际解码图像数据,而只是将其排队以进行异步加载(这意味着在设置src属性后立即将图像对象作为WebGL纹理上载失败;设置上载纹理的onload处理程序成功).为什么?为什么

我有一组大约200个base64编码的PNG(全部来自一个共享的JSON文件),我希望直接作为WebGL纹理加载到循环中,而不必求助于回调/事件处理程序(以简化代码和减少事件处理开销)。有没有办法用Javascript实现这一点


我知道加载base64编码图像的规范方法是通过数据URI。但是,似乎设置
图像
对象的
src
属性并不会实际解码图像数据,而只是将其排队以进行异步加载(这意味着在设置
src
属性后立即将
图像
对象作为WebGL纹理上载失败;设置上载纹理的
onload
处理程序成功).

为什么?为什么要同步执行?浏览器中的JavaScript不是设计为同步运行的。您将冻结浏览器,并可能会出现“此脚本执行时间过长”对话框

异步处理并不难,为什么不这样做呢

var loadTextureFromImage = function(url, callback) {
   // use cyan as the default color.
   var initialColor = new Uint8Array([0,255,255,255]);

   // make a texture with 1x1 pixels so we can use the texture immediately
   // while we wait for the image to load
   var tex = gl.createTexture();
   gl.bindTexture(gl.TEXTURE_2D, tex);
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, 
                 gl.RGBA, gl.UNSIGNED_BYTE, initialColor); 

   var img = new Image();
   img.onload = function() {
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      callback(img);
   };

   return tex;
};

var loadTexturesFromImages(listOfImages, callback) {
   var numLeftToDownload = listOfImages.length;

   var checkFinished = function() {
     --numLeftToDownload;
     if (numLeftToDownload == 0 && callback) {
       callback();
     }
   };

   return listOfImages.map(function(url) {
     return loadTexturesFromImage(url, checkFinished);
   });
};
下面是一些使用上述函数的代码

var imagesToLoad = [
   "http://foo.com/image1.jpg",
   "http://foo.com/image2.jpg",
   "data:image/png;base64,iVBORw0KG...",
];

var textures = loadTexturesFromImages(imagesToLoad);
现在您可以开始渲染了。它们都将以青色渲染,并在下载/解码时更新到图像

如果要等待它们全部下载完毕,请提供对
loadTexturesFromImages
的回调


我想你的问题的简短答案是,“不,你不能同步解码图像”。一个很长的答案是,如果你想同步解码。但是现在你又回到了上面提到的问题。也就是说,你将冻结浏览器,用户可能会收到一个对话框,询问他们是否想终止脚本。

为什么?为什么要同步执行?浏览器中的JavaScript不是设计为同步运行的。Y您将冻结浏览器,可能会出现“此脚本执行时间过长”对话框

异步处理并不难,为什么不这样做呢

var loadTextureFromImage = function(url, callback) {
   // use cyan as the default color.
   var initialColor = new Uint8Array([0,255,255,255]);

   // make a texture with 1x1 pixels so we can use the texture immediately
   // while we wait for the image to load
   var tex = gl.createTexture();
   gl.bindTexture(gl.TEXTURE_2D, tex);
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, 
                 gl.RGBA, gl.UNSIGNED_BYTE, initialColor); 

   var img = new Image();
   img.onload = function() {
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      callback(img);
   };

   return tex;
};

var loadTexturesFromImages(listOfImages, callback) {
   var numLeftToDownload = listOfImages.length;

   var checkFinished = function() {
     --numLeftToDownload;
     if (numLeftToDownload == 0 && callback) {
       callback();
     }
   };

   return listOfImages.map(function(url) {
     return loadTexturesFromImage(url, checkFinished);
   });
};
下面是一些使用上述函数的代码

var imagesToLoad = [
   "http://foo.com/image1.jpg",
   "http://foo.com/image2.jpg",
   "data:image/png;base64,iVBORw0KG...",
];

var textures = loadTexturesFromImages(imagesToLoad);
现在您可以开始渲染了。它们都将以青色渲染,并在下载/解码时更新到图像

如果要等待它们全部下载完毕,请提供对
loadTexturesFromImages
的回调


我想你的问题的简短答案是,“不,你不能同步解码图像”。答案很长,如果你想同步解码它们。但现在你又回到了上面提到的问题。也就是说,你将冻结浏览器,用户可能会收到一个对话框,询问他们是否想终止脚本。

我知道异步方式并不难,在提出问题之前,我已经实现并测试了它。它太复杂了,可能会很慢。太慢了,因为我有大约200个纹理要加载,每个纹理都会产生调度解码、调度onLoad事件处理程序和执行它的开销。每个纹理都是自己使用png.js或libpng的emscripted版本解码的,这是一个巧妙的技巧,但有点达不到目的提高性能。为什么你认为它会提高性能?因为解码是异步的,每个图像可以在不同的线程中解码,而同步解码则不是这样。而且,即使浏览器在同一个线程上解码它们,异步响应JavaScript的开销也非常小,因此差异应该是可以忽略的可以肯定。所以实际上,唯一不同的同步与异步是异步有机会大大加快速度,否则它们只是不同的编码风格。我知道异步方式并不难,在提出问题之前我已经实现并测试了它。它太复杂了,而且可能会很慢。它很慢,因为我有大约200个纹理要做oad和每个都会产生调度解码、调度onLoad事件处理程序和执行它的开销。每个纹理都是使用png.js或libpng的Emscripted版本自己解码的,这是一个巧妙的技巧,但有点违背了获得性能的目的。为什么你认为它会获得性能?因为解码很容易nc每个图像都可以在不同的线程中解码,但同步解码是不正确的。而且,即使浏览器在同一个线程上解码它们,异步响应JavaScript的开销非常小,实际上差异应该是不可测量的。因此,实际上,唯一不同的同步与异步是异步有可能是巨大的更快,否则它们只是不同的编码风格。