Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для мобильных телефонов > Android

Android Разработка игр на платформе Android

Ответ
 
Опции темы
Старый 24.12.2013, 13:35   #1
barsunduk
ПроЭктировщик
 
Аватар для barsunduk
 
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений
(для 271 пользователей)
Работа с пикселами битовой карты

попробовал применять фильтры и матрицы родными средствами андроид. показалось, что медленно. и тут я сделал глупость. накидал свой обработчик битмапов. теперь отрисовка приведенного в оффтопе примера (поворот картинки на произвольный угол с соответствующим увеличением размеров) на эмуляторе проходит за 9 с лишним секунд! вот это ускорил! понимаю, что дурак, но сам никак не соображу, где я не прав. не подскажете?
// кусочек кода активити для теста
    
ImageView ivMain;

    @
Override
    
protected void onCreate(Bundle savedInstanceState) {
        
super.onCreate(savedInstanceState);
        
setContentView(R.layout.activity_main);
        
ivMain = (ImageView) findViewById(R.id.ivMain);
        
Bitmap bmp = BitmapFactory.decodeResource(getApplicationContext().getResources(),
                
getApplicationContext().getResources().getIdentifier("cvetochek", "drawable", getPackageName()));
        
long ms = System.currentTimeMillis();
        
Trans t = Trans(bmp);
        
t.add_act(Trans.T_ROTATE, 45);
        
ivMain.setImageBitmap(t.doit());
        
ms = System.currentTimeMillis() - ms;
        
Log.d("Trans", "time=" + ms);
    } 
package ik.puk.tralyalya;

import java.util.ArrayList;
import java.util.Arrays;

import android.graphics.Bitmap;
import android.util.Log;

// класс для БЫСТРОГО (ага, молния, бля!) выполнения нескольких примитивных трансформаций битмапа
// основные функции:
// конструктор Trans(Bitmap bitmap) - создать оъект класса Trans, добавив битмап, который будет преобразовываться
// void add_act(int action, int[] params) - добавить действие с параметрами
// Bitmap doit() - выполнить все действия с битмапом и получить результирующий битмап
public class Trans {
    
    
// битмапы: исходный и результирующий
    
private static int[] bmp = null;
    private static 
int[] new_bmp = null;
    
    
// размеры битовых карт
    
private static int bmp_w = 0;
    private static 
int bmp_h = 0;
    private static 
int new_bmp_w = 0;
    private static 
int new_bmp_h = 0;
    
    public static final 
int default_color = 0;
    
    
// типы действий, совершаемых над битмапом
    
public static final int T_NONE = 0; // ничего не делать
    
public static final int T_RESIZE = 1; // изменить размер
    
public static final int T_CROP = 2; // размер полотна (вырезать кусок или добавить края)
    
public static final int T_FREE = 3; // свободная трансформация по четырем угловым точкам
    
public static final int T_ROTATE = 4; // повернуть на угол
    
public static final int T_FLIPV = 5; // отобразить по вертикали
    
public static final int T_FLIPH = 6; // отобразить по горизонтали
    
public static final int T_OPACITY = 7; // прозрачность, изменяется только альфа-канал
    
public static final int T_GREY = 8; // оттенки серого
    
public static final int T_ANDMASK = 9; // маска. argb &= mask
    
public static final int T_ORMASK = 10; // маска. argb |= mask
    
public static final int T_XORMASK = 11; // маска. argb ^= mask
    
public static final int T_INVERT = 12; //обратить цвета. a = a; r = !r; g = !g; b = !b
    
    // вспомогательный класс для хранения типа действия и параметров  в одной кучке
    
private class Act {
        
int act;
        
int[] params;
        
