LINUX.ORG.RU

Оптимизация кода смешея цветов

 , ,


1

1

Написал такой код:

#define SML_COL_B(COLOR) (unsigned char)(((uint32_t)(COLOR) & 0x000000FF) >> 0)
#define SML_COL_G(COLOR) (unsigned char)(((uint32_t)(COLOR) & 0x0000FF00) >> 8)
#define SML_COL_R(COLOR) (unsigned char)(((uint32_t)(COLOR) & 0x00FF0000) >> 16)
#define SML_COL_A(COLOR) (unsigned char)(((uint32_t)(COLOR) & 0xFF000000) >> 24)
#define SML_COL_RGB(R, G, B)     (uint32_t)(((unsigned char)(R) << 16) |\
                                            ((unsigned char)(G) << 8 ) |\
                                            ((unsigned char)(B)))
#define SML_COL_RGBA(A, R, G, B) (uint32_t)(((unsigned char)(A) << 24) |\
                                            ((unsigned char)(R) << 16) |\
                                            ((unsigned char)(G) << 8 ) |\
                                            ((unsigned char)(B)))
/// @todo get rid of floats
#define SML_COL_MIX(START, TARGET, INTENSITY)                                      \
    SML_COL_RGBA(                                                                  \
    SML_COL_A(START) + (SML_COL_A(TARGET) - SML_COL_A(START)) / 255.0 * INTENSITY, \
    SML_COL_R(START) + (SML_COL_R(TARGET) - SML_COL_R(START)) / 255.0 * INTENSITY, \
    SML_COL_G(START) + (SML_COL_G(TARGET) - SML_COL_G(START)) / 255.0 * INTENSITY, \
    SML_COL_B(START) + (SML_COL_B(TARGET) - SML_COL_B(START)) / 255.0 * INTENSITY)

Теперь хочу оптимизировать SML_COL_MIX, ибо разворачивается оно в бешеную простыню:

(uint32_t)(((unsigned char)((unsigned char)(((uint32_t)(startcolor) & 0xFF000000) >> 24) + ((unsigned char)(((uint32_t)(color) & 0xFF000000) >> 24) - (unsigned char)(((uint32_t)(startcolor) & 0xFF000000) >> 24)) / 255.0 * value) << 24) | ((unsigned char)((unsigned char)(((uint32_t)(startcolor) & 0x00FF0000) >> 16) + ((unsigned char)(((uint32_t)(color) & 0x00FF0000) >> 16) - (unsigned char)(((uint32_t)(startcolor) & 0x00FF0000) >> 16)) / 255.0 * value) << 16) | ((unsigned char)((unsigned char)(((uint32_t)(startcolor) & 0x0000FF00) >> 8) + ((unsigned char)(((uint32_t)(color) & 0x0000FF00) >> 8) - (unsigned char)(((uint32_t)(startcolor) & 0x0000FF00) >> 8)) / 255.0 * value) << 8 ) | ((unsigned char)((unsigned char)(((uint32_t)(startcolor) & 0x000000FF) >> 0) + ((unsigned char)(((uint32_t)(color) & 0x000000FF) >> 0) - (unsigned char)(((uint32_t)(startcolor) & 0x000000FF) >> 0)) / 255.0 * value))),

Хочу оптимизировать по скорости.

Что эта фиговина делает: смешивает два цвета, используя START как начальный цвет, TARGET - цвет, который накладывается сверху, INTENSITY - степень прозрачности наложения TARGET цвета в рамках от 0 (нет наложения) до 255 (полная закраска).
По какому принципу работает:

FFFFFF           FFFFFF
....  ---------- TARGET
....             ....
START ---------- ....
....             ....
....             ....
000000           000000

Берется разница между каждым каналом цветов, делится на 255, умножается на INTENSITY, плюсуется к START.


Ответ на: комментарий от trycatch

Для оптимизации же смешивания попробуй воспользоваться SSSE3-инструкцией

