2011-03-08 80 views
3

我想创建反射阴影并发现问题。Android:着色器在'onDraw(canvas)'和'new Canvas(bitmap)'中表现不同'

请在我的自定义视图中找到下面的代码:

@Override 
protected void onDraw(Canvas canvas) { 
    //prepare 
    canvas.drawColor(Color.GRAY); 
    Bitmap source = BitmapFactory.decodeResource(getResources(), R.drawable.icon); 

    //First Column 
    canvas.drawBitmap(source, 0, 0, new Paint()); 

    //2nd Column 
    canvas.drawBitmap(source, source.getWidth(), 0, new Paint()); 

    //Reflection 
    Matrix matrix = new Matrix(); 
    matrix.preScale(1.0f, -1.0f); 
    matrix.postTranslate(source.getWidth(), source.getHeight()*2); 
    canvas.drawBitmap(source, matrix, new Paint()); 

    Paint paint2 = new Paint(); 
    LinearGradient shader = new LinearGradient(
      source.getWidth()*3/2, 
      source.getHeight(), 
      source.getWidth()*3/2, 
      source.getHeight()*2, 
      0x7FFFFFFF, 0x00FFFFFF, TileMode.CLAMP); 
    paint2.setShader(shader); 
    paint2.setXfermode(new PorterDuffXfermode(
      android.graphics.PorterDuff.Mode.DST_IN)); 
    canvas.drawRect(
      source.getWidth(), 
      source.getHeight(), 
      source.getWidth()*2, 
      source.getHeight()*2, 
      paint2); 

    //3rd Column 
    Bitmap bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight()*2, Config.ARGB_8888); 
    Canvas canvas2 = new Canvas(bitmap); 
    canvas2.drawBitmap(source, 0, 0, new Paint()); 
    matrix = new Matrix(); 
    matrix.preScale(1.0f, -1.0f); 
    matrix.postTranslate(0, source.getHeight()*2); 
    canvas2.drawBitmap(source, matrix, new Paint()); 


    paint2 = new Paint(); 
    shader = new LinearGradient(
      source.getWidth()*1/2, 
      source.getHeight(), 
      source.getWidth()*1/2, 
      source.getHeight()*2, 
      0x7FFFFFFF, 0x00FFFFFF, TileMode.CLAMP); 
    paint2.setShader(shader); 
    paint2.setXfermode(new PorterDuffXfermode(
      android.graphics.PorterDuff.Mode.DST_IN)); 
    canvas2.drawRect(
      0, 
      source.getHeight(), 
      source.getWidth(), 
      source.getHeight()*2, 
      paint2); 

    canvas.drawBitmap(bitmap, source.getWidth()*2,0, new Paint()); 
} 

我在画布上做相同的(这是我从onDraw(canvas)得到)和canvas2(这创造使用new Canvas(bitmap)

但是,无论是绘图不同的着色器效果如下: different shader effect

为什么着色器效果不同?

回答

3

考虑到在第二列中的黑色矩形:

PorterDuff.MODE.DST_IN被定义为[SA *沓,萨* DC]。由于目的地像素是恒定的不透明灰色(DA = 1)的结果的alpha通道将被设置为从你的线性梯度,其范围从0.5到1。

alpha通道并且有您的问题就在那里...在第二列中,您将Window画布的像素设置为部分透明。从底下显示的是什么?窗口背景,仍然是默认的黑色。

在第三列中,您首先绘制到离屏位图,然后将部分透明的离屏位图绘制到窗口画布上。这是可行的,因为传入的像素(来自屏幕外位图)并不完全替代已经存在但与目标缓冲区混合的像素(以PorterDuff术语来说,我认为它等同于SRC_ATOP)。

+0

感谢您的解释。 – 2011-03-09 03:09:57

+0

感谢您的解释。但是我仍然不清楚源和目的地,目标不是drawRect()调用之前的画布状态(我的意思是,在其上绘制图像的画布)。而是在创建时的状态。我将第三列源代码更改为\t \t //第三列 \t \t位图位图= Bitmap.createBitmap(source.getWidth(),source.getHeight()* 2,Config.RGB_565); \t \t bitmap.eraseColor(Color.GRAY);然后与第二栏相同。看起来我们无法将画布从onDraw(画布)更改为脱离屏幕位图画布? – 2011-03-09 03:55:39

+0

如果您使用Config.RGB_565,则会丢弃屏幕外位图的Alpha通道,因此在绘制到窗口画布时无法将其混合。它将简单地替换目标像素。 – 2011-03-09 10:12:20