Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2014.07.06;
Скачать: CL | DM;

Вниз

Оптимизация кода   Найти похожие ветки 

 
Вова   (2013-08-23 01:21) [160]


 TRGB = record
  case integer of
  1: (RGB: LongInt);
  2: (B, G, R, O: BYTE);

var
 rRGB:TRGB;

 rrgb.RGB := ColorToRGB(color);
 RGBV.red := rrgb.B;
 RGBV.green := rrgb.G;
 RGBV.blue := rrgb.R;

CODE</>


 RGBV.red   := color;
 RGBV.green := color shr 8;
 RGBV.blue := color shr 16;


оба варианта дают одинаковый результат. (второй старый на 24 бита был). то что было раньше желтым теперь красное, и появился голубой....откуда блин голубой, у меня в массиве его вообще нет.

Function ConvertColorToRGBColorMap(color: LongInt; ColSel: string = "None")
 : TColorWithName;
var
 RGBV: trgbcolor;
 bg: Boolean;
 rb: Boolean;
 rg: Boolean;
 rRGB:TRGB;
begin

//  rrgb.RGB := ColorToRGB(color);
//  RGBV.red := rrgb.B;
//  RGBV.green := rrgb.G;
//  RGBV.blue := rrgb.R;

 RGBV.red   := color;
 RGBV.green := color shr 8;
 RGBV.blue := color shr 16;

 rb := almostEqual(RGBV.red, RGBV.blue);
 bg := almostEqual(RGBV.blue, RGBV.green);
 rg := almostEqual(RGBV.red, RGBV.green);

 with RGBV do

   if rg and rb and bg then // тогда это серый или черный или белый
   begin
     if red > 230 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 bg 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 rb and (red > 130) then
     begin
       result.color := RGB(255, 0, 255);
       result.Name := "Pink";
     end // розовый
     else if (blue < green) and (blue < red) and rg 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 (ColSel = result.Name) then
   begin
     result.color := 255; // картинка инвертирована для дальнейшей обработки
   end
   else
   begin
     result.color := 0;
   end;
end;

Procedure InitColorMap();
var
 i, j, k: byte;
begin
 for i := 0 to 15 do
   for j := 0 to 15 do
     for k := 0 to 15 do
       ColorMap[i * 256 + 16 * k + j] := ConvertColorToRGBColorMap
         ((i * 256 * 256 + j * 256 + k) * 16).color;
 // for i:=0 to 15 do for j:=0 to 15 do for k:=0 to 15 do ColorMap[i*256+16*k+j]:=ConvertColorToRGBColorMap((i*16+15)*256*256+(j*16+15)*256+(k*16+15));
end;

Function ConvertBmpToRGBColorMap(var tBmp: Tbitmap;
 ColSel: String = "None"): Boolean;
var
 QP: TQuickPixels;
 Pixel1: Cardinal;
 x: integer;
 y: integer;
 i: integer;
 numCol: byte;
 Start,Stop:pInteger;
begin

 if (tBmp.Height > 2) and (tBmp.Width >= 1) then
 begin
 
   numCol := TextColorToDigit(ColSel);

   if numCol = 0 then
   begin

     Start := tBmp.ScanLine[tBmp.Height - 1];
     Stop := tBmp.ScanLine[0];

     repeat
       i:= Start^;
       Start^ := ColorMap[i shr 12 and $F0F or i and $F0];
       inc(Start);
       inc(Pixel1);
     until Start = Stop;
   end;
   

   Result := true;
 end
 else
   Result := false;

end;



 
Вова   (2013-08-23 01:47) [161]

RGB(255, 255, 255);дело в этой функции...


 
Sapersky   (2013-08-23 01:49) [162]

