编辑:我不一定需要这个问题的解决方案——相反,我想了解为什么它会发生。我不明白为什么我应该在下面得到奇怪的结果......
虽然这个问题针对的是我在使用 HTML5 canvas 应用程序时遇到的问题,但我认为这个问题不太具体。
我有一个 HTML5 Canvas 应用程序,可让您在屏幕上标记图像。这些图像是 32 位 PNG,所以我使用透明度。如果我在同一位置多次标记高度透明的图像(大约 100 次),我最终会得到一个非常糟糕的结果:
我用作图章的图像颜色是 RGB(167, 22, 22) 而我要盖章的背景是 RGB(255, 255 , 255)。这是源图像,如果有人感兴趣的话:
如您所知,图像的 alpha 水平极低。可能大约 2/255 到 5/255 左右。我期望会发生的是,如果您将图像标记重复应用到 Canvas 上的次数足够多,您将获得颜色为 RGBA(167, 22, 22, 255)。不幸的是,我得到了混合颜色,包括一些非常奇怪的灰色区域,其值为 RGB(155, 155, 155)。
我刚刚加载了 Excel 并插入了 source-over alpha 混合的等式 (Wikipedia reference),经过足够的迭代后我似乎收敛到 RGB(167, 22, 22)。我可能遗漏了一些关于 alpha 混合操作以及 HTML5 canvas 如何实现源代码合成的基本知识……谁能帮我理清思路?
谢谢!
注意:this question与我的问题类似,但我不太明白为什么我会得到我在此处发布的结果。
最佳答案
canvas 数学内部的精度和舍入规则大多是未定义的,因此很难确切地说出这里发生了什么。我们真正知道的是像素是无符号字节,并且 alpha 是预乘的。
但是,我们可以通过使用 getImageData 在绘制图章时检查像素来获取一些信息,如下所示:
var px = 75;
var py = 100;
var stamp = new Image;
stamp.onload = function() {
for (var i = 0; i < 100; ++i) {
imageData = context.getImageData(px, py, 1, 1);
console.log(Array.prototype.slice.call(imageData.data, 0, 4));
context.drawImage(stamp, 0, 0);
}
};
stamp.src = 'stamp.png';
px = 75、py = 100 处的样本正好位于灰色 Blob 的中间。在白色 Canvas 上绘制一次图章后,日志显示为:
[254, 254, 254, 255]
在 px = 120、py = 150 处,样本位于红色区域的中间。绘制一次图章后,日志显示为:
[254, 253, 253, 255]
因此,对于灰色像素,看起来 Canvas 被修改为 (-1, -1, -1),对于红色像素,修改为 (-1, -2, -2)。
使用 RMagick 对图章图像中的这些相同像素进行采样给出:
[167, 22, 22, 1] // x = 75, y = 100
[167, 22, 22, 2] // x = 120, y = 150
通过数学计算,使用标准的 alpha 混合方程,您可以测试每个颜色值:
function blend(dst, src) {
var a = src[3] / 255.0
return [
(1.0 - a) * dst[0] + a * src[0],
(1.0 - a) * dst[1] + a * src[1],
(1.0 - a) * dst[2] + a * src[2]
];
}
console.log(blend([255, 255, 255], [167, 22, 22, 1]));
// output: [254.6549..., 254.0862..., 254.0862...]
console.log(blend([255, 255, 255], [167, 22, 22, 2]));
// output: [254.3098..., 253.1725..., 253.1725...]
据此,我们可以猜测 Canvas 混合代码实际上是在对结果进行取整,而不是四舍五入。这将为您提供 [254, 254, 254] 和 [254, 253, 253] 的结果,就像我们在 Canvas 上看到的那样。他们可能根本没有进行任何舍入,并且在转换回无符号字节时隐式地被舍入。
这就是为什么另一篇文章建议将图像数据存储为 float 组,自己进行数学计算,然后用结果更新 Canvas 。这样您可以获得更高的精度,并且可以控制诸如舍入之类的事情。
编辑:事实上,这个 blend() 函数并不完全正确,即使结果是 floored,因为 120 的 Canvas 像素值, 150稳定在[127, 0, 0],这个函数稳定在[167, 22, 22]。同样,当我只将图像绘制到透明 Canvas 中时,120, 150 处像素上的 getImageData 是 [127, 0, 0, 2]。什么?!
原来这是由预乘引起的,预乘似乎应用于加载的Image元素。参见 this jsFiddle举个例子。
预乘像素存储为:
// r, g, b are 0 to 255
// a is 0 to 1
// dst is all 0 to 255
dst.r = Math.floor(r * a);
dst.g = Math.floor(g * a);
dst.b = Math.floor(b * a);
dst.a = a * 255;
它们稍后解压为:
inv = 1.0 / (a / 255);
r = Math.floor(dst.r * inv);
g = Math.floor(dst.g * inv);
b = Math.floor(dst.b * inv);
针对 [167, 22, 22, 2] 运行此打包/解包显示:
a = 2 / 255; // 0.00784
inv = 1.0 / (2 / 255); // 127.5
r = Math.floor(Math.floor(167 * a) * inv); // 127
g = Math.floor(Math.floor(22 * a) * inv); // 0
b = Math.floor(Math.floor(22 * a) * inv); // 0
关于html - source-over alpha 混合效果不佳(HTML5 Canvas ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5360699/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.
我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'
我正在尝试将一个简单的CSV文件读入HTML表格以在浏览器中显示,但我遇到了麻烦。这就是我正在尝试的:Controller:defshow@csv=CSV.open("file.csv",:headers=>true)end查看:输出:NameStartDateEndDateQuantityPostalCode基本上我只获取标题,而不会读取和呈现CSV正文。 最佳答案 这最终成为最终解决方案:Controller:defshow#OpenaCSVfile,andthenreaditintoaCSV::Tableobjectforda
我想用Nokogiri解析HTML页面。页面的一部分有一个表,它没有使用任何特定的ID。是否可以提取如下内容:Today,3,455,34Today,1,1300,3664Today,10,100000,3444,Yesterday,3454,5656,3Yesterday,3545,1000,10Yesterday,3411,36223,15来自这个HTML:TodayYesterdayQntySizeLengthLengthSizeQnty345534345456563113003664354510001010100000344434113622315
考虑一下:现在这些情况:#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2我需要用其他字符串输出URL。我如何保证&符号不会被转义?由于我无法控制的原因,我无法发送&。求助!把我的头发拉到这里:\编辑:为了澄清,我实际上有一个像这样的数组:@images=[{:id=>"fooid",:url=>"http://
我正在使用Maruku,将Markdown(超集)转换为HTML,你知道我该怎么做才能从HTML转换为Markdown吗? 最佳答案 Google发现了一个名为reverse_markdown的ruby脚本.它似乎可以满足您的需求。 关于ruby-on-rails-我需要从HTML转到markdown,有什么建议吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/175162
您好,我正在做Rails应用程序,当我捆绑安装时它返回一个错误:无法在任何来源中找到coffee-script-source-1.1.3我知道coffee-script-source-1.1.3gem已被弃用/取消,但我的其他gem与此有依赖关系。但是这个项目正在与其他机器和heroku产品一起工作。如何在不更改我的gemfile的情况下成功捆绑安装?谢谢 最佳答案 运行这个:bundleupdate--sourcecoffee-script-source如果出现错误,如下所示:Anerroroccurredwhileinstall