色带和文物与渐变尽管使用RGBA_8888无处不在 [英] Color banding and artifacts with gradients despite using RGBA_8888 everywhere
问题描述
我知道,色带是已经讨论了很多次与提供的各种解决方案的问题的一个老栗(基本上可以归结为整个使用32位或使用抖动)。其实不久前我asked并随后回答了关于这个我自己太问题。当时,我以为解决方案,我把在回答这个问题(这是和setFormat(PixelFormat.RGBA_8888)
适用于窗口
,并在的情况下,架
A SurfaceView
)已经解决了的问题,我应用为好。至少该解决方案所取得的梯度很好看在我开发的设备当时(最有可能的Android 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位的默认长的Android 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的条纹运动在我的两个浏览
移动约简言之,在同情。如果我创建一个使用默认全新的Android项目'空'活动
的活动
显示了讨厌的带状渐变背景在我的两个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屋!