С битами всё объяснено в [119], только мне кажется лучше обозвать стандартными "цветными" буквами:
$00aabbcc -> $00000acb
$00RrGgBb -> $00000RBG
внезапно RBG, а не RGB. На этом можно сэкономить, B не двигать, R и G обрабатывать вместе.
Сейчас у нас (с учётом доп. сдвига i := Start^ shr 8):
$00BbGgRr -> $00000BRG
вроде ж всё очевидно: пара B_G двигается на 3 символа вправо (байт - два символа, сдвиг на полтора байта = shr 12), and $F0F отрезает всё лишнее. R никуда не двигается, просто отрезается лишнее маской $F0.
В результате имеем то самое шаманское заклинание.
А цвета в таблицу нужно подставлять в порядке BRG, получается.
Мог бы и сам понять, если бы внимательно читал, что тебе пишут...


 
Вова   (2013-08-23 02:02) [163]

здорово что хоть кому то все очевидно...

т.к. мне и теперь стало еще непонятней чем было.


 
Sapersky   (2013-08-23 02:23) [164]

Ну мне не сразу стало очевидно, пришлось вчитаться в [119].
Sha тоже хорош - изменил порядок цветов и упомянул об этом практически вскользь, я сначала подумал что acb это опечатка.

Делаем нормальный порядок цветов, хотя и менее оптимально:
$BbGgRr00 -> $00000RGB
R на 1 вправо, 4 бита.
G на 4 вправо, 16 бит.
B на 7 вправо, 28 бит.
i := Start^;
Start^ := ColorMap[(i shr 1 and $F) or (i shr 4 and $F) or (i shr 28)];
7 операций вместо 5.


 
Sapersky   (2013-08-23 02:25) [165]

Всё-таки запутался в этих битах:
Start^ := ColorMap[(i shr 4 and $F) or (i shr 16 and $F) or (i shr 28)];


 
Вова   (2013-08-23 02:34) [166]

ша тут нипричем, массив можно выкинуть вообще, и это ничего не изменит.

Start^ := ConvertColorToRGBColorMap(Start^).color;

т.е. вот такой код дает точно такой же результат. но... это значение вернула функция RGB(255,255,0); причем у меня там нет ниодной функции, которая генерит голубой цвет...а в итоговом бмп он есть...т.е. если даже допустить, что входной цвет у меня какой то неправильный, то выходной то как становится голубым? вот в чем вопрос )


 
Вова   (2013-08-23 02:41) [167]


function RGB(r, g, b: Byte): COLORREF;
begin
 Result := (r or (g shl 8) or (b shl 16));
end;


во т.е. я так понимаю она как раз делает BGR? но в Start^ 4 байта, и куда прилепляется 4й?


 
Sapersky   (2013-08-23 02:41) [168]

По поводу варианта с ColorToRGB - посмотрел бы, что она делает, Ctrl-клик и все дела.
В общем, не нужна она тут, rrgb.RGB := color должно работать.
Вариант со сдвигами - ещё в [21] писали, что нужно отрезать нужные байты масками.


 
Вова   (2013-08-23 02:48) [169]

function ColorToRGB(Color: TColor): Longint;
begin
 if Color < 0 then
   Result := GetSysColor(Color and $000000FF) else
   Result := Color;
end;


 
Вова   (2013-08-23 02:58) [170]

function RGB2(r, g, b: Byte): COLORREF;
begin
 Result := (b or (g shl 8) or (r shl 16));
end;

методом научного тыка я выяснил, что теперь каналы как раз RGB  и идут, а были BGR, а вот где альфа канал я так и не понял...


 
Вова   (2013-08-23 03:05) [171]

твою машу, короче мозг сломаешь

 RGBV.red   := color shr 16;;
 RGBV.green := color shr 8;
 RGBV.blue  := color;

входной так, выходной как в 170, вроде цвета на место встали и я запутался окончательно )


 
Вова   (2013-08-23 08:44) [172]

мда уж, хоть с цветами все и решилось.
Но ночь плясок с бубном вокруг разворачивания изображения в разные стороны, отражения координат и т.д. и т.п. успехом не увенчались...

координата 0.0 картинки вовсе не тут Start := tBmp.ScanLine[tBmp.Height - 1];

и не тут!!! Stop := tBmp.ScanLine[0]; она вот тут: dec(Stop,tBmp.Width)


 
Sha ©   (2013-08-23 10:21) [173]

