【问题标题】:How to set combined color for overlapped area of two different color objects?如何为两个不同颜色对象的重叠区域设置组合颜色?
【发布时间】:2012-12-04 19:36:44
【问题描述】:

我正在使用两种不同的颜色创建不同的自定义视图。根据我的应用程序功能,用户将在屏幕上拖动这些对象,拖动对象时会相互重叠。我想区分重叠区域,如何设置重叠区域的组合颜色。 看下图。在这里,我使用画布来创建那些自定义视图,两个圆圈是两个不同的视图。

编辑:如果我使用 opacity 128,我可以看到背景颜色,但我想要重叠对象颜色的组合颜色。

【问题讨论】:

  • 我会说这是一个 alpha 混合答案。问题是您只希望对 OVERLAP 进行 alpha 混合。有趣的问题!!!
  • 我认为他必须自己计算。检查哪些像素与蚂蚁重叠,然后据此更新输出。
  • 你能绘制和着色任意形状吗?尝试计算重叠区域的大小/形状,手动混合颜色并在前两个形状的顶部绘制新形状。只要它在正确的位置,它应该看起来是正确的。
  • @Audrius 如果我只使用两个圆,我可以计算重叠区域,但如果他们使用更多的圆(或多边形),则很难计算重叠区域......

标签: android drawing


【解决方案1】:

您正在寻找的颜色混合有时称为直观的颜色混合,或RYB 颜色系统:

RYB

CC license

引自 Nathan Gossett 和 Baoquan Chen 关于直观颜色混合算法的 this 论文,总结了直观颜色系统的工作原理:

“在这个模型中,红色、黄色和蓝色用作纯原色。红色和黄色混合形成橙色,黄色和蓝色混合形成绿色,蓝色和红色混合形成紫色[...]。这些是未经训练的观众期望使用儿童颜料获得的颜色[...]。此外,许多人并不认为白色是所有颜色的混合,而是认为没有颜色(空白画布)。一个更常见的假设是,将多种颜色混合在一起会产生浑浊的深棕色。”

RYB 未在 Android 的混合模式中实现,并且无法通过混合 alpha/不同的混合模式来真正模拟。

大多数计算机图形应用程序都使用 RGBCMYK 色彩空间:

CMYK

CC license

CMY 基于减色法。减色混合意味着,从白色开始,随着我们添加颜色,结果变得更暗。 CMYK 用于混合用于打印的图像中的颜色,例如Photoshop 和 Illustrator。

RGB

CC license

RGB 基于加色法。计算机屏幕上的颜色是使用加色法用光创建的。加色混合从黑色开始,随着颜色的增加,结果会变浅并以白色结束。

This 网站更详细地讨论了 CMYK 和 RGB。

在 RGB 和 CMYK 中,混合蓝色和黄色都不会产生绿色,或者一般来说,直观的颜色混合。在 Android 上实现一个 RYB 颜色系统将是相当复杂的。上面引用的 Nathan Gossett 和 Baoquan Chen 的论文在论文的最后提出了一个用 C 语言实现的算法的解决方案。该算法可以在 Android 上的自定义混合中实现。 Drawable.setColorFilter() 使用 PorterDuffColorfilter 扩展 ColorFilter。如this SO 问题中所述,子类化ColorFilter 必须使用NDK 在本机代码中完成。

CMYK 颜色混合解决方法

如果您有兴趣使用 CMYK 颜色混合作为解决方法,我在下面提供了一个基本示例来说明如何完成。在这个例子中,一个青色圆圈和一个黄色圆圈将被混合以产生一个绿色的交点。

从在 Adob​​e Illustrator 中创建的这些 .png 图像文件开始:

十六进制颜色值为 0x00ffff(青色)和 0xffff00(黄色)。

将它们添加到名称为 cyancircle.png 和 yellowcircle.png 的可绘制文件夹中。

如下配置你的 main.xml 布局:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" 
    android:background="#ffffff"
    android:padding="30dp">

<ImageView
    android:id="@+id/bluecircle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/cyancircle">
</ImageView>

<ImageView
    android:id="@+id/yellowcircle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/yellowcircle" 
    android:layout_marginTop="30dp">
</ImageView>     
</RelativeLayout>

