色带和文物与渐变尽管使用RGBA_8888无处不在 [英] Color banding and artifacts with gradients despite using RGBA_8888 everywhere

查看:234
本文介绍了色带和文物与渐变尽管使用RGBA_8888无处不在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,色带是已经讨论了很多次与提供的各种解决方案的问题的一个老栗(基本上可以归结为整个使用32位或使用抖动)。其实不久前我asked并随后回答了关于这个我自己太问题。当时,我以为解决方案,我把在回答这个问题(这是和setFormat(PixelFormat.RGBA_8888)适用于窗口,并在的情况下, A SurfaceView )已经解决了的问题,我应用为好。至少该解决方案所取得的梯度很好看在我开发的设备当时(最有可能的Andr​​oid 2.2)。

I'm aware that colour banding is an old chestnut of a problem that has been discussed many times before with various solutions provided (which essentially boil down to use 32-bit throughout, or use dithering). In fact not so long ago I asked and subsequently answered my own SO question regarding this. Back then, I thought that the solution I put in the answer to that question (which is to apply setFormat(PixelFormat.RGBA_8888) to the Window and also to the Holder in the case of a SurfaceView) had solved the problem in my application for good. At least the solution made the gradient look very nice on the devices I was developing on back then (most probably Android 2.2).

我现在开发了的HTC One X(安卓4.0)和华硕的Nexus 7(安卓4.1)。我试图做的是应用灰渐变到 SurfaceView 的整个区域。尽管我理应确保了包含窗口被配置为32位色,我得到可怕的绑扎文物。事实上,对了Nexus 7,我甚至看到了移动文物约。这不仅发生在 SurfaceView 这当然是连续绘画,而且在正常查看我加一起到绘制完全相同的梯度用于测试目的,这将拉伸一次。的方式,这些文物在那里,似乎也当然走动看起来绝对可怕的,它的的真的喜欢观看模拟电视有信号不好的。无论是查看 SurfaceView 表现出完全相同的器物,其中约一起移动。

I'm now developing with a HTC One X (Android 4.0) and an Asus Nexus 7 (Android 4.1). What I tried to do was apply a grey gradient to the entire area of a SurfaceView. Even though I supposedly ensured that the containing Window and the Holder are configured for 32-bit colour, I get horrible banding artifacts. In fact, on the Nexus 7, I even see the artifacts move about. This occurs not only on the SurfaceView which is of course continuously drawing, but also in a normal View I added alongside to draw exactly the same gradient for test purposes, which would have drawn once. The way that these artifacts are there and also appear to move around of course looks absolutely awful, and it's actually like viewing an analogue TV with a poor signal. Both the View and SurfaceView exhibit exactly the same artifacts, which move around together.

我的目的是在整个使用32位,而不是使用抖动。我在IM pression的窗口为32位的默认长的Andr​​oid 4.0之前。通过在 SurfaceView 我本来期望的一切应用 RGBA_8888 来一直32位全境,从而避免任何文物。

My intention is to use 32-bit throughout, and not use dithering. I am under the impression that the Window was 32-bit by default long before Android 4.0. By applying RGBA_8888 in the SurfaceView I would have expected everything to have been 32-bit throughout, thus avoiding any artifacts.

我也注意到,有人们已经观察到, RGBA_8888 似乎不再是在4.0 / 4.1平台,有效的等等一些其他的问题。

I do note that there are some other questions on SO where people have observed that the RGBA_8888 no longer seems to be effective on the 4.0 / 4.1 platforms.

这是从我的Nexus 7的截图,与正常查看在顶部和 SurfaceView 下面,两者都应用相同的梯度到画布。当然,这并不表明文物,以及他们做的时候在屏幕看,所以它可能是相当无意义显示该屏幕抓取。我想强调,虽然该绑扎确实看起来可怕了Nexus的屏幕上。 修改其实截图确实没有表现出文物的所有的。我看到的的Nexus 7的文物不统一绑扎;它看起来是随机的性质的。

