AS3:如何将有色位图的位图数据变成黑白?

5

我该如何在AS3中将有色位图的位图数据更改为黑白?我正在为一个Flash内容管理系统开发一个简单的图像编辑工具。

用户应该能够将上传的位图颜色转换为黑白。 我希望位图数据本身被更改,以便之后可以使用Adobe的JPGEncoder类将其写入ByteArray中。

7个回答

28

我认为这将是最优雅的解决方案(其中 source 是你的 BitmapData):

const rc:Number = 1/3, gc:Number = 1/3, bc:Number = 1/3;
source.applyFilter(source.bitmapData, source.bitmapData.rect, new Point(), new ColorMatrixFilter([rc, gc, bc, 0, 0,rc, gc, bc, 0, 0, rc, gc, bc, 0, 0, 0, 0, 0, 1, 0]));

使用flash.geom::Pointflash.filters::ColorMatrixFilter,...

ColorMatrixFilter可以实现很多功能,如色调偏移、着色、变亮、变暗、去饱和等等...另外,BitmapData::paletteMapBitmapData::colorTransform也是很好的补充...

只想注意一下,使用以下方法:

const rc:Number = 1/3, gc:Number = 1/2, bc:Number = 1/6; 

相对而言,#00FF00#FF0000更亮,而#FF0000又比#0000FF更亮,这看起来更自然一些。

祝你好运... ;)

问候

back2dos


这是正确的解决方案,+1。 - CookieOfFortune
3
我记得典型的颜色加权比例是30%、59%和11%,分别对应R、G和B。尽管如你所写,这种加权有一定的主观性,但它与颜色的亮度值有一定的相关性,如果我没记错的话。就这个方面而言,您的权重略有偏差,但方法是绝对正确的。 - Marcus Stade

2

好的,只需使用getPixel和setPixel,并对颜色取平均值(我相信可能还有其他一些使用滤镜等方式来完成此操作):

for(int i = 0; i < bitmapData.height; i++)
{
    for(int j = 0; j < bitmapData.width; j++)
    {
        var color:uint = bitmapData.getPixel(i, j);
        var red:uint = color & 0xFF0000 >> 16;
        var green:uint = color & 0x00FF00 >> 8;
        var blue:uint = color & 0x0000FF >> 0;
        var bwColor:uitn = red + green + blue / 3;
        bwColor = bwColor << 16 + bwColor << 8 + bwColor; // puts the average in each channel

        bitmapData.setPixel(i, j, bwColor);
    }
}

2
这将起作用,但如果可能的话,尽量避免循环所有像素,因为过滤器会更快,因为它们是本地的。 - grapefrukt

2
事实上,你可以更简单地使用back2dos的解决方案:
const rc:Number = 1/3, gc:Number = 1/3, bc:Number = 1/3;
mc.filters = [ new ColorMatrixFilter([rc, gc, bc, 0, 0,rc, gc, bc, 0, 0, rc, gc, bc, 0, 0, 0, 0, 0, 1, 0]) ];

mc是MovieClip或Sprite容器,其中的bitmapdata作为视觉元素存在。

感谢back2dos :)


1

谢谢Cookie, 复制原始位图数据确实是恢复颜色最简单的解决方案。

   function clearColor() {
      colorbmd = new BitmapData(source.width, source.height);
      colorbmd = source.clone();
      //apply filter here    
    }
    function restoreColor() {
      source = colorbmd;
    }

我认为一旦你将图像转换成黑白,就无法回退(在转换过程中会丢失信息)。在应用滤镜之前,你必须先做一个副本。 - CookieOfFortune

1

我使用这段代码:

//Tweens to black and white
TweenLite.to(DisplayObjectYouWantToTween ,1,{colorMatrixFilter:{matrix:[0.3,0.59,0.11,0, 0,0.3,0.59,0.11,0,0,0.3,0.59,0.11,0,0,0,0,0,1,0]}});

//Tween from black and white to Color
TweenLite.to(DisplayObjectYouWantToTween,1,{colorMatrixFilter:{matrix:[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]}});

0
感谢您的建议,我创建了一个小工具,让您可以调整数值参与其中: http://bjornson.inhb.de/?p=159 初始值是由 Macke 建议的:红色、绿色和蓝色各占 30%、59% 和 11%。
您还可以加载外部图片,并尝试找到最佳结果。

0

我尝试了两种方法。似乎当处理大图片时,ColorMatrixFilter方法的速度更快。

有没有一些方法可以去除过滤器?或者我应该再次更改ColorMatrixFilter的值?


1
我认为一旦你将图像转换为黑白,就无法返回原样(在转换过程中会丢失信息)。在应用滤镜之前,您必须先制作一份副本。 - CookieOfFortune

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接