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

Вниз

Обратная функцыя к RGB() существует?   Найти похожие ветки 

 
lubass ©   (2007-10-22 20:25) [0]

Как мне достать значения цветов (красного, зеленого и синего) из цвета?


 
homm ©   (2007-10-22 20:32) [1]

var
 r,g,b: byte;
 color: TColor;
begin
 r := byte(color);
 g := byte(color shr 8);
 b := byte(color shr 16);
end;


 
Pa5ha ©   (2007-10-22 20:32) [2]

function GetRValue(color: tcolor): byte;
и т.д.


 
lubass ©   (2007-10-22 20:38) [3]

Спосибо


 
antonn ©   (2007-10-22 20:40) [4]

дежавю? :)


 
rts111 ©   (2007-10-22 23:21) [5]

type

TColor4b = record
 r,g,b,a :byte;

...

var
color: TColor;
r: byte;
...

begin

...
r := TColor4b (color).r;
...

end;


 
@!!ex ©   (2007-10-23 11:40) [6]

> [3] lubass ©   (22.10.07 20:38)

варианты [1] и [2] - идеентичны. Но я бы предпочел первый, поскольку нет лишнего вызова процедур.


 
rts111 ©   (2007-10-23 12:37) [7]


> @!!ex ©   (23.10.07 11:40) [6]


А чем тебе мой вариант не нравится, там бообще обращение напрямую к значению без shr.

Правка:
TColor4b = record
r,g,b,a :byte;
end;


 
antonn ©   (2007-10-23 13:42) [8]


> А чем тебе мой вариант не нравится, там бообще обращение
> напрямую к значению без shr.

без shr написано, или без shr откомпилируется?


 
rts111 ©   (2007-10-23 14:35) [9]


> antonn ©   (23.10.07 13:42) [8]
>
> > А чем тебе мой вариант не нравится, там бообще обращение
>
> > напрямую к значению без shr.
>
> без shr написано, или без shr откомпилируется?


Именно без shr откомпилируется.


 
@!!ex ©   (2007-10-23 18:03) [10]

> [7] rts111 ©   (23.10.07 12:37)

Ну хотя бы потому, что придется приведение типов использовать при переходе TColor<->TColor4b.
а так... конечно лучший вариант. С ним лично я и работаю. Только не с WinAPI, а с OpenGL, там так удобнее.


 
homm ©   (2007-10-23 19:19) [11]

> [7] rts111 ©   (23.10.07 12:37)
> А чем тебе мой вариант не нравится, там бообще обращение
> напрямую к значению без shr.

procedure SwapChanels(BMP: TBitmap);
type
  ADWORD = array [0..0] of DWORD;
var
  i, j: Integer;
  Pix: DWORD;
  Line: ^ADWORD;
begin
  for i := 0 to BMP.Height-1 do begin
    Line := BMP.ScanLine[i];
    for j := 0 to BMP.Width-1 do begin
      Pix := Line[j];
      //Line[j] := GetBValue(Pix) + (GetGValue(Pix) shl 8) + (GetRValue(Pix) shl 16);    // 1200 mSec
      //Line[j] := byte(Pix shr 16) + (byte(Pix shr 8) shl 8) + (byte(Pix) shl 16);    // 300 mSec
      //Line[j] :=  TRGBQuad(Pix).rgbRed + (TRGBQuad(Pix).rgbGreen shl 8) + (TRGBQuad(Pix).rgbBlue shl 16);  //650 mSec
      TRGBQuad(Line[j]).rgbBlue := TRGBQuad(Pix).rgbRed;        // 610 mSec
      TRGBQuad(Line[j]).rgbGreen := TRGBQuad(Pix).rgbGreen;
      TRGBQuad(Line[j]).rgbRed := TRGBQuad(Pix).rgbBlue;
    end;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
type
  ADWORD = array [0..0] of DWORD;
var
  i, T: Integer;
begin
  Image1.Picture.Bitmap := TBitmap.Create;
  Image1.Picture.Bitmap.LoadFromFile("C:\1.bmp");
  Image1.Picture.Bitmap.PixelFormat := pf32bit;

  T := GetTickCount;
  for i := 0 to 98 do
    SwapChanels(Image1.Picture.Bitmap);
  ShowMessage(IntToStr(GetTickCount-T));

