Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Оптимизация кода


Страницы:   1 2 3 4 5 6 7 8 9 10 11

Вова ©   (2013-06-25 20:17:00) 

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


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-08-23 02:58:00) [41]

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

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


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

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


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


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:00) [44]

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


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

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

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

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


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

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


Sapersky   (2013-08-23 02:23:00) [47]

Ну мне не сразу стало очевидно, пришлось вчитаться в [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.


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

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

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


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

С битами всё объяснено в [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 01:47:00) [50]

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


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


 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:13:00) [52]


> и ниодной нормальной инструкции с картинками

))))


Вова   (2013-08-23 00:57:00) [53]


> Проще всего как раз в этом месте поменять red и blue, чтобы
> не ковырять биты заново. И ещё  i:= Start^ shr 8, чтобы
> привести BGRA к BGR.


не ( не помогает, еще больше цвета путаются.

ненавижу тех кто придумал вот эту хренотень с битмапами и всем вывернутым на изнанку ( и ниодной нормальной инструкции с картинками.


Sapersky   (2013-08-23 00:50:00) [54]

Проще всего как раз в этом месте поменять red и blue, чтобы не ковырять биты заново. И ещё  i:= Start^ shr 8, чтобы привести BGRA к BGR.


Вова   (2013-08-23 00:34:00) [55]

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


блин, а это теперь тогда тоже не правильно? чот как не крутил все равно лажа (


Вова   (2013-08-23 00:18:00) [56]

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


да (

проблемма в том, что я так и не понял что все это значит(i shr 12 and $F0F or i and $F0). Вообщем первую проблему то я решил.....но, при таком преобразовании, результат вовсе не такой как был раньше (

вместо желтого красный ну и т.д ( как поменять?


Sapersky   (2013-08-23 00:10:00) [57]

[78]:

> Проблемы с цветами видимо из-за того, что порядок цветовых
> компонент изменился, раньше было RGB, сейчас BGR. Нужно
> сдвиги и and'ы с масками поменять соот-но.

Точнее BGRA, раз это 32 бита.


Вова   (2013-08-22 23:43:00) [58]

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

function ConvertBmpToRGBColorMapM(tbmp:TBitmap; var M: TMass;
 Mass: TColorMapByte): Boolean;
var
Pixel1,i,x,y:Integer;
Start,Stop:pInteger;
QP: TQuickPixels;
begin

//    Start := tbmp.ScanLine[tbmp.Height - 1];
//    Stop  := tbmp.ScanLine[0];
//    Pixel1:= 0;
//    repeat
//      i:= Start^;
//      M.Mass[Pixel1] := i;
//      //Mass[i shr 12 and $F0F or i and $F0];
//      inc(Start);
//      inc(Pixel1);
//    until Start = Stop;

QP := TQuickPixels.Create;
 QP.Attach(tbmp);

 for y := 0 to QP.Height - 1 do
 begin
   for x := 0 to QP.Width - 1 do
   begin
     Pixel1 := QP.GetPixels32(x, y);
     M.Mass[x + y * M.Xsize] := Pixel1;
     //Mass[Pixel1 shr 12 and $F0F or Pixel1 and $F0];
   end;
 end;
 Result := true;
   QP.Free;

 Result := true;
end;


DevilDevil   (2013-07-29 21:00:00) [59]

> Вова   (29.07.13 20:31) [151]

дак ты покажи рабочий вариант )

p.s.
и рассчёт индекса в табличке выглядит как-то странно


Вова   (2013-07-29 20:31:00) [60]

как то так было:

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 миллисекунды, ток все через черную полоску.
>   и даж цвета похожи на те что я выводил


только я ему картинку неправильную давал


Страницы:   1 2 3 4 5 6 7 8 9 10 11

Наверх

Титульная страница Поиск, карта сайта Написать письмо