Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2014.07.06;
Скачать: [xml.tar.bz2];

Вниз

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

 
Вова   (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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.84 MB
Время: 0.018 c
15-1387398603
Юрий
2013-12-19 00:30
2014.07.06
С днем рождения ! 19 декабря 2013 четверг


15-1387202271
Token
2013-12-16 17:57
2014.07.06
XE3 Как добавить форму в репозиторий?


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


15-1387088458
SKIPtr
2013-12-15 10:20
2014.07.06
как переслать письмо из рамблера


15-1387139402
Юрий
2013-12-16 00:30
2014.07.06
С днем рождения ! 16 декабря 2013 понедельник





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский