Модераторы: javastic, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с потоком 
V
    Опции темы
bncom
  Дата 9.2.2010, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 2.11.2005

Репутация: нет
Всего: 1



Есть такое задание:

На исходное изображение, которое выведено на экран, поместить aRGB изображение синего цвета (т.е. просто залитый прямоугольник, но с альфа-каналом). Затем необходимо используя поток постепенно проявить нижнее (исходное) изображение начиная с нижней строки (справа налево).

Вот что у меня пока получилось:

Код

import javax.microedition.lcdui.*;

public class Picture extends Canvas implements Runnable
{
    private Image image;
    private Image image_aRGB;
    private int[] arrayPixel = null;
    private int k = 0;

    public Picture()
    {
        super();
        try { image = Image.createImage("/picture.png");}
        catch(java.io.IOException ioe) {System.out.println(ioe.getMessage());}
     }

    public void start()
    {
        Thread thread = new Thread(this);
        thread.start();
    }

    public void run()
    {
        // устанавливаем размер двумерного массива, покрывающий исходное изображение
        if(arrayPixel == null)
            arrayPixel = new int[image.getWidth() * image.getHeight()];
        // для всех пикселей массива устанавливаем синий цвет
        for(int i = 0; i < arrayPixel.length; i++)
            arrayPixel[i] = 0xFF0000FF;
            
        while (true)
        {
            // убрать изображение с альфаканалом и показать исходное изображение
            //for(int k = arrayPixel.length-1; k > 0; k--)
            //    arrayPixel[k] = 0x0000FF00;

            // постепенно убрать изображение с альфаканалом и показать исходное изображение
            // каждый пиксель изображения с альфаканалом становится прозрачным
            // начиная с нижней строки изображения (движение справа налево)

            k = arrayPixel.length - 1;
            while (arrayPixel[k] > 0)
                arrayPixel[k] = 0x0000FF00; // "скрываем" один пиксель
            
            repaint(); // перерисовываем экран
            // останавливаем поток, чтобы увидеть на экране "скрытый" пиксель
            try { Thread.sleep(100); }
            catch (java.lang.InterruptedException exp) {}
            arrayPixel[k]--; // тоже самое и с другими пикселями
        }
    }

    public void paint(Graphics g)
    {
        int width = g.getClipWidth();
        int height = g.getClipHeight();

        g.setColor(0x000000);
        g.fillRect(0, 0, width, height);
        // выводим на экран исходное изображение
        g.drawImage(image, 0, 0, Graphics.LEFT | Graphics.TOP);
        // создаем и выводим на экран aRGB изображение поверх исходного
        image_aRGB = Image.createRGBImage(arrayPixel, image.getWidth(), image.getHeight(), true);
        g.drawImage(image_aRGB, 0, 0, Graphics.LEFT | Graphics.TOP);
  }
}


Как результат - не работает. Точнее, не работает лишь плавное исчезновение aRGВ изображения, видимо дело в том, что я не правильно использую поток.

У меня есть два варианта заполнения массива пикселей изображения прозрачными пикселями:

Код

for(int k = arrayPixel.length-1; k > 0; k--)
arrayPixel[k] = 0x0000FF00;

Как раз по заданию: с нижней строки (справа налево). Но как к такому циклу применить поток - я не знаю, потому что цикл for срабатывает моментально, т.к. все условия цикла уже прописаны в нем сразу (может некорректно выразился, простите).

И еще один вариант:

Код

k = arrayPixel.length - 1;
while (arrayPixel[k] > 0)
arrayPixel[k] = 0x0000FF00;
repaint();
try { Thread.sleep(100); }
catch (java.lang.InterruptedException exp) {}
arrayPixel[k]--;


Однако результат такого алгоритма - просто синяя заливка без поочередного "скрытия" пикселей.


Помогите правильно организовать поток, чтобы плавно проявилось нижнее изображение начиная с нижней строки (справа налево).