> Sha тоже хорош - изменил порядок цветов...

Так я вроде сказал, там выше, что это некий условный номер цвета )

Если особо не вдаваться в детали и не пытаться в этом номере
увидеть нечто большее, то все будет работать, как надо.
Ведь и при записи, и при чтении данных из таблицы мы
для одинаковых цветов будем вычислять одинаковый номер.
Поэтому абсолютно без разницы где там данные лежат в таблице


 
Sha ©   (2013-08-23 10:40) [174]

Таблица используется просто как кеш для запоминания результата функции.
Именно поэтому ей совершенно безразличен порядок цветов: RGB, BGR или
как еще. Альфа не кешируется.


 
Sapersky   (2013-08-23 16:12) [175]

Поправки к [162] и [164]:
Я забыл, что при чтении как Integer порядок байт разворачивается, т.е. в памяти BGRA, в Integer ARGB.
Шаманское преобразование для 32-х бит будет $AaRrGgBb -> $RBG. И это таки влияет на порядок индексов при просчёте таблицы:
ColorMap[r * 256 + b * 16 + g] := ...
Для RGB:
ColorMap[r * 256 + g * 16 + b] := ...
Start^ := ColorMap[(i shr 12 and $F00) or (i shr 8 and $F0) or (i shr 4 and $F)];


 
проф. Преображенский   (2013-08-23 17:04) [176]

Я "нет" говорю вместо "да",
Сажусь туда, где недавно был стул,
Я ложку несу мимо рта,
И просыпаюсь не там где уснул.


 
проф. Преображенский   (2013-08-23 18:37) [177]

Я вижу суть вещей отныне,
Я слышу голос неземной,
А то, что сотворю в пустыне,
Узрят пришедшие за мной.


 
Sha ©   (2013-08-24 08:52) [178]

Предусмотреть все невозможно.
Успех меня опять не уберег.
Ну, нафига мне в руки вложен
Судьбой тот самый молоток?


 
Вова   (2013-08-24 11:37) [179]

ощем, хз как разворачивать цикл. И акромя того, я таки стал разворачивать картинки в нормальное состояние (при переходе от бмп к массивам). Т.к. все расчитано на то, что картинка начинает обрабатывацо с левого верхнего угла, иначе если шаблон не на 100%  накладываецо то всему писец. Да и полный размер программы в памяти ужо 100 мб, причем 2.8 экзешник и 97 база данных и картинки)) так что надо чо то с этим делать и битмапы нафиг слать.


 
Вова   (2013-08-24 11:56) [180]

а вообще вопрос, целесообразно ли переходить от битмапа на одномерный массив. Особенно учитывая, что информация в битмапе явно избыточная, все что мне нужно помещается в 1 байте на пиксель, но очень важна скорость обработки. И еще есть ли смысл с обычным массивом работать через указатели( с точки зрения быстродействия)?


 
Sha ©   (2013-08-24 12:25) [181]

> все что мне нужно помещается в 1 байте на пиксель

и зачем тогда весь огород? столько времени строили...

> И еще есть ли смысл с обычным массивом работать через указатели
> ( с точки зрения быстродействия)?

небольшой дополнительный прирост можно получить,
но сначала алгоритм продумай и перейди на 1 байт, это даст гораздо больше


 
Вова   (2013-08-24 12:53) [182]

как зачем, начинается то все со скриншота, но после обработки от него остается 1 байт на пиксель ) Хотя даже не байт, а бит ) т.е. после фильтрации все что мне нужно знать, есть в таком то месте пиксель или нет.


 
Вова   (2013-08-24 12:55) [183]

а то что мы делали и была фильтрация и взятие скриншота, ну взятие скриншота потом переродилось в более редкое взятие скриншота в отдельном потоке и быстрое копирование его кусков в разные места )


 
Вова   (2013-08-24 13:06) [184]

на байт я уже перешел давно, правда в процессе этого топика я усомнился, что так быстрее, наблюдая за тем как быстро обрабатывается битмап.

