Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   быстрая попиксельная обработка bitmapData (http://www.flasher.ru/forum/showthread.php?t=86921)

miramax 25.10.2006 16:33

быстрая попиксельная обработка bitmapData
 
Так и хотел назвать тему "ПОМОГИТЕ !!!!!", "ГОРЮ !!!!!!"," СРОКИ ЛЕТЯТ!!!!", "РЕБЯТА ПОДМОГНИТЕ".:)
Вобщем есть объект bitmapData. Составляется из других методом copyPixels при каждом кадре заново. По битмапдате разбросаны разноцветные пикселы.

Код:

t = getTimer();
var b:BitmapData = new BitmapData(2000, 2000);
//можно произвести какие-то действия по заливке битмап даты разными пикслеми. copyPixels из других битмапов и т.п.
var ar:Array = []
//назначаем массив с парами цветов которые будем заменять
obj = {}
obj.o = 0xff54d645;
obj.n = 0x2222dd33;
ar.push(obj)
//и так раз 100
//нужно произвести какие-то манипуляции по замене страых цветов на новые
trace(getTimer()-t)  ///нужно меньше 30

Я нашёл три основных решения
1. threshold - как нельзя лучше подходит. Но эта функция слишком медленная. И ищет по одному цвету. Т.е. перерывает весь массив пикселов и заменяет требуемый цвет на другой. Вот если бы в одной функции задать поиск и замену сразу нескольких цветов..... Тогда скорость наверное была бы приемлимой.
2. Последовательный перебор и замена пикселов методами getPixel и setPixel. Картинка 1024*768 обрабатывается > 700 милисекунд. Если создать наследника класса bitmapData и вызывать наследованные функции то скорость немного подрастает.
3. Получить методом getPixels объект ByteArray и по байтово заменить все цвета. Но сам вызов методов setPixels (имея готовый ByteArray) намного медленне чем copyPixels.
По третьему пункту см. топик
http://flasher.ru/forum/showthread.php?t=86918
Вобщем хочу обработать пикселы со скоростью функции copyPixels. Которая очень быстро копирует пикселы. Возможно есть какие-то инкапсулированные возможности bitmapData? Например что бы расширить функцию threshold. Она работает только с одним цветом за время вызова. Но похоже обрабатывает все пикселы в поисках нужного цвета.
Было бы здорово если эта функция заменяла бы несколько цветов, не обрабатывая каждый раз все пикселы заново.

etc 25.10.2006 16:41

Что-то мне подсказывает, что есть только первый вариант. Остальные явно медленнее…

Кстати, 700 мс не так уж и много.

miramax 25.10.2006 16:45

Цитата:

Сообщение от __etc
Что-то мне подсказывает, что есть только первый вариант. Остальные явно медленнее…

Кстати, 700 мс не так уж и много.

Допустим есть битмапдата в которой всего один пиксел цвета ffffff а все остальные 000000. И в первом и во втором случае время обработки одинаковое, сл-но перебираются все пикселы. Как бы заставить функцию менять не один цвет а несколько?

MerlinTwi 25.10.2006 16:58

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

miramax 25.10.2006 17:06

Цитата:

Сообщение от MerlinTwi
Распиши конкретно задачу, возможно будут другие решения кроме копирования пикселей в лоб, как вариант создать несколько битмапов и накладывать друг на друга.

Это карта с битмап кэшированием. Есть эффект наведения и выделения страны, области и т.п. На картинке все страны имеют уникальный цвет, но в зависимости от того выделена страна или нет эти пикселы меняются на зелёный или на жёлтый. Из-за плавного зума и пана необходимо прорисовывать такую картинку довольно быстро. Вот именно с этой заменой возникают проблемы. Все методы что я пробовал - слишком медленные.
В принципе есть и другие пути решения, кроме присвоемия и замены уникальных цветов. Но этот самый короткий и удобный.

etc 25.10.2006 17:12

А floodFill не катит?

miramax 25.10.2006 17:29

Страна может быть извилистой, несколько раз выезжать из-за экрана. На стране, сверху есть реки. floodFill со всех сторон опробовал, подходит только частично и только для простых карт. Может просто я не могу найти правильного пути использования flooFill?.
Неизвестно где и какие пикселы появятся.

etc 25.10.2006 17:30

Сделай карту рек отдельно и накладывай сверху.

Самым нижним слоем будет карта, на которой только обведены страны.