        public 
Act(int act, int[] params) {
            
this.act = act;
            
this.params = params;
        }
    }
    
    
// список последовательности действий, которые будут производиться над битмапом
    
private static ArrayList<Act> actions;
    
    
// конструктор класса. на входе - битмап в виде массива
    
public Trans(Bitmap bitmap) {
        
actions = new ArrayList<Act>();
        
bmp_w = bitmap.getWidth();
        
bmp_h = bitmap.getHeight();
        
bmp = new int[bmp_w*bmp_h];
        
bitmap.getPixels(bmp, 0, bmp_w, 0, 0, bmp_w, bmp_h);
        
bitmap.recycle();
    }

    
// добавить действие без параметров в список
    
public void add_act(int action) {
        
actions.add(new Act(action, null));
    }
    
    
// добавить действие в список
    
public void add_act(int action, int[] params) {
        
actions.add(new Act(action, params));
    }
    
    
// добавить действие с одним параметром
    
public void add_act(int action, int angle) {
        
actions.add(new Act(action, new int[]{angle}));
    }

    
// добавить действие с двумя параметрами
    
public void add_act(int action, int w, int h) {
        
actions.add(new Act(action, new int[]{w, h}));
    }

    
// добавить действие с четырьмя параметрами
    
public void add_act(int action, int x, int y, int w, int h) {
        
actions.add(new Act(action, new int[]{x, y, w, h}));
    }

    
// добавить действие с восемью параметрами
    
public void add_act(int action, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
        
actions.add(new Act(action, new int[]{x0, y0, x1, y1, x2, y2, x3, y3}));
    }
    
    
// перенос нового битмапа в старый
    
private static void exchange() {
        
bmp_w = new_bmp_w;
        
bmp_h = new_bmp_h;
        
bmp = new_bmp;
        
new_bmp = null;
    }
    
    
// находится ли пиксель в пределах битовой карты?
    
private static boolean in_bmp(int x, int y) {
        return ((
x >= 0)&&(y >= 0)&&(x < bmp_w)&&(y < bmp_h));
    }

    
// находится ли пиксель в пределах битовой карты?
    
private static boolean in_new_bmp(int x, int y) {
        return ((
x >= 0)&&(y >= 0)&&(x < new_bmp_w)&&(y < new_bmp_h));
    }
    
    
// свободная трансформация
    // на входе координаты четырех углов, по которым нужно растянуть битмап
    
private static void t_free(int n[]) {
        if (
n.length == 8) {
            
double x0 = n[0]; double y0 = n[1];
            
double x1 = n[2]; double y1 = n[3];
            
double x2 = n[4]; double y2 = n[5];
            
double x3 = n[6]; double y3 = n[7];
            
// new_x = A1*x + B1*x*y + C1*y + x0;
            // new_y = A2*x + B2*x*y + C2*y + y0;
            
new_bmp = new int[bmp_w*bmp_h];
            
Arrays.fill(new_bmp, default_color);
            
double w = bmp_w;
            
double h = bmp_h;
            
double A1 = (x1 - x0)/w;
            
double A2 = (y1 - y0)/w;
            
double C1 = (x3 - x0)/h;
            
double C2 = (y3 - y0)/h;
            
double B1 = (x2 - x3 - x1 + x0)/w/h;
            
double B2 = (y2 - y3 - y1 + y0)/w/h;
            for (
int y = 0; y < h; y++) {
                for (
int x = 0; x < w; x++) {
                    
int new_x = (int)(A1*x + B1*x*y + C1*y + x0);
                    
int new_y = (int)(A2*x + B2*x*y + C2*y + y0);
                    if (
in_bmp(new_x, new_y)) {
                        
new_bmp[new_x + new_y*new_bmp_w] = bmp[x + y*bmp_w];
                    }
                }
            }
            
exchange();
        }
    }

    
// растягивание битмапа
    
private static void t_resize(int[] n) {
        if (
n.length == 2) {
            
new_bmp_w = n[0];
            
new_bmp_h = n[1];
            
new_bmp = new int[new_bmp_w*new_bmp_h];
            
Arrays.fill(new_bmp, default_color);
            for (
int y = 0; y < new_bmp_h; y++) {
                for (
int x = 0; x < new_bmp_w; x++) {
                    
int xx = (int)(Math.round(x*bmp_w/new_bmp_w));
                    
int yy = (int)(Math.round(y*bmp_h/new_bmp_h));
                    if (
in_bmp(xx, yy)) {
                        
new_bmp[x + y*new_bmp_w] = bmp[xx + yy*bmp_w];
                    }
                }
            }
            
exchange();
        }
    }

    
// вырезание куска битмапа (или изменение размера полотна)
    // на входе - новые ширина/высота или координаты нового верхнего левого угла и новые ширина/высота
    
private static void t_crop(int[] n) {
        
int dx = 0; int dy = 0;
        
int new_w = 0; int new_h = 0;
        if ((
n.length == 2)||(n.length == 4)) {
            if (
n.length == 2) {
                
new_w = n[0];
                
new_h = n[1];
                
dx = Math.round((new_w - bmp_w)/2);
                
dy = Math.round((new_h - bmp_h)/2);
            } else {
                
dx = n[0];
                
dy = n[1];
                
new_w = n[2];
                
new_h = n[3];
            }
            
new_bmp_w = new_w;
            
new_bmp_h = new_h;
            
new_bmp = new int[new_w*new_h];
            
Arrays.fill(new_bmp, default_color);
            for (
int y = 0; y < new_bmp_h; y++) {
                for (
int x = 0; x < new_bmp_w; x++) {
                    
int xx = x - dx;
                    
int yy = y - dy;
                    if (
in_bmp(xx, yy)) {
                        
new_bmp[x + y*new_bmp_w] = bmp[xx + yy*bmp_w];
                    }
                }
            }
            
exchange();
        }
    }
    
    
// поворот битмапа на угол
    
private static void t_rotate(int n[]) {
        if (
n.length > 0) {
            
int a = n[0];
            
double sn = Math.sin(Math.toRadians(a));
            
double cs = Math.cos(Math.toRadians(a));
            
new_bmp_w = bmp_w;
            
new_bmp_h = bmp_h;
            
            
int xc = bmp_w/2;
            
int yc = bmp_h/2;
            
int x0 = (int) (Math.cos(Math.toRadians(a))*(bmp_w - xc) + Math.sin(Math.toRadians(a))*(bmp_h - yc) + xc);
            
int x1 = (int) (Math.cos(Math.toRadians(a))*(-xc) + Math.sin(Math.toRadians(a))*(-yc) + xc);
            
int y0 = (int) (Math.cos(Math.toRadians(a))*(bmp_h - yc) - Math.sin(Math.toRadians(a))*(bmp_w - xc) + yc);
            
int y1 = (int) (Math.cos(Math.toRadians(a))*(-yc) - Math.sin(Math.toRadians(a))*(-xc) + yc);
            
new_bmp_w = (int) (Math.abs(x1 - x0));
            
new_bmp_h = (int) (Math.abs(y1 - y0));
            
Log.d("Trans", "w=" + new_bmp_w);
            
Log.d("Trans", "h=" + new_bmp_h);

            
t_crop(new int[] {new_bmp_w, new_bmp_h});
            
xc = bmp_w/2;
            
yc = bmp_h/2;
            
new_bmp = new int[new_bmp_w*new_bmp_h];
            for (
int new_y = 0; new_y < bmp_h; new_y++){
                for (
int new_x = 0; new_x < bmp_w; new_x++) {
                    
int x = (int) ((cs*(new_x - xc) + sn*(new_y - yc)) + xc);
                    
int y = (int) ((cs*(new_y - yc) - sn*(new_x - xc)) + yc);
                    if (
in_bmp(x, y)&&(in_new_bmp(new_x, new_y))) {
                        
new_bmp[new_x + new_y*new_bmp_w] = bmp[x + y*bmp_w];
                    }
                }
            }
            
exchange();
        }
    }
    
    
// отобразить битмап по горизонтали
    
private static void t_fliph() {
        
new_bmp_w = bmp_w;
        
new_bmp_h = bmp_h;
        
new_bmp = new int[bmp_w*bmp_h];
        for (
int y = 0; y < bmp_h; y++) {
            for (
int x = 0; x < bmp_w; x++) {
                
new_bmp[x + y*bmp_w] = bmp[bmp_w - x - 1 + y*bmp_w];
            }
        }
        
exchange();
    }


    
// отобразить битмап по вертикали
    
private static void t_flipv() {
        
new_bmp_w = bmp_w;
        
new_bmp_h = bmp_h;
        
new_bmp = new int[bmp_w*bmp_h];
        for (
int y = 0; y < bmp_h; y++) {
            for (
int x = 0; x < bmp_w; x++) {
                
new_bmp[x + y*bmp_w] = bmp[x + (bmp_h - y - 1)*bmp_w];
            }
        }
        
exchange();
    }
    
    
// выполнить все преобразования из списка и вернуть результат в виде битмапа
    
public Bitmap doit() {
        
new_bmp_w = bmp_w;
        
new_bmp_h = bmp_h;
        
new_bmp = new int[new_bmp_w*new_bmp_h];
        while (
actions.size() > 0) {
            
Act act = actions.get(0);
            switch (
act.act) {
                case 
T_RESIZE:
                    
t_resize(act.params);
                    break;
                case 
T_CROP:
                    
t_crop(act.params);
                    break;
                case 
T_FREE:
                    
t_free(act.params);
                    break;
                case 
T_ROTATE:
                    
t_rotate(act.params);
                    break;
                case 
T_FLIPH:
                    
t_fliph();
                    break;
                case 
T_FLIPV:
                    
t_flipv();
                    break;
            }
            
actions.remove(0);
        }
        
new_bmp = null;
        return 
Bitmap.createBitmap(bmp, bmp_w, bmp_h, Bitmap.Config.ARGB_8888);
    }
    
} 
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
(Offline)
 
