Javascript生成dataURL格式的透明1X1像素

Javascript生成dataURL格式的透明1X1像素,javascript,image-processing,png,base64,pixel,Javascript,Image Processing,Png,Base64,Pixel,我想知道一种在JavaScript中生成单个像素并将其转换为base64的方法。理想的功能是: function createPixel(hexColor, opacity){ //...Calculate return base64DataURL; } 我对图像处理不是很熟悉。任何格式都可以(png、gif等)。我想用它来覆盖背景图像(是的,我可以使用rgba css3,但我试图将其与背景图像一起放置在一个元素上,因此我不会将一个元素覆盖在另一个元素上以实现效果) 提前谢谢 编辑

我想知道一种在JavaScript中生成单个像素并将其转换为base64的方法。理想的功能是:

function createPixel(hexColor, opacity){
   //...Calculate
   return base64DataURL;
}
我对图像处理不是很熟悉。任何格式都可以(png、gif等)。我想用它来覆盖背景图像(是的,我可以使用rgba css3,但我试图将其与背景图像一起放置在一个元素上,因此我不会将一个元素覆盖在另一个元素上以实现效果)

提前谢谢


编辑:我不想使用canvas,我确信您可以使用canvas来获取base64数据URL,但我确信它没有字符串操作那么快。另外,我并不担心将图像转换为base64,而是对创建图像更感兴趣。

试试这个。它使用了一种有点深奥的图像格式(),但您说过任何格式都可以,而且它确实有效!它没有经过优化,所以速度可能很慢,但是,它可以工作

编辑:好的,我对它进行了一点优化

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;
    }
})();
var createPixel=(函数(){
var表=[];

对于(var i=0;i,这里有一个使用
()的完全跨浏览器兼容的实现

我很想看看它在性能方面的表现如何
(对于透明像素)

4年多后,这里有一个更简单的解决方案,它可以生成标准GIF,因此可以在浏览器中实际工作(我无法让PEM解决方案在任何情况下工作),并且比PEM/canvas快一个数量级。唯一的缺点是GIF不支持alpha不透明度,但可以通过CSS进行控制

它基于(未知美丽的作者),但经过基本的优化-重用keyStr并接受十六进制字符串('#FF0000')和十六进制文字(0xFF0000)-后者更快(感谢icktoofay)


功能测试(){
var img=新图像;
img.src=createPixelGIF(0xff0000);//生成一个红色像素数据URI
img.height=100;img.width=100;//可选:添加尺寸
document.body.appendChild(img);//添加到页面
}
//例行程序=============
var createPixelGIF=(函数(){
var keyStr=“abcdefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyz012456789+/=”;
返回函数createPixelGIF(hexColor){
return“data:image/gif;base64,r0lgodlhaqabaaa”+encodeHex(hexColor)+“/yh5baaaaaaaaaaaaaaaaicraaw==”;
}
函数encodeHex(hexColor){
var-rgb;
if(typeof hexColor=='string'){
var s=六角色子串(1,7);
如果(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)];
}
其他的
rgb=[(hexColor&(0xFF>16,(hexColor&(0xFF>8,hexColor&0xFF)];
返回encodeRGB(rgb[0],rgb[1],rgb[2]);
}
函数编码器RGB(r、g、b){
返回编码三元组(0,r,g)+编码三元组(b,255,255);
}
函数编码_三元组(e1、e2、e3){
enc1=e1>>2;
enc2=((e1&3)>4);
enc3=((e2&15)>6);
enc4=e3&63;
返回字符键(enc1)+字符键(enc2)+字符键(enc3)+字符键(enc4);
}
})();

更新的JSPerf结果:(上面的代码是“createPixelGIF2”)。您会看到我尝试了进一步的优化(3+4),但JS似乎更喜欢使用堆栈操作,而不是难以阅读的组合函数:)


我还为canvas方法添加了一个更新的测试,出于某种原因,它排除了canvas对象的实例化,这是现实世界中使用的最大性能阻力。

老实说,使用canvas+toDataURL可能是最简单的解决方案。否则,您基本上必须弄清楚给定列的1x1图像是如何实现的或者,不透明度以任何格式表示(例如PNG)然后在这些信息上使用JavaScript base64编码器,或者自己找出外部编码的模式和快捷方式。这真的值得吗?你可能还会发现使用
实际上比JavaScript base64编码器更快。谢谢,我想我会坚持使用canvas。我对答案进行了一些优化,所以不会太快每次都要创建函数和查找表。看看优化后的函数如何与
画布
抗衡会很有趣。而且,很明显,在某些浏览器中有一个本机Base64编码器(
window.btoa
),所以我也添加了它。太好了,我更新了jsperf。我确实正确地调用了你的函数,对吗?你的优化版本(使用原生的
btoa
)将另外两个从水中吹出来。是的,这是有意义的。将几个字符串连接在一起,然后对其进行Base64编码,这将比创建画布、渲染到画布、将其编码为PNG,然后将其编码到Base64快得多。无论如何,我的JavaScript本机版本是相当无用的;PAM是一种非常罕见的格式,并且没有链接ely对很多人都有用。这个主意很酷,但在firefox4或IE8中,输出似乎没有显示出来…:/“加载url失败”@aaaidan:当然;PAM是相当少见的。Firefox和IE不支持它是有道理的。@aaaidan:你可以通过将Base64内容解码成
.PAM
文件并用ImageMagick进行转换来证明它是有效的。这对OP所需要的东西没有帮助。
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);
}
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;
}
<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>