Форум 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)
-   -   Параметры getColorBoundsRect (http://www.flasher.ru/forum/showthread.php?t=112652)

Волгоградец 04.06.2008 11:47

Параметры getColorBoundsRect
 
Привет всем. Гуру, помогите понять назначение параметров в методе getColorBoundsRect. Описание в хэлпе:
Цитата:

Например, если у вас есть изображение и вы хотите определить прямоугольную область, которая содержит ненулевой альфа-канал, вы должны ввести в качестве параметров {mask: 0xFF000000, color: 0x00000000}. Изображение будет исследовано на предмет поиска границ пикселов, чьи (value & mask) != color. Для определения белого пространства вокруг изображения вы должны ввести {mask: 0xFFFFFFFF, color: 0xFFFFFFFF} для того, чтобы найти границы не белых пикселов.
Вообще не понятно, если я ищу ненулевой альфа-канал, причем тут черный цвет в качестве параметра color??? И вообще зачем там два параметра - например во втором примере оба они одинаковые?

Alex_beginner 04.06.2008 21:41

Параметр mask выделяет определенную составляющую из цвета пикселя. Например, у Вас есть пискель c color = 0x03050604. Как из его цвета выделить флешу альфа-составляющую цвета. А делается это просто - он делает логическое "И" этого значения с маской, указывающей какие биты в цвете Вы хотите контролировать. Т.е 0x03050604 & 0xFF000000 = 0x03000000 означает, что Вы выделили из цвета color только альфа-составляющую.
А метод делает следующее сравнивает значение, полученное при опирации "И" маски и текущего значения пикселя с заданным в качестве параметра color и определает прямоугольную область где эти занчения не равны.
А насчет примера, значения mask и color равны 0xFFFFFFFF, а значит mask & color дадут результат 0xFFFFFFFF. И это значит флеш будет искать область где нет белых (0xFFFFFFF) пикселей.

Волгоградец 05.06.2008 11:11

Вроде ясно. Т.е. в качестве маски я всегда должен задавать 0xFF000000 или 0x00FF0000 ну или другое, но главное чтобы там были FF - это как бы указывает по какой составляющей цвета (R, G, B или A) искать, так? И получается что метод ищет область, где НЕ присутствует цвет, указанный в качестве параметра color. Мне казалось наооборот - возвращает область, ГДЕ присутствует этот цвет. А что будет если у меня несколько клякс определенного цвета, что за область вернет, несколько областей?

Alex_beginner 05.06.2008 11:26

Нет. Не обязательно 0xFF000000 или 0x00FF0000, можно и 0x3456FF00. Ведь цвета бывают не только чисто красный, зеленый и синий, есть и другие, которые Вы, собственно, вдруг захотите изолировать.

А как маскирование работает Вы можете узнать если представите параметр mask и value в двоичном виде. Ну вот например, 0xFF000000 = mask = 11111111000000000000000000000000; value = 0x03050604 = 00000011000001010000011000000100.

Побитовая операция "И" тогда даст

11111111000000000000000000000000
&
00000011000001010000011000000100
------------------------------------
00000011000000000000000000000000

Т.е. посути Вы выделили биты определнной области - верхнего байт числа value.

На счет клякс, тут, наверно, Вам лучше поэкспериментировать и сразу будет все понятно.

Волгоградец 05.06.2008 11:48

Вот что хочу узнать - если в качестве параметра mask введу 0x3456FF00 - это значит буду искать по составляющим A, R и G (т.е. на предмет прозрачности, красного и зеленого цветов). Синий не будет учитываться. И эта строчка 0x3456FF00 получается равносильна, скажем 0xFFFFFF00 или 0x01010100 - неважно какие числа - я ведь просто указываю маску - те цвета, по которым будет поиск.
Цитата:

Ведь цвета бывают не только чисто красный, зеленый и синий, есть и другие, которые Вы, собственно, вдруг захотите изолировать
Ведь я изолирую те цвета, которые задаю в параметре color.

Нипанятноооо...

Alex_beginner 05.06.2008 12:11

На счет 0x3456FF00. То что синяя составляющая цвета не будет учитываться сказано абсолютно, точно. А вот на равносильность 0x3456FF00 и 0xFFFFFF00 ставиться под сомнение. Попробуйте представить эти два числа в двочном виде. И если задаться что это маски для value, то при побитовом сложении этих масок с value получатся совсем разные значения. В первом случае для значения битов маски - 1 будет "просачиваться" соотвествующий бит value. Во втором, все биты value воидут в тестируемое значение с color.

Волгоградец 05.06.2008 13:21

Фуф, вроде дошло. Alex_beginner, спасибо, дружище!

chingachgoog 29.07.2008 22:44

Нда, метод крайне глючный. :(
По-крайней мере с прозрачной битмапой это так.

Код:

import flash.display.BitmapData;
import flash.geom.Rectangle;
// рисуем прозрачную битмапу с цветом 0x705500FF
myBitmapData = new BitmapData(300, 200, true, 0x705500FF);

mc = this.createEmptyMovieClip("mc", this.getNextHighestDepth());
mc.attachBitmap(myBitmapData, this.getNextHighestDepth());

// дорисовываем препятствия
myBitmapData.fillRect(new Rectangle(100, 50, 50, 50), 0xFFFF0000);
myBitmapData.fillRect(new Rectangle(250, 0, 50, 200), 0xFF0000FF);

Сразу возникает первая проблема (см. ссылку выше):

Код:

trace("getPixel = 0x"+myBitmapData.getPixel(10,10).toString(16))
trace("getPixel32>> = 0x"+(myBitmapData.getPixel32(10,10)>>24).toString(16)+(myBitmapData.getPixel32(10,10) & 0xFFFFFF).toString(16))
// выдает цвет getPixel = 0x5400ff и getPixel32>> = 0x705400ff соответственно
// вместо ожидаемого 0x5500FF и 0x705500FF соответственно

Ладно, используем getColorBoundsRect:

Код:

colorBoundsRect = myBitmapData.getColorBoundsRect(0xffff00ff, 0x705400ff, true);
trace(colorBoundsRect) // (x=0, y=0, w=250, h=200)

Обратите внимание: в маске канала R (RGB) параметр установлен в 0xFF, а в параметре цвета этого же канала установлено "левое" (реальное) значение в 0x54. Результат - все показывает верно.

Меняем параметр цвета на правильный (заданный), т.е. на 0х55:

Код:

colorBoundsRect = myBitmapData.getColorBoundsRect(0xffff00ff, 0x705500ff, true);
trace(colorBoundsRect) // (x=0, y=0, w=250, h=200)

Опять правильно! Как такое возможно?!

Дальше больше, работаем с маской:

Код:

//Смотрим какой цвет ожидается, если маску у R задать 0х54:
myColor32=myBitmapData.getPixel32(10,10)
trace((0x705400ff & myColor32).toString(16))
// 705400ff - т.е. побитовое И флеш с данными числами считает нормально (что вовсе не очевидно)

Проверяем теорию на практике:

Код:

colorBoundsRect = myBitmapData.getColorBoundsRect(0x705400ff, 0x705400ff, true);
trace(colorBoundsRect) // (x=0, y=0, w=0, h=0)

Ничего не вышло! Смена 0х54 на 0х55 ничего не дала...

PS
Возможно дело в ограничениях с работой флеша с 32 разрядными числами. Не знаю.
Например максимальное положительное число, которое переваривает toString(16) вовсе не 0xFFFFFFFF, как можно было бы подумать, а 0x7fffffff

Код:

z=0x7fffffff
trace(z.toString(16))

т.е. 31-разрядное (1 разряд уходит на знак)
Видимо отсюда же проблемы и с отображением getPixel32.

Но побитовое И в теории сработало же безошибочно (см. выше), а в практике (getColorBoundsRect) ничего не вышло. :(

Волгоградец 30.07.2008 10:54

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

var myBitmapData:BitmapData = new BitmapData(300, 200, true, 0x700100FF);
trace("getPixel = 0x"+myBitmapData.getPixel(10,10).toString(16));//0xff

0x990400FF
trace("getPixel = 0x"+myBitmapData.getPixel(10,10).toString(16));//0x300ff


0xFF0400FF
trace("getPixel = 0x"+myBitmapData.getPixel(10,10).toString(16));//0x400ff

Т.е. при прозрачности, отличной от FF округление альфы дает неверный результат.

Alex_beginner 30.07.2008 12:19

chingachgoog! Очень любопытные исследования. Я, увлекся ими.

Цитата:

Ладно, используем getColorBoundsRect:

Код:

colorBoundsRect = myBitmapData.getColorBoundsRect(0xffff00ff, 0x705400ff, true);
trace(colorBoundsRect) // (x=0, y=0, w=250, h=200)

Обратите внимание: в маске канала R (RGB) параметр установлен в 0xFF, а в параметре цвета этого же канала установлено "левое" (реальное) значение в 0x54. Результат - все показывает верно.

Меняем параметр цвета на правильный (заданный), т.е. на 0х55:


Код:

colorBoundsRect = myBitmapData.getColorBoundsRect(0xffff00ff, 0x705500ff, true);
trace(colorBoundsRect) // (x=0, y=0, w=250, h=200)

Опять правильно! Как такое возможно?!
Ну, я думаю, проблема здесь в конфликте попиксельного смешивания прозрачности цвета (параметр transparent) и альфа-составляющей значений маски и искомого цвета.
Грубо говоря, установите, параметр transparent в false, и данный пример заработает, т.е.:

Код:

myBitmapData = new BitmapData(300, 200, false, 0x705500FF);
Я, не совсем понимаю, зачем использовать transparent==true и при этом еще манипулировать альфа-каналом в кокретных используемых значениях. Практичнского значения это не имеет.
Используйте, лучше transparent==false и значения альфа-канала.

Буду исследовать дальше.

chingachgoog 30.07.2008 14:30

Цитата:

Сообщение от Волгоградец (Сообщение 755257)
Возможно дело с округлением альфы. Т.е. с цветами флэш нормально работает - а вот с прозрачностью - не очень.

Я тоже склонен считать, что дело в округлениях. Но, возможно, не из-за самой альфы, а из-за того, как НА САМОМ ДЕЛЕ храниться/записывается/считывается цвет в модели ARGB.

Цитата:

Сообщение от Волгоградец (Сообщение 755257)
Вот что выдает трейс при разных значениях цвета:
Код:

var myBitmapData:BitmapData = new BitmapData(300, 200, true, 0x700100FF);
trace("getPixel = 0x"+myBitmapData.getPixel(10,10).toString(16));//0xff


Ну как раз прозрачность тут считается правильно:
Код:

trace("getPixel32>> = 0x"+(myBitmapData.getPixel32(10,10)>>24).toString(16)+(myBitmapData.getPixel32(10,10) & 0xFFFFFF).toString(16)) // 0x70ff
// т.е. на самом деле 0x700000ff

А ошибка только в красном канале: вместо 0х01 посчитано 0х00

Цитата:

Сообщение от Волгоградец (Сообщение 755257)
Код:

0x990400FF
trace("getPixel = 0x"+myBitmapData.getPixel(10,10).toString(16));//0x300ff


Вот тут уже ошибка и в красном канале и в прозрачности:
Код:

//0x300ff т.е. на самом деле 0x0300ff
//getPixel32>> = 0x-67300ff

Итак getPixel опять ошибся на единицу в красном канале, а вот getPixel32 круто наврал...

Цитата:

Сообщение от Волгоградец (Сообщение 755257)
Код:

0xFF0400FF
trace("getPixel = 0x"+myBitmapData.getPixel(10,10).toString(16));//0x400ff


Тут тоже забавно:
Код:

getPixel = 0x400ff т.е. на самом деле 0x0400ff - ошибки нет
getPixel32>> = 0x-1400ff т.е. на самом деле 0x-10400ff  - ошибка только в альфа канале

Надо помнить, что мы трассируем через toString(16), поэтому при значении альфа канала более 0x7F toString(16) глючит (см. выше).
Хотя и непонятно почему - мы же проверили побитовый сдвиг вправо?
Но тождество налицо - до значения 0x7F определяется верно, более - ошибка.

Цитата:

Сообщение от Alex_beginner
Ну, я думаю, проблема здесь в конфликте попиксельного смешивания прозрачности цвета (параметр transparent) и альфа-составляющей значений маски и искомого цвета.
Грубо говоря, установите, параметр transparent в false, и данный пример заработает

Да, я писал, что это только для прозрачной битмапы такие глюки.

Цитата:

Сообщение от Alex_beginner
т.е.:
Код:

myBitmapData = new BitmapData(300, 200, false, 0x705500FF);
Я, не совсем понимаю, зачем использовать transparent==true и при этом еще манипулировать альфа-каналом в кокретных используемых значениях. Практичнского значения это не имеет.
Используйте, лучше transparent==false и значения альфа-канала.

Не понял насчет transparent==false. Тогда же битмапа непрозрачная будет и параметр A модели ARGB вообще роли не играет (как и метод getPixel32 теряет свой смысл).
А ведь битмапа с прозрачностью - наиболее востребованная, разве нет?

add:
Ступил с трейсом на getPixel32, там надо было побитовый сдвиг без знака делать, тогда toString(16) правильный альфа канал показывает ВСЕГДА!
Код:

trace("getPixel32>> = 0x"+(myBitmapData.getPixel32(10,10)>>>24).toString(16)+(myBitmapData.getPixel32(10,10) & 0xFFFFFF).toString(16))
add2:
вроде нашел причину
http://flasher.ru/forum/showpost.php...25&postcount=3
ПУстячок, а приятно, что я верно предположил, что все дело в том, как НА САМОМ ДЕЛЕ ХРАНИТЬСЯ цвет в модели ARGB.

Bred45 25.03.2009 11:22

Ребята, спасибо за эту тему. Тоже на днях ломал голову над похожей задачей при использовании Threshold.

В результате, причину проблемы нашел в мануале по getPixel:
Все цветовые пикселы в объекте BitmapData хранятся уже умноженными на значение альфы (premultiplied color values).
И в мануале даже упомянуто, что потеря данных может вызывать некоторые проблемы. Вот с этими проблемами мы, похоже, и столкнулись.

Так что chingachgoog, видимо, в своем конечном выводе прав.


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

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