Т.е. базовый вариант, это берется кусок скрина и переводится в градацию серого в этот момент я переношу кусок битмапа в одномерный массив of Byte, после доп обработки, я переношу во второй массив точно такой же, но в нем у меня во всех точках либо 255 либо 0, т.е. по сути уже биты....

Вот кажется мне, что быстрее прям в битмапе переводить в серый, его обрабатывать и только потом переносить в массив с байтами....или с битами?


 
Sapersky   (2013-08-24 13:16) [185]

Раз уж ты начинаешь задумываться об альтернативах TBitmap, предложу TFastDIB, там работа с 8-битными картинками достаточно удобна:
http://sourceforge.net/projects/tfastdib/files/Library/FastDIB%204.0/FastDIB%204.0.zip/download
Чтобы получить начало в левом верхнем углу, как я уже говорил, нужно задать отрицательную высоту.

1 бит на пиксель - не нужно, неудобно обрабатывать.


 
Sha ©   (2013-08-24 13:52) [186]

> Вова   (24.08.13 13:06) [184]

Просто нет слов...

И что должно получиться в итоге?


 
Вова   (2013-08-24 16:00) [187]

1) screenshot -> GrayScale -> Monochrome -> Search
2) screenshot -> Monochrome -> Search Это вариант который мы тут мучали, ничего не пропало зря. Просто мы преобразовывали битмап и в него же складывали результат, а на боевой результат копируется в массив байтов. хотя кажется мне что вот этим самым копированием замедляется работа (


 
Вова   (2013-08-24 16:05) [188]

короче, просто взять битмап и отрезать от него нужный байт  это не варинт ) так что не пойму, чего ты разволновался то )


 
ProgRAMmer Dimonych ©   (2013-08-24 16:09) [189]

> хотя кажется мне что вот этим самым копированием замедляется
> работа (

«Кажется» — это для астрологов и прочих экстрасенсов. У нас все копирования меряются и сравниваются с остальными операциями, выбирается самая медленная и оптимизируется. Процесс повторяется до получения приемлемого результата: при обработке больших массивов данных — до тех пор, пока не получится обрабатывать со скоростью, достаточной, чтобы данные не накапливались, при написании GUI-приложения — до тех пор, пока пользователь не перестанет замечать задержку во времени (кажется, около 100 мс — минимум, который можно ощутить).


 
Вова   (2013-08-24 16:38) [190]

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


 
Вова   (2013-08-24 16:40) [191]

*т.е. для неперевернутого....ну вообщем для такого как в битмапе ))


 
Вова   (2013-08-24 17:39) [192]

ощема, вот так вот 4 миллисекунды, вместо 2х когда конвертишь сам битмап. В указателях слаб, поэтому невкурил как вместо m:TArrInt указатель на него передать и указателем по массиву бежать, так что ввел num (
Procedure Convert(Start,Stop:pInteger;Width:integer;m:TArrInt;Mass: TColorMapByte);
var
 count,i,num:Integer;
begin
 count := Width;
 num   := 0;
 repeat
   repeat
   i := Start^;
   m[num] := Mass[i shr 12 and $F0F or i and $F0];
   inc(Start);
   inc(num);
   dec(count);
   until count = 0;
   count := Width;
   dec(Start,Width*2);
 until Start = Stop;
end;

function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
 Mass: TColorMapByte): Boolean;
var
 Start, Stop: pInteger;
begin
 //tbmp.SaveToFile("C:\yui.bmp");
 Start := tBmp.ScanLine[0];
 dec(Start,tBmp.Width);
 Stop  := tBmp.ScanLine[tBmp.Height - 1];
 inc(Stop,tBmp.Width);
 Convert(Start,Stop,tBmp.Width,M.Mass,Mass);
 Result := true;
end;


 
Sha ©   (2013-08-24 17:41) [193]

> Вова   (24.08.13 16:00) [187], [188]

1. правильная работа массивом 1-байтных элементов будет заметно быстрее
2. все можно сделать за один проход
3. перевороты изображения - очевидный бред
4. рассуждения про скорость позиционирования - самоуспокаивающий бред
5. то, что ты не умеешь - не аргумент, учись


 
Вова   (2013-08-24 17:53) [194]