Это сообщение отредактировал(а) bncom - 10.2.2010, 11:25
--------------------
"Мы никогда не живем, мы лишь надеемся, что будем жить." Вольтер 
PM MAIL   Вверх
Dancer
Дата 9.2.2010, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 33
Всего: 37



наверное как-то так.
Код не проверял, написано "на коленке", но принцип такой.

Код

    public void run() {
        // устанавливаем размер двумерного массива, покрывающий исходное изображение
        if(arrayPixel == null)
            arrayPixel = new int[image.getWidth() * image.getHeight()];
        // для всех пикселей массива устанавливаем синий цвет
        for(int i = 0; i < arrayPixel.length; i++)
            arrayPixel[i] = 0xFF0000FF;
            
        for(int k = arrayPixe.length - 1; k > 0; k--) {
            int alpha = 0xFF;
            for(int endDarkPixel = k; 
                    endDarkPixel < arrayPixe.length && ((endDarkPixes%arrayPixel.length) < 0xFF); 
                    endDarkPixel++) {
                int pixelColor = arrayPixel[endDarkPixel] & 0x00FFFFFF;
                arrayPixel[endDarkPixel] = (alpha<<24) | 0x00FFFFFF | pixelColor;
                repaint(); 
                try { 
                    Thread.sleep(100); 
                } catch (java.lang.InterruptedException exp) {}
                alpha--;
            }
        }
    }






--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
bncom
Дата 9.2.2010, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 2.11.2005

Репутация: нет
Всего: 1



Попробовал, работает, правда коряво. Пиксели становятся прозрачными справа налево с верхней строки (хотя надо с нижней строки) с небольшого отступа слева (хотя надо начинать с правой стороны экрана).

Ваш метод работает очень медленно, одна строка пикселей становится прозрачной через где-то 5 минут, даже при значении Thread.sleep(1). Дальше уже терпения не хватило за этим наблюдать.

Наверно все же есть вариант проще...
--------------------
"Мы никогда не живем, мы лишь надеемся, что будем жить." Вольтер 
PM MAIL   Вверх
eugine_s
Дата 10.2.2010, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 581
Регистрация: 14.11.2007
Где: Киев

Репутация: 17
Всего: 17



Цитата(bncom @  9.2.2010,  21:41 Найти цитируемый пост)
 Пиксели становятся прозрачными справа налево с верхней строки (хотя надо с нижней строки) с небольшого отступа слева (хотя надо начинать с правой стороны экрана).


Вот приблизительно, что ты написал: У меня программа выводит "Hello, World", а должна "World, hello", поэтому программа работает не правильно. 


Цитата(bncom @  9.2.2010,  21:41 Найти цитируемый пост)
Ваш метод работает очень медленно, одна строка пикселей становится прозрачной через где-то 5 минут, даже при значении Thread.sleep(1). Дальше уже терпения не хватило за этим наблюдать.


Так ускорь его. В чем проблема? В том что готовое решение не написали? 
Из того что написано, нужно буквально две строчки (изменение цвета пикселя): 
Код

int pixelColor = arrayPixel[endDarkPixel] & 0x00FFFFFF;
arrayPixel[endDarkPixel] = (alpha<<24) | 0x00FFFFFF | pixelColor;

Все остальное - только способ прохождения по массиву пикселей и изменение их цвета. 
А если завтра тебе нужно будет не с края показывать картинку - а с центра? 
Как вариант ускорения: 
1) не вызывать repaint/sleep (даже sleep(1) - это реально может тормозить) после каждого изменения цвета одного пикселя
2) работать не с квадратиками 1х1 (что равно одному пикселю), а с квадратиками 2х2, 3х3, 5х5
3) менять прозрачность не с шагом 1, а с шагом 10 например. 
4) полностью изменить алгоритм, так как по большей степени тебе писался не алгоритм, а пример как изменить цвет, про функциональность нигде не говорилось. 

PM MAIL   Вверх
Dancer
Дата 10.2.2010, 03:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 33
Всего: 37