Можно и моря выше наложить. Т.е. склеить всё copyPixels-ом.

MerlinTwi 25.10.2006 17:30

Что-то я не понял, почему
> Из-за плавного зума и пана необходимо прорисовывать такую картинку довольно быстро.
разве картинка меняется не при выделении страны? Зачем ее перерисовывать при зуме?

iNils 25.10.2006 17:31

Мне интересно, а откуда copyPixels берет начальную инфу которая картинку формирует?

MerlinTwi 25.10.2006 17:36

Можно в самом начале, при загрузке этой карты, взять ее getPixels, пробежаться по нему и составить маску для каждой страны. После чего использовать эту маску в copyPixels как alphaBitmapData.

miramax 25.10.2006 17:37

Цитата:

Сообщение от __etc
Сделай карту рек отдельно и накладывай сверху.

Самым нижним слоем будет карта, на которой только обведены страны.

Можно и моря выше наложить. Т.е. склеить всё copyPixels-ом.

Карта очень большая, разбита на кусочки по битмапам. Страна может залазить на один кусочек в нескольких местах. х и у для floofFill не определить.

miramax 25.10.2006 17:40

Цитата:

Сообщение от MerlinTwi
Можно в самом начале, при загрузке этой карты, взять ее getPixels, пробежаться по нему и составить маску для каждой страны. После чего использовать эту маску в copyPixels как alphaBitmapData.

Стран много, вызов 100 раз подряд copyPixels убивает проц. Этот способ я сейчас и юзаю. Но очень не доволен им, тк. сейчас у меня 20 тсран еле обрабатывается.

miramax 25.10.2006 17:43

Цитата:

Сообщение от MerlinTwi
Что-то я не понял, почему
> Из-за плавного зума и пана необходимо прорисовывать такую картинку довольно быстро.
разве картинка меняется не при выделении страны? Зачем ее перерисовывать при зуме?

Картинка генерится из векторной карты. Под каждый зум своя серия битмапов. Кстати говоря они кэширутся перед запуском программы. И памяти флеш плеер кушает около 300 мб ( ну во всяком случае на моей оперативке). Под каждый зум есть массив битмапов на которые разбита закэшированная карта. Потом во время пана определяются битмапы которые нужно совместить и методом copyPixels собрать ещё в один битмап , который будет показан на мониторе

etc 25.10.2006 17:43

Ну тогда остаётся только threshold :)

MerlinTwi 25.10.2006 17:54

Можно скриншот, чтобы нормально все себе представить, что получается в итоге.
Выделена может быть только одна страна?

Badim 25.10.2006 18:49

Цитата:

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

ну или в векторной форме все это делать, смотря какие исходные данные.

miramax 27.10.2006 07:03

Остановился на следующем решении.
Метод floodFill самый быстрый. Но вот определить места где им заливать - не просто.
Так вот, перед тем как показывать картинку пользвателю нужно определить точки для floodFill из которых надо заливать.
Для этого нужно создать копию юитмап даты. И делать следущее:
Нашли пиксел нужного цвета, записали его координты в массив, залили floodFill, потом опять на битмапдате ищем пиксел нужного цвета заносим в массив и заливаем. Всё, теперь у нас есть массив точек , и при любом удобном случае иы можем поменять все пикселы одного цвета на любой другой цвет поочерёдно сделав floodFill для каждой точки из массива.
Для определения точек под floodFill, на первом этапе работы желатьльно рекурсивно юзать getColorBoundsRect. Сначала надо получить этот прямоугольник на все битмапдате, попробовать залить центр, если пиксел в центре искомого цвета. Если после заливки размеры getColorBoundsRect не изменились - разбиваем полученный прямоугольник на четыре части и вносим каждую часть в новую битмапдату и продолжаем тестировать центры прямоугольников цветовых границ далее. Иначе последовательный перебор getPixel займёт в несколько десятков раз больше времени, т.к. заливаются довольно обширные зоны. Хотя если у вас картинка сложна, например jpg фотография, то лучше юзать getPixel )))
Время флуд фила зависит от размера заливаемой области. Конечно залить методом floodFill одноцветную битмапдату 2880 на 2880 в один цвет займёт больше времени чем применить threshold для замены цвета. Но если нужно залить 100 мелких областей на большой плоскости, то threshold проиграет, т.к. он каждый раз проверяет всю битмап дату на наличей нужных пикселов и делает много лишней работы.

