Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   [Алгоритмы] заменить медленный setPixel32 (http://www.flasher.ru/forum/showthread.php?t=211681)

voidmain 13.10.2015 15:45

заменить медленный setPixel32
 
Добрый день!
Мне нужно заменить "преобладающий" цвет из RGB на прозрачный.

например для удаления зеленого цвета я делаю так:

Код AS3:

sourceBmdSmall.lock();
for (var i:uint = 0; i < sourceBmdSmall.width; i++)
for (var j :uint = 0; j < sourceBmdSmall.height ; j++)
{
  var color:uint = sourceBmdSmall.getPixel(i, j);
  var rgb:Object = ColorUtil.getRGB(color);
 
  var maxColor:uint = rgb.r > rgb.b ? rgb.r : rgb.b;
  if (rgb.g > maxColor + 7)  // число 7 - некий порог с которым нужно удалить цвет
    sourceBmdSmall.setPixel32(i, j, 0x00000000);
}
sourceBmdSmall.unlock();

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

Можно ли этот вариант сделать каким то другим способом?
Например через тот же threshold? Что то ни как не соображу.. Кстати говоря до этого удалял цвет как раз с помощью threshold, но работает все таки не так хорошо как в коде выше. Либо я не допонял возомжности threshold.

nuToH 13.10.2015 16:42

Добрый день. Не думая, навскидку:
Код AS3:

var vector:Vector.<uint> = sourceBmdSmall.getVector( sourceBmdSmall.rect );
var length:int = vector.length;
for ( var i:int = 0; i < length; i++ ) {
// do something
}
sourceBmdSmall.setVector( sourceBmdSmall.rect, vector );

должно работать в разы быстрее

voidmain 13.10.2015 17:42

Спасибо за ответ!
Первый вариант по скорости работает примерно как мой...ускорения не заметно никакого.
а по второму не очень понял.

В своем примере я показал как убираю зеленый цвет. и очень близкие к зеленому цвета.
например в моем случае
варианты цветов:
100 108 100
0 108 100
0 208 200
200 208 0

будут считаться близкими к зеленому с порогом 7. (if (rgb.g > maxColor + 7))
И вот этот вариант максимально хорошо работает..но медленный зараза)

nuToH 13.10.2015 17:49

Прошу прощения, поспешил.

voidmain 13.10.2015 18:16

Исправил на такой вариант:

Код AS3:

for (i = 0; i < length; i++)
{
if ((vector[i] >> 8 & 0xFF) > Math.max(vector[i] >> 16 & 0xFF, vector[i] & 0xFF) + 7)
vector[i] = 0;
}

Стало заметно быстрее. Впринципе уже приемлимо. Спасибо!

Но если еще есть варианты я послушаю)

gloomyBrain 13.10.2015 18:52

Точно нужно только один раз читать из вектора + заменить Math.max на самописную, типа такого:
Код AS3:

for (i = 0; i < length; i++)
{
    var elem:uint = vector[i]; // одно чтение из вектора
 
    var a:uint = elem >> 16 & 0xFF;
    var b:uint = elem & 0xFF;
    var max:uint = a > b ? a : b; // самописная проверка
 
    if ((elem >> 8 & 0xFF) > max + 7)
    {
        vector[i] = 0;
    }
}

Потому что
а) индексный доступ к массивам в AS3 довольно медленный
б) Math.max - это статический метод, в AS3 это тоже очень и очен медленно работает

nuToH 13.10.2015 19:21

Код AS3:

var width:int = sourceBmdSmall.width;
var height:int = sourceBmdSmall.height;
var rect:Rectangle = sourceBmdSmall.rect;
var point:Point = new Point();
 
var greenChannel:BitmapData = new BitmapData( width, height, false, 0xFFFFFFFF );
greenChannel.copyChannel( sourceBmdSmall, sourceBmdSmall.rect, new Point(), BitmapDataChannel.GREEN, BitmapDataChannel.RED );
greenChannel.copyChannel( sourceBmdSmall, sourceBmdSmall.rect, new Point(), BitmapDataChannel.GREEN, BitmapDataChannel.GREEN );
greenChannel.copyChannel( sourceBmdSmall, sourceBmdSmall.rect, new Point(), BitmapDataChannel.GREEN, BitmapDataChannel.BLUE );
// 0xGGGGGG
 
var a:BitmapData = sourceBmdSmall.clone();
a.draw( greenChannel, null, null, BlendMode.LIGHTEN ); // a = max( src, 0xGGGGGG )
 
a = a.compare( sourceBmdSmall ) as BitmapData; // a = a - source
 
var b:BitmapData = new BitmapData( width, height, false, 0 );
b.threshold( a, rect, point, ">", 0x070000, 0xFFFF0000, 0xFF0000 ); // g - r > 7
 
var c:BitmapData = new BitmapData( width, height, false, 0 );
c.threshold( a, rect, point, ">", 0x000007, 0xFFFF0000, 0xFF0000 ); // g - b > 7
 
b.merge( c, rect, point, 128, 128, 128, 128 ); // f0.5 * 0xFF0000 + f0.5* 0xFF0000 == 0xFF0000
 
sourceBmdSmall.threshold( b, rect, point, "==", 0xFF0000, 0x00000000, 0x00FF0000 ); // 0xFF00FF ? 0x00000000 : dst

извращение.. но вырезает зелёный.)

AlexCooper 14.10.2015 01:34

Попробуйте PixelBender, замечательно справлялся с задачей (там же есть скрин с готовым кодом, вам нужно будет только сменить "<" на ">" в условии.
Правда, говорят сейчас он тормозит... Но попробывать стоит. Еще можно через воркер

voidmain 14.10.2015 11:22

всем спасибо! :victory:

cleptoman 16.10.2015 11:44

а это не канает уже?
http://help.adobe.com/ru_RU/FlashPla...hreshold%28%29


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

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