我想知道一种在JavaScript中生成单个像素的方法,将其转换为base64。理想的功能是:
function createPixel(hexColor, opacity){
//...Calculate
return base64DataURL;
}
我对图像处理不太熟悉。任何格式都可以(png,gif等)。我想使用它来叠加背景图像,(是的,我可以使用rgba css3,但我试图将它与背景图像仅放在一个元素上,所以我不会将元素叠加在另一个元素之上以实现效果)
提前致谢。
编辑:我不想使用canvas,我相信你可以使用canvas来获取base64 dataURL,但我确信它没有字符串操作那么快。此外,我并不担心将图像转换为base64,而是对创建图像更感兴趣。
答案 0 :(得分:4)
以下是使用<canvas>
(demo @ jsfiddle)的完全跨浏览器兼容的实现。
var canvas = document.createElement('canvas');
// http://code.google.com/p/explorercanvas/wiki/Instructions#Dynamically_created_elements
if (!canvas.getContext) G_vmlCanvasManager.initElement(canvas);
var ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
// for simplicity, assume the input is in rgba format
function createPixel(r, g, b, a) {
ctx.fillStyle = 'rgba(' + [r,g,b,a].join() + ')';
ctx.fillRect(0,0,1,1);
// 'data:image/png;base64,'.length => 22
return canvas.toDataURL('image/png','').substring(22);
}
我很想知道这是如何与性能明智的icktoofay's answer相提并论的。请注意,这将不得不使用excanvas用于IE&lt; 9,这意味着性能几乎肯定会更差(但有什么新的)。
查看jsperf:http://jsperf.com/base64image
答案 1 :(得分:4)
function createPlaceholder(w, h) {
var img = document.createElement('img');
img.setAttribute('style', 'width:'+w+'px;height:'+h+'px;border:none;display:block');
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
return img;
}
(对于透明像素)
答案 2 :(得分:3)
它基于this JSFiddle(未知的美丽作者),但基本优化 - 重用keyStr并接受十六进制字符串('#FF0000')和十六进制文字(0xFF0000) - 后者更快(谢谢 icktoofay )。
<html>
<body onload="Test()">
<script>
function Test() {
var img = new Image;
img.src = createPixelGIF(0xff0000); // generate a red pixel data URI
img.height = 100; img.width = 100; // optional: add dimensions
document.body.appendChild(img); // add to the page
}
// ROUTINES =============
var createPixelGIF = (function() {
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return function createPixelGIF(hexColor) {
return "data:image/gif;base64,R0lGODlhAQABAPAA" + encodeHex(hexColor) + "/yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==";
}
function encodeHex(hexColor) {
var rgb;
if(typeof hexColor == 'string') {
var s = hexColor.substring(1, 7);
if (s.length < 6) s = s[0] + s[0] + s[1] + s[1] + s[2] + s[2];
rgb = [ parseInt(s[0] + s[1], 16), parseInt(s[2] + s[3], 16), parseInt(s[4] + s[5], 16) ];
}
else
rgb = [ (hexColor & (0xFF << 16)) >> 16, (hexColor & (0xFF << 8)) >> 8, hexColor & 0xFF ];
return encodeRGB(rgb[0], rgb[1], rgb[2]);
}
function encodeRGB(r, g, b) {
return encode_triplet(0, r, g) + encode_triplet(b, 255, 255);
}
function encode_triplet(e1, e2, e3) {
enc1 = e1 >> 2;
enc2 = ((e1 & 3) << 4) | (e2 >> 4);
enc3 = ((e2 & 15) << 2) | (e3 >> 6);
enc4 = e3 & 63;
return keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
})();
</script>
</body>
</html>
更新了JSPerf结果:http://jsperf.com/base64image/4(上面的代码是“createPixelGIF2”)。你会看到我尝试了进一步的优化(3 + 4),但似乎JS对堆栈操作比对难以阅读的组合函数更满意:)
我还为canvas方法添加了一个更新的测试,由于某种原因排除了canvas对象的实例化 - 这是在现实世界中使用的最大性能拖拽。
答案 3 :(得分:2)
试试这个。它使用了一种有点深奥的图像格式(PAM),但你说任何格式都很好,它确实有效!它没有优化或任何东西,所以它可能很慢,但嘿,它的工作原理。
编辑:好的,我稍微优化了一下......
var createPixel=(function() {
var table=[];
for(var i=0;i<26;i++) {
table.push(String.fromCharCode("A".charCodeAt(0)+i));
}
for(var i=0;i<26;i++) {
table.push(String.fromCharCode("a".charCodeAt(0)+i));
}
for(var i=0;i<10;i++) {
table.push(i.toString(10));
}
table.push("+");
table.push("/");
function b64encode(x) {
var bits=[];
for(var i=0;i<x.length;i++) {
var byte=x.charCodeAt(i);
for(var j=7;j>=0;j--) {
bits.push(byte&(1<<j));
}
}
var output=[];
for(var i=0;i<bits.length;i+=6) {
var section=bits.slice(i, i+6).map(
function(bit) { return bit?1:0; });
var required=6-section.length;
while(section.length<6) section.push(0);
section=(section[0]<<5)|
(section[1]<<4)|
(section[2]<<3)|
(section[3]<<2)|
(section[4]<<1)|
section[5];
output.push(table[section]);
if(required==2) {
output.push('=');
}else if(required==4) {
output.push('==');
}
}
output=output.join("");
return output;
}
if(window.btoa) {
b64encode=window.btoa;
}
return function createPixel(hexColor, opacity) {
var colorTuple=[
(hexColor&(0xFF<<16))>>16,
(hexColor&(0xFF<<8))>>8,
hexColor&0xFF,
Math.floor(opacity*255)
];
var data="P7\nWIDTH 1\nHEIGHT 1\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n";
colorTuple.forEach(function(tupleElement) {
data+=String.fromCharCode(tupleElement);
});
var base64DataURL="data:image/pam;base64,"+b64encode(data);
return base64DataURL;
}
})();
...但实际上,canvas
应该可以正常工作。