end;


 
rts111 ©   (2007-10-23 23:24) [12]


> homm ©   (23.10.07 19:19) [11]


procedure SwapChanels(BMP: TBitmap);
type
 ADWORD = array [0..0] of DWORD;
var
 i, j: Integer;
 //Pix: DWORD;
 Line: ^ADWORD;
 Temp: byte;
begin
 for i := 0 to BMP.Height-1 do
 begin
   Line := BMP.ScanLine[i];
   for j := 0 to BMP.Width-1 do
   with TRGBQuad(Line[j]) do
   begin
    Temp    := rgbRed;             // 1 mSec!!!  :)
    rgbRed  := rgbBlue;
    rgbBlue := Temp;
   end;
 end;
end;


 
Pa5ha ©   (2007-10-24 01:32) [13]

операции битового сдвига выполняюца за один такт процессора и этим все сказано.


 
homm ©   (2007-10-24 05:52) [14]

> [12] rts111 ©   (23.10.07 23:24)


В таком варианте действительно пошустрее работает.

procedure SwapChanels(BMP: TBitmap);
type
  ADWORD = array [0..0] of DWORD;
var
  i, j: Integer;
  Pix: DWORD;
  Line: ^ADWORD;
  Temp: byte;
begin
  for i := 0 to BMP.Height-1 do begin
    Line := BMP.ScanLine[i];
    for j := 0 to BMP.Width-1 do begin
      Pix := Line[j];
      //Line[j] := GetBValue(Pix) + (GetGValue(Pix) shl 8) + (GetRValue(Pix) shl 16);    // 1200 mSec
      //Line[j] := byte(Pix shr 16) + (byte(Pix shr 8) shl 8) + (byte(Pix) shl 16);    // 300 mSec
      //Line[j] :=  TRGBQuad(Pix).rgbRed + (TRGBQuad(Pix).rgbGreen shl 8) + (TRGBQuad(Pix).rgbBlue shl 16);  //650 mSec
      {TRGBQuad(Line[j]).rgbBlue := TRGBQuad(Pix).rgbRed;        // 610 mSec
      TRGBQuad(Line[j]).rgbGreen := TRGBQuad(Pix).rgbGreen;
      TRGBQuad(Line[j]).rgbRed := TRGBQuad(Pix).rgbBlue;}
      with TRGBQuad(Line[j]) do begin    // 300 mSec
        Temp    := rgbRed;
        rgbRed  := rgbBlue;
        rgbBlue := Temp;
        rgbGreen  := rgbGreen;
      end;
    end;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
type
  ADWORD = array [0..0] of DWORD;
var
  i, T: Integer;
begin
  Image1.Picture.Bitmap := TBitmap.Create;
  Image1.Picture.Bitmap.LoadFromFile("C:\1.bmp");
  Image1.Picture.Bitmap.PixelFormat := pf32bit;

  T := GetTickCount;
  for i := 0 to 99 do
    SwapChanels(Image1.Picture.Bitmap);
  ShowMessage(IntToStr(GetTickCount-T));

end;


Но твоего юмора насчет одной миллисекундны я не вкурил.


 
rts111 ©   (2007-10-24 07:44) [15]


> homm ©   (24.10.07 05:52) [14]


А зачем ты  rgbGreen := rgbGreen;


 
rts111 ©   (2007-10-24 07:53) [16]


> Но твоего юмора насчет одной миллисекундны я не вкурил.


Да, глупо. Так я хотел сказать что такой способ быстрее.


 
homm ©   (2007-10-24 11:28) [17]

> [15] rts111 ©   (24.10.07 07:44)
> А зачем ты  rgbGreen := rgbGreen;

А за тем, что-бы убрать оптимизацию алгоритма под задачу, и абстрагироватся от задачи как можно больше.
В принципе можешь и так написать:
       Temp    := rgbRed;
       rgbRed  := rgbGreen;
       rgbGreen := rgbBlue;
       rgbBlue  := Temp;


Но я думаю это еше более замедлит твой вариант.


 
rts111 ©   (2007-10-24 11:57) [18]


> homm ©   (24.10.07 11:28) [17]