Код

import javax.microedition.lcdui.*;

public class Picture extends Canvas implements Runnable {
    private Image image;
    private Image image_aRGB = null;
    private int[] arrayPixel = null;
    private static int[] alphaMask = null;
/*
 {
        0xFF0000FF, 0xFB0000FF, 0xFA0000FF, 0xF70000FF, 0xF40000FF, 0xF10000FF,
        0xEE0000FF, 0xEB0000FF, 0xEA0000FF, 0xE70000FF, 0xE40000FF, 0xE10000FF,
        0xDE0000FF, 0xDB0000FF, 0xDA0000FF, 0xD70000FF, 0xD40000FF, 0xD10000FF,
        0xCE0000FF, 0xCB0000FF, 0xCA0000FF, 0xC70000FF, 0xC40000FF, 0xC10000FF,
        0xBE0000FF, 0xBB0000FF, 0xBA0000FF, 0xB70000FF, 0xB40000FF, 0xB10000FF,
        0xAE0000FF, 0xAB0000FF, 0xAE0000FF, 0xA70000FF, 0xA40000FF, 0xA10000FF,
        0x9E0000FF, 0x9B0000FF, 0x9A0000FF, 0x970000FF, 0x940000FF, 0x910000FF,
        0x8E0000FF, 0x8B0000FF, 0x8A0000FF, 0x870000FF, 0x840000FF, 0x810000FF,
        0x7E0000FF, 0x7B0000FF, 0x7A0000FF, 0x770000FF, 0x740000FF, 0x710000FF,
        0x5E0000FF, 0x5B0000FF, 0x5A0000FF, 0x570000FF, 0x540000FF, 0x510000FF,
        0x3E0000FF, 0x3B0000FF, 0x3A0000FF, 0x370000FF, 0x340000FF, 0x310000FF,
        0x1E0000FF, 0x1B0000FF, 0x1A0000FF, 0x170000FF, 0x140000FF, 0x110000FF,
        0x0E0000FF, 0x0B0000FF, 0x0A0000FF, 0x070000FF, 0x040000FF, 0x000000FF,
    };
*/
    public Picture() {
        super();
        try { 
            image = Image.createImage("/picture.png");
            // устанавливаем размер двумерного массива, покрывающий исходное изображение
            if(arrayPixel == null) {
                arrayPixel = new int[image.getWidth() * image.getHeight()];
            // для всех пикселей массива устанавливаем синий цвет
                for(int i = 0; i < arrayPixel.length; i++)
                    arrayPixel[i] = 0xFF0000FF;
            }

            if(alphaMask == null) {
                alphaMask = new int[0x100];
                for(int i=alphaMask.length-1; i != -1 ; i--) {
                    alphaMask[i] = ((alphaMask.length - i - 1) << 24) | 0x000000FF;
                }
            }

        } catch(java.io.IOException ioe) {
            System.out.println(ioe.getMessage());
        }
     }

    public void start() {
        Thread thread = new Thread(this);
        thread.start();
    }

    public void run() {
        int copyBytes = 0;
        if(arrayPixel.length > alphaMask.length) {
            for(int i = arrayPixel.length - 1; i != -1; i--) {
                int diff = arrayPixel.length - i;
                copyBytes = ( diff < alphaMask.length) ? (diff)%alphaMask.length : alphaMask.length;
                System.arraycopy(alphaMask, 0, arrayPixel, i, copyBytes);
                if(i%33 == 0) {
                    repaint(); // перерисовываем экран
                    System.gc();
                }
            }
        } else {
            copyBytes = arrayPixel.length;
        }

        while(copyBytes != 0) {
            System.arraycopy(alphaMask, alphaMask.length - copyBytes, arrayPixel, 0, copyBytes);
            repaint();
            System.gc();
            copyBytes--;
        }
    }