This is a screenshot from my Nexus 7, with a normal View at the top and a SurfaceView below, both applying the same gradient to the Canvas. Of course, it does not show the artifacts as well as they do when looking at the display, and so it is probably fairly pointless showing this screen grab. I want to emphasise though that the banding really does look terrible on the screen of the Nexus. In fact, the screenshot really doesn't show the artifacts at all. The artifacts I'm seeing on the Nexus 7 aren't uniform banding; it looks random in nature.

测试活动用于创建上面的:

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Shader;
import android.os.Bundle;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.widget.LinearLayout;

public class GradientTest extends Activity {

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        getWindow().setFormat(PixelFormat.RGBA_8888);
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);      
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
        lp.copyFrom(getWindow().getAttributes());
        lp.format = PixelFormat.RGBA_8888;
        getWindow().setAttributes(lp);     
        LinearLayout ll = new LinearLayout(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(500,500);
        params.setMargins(20, 0, 0, 0);
        ll.addView(new GradientView(this), params);    
        ll.addView(new GradientSurfaceView(this), params);
        ll.setOrientation(LinearLayout.VERTICAL);
        setContentView(ll);
    }


    public class GradientView extends View {

        public GradientView(Context context) {
            super(context);     
        }

        @Override
        protected void onDraw(Canvas canvas) {

            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(false);
            paint.setFilterBitmap(false);
            paint.setDither(false); 
            Shader shader = new LinearGradient(
                    0,
                    0,
                    0,
                    500,
                    //new int[]{0xffafafaf, 0xff414141},
                    new int[]{0xff333333, 0xff555555},
                    null,

                    Shader.TileMode.CLAMP
                    );

            paint.setShader(shader);    
            canvas.drawRect(0,0,500,500, paint);
        }       
    }




    public class GradientSurfaceView extends SurfaceView implements Callback {

        public GradientSurfaceView(Context context) {
            super(context);

            getHolder().setFormat(PixelFormat.RGBA_8888); // Ensure no banding on gradients 
            SurfaceHolder holder = getHolder();
            holder.addCallback(this);    
        }


        Paint paint;
        private GraphThread thread;

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            holder.setFormat(PixelFormat.RGBA_8888); // Ensure no banding on gradients    

            paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(false);
            paint.setFilterBitmap(false);
            paint.setDither(false); 

            Shader shader = new LinearGradient(
                    0,
                    0,
                    0,
                    500,
                    //new int[]{0xffafafaf, 0xff414141},
                    new int[]{0xff333333, 0xff555555},
                    null,
                    Shader.TileMode.CLAMP
                    );


            paint.setShader(shader);  



            thread = new GraphThread(holder, new Handler() );
            thread.setName("GradientSurfaceView_thread");
            thread.start();
        }

        class GraphThread extends Thread {

            /** Handle to the surface manager object we interact with */
            private SurfaceHolder mSurfaceHolder;   

            public GraphThread(SurfaceHolder holder, Handler handler) {
                mSurfaceHolder = holder;
                holder.setFormat(PixelFormat.RGBA_8888); // Ensure no banding on gradients  
            }

            @Override
            public void run() {

                Canvas c = null;

                while (true) {

                    try {
                        c = mSurfaceHolder.lockCanvas();

                        synchronized (mSurfaceHolder) {

                            if (c != null){


                                c.drawRect(0,0,500,500, paint);

                            }
                        }                                 
                    } 

                    finally {
                        if (c != null) {
                            mSurfaceHolder.unlockCanvasAndPost(c);
                        }
                    }
                }
            }    

        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
    }


}

我已经安装了所谓的显示仪,从谷歌的应用程序播放。这种应用可用于在屏幕上创建测试梯度。虽然它的梯度看起来不完美,他们似乎比我已经能够实现,这使我不知道是否有进一步的措施,我可以做prevent绑扎好一点。

I have installed an application called Display Tester from Google Play. This application can be used to create test gradients on the screen. Although its gradients do not look perfect, they seem a bit better than what I have been able to achieve, which makes me wonder if there is a further measure I can do to prevent banding.