dantist86 29.10.2006 02:47

Сегодня шеф демонстрировал гладкий zoom & pan карты без потери качества. Скорость чуть меньше чем при сниженном _quality, но мягкость движения хорошая. Не знаю этими методами или по другому он решал задачу, но прогресс есть.
Сказал, что движек еще не универсальный, но на Рождество закончит это дело и будем менять все демонстрашки на сайте и поднимать стоимость. :)

miramax 29.10.2006 07:08

Цитата:

Сообщение от dantist86
Сегодня шеф демонстрировал гладкий zoom & pan карты без потери качества. Скорость чуть меньше чем при сниженном _quality, но мягкость движения хорошая. Не знаю этими методами или по другому он решал задачу, но прогресс есть.
Сказал, что движек еще не универсальный, но на Рождество закончит это дело и будем менять все демонстрашки на сайте и поднимать стоимость. :)

Хм.... Давай тогда покажем всем, что у кого получится :)

dantist86 29.10.2006 13:48

Я не решаю этих вопросов. Но раз менять демо на сайте, значит показывать будем.
ЗЫ. О стоимости, вот эти Амеры действительно продают свою продукцию по 5-10К. http://mapnetwork.com/.
ЗЫ1. Показали вариант без потери качества одному текущему клиенту - он не обратил на это никакого внимания. Похоже, что часть народа как брала недорогие старые варианты, так и будет брать.

__i 30.10.2006 12:12

а на AS3|flex , не хотите попробывать?.
картинка 800х600 если по ней тупо пройтись getPixel и заменить какойто цвет на другой setPixel занимает приблизительно 70-150 мс (в зависимости от количетва замененых пикселей). Помоемому круто %)

dantist86 30.10.2006 14:39

miramax похоже там и работает.
У нас же конвейерная продукция и мы не хотим пока терять клиента, который бурчит : " 9-й плейер не установлен в браузерах и половина пользователей не будут его подгружать".
После Нового Года планируем поставлять два варианта на АС1 и АС3 ( АС2 тормозит, у нас по крайней мере ).

etc 30.10.2006 15:15

Цитата:

Сообщение от dantist86
АС2 тормозит

Его не существует.
Или вы просто не умеете готовить :D

Базиль 31.10.2006 18:40

А почему бы во флэше не использовать ВЕКТОРНУЮ карту? Нафига козе баян?

miramax 31.10.2006 19:38

Цитата:

Сообщение от Базиль
А почему бы во флэше не использовать ВЕКТОРНУЮ карту? Нафига козе баян?

А ты попробуй повертеть в плеере векторный рисунок кб на 150 ))))

Badim 07.11.2006 18:55

casheAsBitmap, мне помогло.

miramax 07.11.2006 19:07

Цитата:

Сообщение от Badim
casheAsBitmap, мне помогло.

Ага, а теперь сделай эту фиговину размером 20 000 на 12 000 и сделай на ней области реагирующие на маус овер изменением цвета. Без существенного ущерба производительности.

ALiEN_ 18.07.2007 21:56

Вобщем-то может уже и поздно сюда постить, но все таки я решил написать, так как больше не нашел нигде описанного способа =)

Я давно еще, когда компьютеры были 286 - самые продвинутые =) баловался на турбосях, и чуток на асме. И проблемы были те же - быстро сменить цвет пикселя можно было несколькими способами. И самый быстрый способ был - это работа с палитрой. т.е. мы берем один регистр палитры, правим его и вуаля, целый массив пикселей мгновенно меняет свой цвет.

А было так потому - что мы не обращались к каждому пикселю в памяти по отдельности - а обращались программно к палитре, в памяти видеокарты, а она в свою очередь аппаратно меняла цвет (мгновенно).

Вобщем я тут подумал, может ли такая конструкция работать во флеше? Я решил поискать на эту тему в гугле, и не нашел ничего. На форумах тоже не нашел.

Вобщем я написал небольшой тестик, и! Ура, этот способ в среднем в 10-20 раз быстрее, самого быстрого способа известного всем флешерам =))) Прицепляю тестик здесь (http://***********/1472549).

Странно, почему еще никто не догадался таким образом менять цвет во Flash =)

P.S. Демка открывается браузером. После открытия, надо тыкнуть на планету.

iNils 19.07.2007 07:44

Вы про paletteMap?

ALiEN_ 20.07.2007 16:51

да, именно.


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

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.