创建您的活动:

import android.app.Activity;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.widget.ImageView;

public class PorterDuffTestActivity extends Activity {
/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ImageView yellowCircle = (ImageView)findViewById(R.id.yellowcircle);

        yellowCircle.getDrawable().setColorFilter(0x88ffff00, PorterDuff.Mode.MULTIPLY);
    }
}

输出:

此方法的限制是顶部形状的 alpha 必须设置为 50%(“0x88ffff00”中的“88”)。对于黄色,这可以很好地工作,但对于其他颜色,alpha 效果可能不可接受(颜色可能看起来是另一种颜色,例如红色变成粉红色,白色背景上的 alpha 值较低)。您最终可以接受哪种混合模式取决于您要使用的颜色集,并且需要进行一些实验。另请注意,背景颜色可能会影响混合模式下圆圈的颜色。在本例中,背景设置为白色。

【讨论】:

  • 您好,感谢您回答我的问题,我正在检查此过程,让您了解解决方案。
  • 我在这里没有使用任何可绘制对象,我正在使用自定义视图上的画布绘制这些圆圈,我有在屏幕上移动这些对象的功能,此时它将重叠,所以我想重叠时自动更改重叠的颜色,无需任何计算。
  • 优秀的答案。如果我可以多次投票,我会;)
【解决方案2】:

我已经为 6 个对象做了另一个 example

关键点:

  1. 对象视图的onDraw方法不会被覆盖,背景也将设置为透明

    setBackgroundColor(Color.TRANSPARENT);

  2. 但是,onDraw 方法将被重命名为 onDrawEx 将从 Overlay View 中调用。

    public void onDrawEx(Canvas canvas) {

  3. 叠加视图将传递一个自定义画布进行绘制。在传递到对象视图之前,它会进行必要的翻译。

        mOverlayView = new View(this){
        @Override
        protected void onDraw(Canvas canvas) {
            Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
            Canvas canvasBitmap = new Canvas(bitmap);
            ViewGroup viewGroup = (ViewGroup)getParent();
            for(int i = 0 ; i < viewGroup.getChildCount()-1;i++){
                ObjectView objectView = (ObjectView) viewGroup.getChildAt(i);
                canvasBitmap.save();
                canvasBitmap.translate(objectView.getTranslationX(), objectView.getTranslationY());
                objectView.onDrawEx(canvasBitmap);
                canvasBitmap.restore();
            }
            canvas.drawBitmap(bitmap, 0, 0, new Paint());
        }
    };
    
  4. 使用 mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));添加颜色。但是所有对象都应该使用像 0xFF000030,0xFF0000C0,0xFF003000,0xFF00C000,0xFF300000,0xC00000 这样的颜色,然后只有所有可能的重叠我们才能得到不同的颜色。这取决于您的最大对象数。

        int k = 0 ;
    for(int i = 0 ; i < 2;i++,k++){
        int color = 0xFF000000|(0x000030<<i*2);
        frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
    }
    for(int i = 0 ; i < 2;i++,k++){
        int color = 0xFF000000|(0x003000<<i*2);
        frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
    }
    for(int i = 0 ; i < 2;i++,k++){
        int color = 0xFF000000|(0x300000<<i*2);
        frameLayout.addView(new ObjectView(this,color,k*50,k*50,k), new FrameLayout.LayoutParams(50, 50));
    }
    

这里我有modified 支持版本 8

使用

mPaint.setXfermode(new PixelXorXfermode(0x00000000));

mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));

我使用布局参数进行翻译。

【讨论】:

  • 绘画中没有类似 PorterDuffXfermode(Mode.ADD) 的属性。我试过这样 Inner_Paint.setXfermode(new PorterDuffXfermode(Mode.ADD));不成功..
  • 您的最低 sdk 版本应该 >= 11,如果低于该版本,请尝试 mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));但这在最新的 SDK 中已被贬值。
  • 抱歉尝试更改 mPaint.setXfermode(new PorterDuffXfermode(Mode.ADD));--> mPaint.setXfermode(new PixelXorXfermode(0xFFFFFFFF));
  • 我修改了版本 8 并上传了dl.dropbox.com/u/7717254/MainActivity08.java
  • 它不会将重叠颜色更改为组合颜色,它只会在另一个对象上形成 50% 的透明。看看我的问题中的图像它如何改变重叠的颜色。