其他的事情,我注意到的是,显示器测试仪应用报告我的Nexus屏幕是32位。

The other thing I note is that the Display Tester application reports that my Nexus' screen is 32-bit.

有关信息,我明确地支持硬件加速。我的SDK级别是:

For information, I am explicitly enabling hardware acceleration. My SDK levels are:

 <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15"></uses-sdk>

另一件事我注意到的是,默认的渐变背景的活动,我的理解是全息的特点,也很带状。这还没有显示在所有的截图。而且,我也只注意到后台的绑扎在我的Nexus 7的条纹运动在我的两个浏览移动约简言之,在同情。如果我创建一个使用默认全新的Andr​​oid项目'空'活动活动显示了讨厌的带状渐变背景在我的两个Nexus和HTC一十,这是正常的吗?据我了解,这个黑/紫色渐变默认背景是一个活动应,如果启用硬件加速。好了,无论硬件加速是否已启用,我看到相同的讨厌的带状活动背景渐变。这甚至在我空的测试项目,其目标SDK是15.要澄清,我启用或禁用硬件加速的方式发生了显式使用安卓hardwareAccelerated =真正的机器人:hardwareAccelerated =假

Another thing I notice is that the default gradient background for the Activity, which I understand to be a feature of Holo, is also very banded. This also doesn't show at all in the screenshot. And, I also just noticed the banding of the background moves about briefly on my Nexus 7, in sympathy with the banding movement in my two Views. If I create a completely new Android project with the default 'empty' Activity, the Activity shows a nasty banded gradient background on both my Nexus and HTC One X. Is this normal? I understand that this black / purple gradient default background is what an Activity shall have if hardware acceleration is enabled. Well, regardless of whether hardware acceleration is enabled or not, I see the same nasty banded Activity background gradient. This even happens in my empty test project, whose target SDK is 15. To clarify, the way I am enabling or disabling hardware acceleration is explicitly using android:hardwareAccelerated="true" and android:hardwareAccelerated="false".

我不知道如果我的观察对河洛黑/紫色活动渐变背景有什么与我的首要问题,但它似乎很奇怪相关。这也是奇怪的是,它看起来如此差的质量(即带状),看起来一样的,不管硬件加速是否打开。因此,二次的问题是:当你有一个活动使用默认霍洛渐变背景,以及对硬件加速的每一种情况下被明确地启用,然后禁用的,应此渐变背景(一)是present和(b)看起来非常光滑?我会问这个在一个单独的问题,但同样,似乎有关。

I'm not sure if my observation about the Holo black / purple Activity gradient background has anything to do with my primary question, but it does seem oddly related. It's also odd that it looks such poor quality (i.e. banded) and looks the same regardless of whether hardware acceleration is turned on. So, a secondary question would be: When you have an Activity with the default Holo gradient background, and for each case of hardware acceleration being explicity enabled and then disabled, should this gradient background (a) be present and (b) look perfectly smooth? I would ask this in a separate question, but again, it seems related.

因此,简言之:的基本问题我已经是应用渐变背景到 SurfaceView 根本无法做到的,现在看来,在我的Nexus 7,这不只是绑扎这是(我会愉快地忍受了,如果它只是说)这个问题;它实际上是一个事实,即条纹是随机在每个抽奖性质。这意味着 SurfaceView 的不断重绘结束有一个移动的,模糊的背景。

So, in summary: The basic problem I have is that applying a gradient background to a SurfaceView simply cannot be done, it seems, on my Nexus 7. It's not just banding that's the problem (which I could happily put up with if it were just that); it's actually the fact that the banding is random in nature on each draw. This means that a SurfaceView that constantly redraws ends up having a moving, fuzzy background.

推荐答案

来包装这一个答案,我得出的结论是,的Nexus 7只是有一些硬件/固件问题,这意味着它是完全裤子在呈现梯度。

Just to wrap this up with an answer, the conclusion I have reached is that the Nexus 7 just has some hardware / firmware issue which means that it is utterly pants at rendering gradients.

这篇关于色带和文物与渐变尽管使用RGBA_8888无处不在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