![]() |
| ||
|
|
Новости |
Поиск |
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;
Вова (2013-07-01 17:49:00) [121]я твой не менял, просто передал в функцию вот это...
Sha (2013-07-01 17:46:00) [122]У меня компилится без проблем. Ты мой код меняй.
Свой меняй. И свою секретную ошибку сюда давай.
Sha (2013-07-01 17:46:00) [123]* Ты мой код неменяй.
Вова (2013-07-01 17:42:00) [124]
> результат давай: проценты или разы?
пока только ошибка j:=p[1];
Если p := tbmp.Scanline(tbmp.Height-1)
RWolf (2013-07-01 17:41:00) [125]
> есть где нибудь описание "на пальцах"
учебник по информатике, 7-й класс.
Sha (2013-07-01 17:38:00) [126]Там в коде [81] ошибочка вкралась, исправить надо:
if rest>0 then begin; //последний нечетный пиксел
i:=pWordArray(p)[0]+pByteArray(p)[2] shl 16;
i:=ColorMap[i and $F0 or i shr 12 and $F0F];
pWordArray(p)[0]:=i;
pByteArray(p)[2]:=i shr 16;
inc(pAnsiChar(p),3);
end;
Sha (2013-07-01 17:24:00) [127]результат давай: проценты или разы?
Вова (2013-07-01 17:24:00) [128]есть где нибудь описание "на пальцах" как вот это i shr 24 and $F0 or j shr 4 and $F0F понять? )
Вова (2013-07-01 17:22:00) [129]омг, ну ради такого профита можно перейти и на 32, но вот только все эти i and $F0 это писец ) статью выше я читал, понял не очень, но это по сравнению с той статьей вообще космос )
Sha (2013-07-01 17:12:00) [130]> Sapersky
> В целом, насчёт ускорения в 5-10 раз Sha всё-таки загнул.
> ещё вариант - обрабатывать пачками по 4 пикселя
как бы нам это проверить... )
> Вова
> и в добавок эта битовая математика ад какой то
если скорость нужна, научишься и разберешься: )
var
ColorMap: array[0..16*16*16-1] of integer;
procedure ShaConvert(p: pIntegerArray; rowcount, pixelcount: integer);
var
i, j, t, rest: integer;
begin;
pixelcount:=pixelcount*3;
while rowcount>0 do begin;
rest:=pixelcount;
while rest>=6 do begin;
i:=p[0];
j:=p[1];
t:=ColorMap[i shr 24 and $F0 or j shr 4 and $F0F];
i:=ColorMap[i and $F0 or i shr 12 and $F0F];
p[0]:=i or t shl 24;
if rest<12 then begin;
pWordArray(p)[2]:=t shr 8;
inc(pAnsiChar(p),6);
dec(rest,6);
break;
end;
i:=p[2];
j:=ColorMap[j shr 16 and $F0 or j shr 28 and $F or i shl 4 and $F00];
p[1]:=t shr 8 or j shl 16;
p[2]:=j shr 16 or ColorMap[i shr 8 and $F0 or i shr 20 and $F0F] shl 8;
inc(pAnsiChar(p),12);
dec(rest,12);
end;
if rest>0 then begin; //последний нечетный пиксел
i:=pWordArray(p)[0]+pByteArray(p)[2] shl 16;
i:=ColorMap[i and $F0 or i shr 12 and $F0F];
pWordArray(p)[0]:=i;
pByteArray(p)[2]:=i shr 16;
end;
dec(rowcount);
inc(pAnsiChar(p),(4-pixelcount) and 3);
end;
end;
Вова (2013-07-01 16:36:00) [131]и в добавок эта битовая математика ад какой то, я ничего не могу в ней понять ) откуда все понимают какие маски накладывать и все такое..
Sapersky (2013-07-01 15:17:00) [132]Или, если перейти на 32 бита сложно, ещё вариант - обрабатывать пачками по 4 пикселя (12 байт, 3 чтения по 4 байта). Опять же, развёртка цикла получается, тоже полезно.
Но для того чтобы выковырять эти 4 пикселя, понадобятся дополнительные сдвиги и and'ы. Функция станет совсем уж монструозной, через полгода сам без комментариев (и/или поллитры) не разберёшься.
Sapersky (2013-07-01 14:54:00) [133]Указатель увеличиваешь на 4, а цвет 24-битный, поэтому и полоска.
Скорость повышается из-за того, что доступ по выровненным на 4 адресам быстрее, чем невыровненный с шагом 3 (+ обращений на 25% меньше). Отсюда вывод - 32-битные битмапы должны быть быстрее, даже при большем размере данных.
Как вариант, результирующий битмап (или массив) можно сделать 8-битным, всё равно там цвета можно по пальцам пересчитать. Хотя не факт, что скорость при этом вырастет.
Проблемы с цветами видимо из-за того, что порядок цветовых компонент изменился, раньше было RGB, сейчас BGR. Нужно сдвиги и and'ы с масками поменять соот-но.
В целом, насчёт ускорения в 5-10 раз Sha всё-таки загнул. Не может такого быть за счёт отказа от вызова одной (несложной) функции и причёсывания всяких мелочей. Скорее уж проценты, а не разы.
При шаге 4 байта получились разы, но это другое.
Вова (2013-07-01 13:31:00) [134]последним пикселем можно пренебречь и не обрабатывать его вообще.
Вова (2013-07-01 13:30:00) [135]
function LockConvertBmpToRGBColorMapM(ppixel: pAnsiChar;last:pAnsiChar): Boolean;
var
i : integer ;
begin
repeat;
i:=pInteger(ppixel)^;
pInteger(ppixel)^:=ColorMap[i shr 12 and $F0F or i and $F0];
inc(ppixel,4)
until ppixel=last;
Result := true;
end;
лол, а вот так 2 миллисекунды, ток все через черную полоску. и даж цвета похожи на те что я выводил
Sha (2013-06-30 22:40:00) [136]но в цикле [74] есть 2 ошибки
1. Затираем результатом то, что еще не обработали.
2. теоретически на последнем пикселе может быть AV из-за выхода за границу строки
Думай, как исправить
Sha (2013-06-30 22:36:00) [137]> а на что влияет and $FFFFFF
Оно отрезает старший байт прочитанного из памяти целого i, т.к. нужный нам триплет лежит в младших байтах. Без него все также работает только потому, что при вычислении индекса в таблице старший байт не участвует: [i shr 12 and $F0F or i and $F0].
//цикл по строке
repeat;
i:=pInteger(p)^;
pInteger(p)^:=ColorMap[i shr 12 and $F0F or i and $F0];
inc(p,3)
until p<last;
Вова (2013-06-30 20:50:00) [138]да в массив наверное быстрее даж 10 будет, но в перевернутый (
Вова (2013-06-30 20:46:00) [139]
function LockConvertBmpToRGBColorMapM(ppixel: pAnsiChar;Count:integer): Boolean;
var
//pixel: integer;
pp : pInteger;
begin
repeat
pp := pInteger(ppixel);
//pixel:=pInteger(ppixel)^ and $FFFFFF;
pp^ := ColorMap[pp^ shr 12 and $F0F or pp^ and $F0];
inc(ppixel,3);
dec(Count);
until Count <1;
Result := true;
end;
капитально ничего лишнего 16 миллисекунд. непонятные цвета. а на что влияет and $FFFFFF... я че то не понял вроде без него все также.
Вова (2013-06-30 20:08:00) [140]по моему купиксели выигрывают битву )) если конечно из за 3 миллисекунд не переделывать все на перевернутый массив )