> Но я думаю это еше более замедлит твой вариант.


Я не понял, при чем тут ЕЩЕ БОЛЬШЕ замедлит, ведь мой вариант быстрее?
Или у тебя на ПК не быстрее?


 
rts111 ©   (2007-10-24 12:00) [19]


> homm ©   (24.10.07 11:28) [17]


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


 
homm ©   (2007-10-24 12:09) [20]

> [18] rts111 ©   (24.10.07 11:57)
> Я не понял, при чем тут ЕЩЕ БОЛЬШЕ замедлит, ведь мой вариант
> быстрее?

Твой вариант на моей машине на моем тестовом примере, который прогоняется ровно 100 раз отрабатывает за 300 mSec, как и мой вариант с shr и shl.


> [19] rts111 ©   (24.10.07 12:00)
> А от задачи, никак невозможно абстрагироваться.
Согласен, но то, что в [12] на трогается один из каналов — явное читерство :)


 
rts111 ©   (2007-10-24 13:48) [21]


> Твой вариант на моей машине на моем тестовом примере, который
> прогоняется ровно 100 раз отрабатывает за 300 mSec, как
> и мой вариант с shr и shl.


А ты  ( //Pix := Line[j]; ) не забыл закоментировать? Там ведь эта операция лишняя. Хотя, по идее компилятор сам должен игнорировать.


> Согласен, но то, что в [12] на трогается один из каналов
> — явное читерство :)


:)
Да уж читерство, но ведь функция то делает именно то что нужно.
Вот пример, как обещал:


var
TestColor :TColor  =$01010101;
TestSum   :integer =0;

procedure Test1;
var
i :integer;
begin
for i := 0 to 1000 do
begin
 TestSum := TestSum + TRGBQuad(TestColor).rgbRed + TRGBQuad(TestColor).rgbGreen + TRGBQuad(TestColor).rgbBlue; // 703
 //TestSum := TestSum + byte(TestColor) + byte(TestColor shr 8) + byte(TestColor shr 16);    // 1318
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
i :Integer;
T :cardinal;
begin
T := GetTickCount;
for i := 0 to n do Test1;
Caption := IntToStr(GetTickCount-T);
end;


Тут уж не придраться, все один к одному.А можно придумать пример когда будут все наоборот.

Вовод такой: не стоит обобщать, и нужно писать для компилятора а не для себя, когда требуется скорость.


 
homm ©   (2007-10-24 14:01) [22]

> [21] rts111 ©   (24.10.07 13:48)
> А ты  ( //Pix := Line[j]; ) не забыл закоментировать?

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


> TestSum := TestSum + TRGBQuad(TestColor).rgbRed + TRGBQuad(TestColor)
> .rgbGreen + TRGBQuad(TestColor).rgbBlue; // 703
> //TestSum := TestSum + byte(TestColor) + byte(TestColor
> shr 8) + byte(TestColor shr 16);    // 1318

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


 
homm ©   (2007-10-24 14:07) [23]

Впрочем я не настаиваю, что вариант  shr (который кстати и не мной) быстрее, просто действительно нужно под задачу подбирать, а в данной задаче, и так ясно, что быстрее MMX :)


 
rts111 ©   (2007-10-25 01:56) [24]

Кстати, там можно тогда сказать что и с твоей стороны тоже читерство:
Зачем Pix то для "моего" ( который тоже не мой ) случая использовать?

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


procedure SwapChanels(BMP: TBitmap);
type
 ADWORD = array [0..0] of DWORD;
var
 i, j: Integer;
 Pix: DWORD;
 Line: ^ADWORD;
 Temp: byte;
begin
 for i := 0 to BMP.Height-1 do begin
   Line := BMP.ScanLine[i];
   for j := 0 to BMP.Width-1 do begin

    Pix := Line[j];
    //Line[j] := byte(Pix shr 16) + (byte(Pix shr 8) shl 8) + (byte(Pix) shl 16);

   with TRGBQuad(Line[j]) do Line[j]:=rgbBlue+(rgbGreen shl 8)+(rgbRed shl 16);

   end;
 end;
end;


 
homm ©   (2007-10-25 07:15) [25]