    public void paint(Graphics g) {
        int width = g.getClipWidth();
        int height = g.getClipHeight();

        g.setColor(0x000000);
        g.fillRect(0, 0, width, height);
        // выводим на экран исходное изображение
        g.drawImage(image, 0, 0, Graphics.LEFT | Graphics.TOP);
        // создаем и выводим на экран aRGB изображение поверх исходного
        image_aRGB = Image.createRGBImage(arrayPixel, image.getWidth(), image.getHeight(), true);
        g.drawImage(image_aRGB, 0, 0, Graphics.LEFT | Graphics.TOP);
        image_aRGB = null;
    }
}




--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
bncom
Дата 10.2.2010, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 2.11.2005

Репутация: нет
Всего: 1



Ваши способы хорошие, но я все же хочу сделать так, как более логично и проще (т.е. так, как у меня придумала голова):

Код

k = arrayPixel.length - 1;
            while (arrayPixel[k] > 0)
                arrayPixel[k] = 0x0000FF00; // "скрываем" один пиксель
            
            repaint(); // перерисовываем экран
            // останавливаем поток, чтобы увидеть на экране "скрытый" пиксель
            try { Thread.sleep(100); }
            catch (java.lang.InterruptedException exp) {}
            arrayPixel[k]--; // тоже самое и с другими пикселями


Но этот алгоритм не работает так, как от него хотелось бы по заданию (видимо, голова у меня работает не так совершенно, как хотелось бы). Результат - просто синяя заливка без поочередного "скрытия" пикселей.

Так в чем проблема?


ЗЫ: хочется же найти решение проблемы своего метода, а брать за идею чужие.

Это сообщение отредактировал(а) bncom - 10.2.2010, 11:26
--------------------
"Мы никогда не живем, мы лишь надеемся, что будем жить." Вольтер 
PM MAIL   Вверх
Dancer
Дата 10.2.2010, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 33
Всего: 37



