Растровое изображение не нарисовано сглаживанием
У меня есть пользовательский View
, который всегда рисует Bitmap
при определенном вращении. Я перезаписываю метод onDraw
, поворачиваю Canvas
и рисую растровое изображение с помощью сглаживания Paint
.
public RotatedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
someBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.placeholder);
}
@Override
protected void onDraw(Canvas canvas) {
// Save and rotate canvas
canvas.save();
canvas.rotate(3F, getWidth() / 2, getHeight());
// Draw the icon
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(someBitmap, 0, 0, p);
canvas.drawRoundRect(new RectF(75, 50, 225, 200), 10, 10, p);
// All done; restore canvas
canvas.restore();
}
Однако, я всегда получаю зубчатые края в растровом изображении. Обратите внимание, что рулонный прямоугольник получает красиво сглаженные края. Кроме того, когда я применяю p.setFilterBitmap(true);
, это работает (поверхность растрового изображения фильтруется/сглаживается) правильно. Я что-то пропустил?
![No anti-aliasing on the photo]()
Здесь минимальный проект Android с изолированным примером одного экрана, который показывает представление, которое рисует не сглаженный Bitmap, загруженный из ресурса: https://bitbucket.org/erickok/antialiastest
ОБНОВЛЕНИЕ: Я также пробовал следующее:
Paint p = new Paint();
p.setAntiAlias(true);
p.setFilterBitmap(true);
p.setDither(true);
canvas.drawBitmap(someBitmap, 0, 0, p);
Но это не помогает, поскольку setFilterBitmap
фильтрует поверхность; он не сглаживает края. Кроме того, setAntiAlias
делает то же самое, что непосредственно устанавливает флаг в конструкторе Paint
. Если есть сомнения, попробуйте мой минимальный тестовый проект. Большое спасибо за любую помощь!
Ответы
Ответ 1
Я выяснил, почему я не получил никакого сглаживания: аппаратное ускорение. После того, как я (по чистой случайности) протестировал на своем Nexus One, он внезапно сработал, а мой Nexus 7 - нет. Оказывается, что ANTI_ALIAS_FLAG
ничего не делает, когда Canvas
создается с помощью аппаратного ускорения. С этим пониманием я нашел fooobar.com/questions/350007/..., который отвечает на мой вопрос.
Решения выглядят так: добавление прозрачной границы для каждого растрового изображения (вручную или "на лету" ) или "делать что-то с шейдерами". Мне тоже не очень нравятся. Вместо этого я отключил аппаратное ускорение на моем пользовательском представлении с помощью метода setLayerType
. Обратите внимание, что это доступно с уровня API 11, но (не случайно) вам не придется заниматься аппаратным ускорением до любого способа. Поэтому я добавил в конструкторе вида:
if (android.os.Build.VERSION.SDK_INT >= 11) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
Я обновил вышеупомянутый проект с открытым исходным кодом на BitBucket для заинтересованных.
Ответ 2
Используйте setFilterBitmap (true).
paint_object.setFilterBitmap(true);
он работает для меня тоже..
Я получил это от этого вопроса
Рисование растрового растрового изображения с анти-алиасами
установите флаг AntiAlias и флаг FilterBitmap в true, они вместе сделают планки растровых изображений плавными, я протестировал их на Samsung Galaxy Ace, android 2.2...
Мой тестовый код
Paint p = new Paint();
p.setAntiAlias(true);
p.setFilterBitmap(true);
canvas.drawBitmap(someBitmap, new Matrix(), p);
Ответ 3
В моем случае я сделал это, но может быть, вам понравилось:
Paint paint = new Paint();
paint.setAntiAlias(true);
Просто попробуйте.
Удачи!
Ответ 4
Я тестировал предыдущие предложения, и они работают для меня. Может быть, проблемы в вашем растровом изображении? Может быть, в вашем устройстве? Вот код, который создает bitmap inline. Проверьте, работает ли этот пример для вас.
public class BitmapRotateActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
class MyView extends View {
Bitmap bitmap;
public MyView(Context context) {
super(context);
bitmap = Bitmap.createBitmap(160, 160, Bitmap.Config.RGB_565);
Paint p = new Paint();
p.setColor(Color.RED);
p.setStyle(Paint.Style.FILL);
Canvas c = new Canvas(bitmap);
c.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), p);
}
@Override
protected void onDraw(Canvas canvas) {
Paint pbg = new Paint();
pbg.setStyle(Paint.Style.FILL);
pbg.setColor(0xffe0e0ff);
canvas.drawRect(0, 0, getWidth(), getHeight(), pbg);
Paint p = new Paint();
p.setAntiAlias(true);
p.setFilterBitmap(true);
canvas.save();
canvas.rotate(3F, getWidth() / 2, getHeight() / 2);
canvas.drawBitmap(bitmap, 30, 30, p);
canvas.restore();
}
}
}
Ответ 5
У меня была такая же проблема, и я попробовал все эти исправления. Что в конечном итоге сработало, это глобальное отключение аппаратного ускорения в файле AndroidManifest.xml:
<application
android:hardwareAccelerated="false"
...
>
а затем отключив inSampleSize, когда я загрузил растровое изображение изображения, чтобы (я полагаю) изображение загрузилось с достаточно высоким качеством, чтобы избежать любых зигзагов, а затем для моего фактического ImageView, используя приведенный выше совет: установка уровня введите в View.LAYER_TYPE_SOFTWARE, с объектом рисования с растровым изображением фильтра, установленным в true (как указано выше) и сглаживанием.