【解决方案3】:

我能想到的最简单的解决方案是通过将每个不透明度设置为 0.5 来简单地使用 alpha 通道,无论是在代码中还是在 xml 中。然后颜色应该在重叠时相互淡入。这确实意味着非重叠部分的颜色会有些褪色,并且根据形状背后的背景,让它们完全透明可能看起来不太好。

【讨论】:

  • 这就是我在评论中所说的,但我不认为这是他想要的,我认为他想在不重叠的区域保持不透明度!!!
  • 如果我使用我可以透明地看到背景对象的颜色,但我想要重叠对象颜色的组合颜色..
【解决方案4】:

我创建了一个包含两个视图的示例 Activity DemoDrawShapeActivity 在 vi​​ew2 中我使用 canvas.clipPath 和 canvas.translate

为此,我设置了最低 sdk 版本 4

protected void onDraw(Canvas canvas) {
    Paint paint = new Paint();
    paint.setColor(Color.RED);
    path2.addCircle(getWidth()/2, getHeight()/2, getWidth()/2, Direction.CCW);
    canvas.drawPath(path2, paint);
    canvas.clipPath(path2);
    canvas.save();
    canvas.translate(-getTranslationX()+view1.getTranslationX(), -getTranslationY()+view1.getTranslationY());

    paint.setColor(Color.BLUE|Color.RED);
    canvas.drawPath(path1, paint);
    canvas.restore();

}

您可以编辑paint.setColor(Color.BLUE|Color.RED);根据您的逻辑获得必要的颜色。

我正在使用 setTranslationX setTranslationY 来移动视图。

        public boolean onTouchEvent(MotionEvent event) {
                switch(event.getActionMasked()){
                case MotionEvent.ACTION_UP:
                    touched[0]=touched[1]=false;
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    if(touched[1]){
                        view2.setTranslationX(event.getX()-view2.getWidth()/2);
                        view2.setTranslationY(event.getY()-view2.getHeight()/2);
                    }else if(touched[0]){
                        view1.setTranslationX(event.getX()-view1.getWidth()/2);
                        view1.setTranslationY(event.getY()-view1.getHeight()/2);
                        view2.invalidate();
                    }
                }
                return true;
            }

【讨论】:

  • 我使用 setTranslationX , setTranslationY 来移动屏幕上的视图。所以 getTranslationX 会告诉我们视图的位置。
  • 这里我正在创建具有不同 onDraw() 函数的自定义视图,如果我像你说的那样使用我不能为应用程序提供更多功能,是否可以通过使用 customview 来实现。我在 setColor() 上尝试过这个面临的问题。
  • 你能不能发一个你的onDraw方法的示例代码,你必须单独定义形状逻辑并封装在单独的方法中,并且应该可以从其他视图中引用。
  • 我有一个框架布局并创建自定义视图并动态添加到该框架布局中,因此每个自定义视图都有不同的 onDraw() 函数。我没有在一个自定义视图中创建所有对象。
  • 请确认,1. 您将拥有多个对象,每个对象都来自不同的视图类型。 2. 但一切都将按照特定的顺序进行。如果仍然如此,您可以拥有多个 .clipPath,如果您检查我的示例,我有两个不同的视图,都有两个不同的 onDraw 方法。在您的情况下,向上视图应该担心向下视图并相应地绘制重叠部分。为此,您应该保留一个参考列表,按添加顺序排列。
【解决方案5】:

我认为您可能希望在混合模式下进行绘制。 Android 会让你这样做,只要看看这个第一个链接。 Composite operations in Android Canvas

这里是所有合成选项 http://developer.android.com/reference/android/graphics/PorterDuffXfermode.html

以及来自 Mozilla 的解释 https://developer.mozilla.org/en/Canvas_tutorial/Compositing

【讨论】:

    【解决方案6】:

    你可以从中得到帮助 -

    http://www.learnopengles.com/android-lesson-five-an-introduction-to-blending/

    www.pushing-pixels.org/category/android/page/6

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-31
      • 1970-01-01
      • 2015-11-12
      相关资源
      最近更新 更多