> [24] rts111 ©   (25.10.07 01:56)
> Смотри, код по структуре абсолютно аналогичный, и сравни
> результаты:

Идентично
with TRGBQuad(SL[j]) do begin    // 300 mSec
         Temp    := rgbRed;
         rgbRed  := rgbBlue;
         rgbBlue := Temp;
         rgbGreen  := rgbGreen;
       end;


Ладно, хватит игратся, теперь сравни с этим:
procedure SwapChanels(SourceBitmap: TBitmap);
type
 ARGBQuad = array [0..0] of DWORD;
 PARGBQuad = ^ARGBQuad;
 AByte = array [0..0] of Byte;
 PAByte = ^AByte;
const
 int62: int64 = $ff00ff00ff00ff00;
 int63: int64 = $000000ff000000ff;
var
 SL: PARGBQuad;
 //V1, V2: TRGBQuad;
 //R: ^TRGBQuad;
 i, j: Integer;
 A_1, A: Integer;
 Delta: DWORD;
 W, H: Integer;
 Temp: byte;
 Pix: DWORD;
begin
 SL := SourceBitmap.ScanLine[0];
 Delta := DWORD(SourceBitmap.ScanLine[1]) - DWORD(SourceBitmap.ScanLine[0]);
 W := SourceBitmap.Width shr 1;
 h := SourceBitmap.Height;
 if CPUisMMX then begin
   asm
     movq mm3, [int62]
     movq mm4, [int63]
     mov ecx, H
     push ecx
@@loop1:
       mov edx, [SL]
       mov ecx, W
@@loop2:
         movq mm0, [edx]
         movq mm1, mm0
         pslld mm0, 24
         movq mm2, mm1
         psrld mm1, 16
         psrld mm0, 8
         pand mm1, mm4
         por mm0, mm1
         pand mm2, mm3
         por mm0, mm2
         movq [edx], mm0
         add edx, 8
       dec ecx
       jnz @@loop2

       mov eax, [Delta]
       add [SL], eax
     dec dword ptr [esp]
     jnz @@loop1

     pop ecx
     emms

   end;
 end else begin
……
 end;
end;


У меня 190 мсек все на том-же тестовом примере. Единственный минус, размер изображения должен быть кратен 2-м, иначе последние пиксели в строке обрабатыватся не будут.


 
rts111 ©   (2007-10-25 12:42) [26]


> Ладно, хватит игратся, теперь сравни с этим:


Тогда уж так:


procedure SwapChanels(SourceBitmap: TBitmap);
type
ARGBQuad = array [0..0] of DWORD;
PARGBQuad = ^ARGBQuad;
AByte = array [0..0] of Byte;
PAByte = ^AByte;
const
int62: int64 = $ff00ff00ff00ff00;
int63: int64 = $000000ff000000ff;
var
SL: PARGBQuad;
//V1, V2: TRGBQuad;
//R: ^TRGBQuad;
i, j: Integer;
A_1, A: Integer;
Delta: DWORD;
W, H: Integer;
Temp: byte;
Pix: DWORD;
begin
SL := SourceBitmap.ScanLine[0];
Delta := DWORD(SourceBitmap.ScanLine[1]) - DWORD(SourceBitmap.ScanLine[0]);
W := SourceBitmap.Width shr 1;
h := SourceBitmap.Height;
if CPUisMMX then begin
  asm
    movq mm3, [int62]
    movq mm4, [int63]
    mov ecx, H
    push ecx
@@loop1:
      mov edx, [SL]
      mov ecx, W
@@loop2:

        {
        movq mm0, [edx]
        movq mm1, mm0
        pslld mm0, 24
        movq mm2, mm1
        psrld mm1, 16
        psrld mm0, 8
        pand mm1, mm4
        por mm0, mm1
        pand mm2, mm3
        por mm0, mm2
        movq [edx], mm0
        }

        movq   mm0, [edx]
        pshufw mm1, mm0, $b1
        pand   mm0, mm3
        por    mm0, mm1
        movq [edx], mm0

        add edx, 8
      dec ecx
      jnz @@loop2

      mov eax, [Delta]
      add [SL], eax
    dec dword ptr [esp]
    jnz @@loop1

    pop ecx
    emms

  end;
