【问题标题】:Can browsers produce different resolutions of an image?浏览器可以生成不同分辨率的图像吗?
【发布时间】:2020-11-01 11:29:46
【问题描述】:

给定一张图片,比如 jpeg 文件,有没有办法在网页上以不同的分辨率显示它?

请注意,与措辞相似的问题不同,我不是在谈论更改页面上图像的大小。

不,我不是要求 CSI 软件可以神奇地为低分辨率图像添加细节。

我想要的是这样的:

其中第一张图片为原始高分辨率文件 (205×304),其他图片为中 (82×122) 和低 (41×61) 分辨率显示的同一文件。

是否有 CSS 或 javascript 可以做到这一点?

(CSS filter: blur() 有类似的效果,但不是我想要的(例如没有锯齿)。)

【问题讨论】:

  • 据我所知,您需要使用 JS 降级图像。 CSS4 将具有image-resolution 属性(可能...)

标签: javascript css image-processing


【解决方案1】:

当然,您可以使用 元素非常简单地做到这一点,只需将其 widthheight 属性设置为目标属性,然后在其上绘制您的图像。然后,如果您愿意,只需使用 CSS 调整这些画布的大小:

function downscale( img, width, height ) {
  const canvas = document.createElement( 'canvas' );
  canvas.width = width;
  canvas.height = height;
  const ctx = canvas.getContext('2d');
  return new Promise( (resolve, reject) => {
    if( img.naturalWidth ) { // if already loaded
      draw();
    }
    else {
      img.addEventListener( 'load', draw, { once: true } );
      img.addEventListener( 'error', reject, { once: true } );
    }
    
    function draw() {
      ctx.drawImage( img, 0, 0, width, height );
      resolve( canvas );
    }
  } );
}

const img = document.querySelector( 'img' );
// original image size: 158 * 240
Promise.all( [
  downscale( img, 79, 120 ),
  downscale( img, 40, 60 )
] ).then( (canvases) =>
  document.querySelector( '.img-container' )
    .append( ...canvases )
)
.catch( console.error );
img, canvas { height: 240px }
<div class="img-container">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Mona_Lisa.jpg/158px-Mona_Lisa.jpg"></div>

用 CSS 做这件事在理论上听起来是可行的,例如通过使用 widthheight 属性进行放大,然后使用转换进行缩小,但似乎实现只会批处理所有操作而不是一个一个地应用,因此两者操作只会相互还原。

【讨论】:

  • 嗨 Kaiido,如果您能抽出时间,您能否评论一下我的回答,并讨论与您的“承诺”回答相比可能存在的陷阱。我确实理解为什么使用“承诺”是首选的编码方式,尤其是。有很多在线 I/O(延迟)正在进行。顺便说一句,当 CSS img,canvas {...} 与不同的值一起使用时,您的版本会失败(例如,img, canvas { width: 15% } 失败,在 SO 之外尝试过)。
【解决方案2】:

图像处理(通常)通过创建/加载&lt;canvas&gt;、在&lt;canvas&gt; 上绘制图像并进行一些必要的修改来完成。在这种情况下,只需在&lt;canvas&gt; 中加载图像,然后在画布2d context 上用不同的大小重新绘制它。

下面的 sn-p 显示了两种风格:with degradeImage()without degradeImageOnParent() 预先存在的&lt;canvas&gt;文件。

奇怪 sn-p 只显示一张图像,而在 Stackoverflow 之外它显示四张:原始图像和 3 张降级图像。一定是文档加载问题,正在处理这个....

已解决禁用docInit...

//document.addEventListener('DOMContentLoaded',docInit);

//function docInit() {
    document.getElementById('source').onload = function () { 
        degradeImage(0.75, this, document.getElementById("cvs1"));
        degradeImage(0.50, this, document.getElementById("cvs2"));

        // Add canvas on-the-fly
        degradeImageOnParent(document.getElementById('parent'),0.25,this,'cvs3');
    };
//};

function degradeImage(scale,img,cvs) {
    if (!cvs) { // if not passed, create canvas on-the-fly
        cvs = document.createElement('canvas');
    }
    var ctx = cvs.getContext('2d');

    cvs.width  = img.width  * scale; // assign scaled size
    cvs.height = img.height * scale;

    ctx.imageSmoothingEnabled = true; // default value, here for reference only
    ctx.drawImage(img, 0, 0, cvs.width, cvs.height); // fill the canvas
    
    return cvs; // Useful when created inside function
}

function degradeImageOnParent(parent,scale,img,cvsID) {
    var cvs = degradeImage(scale,img);
    if (cvsID) cvs.id = cvsID; // [optional ID]
    parent.appendChild(cvs);
}
.wrapper   { width: 100% }
canvas,img { width:  24% } /* original is 400x600 */
<div class="wrapper" id="parent">
    <img id="source" src="https://i.postimg.cc/76JT0MBh/Mona-Lisa-400.jpg">
    <canvas id="cvs1"></canvas>
    <canvas id="cvs2"></canvas>
</div>

【讨论】:

  • 我的版本正在使用承诺,因为与您的相反,它确实处理等待源图像加载。否则,您的答案只是我的副本,没有添加任何内容,所以我不确定您对我的部分的期望是什么……而且我不确定您对 15% 的内容是什么意思,15% 的内容你觉得应该这样吗?
  • 当前父宽度的 15%,不管是什么......
  • 这是从哪里来的?当然你可以把我回答中的图片设置成这个尺寸,你只需要设置父母的宽度即可。
猜你喜欢
  • 1970-01-01
  • 2017-07-23
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 2015-03-14
  • 2010-10-27
相关资源
最近更新 更多