Ответить с цитированием
Старый 24.12.2013, 14:16   #2
Romanzes
Разработчик
 
Аватар для Romanzes
 
Регистрация: 06.04.2008
Сообщений: 541
Написано 196 полезных сообщений
(для 638 пользователей)
Ответ: Работа с пикселами битовой карты

Я думаю, если у тебя идет такая интенсивная работа с изображениями - масштабирование, повороты, стоит попробовать OpenGL, причем не напрямую, а какой-нибудь бесплатный открытый движок, рекомендую LibGDX. Гонять туда-сюда битмапы - не вариант.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
barsunduk (24.12.2013)
Старый 24.12.2013, 15:24   #3
barsunduk
ПроЭктировщик
 
Аватар для barsunduk
 
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений
(для 271 пользователей)
Ответ: Работа с пикселами битовой карты

работа не очень интенсивная, как я считал. раз в 100 миллисекунд крутнуть, растянуть 2-4 картинки. и то не всё время, а на время анимации объектов...
додумался проверить только что время работы функций извлечения битмапов. взять/положить один битмап - 800мс. прогнать фильтр по каждой точке - еще секунды полторы-две. пипец. а хотел использовать для работы именно с imageView, чтобы она сама мне результат уже масштабированный как надо на экран выводила (
ок, буду пользоваться движками. тогда и контролы самому придется изобретать, как я понял, да?
---
з.ы.: еще немного тут с Romanzes-ом пообщаюсь - и сам программистом стану)))
__________________
to be or not to be - it's not a question!
2b or not 2b = ff

Последний раз редактировалось barsunduk, 25.12.2013 в 12:10.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 12:04.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com