Определение цвета в прозрачной BitmapData
Запись от chingachgoog размещена 02.02.2009 в 14:39
Хотя тут некоторые продолжают утверждать, что флешеру не надо знать внутреннию реализацию механизмов флеш плеера (знай мол себе AS и не думай ни о чем, за тебя уже подумали дяди из адоба), жизнь и практика показывают обратное.
В свое время я открыл тему прозрачная битмапа не распознает цвета 0xCC и высказал гипотезу, что все дело именно в том, как на самом деле работает прозрачность.
С выходом очередной нетленки Мука ситуация прояснилась.
(Анализ растрового изображения. Влияние прозрачности на получение значения цвета. с. 729)
Цитата:
Из-за особенностей внутренней архитектуры механизма визуализации ... Для повышения производительности процесса визуализации, ... среда Flash преобразует это значение [значение цвета] во внутренний формат, называемым предумноженным значением цвета. Оно объединяет значения канала Alpha и каналов Red, Green и Blue этого цвета... В результате исходные значения, присвоенные каналам Red, Green и Blue, будут потеряны.
При получение значений цвета ... Flash осуществляет их автоматическое преобразование из предумноженного в стандартный (неумноженный) формат ARGB, ... приводя к потери точности.
При получение значений цвета ... Flash осуществляет их автоматическое преобразование из предумноженного в стандартный (неумноженный) формат ARGB, ... приводя к потери точности.
Ну да - перемножив на ноль - ноль и получим.
Но не все так просто.
Вот мой пример:
Код:
import flash.display.BitmapData; bmd=new BitmapData(100, 100, true, 0x90CCCCCC) trace("getPixel32>> = 0x"+(bmd.getPixel32(10,10)>>>24).toString(16)+(bmd.getPixel32(10,10) & 0xFFFFFF).toString(16))
(всего-то вместо 204 показывает 203 для канала)
Непонятно как так "предумножился" каждый цвет 0xCC на альфу 0x90, что при обратном преобразовании вышло 0xCB.
Ведь альфа-то как раз показывается при getPixel32 верно! Т.е. множитель 0x90 не изменился. Для обычных чисел флеш тут не глючит:
Код:
zz=0x90CCCCCC del=(zz>>>24)/0xFF zz*=del zz/=del trace("0xZZ=0x"+(zz>>>24).toString(16)+(zz & 0xFFFFFF).toString(16))
Значит механизм "предумножения" работает еще хитрее и в чем прав Мук, так в том, что на getPixel32 в точке с прозрачностью не равной 0xFF нельзя положиться.
Всего комментариев 19
Комментарии
28.09.2009 12:57 | |
Цитата:
0xCCCCCC - это монохромный цвет
И почему он должен лучше кодироваться/декодироваться? |
|
Обновил(-а) Котяра 28.09.2009 в 15:42
|
28.09.2009 23:01 | |
Ну да естественно в реальности перемножаются компоненты цвета каждый в отдельности при этом на каждый компонент отводится по одному октету... и это... с чего вы взяли, что операции, которые плеер делает на нативном уровне используют те же типы данных, что и AS? Плеер же не на AS написан... т.е. грубо говоря, что, как мне кажется происходит:
Код:
R = 0xFF & (k * R); G = 0xFF & (k * G); B = 0xFF & (k * B); color = (R << 16) | (G << 8) | B; так вы сможете бесконечно накладывать цвета один на другой (что собственно и требуется для отображения). Т.е. предположим, что пиксел, который был под уже рассчитаным пикселом имел так же посчитаные значения, тогда, чтобы узнать результирующий цвет мы просто сделаем: Код:
resultColor = color | backgroundColor; EDIT: А, и ну, естесственно, когда мы рассчитываем "процент" цветовой компоненты, то из-за того, что для подсчета мы используем число с восмю октетами, совсем не следует, что плеер использует тот же самый численный тип для подсчетов, так, например, если бы он использовал SF32 (signed 32-bit float), то подсчеты бы выглядели примерно так: Код:
trace((0x90 / 0xFF).toFixed(8)); //0.56470588 trace((0.56470588 * 0xFF).toString(16)); //8f |
|
Обновил(-а) wvxvw 28.09.2009 в 23:23
|
03.10.2009 03:16 | |
wvxvw, Вы теперь за этих .
|
04.10.2009 03:25 | |
Код:
function setPixel32(color) { A = (color >>> 24); R = (color >>> 16) & 0xFF; G = (color >>> 8) & 0xFF; B = color & 0xFF; newA = A; newR = Math.round(A*R/255); newG = Math.round(A*G/255); newB = Math.round(A*B/255); color = (newA << 24) | (newR << 16) | (newG << 8) | newB; } function getPixel32() { A = (color >>> 24); R = (color >>> 16) & 0xFF; G = (color >>> 8) & 0xFF; B = color & 0xFF; oldA = A; oldR = R*255/A; oldG = G*255/A; oldB = B*255/A; color = (oldA << 24) | (oldR << 16) | (oldG << 8) | oldB; return color; } |
|
Обновил(-а) Яски 05.10.2009 в 15:26
|
05.10.2009 15:27 | |
Так странно, в посте почему то указал left shift, вместо right shift. Исправил старый пост.
|
06.10.2009 11:15 | |
Ну все!
Тайна формулы предумножения раскрыта Яски! Респект! |
09.10.2009 22:07 | |
Яски, а откуда формулу взял? Или силой мысли?
|
11.10.2009 01:49 | |
Это просто получение компонентов цвета, умножение и немного грубой силы
|
Последние записи от chingachgoog
- Работа в Цинке с несколькими COM-портами (17.12.2009)
- ASnative. Новые находки. Примеры применения. (02.06.2009)
- Решение проблемы ввода кириллицы на прозрачном фоне (20.05.2009)
- Полиморфизм (03.04.2009)
- Спасибо форуму Флешер.ру! (27.03.2009)