![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Оптимизация кода
Вова © (2013-06-25 20:17:00)
Страницы: < 1 2 3 4 5 6 7 8 9 10 11 >
Есть процедура задачей которой является приведения пикселя любого цвета к цвету одного из диапазонов. Но скорость ее работы огорчает меня, можно ли ее как нибудь ускорить?
function almostEqual(a, b: byte): Boolean;
begin
if ABS(a - b) < 10 then
result := true
else
result := false;
end;
Function ConvertColorToRGBColorMap(color: LongInt; ColSel: String = 'None')
: TColorWithName;
var
RGBV: trgbcolor;
begin
RGBV.red := color;
RGBV.green := color shr 8;
RGBV.blue := color shr 16;
with RGBV do
if almostEqual(red, green) and almostEqual(red, blue) and
almostEqual(blue, green) then // тогда это серый или черный или белый
begin
if almostEqual(red, 255) then // белый
begin
result.color := RGB(255, 255, 255);
result.Name := 'White';
end
else if red > 120 then
begin
result.color := RGB(190, 190, 190);
result.Name := 'LightGray';
end
else if (red > 92) then // темно серый
begin
result.color := RGB(100, 100, 100);
result.Name := 'DarkGray';
end
else
begin
result.color := RGB(0, 0, 0);
result.Name := 'Black';
end // черный
end
else
begin
if (red < green) and (red < blue) and almostEqual(green, blue) and
(blue > 130) then
begin
result.color := RGB(0, 0, 255);
result.Name := 'Blue';
end // result:= rgb(0,255,255)//голубой
else if (green < red) and (green < blue) and almostEqual(red, blue) and
(red > 130) then
begin
result.color := RGB(255, 0, 255);
result.Name := 'Pink';
end // розовый
else if (blue < green) and (blue < red) and almostEqual(green, red) and
(green > 130) then
begin
result.color := RGB(255, 255, 0);
result.Name := 'Yellow';
end // желтый
else if (red > green) and (red > blue) and (red > 130) then
begin
result.color := RGB(255, 0, 0);
result.Name := 'Red';
end // красный
else if (blue > green) and (blue > red) and (blue > 130) then
begin
result.color := RGB(0, 0, 255);
result.Name := 'Blue';
end // синий
else if (green > blue) and (green > red) and (green > 130) then
begin
result.color := RGB(0, 255, 0);
result.Name := 'Green';
end // зеленый
else
begin
result.color := RGB(0, 0, 0);
result.Name := 'Black';
end
end;
if not (ColSel = 'None') then
if not (ColSel = Result.Name) then
begin
result.color := RGB(255, 255, 255);
result.Name := 'White'; //Если выборка только по одному цвету, то
//все остальные цвета переводим в белый
end
else
begin
result.color := RGB(0, 0, 0);
result.Name := 'Black'; //Если выборка только по одному цвету, то
//этот цвет переводим в черный
end
end;
Sha (2013-07-02 21:31:00) [81]У меня другой прием:
куски, которые вычисляются по отдельности пишу каждый на своей строчке,
а внутри кусков операции выполняются последовательно.
В результате и ясно все, и скобки не нужны.
Rouse_ (2013-07-02 21:28:00) [82]Да это-то понятно, просто мне в своем крипто приходится писать примерно такого-же плана конструкции (побольше, правда) и чтобы не запутаться кто от чего зависит я и привык все скобками обрамлять.
Ну а исходя из этого я на автомате за скобки глазом цепляюсь и влет разбиваю конструкцию на составляющие, а вот в твоем варианте пришлось подзадуматься (вчитаться тобишь...) :)
Sha (2013-07-02 21:26:00) [83]Саш, ну ты мысленно сделай замену как в [126].
Стал бы ты тогда ставить скобки?
Согласись, они бы только мешали.
Ну вот и мне мешают. Потому и не ставлю )
Rouse_ (2013-07-02 21:22:00) [84]Ну я раза три перечитал сей код, дабы осмыслить :)
Оть так-же гораздо удобней:
or (((i shr 16) and $FF) div 3) shl 16
Sha (2013-07-02 21:17:00) [85]нормально читаю, с удовольствием:
or читается как +
and, shr, shl читаются как *
в чем проблема-то?
не понимаю )
Rouse_ (2013-07-02 21:13:00) [86]Фига, Сань, у тебя конструкции:
or i shr 16 and $FF div 3 shl 16
Я понимаю, запятые там можно понапропускать, все равно читабельно будет - но зачем скобки то игнорировать на таких операциях? :)
Ни разу ж не читабельно :)
Sha (2013-07-02 17:43:00) [87]После 2+2*2=?не читай.
Это копипаста твоего поста
Sha (2013-07-02 17:41:00) [88]> Вова (02.07.13 13:25) [115]
че-то ты притих )
i shr 24 and $F0 - ставим нулевой байт второго триплета на нулевое место и оставляем в нем только 4 старших бита в старшем нибле,
j shr 4 and $F0F - ставим старший нибл первого байта второго триплета на место младшего нибла нулевого байта,
а старший нибл второго байта второго триплета на место младшего нибла первого байта,
or-им их между собой - получаем индекс для второго триплета в нашей таблице.
проще пареной репы )
> если у shl приоритет такой же как у or то вообще какая то херня
ну с приоритетами ты уж разберись, даже неудобно как-то, ты программист или где?
2+2*2=?
or j - первых 4 байта у которых значащими остались только первые 4 бита в последнем байте, накладываются на вторые 4 байта, получается вообще непонятно что )
j shr 4 - 4 правых бита от j удаляются. получается 4 байта с пустыми 4 битами в начале, и с какой то непонятной лажей (получившейся в результате or j) в самых правых 4 битах, а потом вообще ппц объединение с 111100001111, это ж полтора байта, как оно вообще накладывается (( на 4 байта! Обнуляются первые 4 бита правого байта? сдается мне что это не так, т.к почему тогда не 0F? ( но что за хрень это тогда?
В общем, к данному моменту кода у меня в голове полная каша не позволяющая идти дальше. Напоминает школу ) "В результате тривиальных вычислений получаем....." что получаем, откуда непонятно ( и как результат 10 впустую потраченных лет.
i := ColorMap[i and $F0 or i shr 12 and $F0F]; ну это понятно, см. выше ((
p[0] := i or T shl 24; - объединение 2х абракадабр, если у shl приоритет такой же как у or то вообще какая то херня, выкинули 3 байта остался 1 Оо
Все что я нашел об этом, это надписи о том, что в интернете куча статей об этом, видимо не такая уж и куча....Дайте ссылку хоть на одну! то что '1111000' or '00001111' = '11111111' это я вроде понял, только вот это никак не помогает понять, что в этом коде написано.
Jeer (2013-07-02 17:08:00) [89]P.S.
Что-то это мне напомнило "Радио? Это очень просто!" Айсберга.
Кстати, на самом деле, замечательный методический прием.
Jeer (2013-07-02 17:05:00) [90]Приятно, когда мастера общаются in self и это правильно:)
Sha (2013-07-02 14:39:00) [91]Обрабатывать цвет по определению надо триплетами, читать-писать для скорости надо двойными словами.
Из-за этого небольшого противоречия возникают некоторые сложности с пониманием алгоритма )
Давай посмотрим это на простом примере. Пусть в памяти m последовательно лежат 4 байта. Надо первый из них увеличить на 1, второй умножить на 2, третий разделить на 3, четвертый оставить без изменений. Читать и писать переменную m разрешается только 1 раз.
Решение:
i:=m;
m:=(i + 1) and $FF
or i and $7F00 shl 1
or i shr 16 and $FF div 3 shl 16
or i and $FF000000;
Sha (2013-07-02 14:10:00) [92]Допустим в переменной i лежит цвет,
интесивность каждой составляющей в своем байте (байты 0..2).
Пусть
i:=$00aabbcc;
Каждую из них усекаем до старших 4х битов:
i:=i and $F0F0F0;
Получаем
i:=$00a0b0c0;
Формируем число от 0 до 16*16*16-1 - будущий индекс цвета в таблице:
i:=(i shr 12 and $F) + (i and $F0) + (i shr 12 and $F00);
Получаем
i:=$00000acb;
Tот же самый результат дает
i:=i and $F0 or i shr 12 and $F0F;
Sha (2013-07-02 13:54:00) [93]Зарапортовался, все с точностью до наоборот:
2. В теории, в голове и на бумаге младший байт обычно изображают справа,старший слева,
Sha (2013-07-02 13:51:00) [94]1. Байты в integer нумеруются с 0 до 3. Младший байт содержит содержит младшие 8 бит, т.е. остаток от деления на 256.
2. В теории, в голове и на бумаге младший байт обычно изображают слева, старший справа, (это похоже на десятичную систему, только здесь она 256-ричная).
3. В памяти машины с архитектурой IA-32 адрес integer совпадает с адресом его младшего байта, байт номер 1 хранится по адресу на 1 больше, старший байт - по адресу на 3 больше. Можно считать, что адреса растут справа налево.
4. Команды shr и shl имеют дело с представлением 2, причем сдвиг в действительности выполняется на указанное число бит, взятое по модулю размера операнда (т.е. 32 для integer).
5. Команды and и or с integer-операндами выполняются побитно, т.е. i and 1 вернет значение младшего бита младшего байта (1 для нечетного числа, 0 для четного), a i or 1 вернет первое нечетное после i для четного i или само i для нечетного i.
Вова (2013-07-02 13:28:00) [95]блин (((
Вова (2013-07-02 13:25:00) [96]блиииин! жил же спокойно (( раз рассказали все это теперь расскажите и что это значит
старший байт тот что в конце (слева направо)?
i := p[0]; //Берем первые 4 байта в строке (BGR + 1 байт канал B от следующего пикселя)
j := p[1]; //Берем вторые 4 байта в строке
Дальше ад:
T := ColorMap[i shr 24 and $F0 or j shr 4 and $F0F];
i shr 24 - смещение вправо 3 байт, т.е. остается канал B первого пикселя? правда он теперь на месте B второго пикселя. объединяется с `11110000` опять же не понятно как, i это же 4 байта, а не 1, или он только с последним самым правым байтом или со всеми по очереди? И главное - какой в этом смысл? Блин ну это ведь что то значит ) просто так наложили какую то лажу на канал цвета, что это с цветом то делает? ) т.е. 4 последних бита обнуляются, но нафига???
or j - первых 4 байта у которых значащими остались только первые 4 бита в последнем байте, накладываются на вторые 4 байта, получается вообще непонятно что )
j shr 4 - 4 правых бита от j удаляются. получается 4 байта с пустыми 4 битами в начале, и с какой то непонятной лажей (получившейся в результате or j) в самых правых 4 битах, а потом вообще ппц объединение с 111100001111, это ж полтора байта, как оно вообще накладывается (( на 4 байта! Обнуляются первые 4 бита правого байта? сдается мне что это не так, т.к почему тогда не 0F? ( но что за хрень это тогда?
В общем, к данному моменту кода у меня в голове полная каша не позволяющая идти дальше. Напоминает школу ) "В результате тривиальных вычислений получаем....." что получаем, откуда непонятно ( и как результат 10 впустую потраченных лет.
i := ColorMap[i and $F0 or i shr 12 and $F0F]; ну это понятно, см. выше ((
p[0] := i or T shl 24; - объединение 2х абракадабр, если у shl приоритет такой же как у or то вообще какая то херня, выкинули 3 байта остался 1 Оо
Все что я нашел об этом, это надписи о том, что в интернете куча статей об этом, видимо не такая уж и куча....Дайте ссылку хоть на одну! то что '1111000' or '00001111' = '11111111' это я вроде понял, только вот это никак не помогает понять, что в этом коде написано.
Sha (2013-07-02 08:10:00) [97]кто ж всю лапшу сразу вываливает на клиента, так можно отпугнуть )
Sapersky (2013-07-02 07:19:00) [98]Ну, так все-таки разы? ))
Разы.
Мне показалось, что было утверждение вроде "выкинь купиксели и будет тебе 5-10 раз", только за счёт выкидывания. А оказывается в [57] уже была запланирована развёртка цикла с выравниванием доступа к памяти, кто бы мог подумать :)
Sha (2013-07-01 20:12:00) [99]> Вова (01.07.13 18:41) [111]
Если преобразовывать цвет в цвет, то быстрее [81,85] для 24-битного цвета не получится.
А если цвет в булеан, то можно отжать еще несколько процентов.
32-битный цвет, наверно, будет в 1.2-2.0 раза быстрее в зависимости от процессора.
Вова (2013-07-01 18:41:00) [100]интересно, а через SetDIBits будет еще быстрее чем через сканлайн? )
может уже чтобы 2 раза потом не переделывать разобраться)