Есть не везде.

Что ты такое страшное делаешь с альфа-каналом?

А что я с ним делаю?

inn
() автор топика
Ответ на: комментарий от inn

Используй битовые поля. Компилятор лучше тебя оптимизирует. И выглядеть будет по человечески.

upd: да тут даже они не нужны. Просто структуры с unsigned char полями.

ziemin ★★
()
Последнее исправление: ziemin (всего исправлений: 1)

Это чего самое тормозное в твоей программе? Напиши тест, посмотри сколько операция в секунду выполняется, подумай и займись чем-нить полезным.

vtVitus ★★★★★
()

кода смешея цветов
смешея цветов
смешея

О, рассмейтесь, смехачи!
О, засмейтесь, смехачи!
Что смеются смехами, что смеянствуют смеяльно,
О, засмейтесь усмеяльно!
О, рассмешищ надсмеяльных - смех усмейных смехачей!
О, иссмейся рассмеяльно, смех надсмейных смеячей!
Смейево, смейево!
Усмей, осмей, смешики, смешики!
Смеюнчики, смеюнчики.
О, рассмейтесь, смехачи!
О, засмейтесь, смехачи!

anonymous
()

Скоро уже 2014 год, а вы все на макросах делаете.

inline uint8_t sml_col_r(uint32_t c);
/* ... */
Компилятор это сам оптимизирует вполне прилично. Ну и SSE тоже вариант.

Если нет inline (в каком компиляторе?), то

#define inline static

rymis ★★
()
Ответ на: комментарий от inn

Убрать float:

#define SML_COL_MIX(START, TARGET, INTENSITY) \
	SML_COL_RGBA( \
	(SML_COL_A(START) * (255 - (INTENSITY)) + SML_COL_A(TARGET) * (INTENSITY) + 127) / 255, \
	(SML_COL_R(START) * (255 - (INTENSITY)) + SML_COL_R(TARGET) * (INTENSITY) + 127) / 255, \
	(SML_COL_G(START) * (255 - (INTENSITY)) + SML_COL_G(TARGET) * (INTENSITY) + 127) / 255, \
	(SML_COL_B(START) * (255 - (INTENSITY)) + SML_COL_B(TARGET) * (INTENSITY) + 127) / 255)

Если известно, что все операнды находятся в памяти (не константы), то на мой взгляд, так будет проще:

static inline void blend(uin8_t *dst, uint8_t *start, uint8_t *target, int intensity)
	{
	int i;

	for(i = 0; i < 4; ++i)
		dst[i] = (start[i] * (255 - intensity) + target[i] * intensity + 127) / 255;
	}

По желанию, можно развернуть цикл.

cdslow ★★
()

С небольшой погрешностью, зато быстро:

dst[0] = (start[0] * (255 - intensity) + target[0] * intensity) >> 8;
dst[1] = (start[1] * (255 - intensity) + target[1] * intensity) >> 8;
dst[2] = (start[2] * (255 - intensity) + target[2] * intensity) >> 8;

Deleted
()

Возьми pixman. Или посмотри хотя бы там исходники. Эта библиотека как раз про то, что ты делаешь, но она еще и оптимизирована под разные архитектуры.

git clone git://anongit.freedesktop.org/git/pixman
Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Спасибо.

Но это читерство же ><

*Ушел глушить водку*

inn
() автор топика
Ответ на: комментарий от inn

Что в лоб, что по лбу. У меня альфа целое 0..255, у них 0..1 дробное.

SSE - это про векторные вычисления и оптимизацию использования пропускной способности памяти.

mv ★★★★★
()
Ответ на: комментарий от mv

Я понимаю, но я еще не ткой эксперт по асму, чтобы 1) понять, что они там делают, 2) поправить так, чтобы там было не 0..1, а 0..255

inn
() автор топика
Ответ на: комментарий от inn

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

mv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.