Хорошо, идём по твоему коду smile
Код

 public void run()
    {
        // устанавливаем размер двумерного массива, покрывающий исходное изображение
        if(arrayPixel == null)
            arrayPixel = new int[image.getWidth() * image.getHeight()];
        // для всех пикселей массива устанавливаем синий цвет
        for(int i = 0; i < arrayPixel.length; i++)
            arrayPixel[i] = 0xFF0000FF;

То есть заполнили arrayPixel "ОТРИЦАТЕЛЬНЫМИ" значениями, так как старший бит отвечает за знак, а ты его принудительно выставил в "1".
присвоив всем элементам твоего массива 0xFFrrggbb;
Далее while(true), то есть у нас в потоке будет всегда что-то исполняться, даже если мы уже показали всю картинку целиком - Это не есть гуд. Нужно предусмотреть варианты с окончанием работы цикла и выхода из него.
Код

        while (true)
        {

            // убрать изображение с альфаканалом и показать исходное изображение
            //for(int k = arrayPixel.length-1; k > 0; k--)
            //    arrayPixel[k] = 0x0000FF00;

            // постепенно убрать изображение с альфаканалом и показать исходное изображение
            // каждый пиксель изображения с альфаканалом становится прозрачным
            // начиная с нижней строки изображения (движение справа налево)

            k = arrayPixel.length - 1;
            while (arrayPixel[k] > 0)
                arrayPixel[k] = 0x0000FF00; // "скрываем" один пиксель
            
            repaint(); // перерисовываем экран
            // останавливаем поток, чтобы увидеть на экране "скрытый" пиксель
            try { Thread.sleep(100); }
            catch (java.lang.InterruptedException exp) {}
            arrayPixel[k]--; // тоже самое и с другими пикселями
        }


На момент первого старта у нас есть массив с непрозрачным синим цветом, и мы делаем repaint(). что получим - правильно, залитый синим прямоугольник, на том месте, где у нас картинка (0,0, image.width, image.heigth). причём картинка у нас точно есть под этим прямоугольником, это видно из paint() метода.

Код

            while (arrayPixel[k] > 0)
                arrayPixel[k] = 0x0000FF00; // "скрываем" один пиксель

не будет вызываться достаточно долго, так как "arrayPixel[k]"  у нас отрицательный (про это думаю уже понятно? smile )

Код

            arrayPixel[k]--; // тоже самое и с другими пикселями

Вот здесь видно, что мы работаем с одинм и тем же пикселом, берём этот пиксел из массива и уменьшаем значение в этом элементе
А где переход к другому пикселу(индексу массива)? Может быть хотели так написать: 
            arrayPixel[k--]; // тоже самое и с другими пикселями
но если написать так, то ниже следующий код вообще никогда выполняться не будет.
Код

            while (arrayPixel[k] > 0)
                arrayPixel[k] = 0x0000FF00; // "скрываем" один пиксель



Разберитесь с индексами и значениями в элементах массива, и где и когда нужно делать инкремент/декремент индекса
Или опишите словами ваш алгоритм, тогда будет понятно ЧТО и главное КАК исправлять.


--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
W0LF
Дата 10.2.2010, 12:29 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


alexander lonsky
***


Профиль
Группа: Участник
Сообщений: 1164
Регистрация: 9.2.2006
Где: Ukraine.Dnepropet rovsk

Репутация: 19
Всего: 20



Цитата

хочется же найти решение проблемы своего метода, а брать за идею чужие

Вы все алгоритмы садитесь и придумываете сами?? Заново?
И это уже алгоритмика больше, нежели j2me - есть специальная, отдельная ветка форума для этого.


--------------------
iOS developer
PM MAIL WWW Skype GTalk   Вверх
Dancer
Дата 10.2.2010, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 33
Всего: 37



Цитата(bncom @  9.2.2010,  17:46 Найти цитируемый пост)
У меня есть два варианта заполнения массива пикселей изображения прозрачными пикселями:КодincludeSyntax('java');for(int k = arrayPixel.length-1; k > 0; k--)arrayPixel[k] = 0x0000FF00;highlightSyntax('java_MmQ1ZT','java');Как раз по заданию: с нижней строки (справа налево). Но как к такому циклу применить поток - я не знаю, потому что цикл for срабатывает моментально, т.к. все условия цикла уже прописаны в нем сразу (может некорректно выразился, простите).

всё понял. Перечитал пост заново.

bncom, ты хочешь пройти цикл и за каждый проход делать прозрачным пиксель с конца, то есть полностью прозрачным и всё, без всяких там градаций (блин, вот я тупая скотина). Цикл for можно использовать и не только одной строчкой, а можно к нему применять так же опрератор "фигурные скобки", и то что будет внутри скобок находится, так же будет выполняться в цикле.
Код

public void run() {
    for(int k = arrayPixel.length-1; k !=-1; k--) {
        arrayPixel[k] = arrayPixel[k] & 0x00FFFFFF;
        if(k%10 == 0) {
            repaint(); // перерисовываем экран
            System.gc();
        }
    }
    repaint();
}

Если будет слишком быстро, после repaint() можешь добавить sleep(), код у тебя этот уже есть.
А заполнение массива arrayPixel  лучше сделать в конструкторе, как я в последнем моём коде приводил. И метот paint() лучше использовать мой smile

Это сообщение отредактировал(а) Dancer - 10.2.2010, 12:58


--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
bncom
Дата 11.2.2010, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 2.11.2005

Репутация: нет
Всего: 1



Спасибо, смысл понятен  smile 
--------------------
"Мы никогда не живем, мы лишь надеемся, что будем жить." Вольтер 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса

  • Прежде чем задать вопрос прочтите это!
  • Литература по Java находится здесь.
  • Литературу по Java обсуждаем здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит" (возле кнопок кодов) если у Вас нет русских шрифтов.
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда

  • FAQ раздела лежит здесь!
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java ME (J2ME) | Следующая тема »


 




[ Время генерации скрипта: 0.0925 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.