end else begin
……
end;
end;


 
rts111 ©   (2007-10-25 12:53) [27]

Т.е. вот так точнее будет:

...
const
//int62: int64 = $ff00ff00ff00ff00;
int62: int64 = $00ff00ff00ff00ff;
...
...
movq   mm0, [edx]
pshufw mm1, mm0, $b1
pand   mm1, mm3
por    mm0, mm1
movq [edx], mm0
...


 
rts111 ©   (2007-10-25 13:03) [28]

Вааа, ошибся!

Вот так правильно:

...
const
// int62: int64 = $ff00ff00ff00ff00;
// int63: int64 = $000000ff000000ff;
int62: int64 = $00ff00ff00ff00ff;
int63: int64 = $ff00ff00ff00ff00;
...
...
movq   mm0, [edx]
pshufw mm1, mm0, $b1
pand   mm1, mm3
pand   mm0, mm4
por    mm0, mm1
movq [edx], mm0
...


 
homm ©   (2007-10-25 19:32) [29]

> [28] rts111 ©   (25.10.07 13:03)

Только не падай, но код
         movq mm0, [edx]
         pshufw mm1, mm0, $E4
         pslld mm0, 24
         pshufw mm2, mm1, $E4
         psrld mm1, 16
         psrld mm0, 8
         pand mm1, mm4
         por mm0, mm1
         pand mm2, mm3
         por mm0, mm2
         movq [edx], mm0


работает на 2,5% быстрее, чем приведенный тобой. Сам в шоке.


 
homm ©   (2007-10-25 21:56) [30]

> [29] homm ©   (25.10.07 19:32)
> Только не падай, но код работает на 2,5% быстрее, чем приведенный тобой.

За то твой вариант можно оттюнинговать еше на 12% быстрее за счет одной хитрой команды в самом начале, чего лишен мой вариант…
PREFETCHT0 [edx+40]


 
rts111 ©   (2007-10-26 09:04) [31]

Вот вариант с одним циклом, и компактней и наглядней. ( и вроде быстрее )
К тому же, обычный код и код на asm не смешаны внутри одной функции,
а то кто его знает как там компилятор все перетусует:

procedure SwapChanels( BMP :TBitmap );

procedure ExchangeRB( Data :pointer; Count :integer );
const
 ii2 :int64 = $ff00ff00ff00ff00;
 ii3 :int64 = $00ff00ff00ff00ff;
asm
 movq mm2, [ii2]
 movq mm3, [ii3]
 mov  ecx, edx
 @@loop:

  movq   mm0, [eax]
  pshufw mm1, mm0, $b1
  pand   mm0, mm2
  pand   mm1, mm3
  por    mm0, mm1
  movq   [eax], mm0

 add eax, 8
 dec ecx
 jnz @@loop
 emms
end;

begin

with BMP do ExchangeRB( ScanLine[Height-1] , ( Width * Height ) shr 1 );

end;


А что ты QueryPerformanceCounter не юзаешь?
Результаты теста точнее ведь же будут.

procedure TForm1.Button1Click(Sender: TObject);
var
i     :Integer;
t1,t2 :int64;
begin

Image1.Picture.Bitmap := TBitmap.Create;
Image1.Picture.Bitmap.LoadFromFile("1.bmp");
Image1.Picture.Bitmap.PixelFormat := pf32bit;

QueryPerformanceCounter(t1);
for i:=0 to 100 do SwapChanels( Image1.Picture.Bitmap );
QueryPerformanceCounter(t2);

caption := IntToStr(t2-t1);
beep;

end;



Страницы: 1 вся ветка

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

Наверх




Память: 0.57 MB
Время: 0.087 c
15-1341492118
Unknown user
2012-07-05 16:41
2013.03.22
Определить или открыто главное меню


15-1349469003
Юрий
2012-10-06 00:30
2013.03.22
С днем рождения ! 6 октября 2012 суббота


15-1344857976
БарЛог
2012-08-13 15:39
2013.03.22
А как такая программа будет называться?


15-1328599963
igorserg
2012-02-07 11:32
2013.03.22
XMLDocument - косяк при изменении порядка следования тегов.


15-1345197008
Painner777
2012-08-17 13:50
2013.03.22
Рисование, обводка в фотошопе?