1) однобайтный массив еще нужно получить в коде вверху я это и делаю.
2) несомневаюсь, но как перевернуть картинку в 1 проход я не знаю, и я не могу сделать то чего не знаю как сделать )
3) может и бред, но у меня не хватает воображения чтобы потом с отзеркаленым изображением работать (даже если его по вертикали развернуть легко, но еще нужно по x отразить).  тем более что поиск должен идти сверху вниз и слева направо, т.е. если не перевернуть его тут, то потом при поиске все равно нужно извращаться. Что у меня и не получилось )
4) оке, за счет чего тогда в 2 раз медленней? без разворота будет 3-3.5 миллисекунды
5) все стоит времени и не всегда результат окупает затраты. Может и научусь, так ведь никто ж не ценит твоего времени и не показывает как. 20 минут гугла ничему мну не научили )


 
Sha ©   (2013-08-24 18:49) [195]

> оке, за счет чего тогда в 2 раз медленней?

за счет чего угодно, если интересно, приведи здесь оба кода, посмотрим


 
Вова   (2013-08-24 19:29) [196]


Procedure Convert(Start,Stop:pInteger;Width:integer;m:pByte;Mass: TColorMapByte);
var
 count,i:Integer;
begin
 count := Width;
 repeat
   repeat
   i := Start^;
   m^ := Mass[i shr 12 and $F0F or i and $F0];
   inc(Start);
   inc(m);
   dec(count);
   until count = 0;
   count := Width;
   dec(Start,Width*2);
 until Start = Stop;
end;

function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
 Mass: TColorMapByte): Boolean;
var
 Start, Stop: pInteger;
begin
 //tbmp.SaveToFile("C:\yui.bmp");
 Start := tBmp.ScanLine[0];
 dec(Start,tBmp.Width);
 Stop  := tBmp.ScanLine[tBmp.Height - 1];
 inc(Stop,tBmp.Width);
 Convert(Start,Stop,tBmp.Width,@M.Mass[0],Mass);
 Result := true;
end;


я вкурил как указатель на массив передать, 3 миллисекунды, вместо 4.


 
Вова   (2013-08-24 19:36) [197]

хе хе, попробовал второй массив через указатель, получилось на пол милисекунды медленней.

 m^ := (Mass + (i shr 12 and $F0F or i and $F0))^;


 
Вова   (2013-08-24 19:39) [198]

а нет....это не из за этого...


 
Вова   (2013-08-24 19:43) [199]

ощем нет смысла бороться из за одной миллисекунды, т.к. тут еще и загруженность компа влияет и содержимое скриншота... так что это просто погрешность )


 
Sha ©   (2013-08-24 19:51) [200]

> ведь никто ж не ценит твоего времени и не показывает как

Пример чтения четырех пикселей за три операции в приведен [81].
Там же показано, как развернуть цикл и сэкономить на проверках.
В [12] и [119] разжевано кеширование результата функции.
По ходу обсуждения немного разобраны битовые операции.
В [193] в 100й раз повторено, что *ВСЯ* твоя задача решается
за один проход без предварительного копирования, переворотов и т.п.

Но это мало помогает, никто ж не ценит твоего времени, и не решает за тебя.
Имеет смысл учить только тех, кто хочет учиться.



Страницы: 1 2 3 4 5 6 вся ветка

Текущий архив: 2014.07.06;
Скачать: CL | DM;

Наверх




Память: 0.85 MB
Время: 0.019 c
15-1387177349
Scott Storch
2013-12-16 11:02
2014.07.06
Снова о devexpress


2-1378443004
shura
2013-09-06 08:50
2014.07.06
Перевести char


2-1378276409
Сергей
2013-09-04 10:33
2014.07.06
EXE из HTML


2-1378324069
sas9568635
2013-09-04 23:47
2014.07.06
Вызов процедуры после выполнения таймера


2-1378437422
Den
2013-09-06 07:17
2014.07.06
Вызвать webbrowser.onDocumentComplete из timer?