首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >填充背景色,然后覆盖PNG

填充背景色,然后覆盖PNG
EN

Stack Overflow用户
提问于 2016-06-19 11:16:47
回答 2查看 3.1K关注 0票数 3

我试图使一个帆布有一个背景颜色,然后覆盖一个PNG在上面。

这是png的纹理:

*‏

例如,如果backgroundColor = #D95753 (亮红色),则画布填充级别为:

1.-设定背景颜色

2.-将png覆盖在背景色之上。

这是我的代码,但不起作用。你看不到背景色,只有png图像。

代码语言:javascript
复制
var background = new Image();
background.src = "http://i.stack.imgur.com/LF1P0.png";
background.height = y; // set it before
background.width = x; // set it before

ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, background.width, background.height);

background.onload = function() {
    ctx.drawImage(background,0,0, background.width, background.height);
    memeEverything();
}

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-19 11:41:13

通过定义fillRect()和rgba格式的颜色,尝试如下所示,

代码语言:javascript
复制
<canvas id="canvs" width="500" height="500">
<img src="http://i.stack.imgur.com/LF1P0.png" id="img">
</canvas>

function onld(){
var can = document.getElementById('canvs');
var img = document.getElementById('img');
var ctx = can.getContext('2d');
ctx.fillStyle = 'rgba(217, 87, 83, 1)';
ctx.fillRect(10,10,500,500);
ctx.globalAlpha=0.6;
ctx.drawImage(img,10,10);
}
window.addEventListener('load',onld);
票数 1
EN

Stack Overflow用户

发布于 2016-06-19 13:57:22

ctx.globalCompositeOperation =“乘”

您可以使用复合方法,并避免失去动态范围,因为由frnt的答案将做,阿尔法0.6将减少对比,从原来的面具显着。

有许多混合选项,但对于一个图像,你不想让白色显示,只想增加黑暗,使用混合模式“乘”,这种方法将给你最好的对比度可能。

代码语言:javascript
复制
ctx.fillStyle = ???  // the background colour you want
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); // fill canvas with colour. This is now the destination
// Destination pixels get multiplied by source pixels 
// nC = dC  * (sC / 255);  ( seperate for each channel RGB. no effect on alpha )
// where nC is the new colour, dC is destination colour and, sC is source colour;
// White pixels make no change, all others reduce the the colour
ctx.globalCompositeOperation = "multiply"; 
// draw the image over the top.
ctx.drawImage(img, 0, 0, canvas.width, cvtx.canvas.height);
ctx.globalCompositeOperation = "source-over";  // reset to default

最佳质量

有一个更好的方法,但这涉及到获取像素数据和做一个光子计数在每个像素之前的乘法。这将使一个更接近原来的面具匹配。公式是nC =Math.sqrt(dC * dC * (sC * sC / (255*255)));,其中nC是新颜色,dC是目标颜色,sC是源颜色。应用于每个通道RGB忽略alpha。

代码语言:javascript
复制
// r,g,b are the background colour
// img is a loaded image to convert
var r = ?, g = ?, b = ?;
// create canvas and context for image
var c = document.createElement("canvas");
c.width = img.width;
c.height = img.height;
var ctx = c.getContext("2d");
// draw image onto the canvas
ctx.drawImage(img, 0,0);
// get the pixel data
var data = ctx.getImageData(0,0,c.width,c.height);
var d = data.data;
// Convert background colour to photon count and normalise 
r = r * r / (255 * 255);
g = g * g / (255 * 255);
b = b * b / (255 * 255);
var i = 0, len = d.length;;
// for each pixel do the multiply using photon counts
while(i < len){
    d[i] = Math.sqrt(d[i] * d[i++] * r);
    d[i] = Math.sqrt(d[i] * d[i++] * g);
    d[i] = Math.sqrt(d[i] * d[i++] * b);
    i ++;
}
// put the image data back onto the canvas.
ctx.putImageData(data,0,0);

通过α复合.

在您也可以使用alpha组合之后,乘法可能不是您的效果。有两种方法,简单和光子计数。请注意,,这两种方法假设背景颜色的alpha值为255,并且只对该值使用

简单的方法是获得像素的alpha。如果您已经设置了alpha通道,并且只使用了画布源-over(默认)混合函数,那么它是如何完成的。

代码语言:javascript
复制
// assume you have got the pixel data etc.. see above snipets
var amount = ?; // the mixing amount
var i = 0, len = d.length;;
// for each pixel do the alpha blend
while(i < len){
    var rr = d[i];   // get source channels
    var gg = d[i + 1]; 
    var bb = d[i + 2]; 
    var alpha = (rr + gg + bb) / ( 3 * 255); // calculate alpha by finding the mean 
    // alpha is inverted  but also need to clamp alpha as floating point may give a value too high so clamp and invert
    alpha = Math.min(1, 1 - alpha);
    alpha *= amount;   // set the mix amount
    var aInv = 1 - alpha; // invert again
    // each channel is the sum of background and image colour time their respective mix amounts
    d[i++] = aInv * r + alpha * rr;  
    d[i++] = aInv * g + alpha * gg;
    d[i++] = aInv * b + alpha * bb;
    d[i++] = 255;  // in this case alpha is always 255
}
// put the image data back onto the canvas.
ctx.putImageData(data,0,0);

以及正确的方法(如何进行高质量的专业混合)

代码语言:javascript
复制
// assume you have got the pixel data etc.. see above snipets
var amount = ?; // the mixing amount
// Convert background colour to photon count and normalise 
r = r * r / (255 * 255);
g = g * g / (255 * 255);
b = b * b / (255 * 255);
var i = 0, len = d.length;;
// for each pixel do the alpha blend using photon counts
while(i < len){
    var rr = d[i];   // get source channels
    var gg = d[i + 1]; 
    var bb = d[i + 2]; 
    rr *= rr;
    gg *= gg;
    bb *= bb;
    var alpha = (rr * + gg + bb) / ( 3 * 255 * 255); // calculate alpha by finding the mean in photon space
    // alpha is inverted but also need to clamp alpha as floating point may give a value too high so clamp and invert
    alpha = Math.min(1, 1 - alpha);
    alpha *= amount;   // set the mix amount
    var aInv = 1 - alpha; // invert again
    // each channel is the sum of background and image colour time their respective mix amounts
    d[i++] = Math.sqrt(aInv * r + alpha * rr);  
    d[i++] = Math.sqrt(aInv * g + alpha * gg);
    d[i++] = Math.sqrt(aInv * b + alpha * bb);
    d[i++] = 255;  // in this case alpha is always 255
}
// put the image data back onto the canvas.
ctx.putImageData(data,0,0);

为什么使用光子计数颜色模型.

我使用的颜色模型是基于设备显示器发出的光子数。每个彩色通道的值从0到255之间,但这些值与监视器的实际输出不匹配,也不代表摄像机(输入设备)捕获的光子数。它们是光子通量的平方根。如果你用简单的线性均值混合一种颜色,并且不考虑这一点,那么所产生的颜色将比它们应该的颜色更深(当图像具有高色调对比度时,这是特别明显的),并且对比度曲线将被拓宽。当你直接操纵像素以获得最好的结果时,总是把r,g,b值平方,做混合,混合,什么都行。准备好后,通过计算结果的平方根,将值转换回对数表示形式。

这个视频将更详细地解释电脑颜色坏了

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37906622

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档