Конференция "Игры" » Обратная функцыя к RGB() существует? [Delphi, Windows]
 
  • homm © (24.10.07 12:09) [20]
    > [18] rts111 ©   (24.10.07 11:57)
    > Я не понял, при чем тут ЕЩЕ БОЛЬШЕ замедлит, ведь мой вариант
    > быстрее?

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


    > [19] rts111 ©   (24.10.07 12:00)
    > А от задачи, никак невозможно абстрагироваться.
    Согласен, но то, что в [12] на трогается один из каналов — явное читерство :)
  • rts111 © (24.10.07 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 © (24.10.07 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 © (24.10.07 14:07) [23]
    Впрочем я не настаиваю, что вариант  shr (который кстати и не мной) быстрее, просто действительно нужно под задачу подбирать, а в данной задаче, и так ясно, что быстрее MMX :)
  • rts111 © (25.10.07 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 © (25.10.07 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 © (25.10.07 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 © (25.10.07 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 © (25.10.07 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 © (25.10.07 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 © (25.10.07 21:56) [30]
    > [29] homm ©   (25.10.07 19:32)
    > Только не падай, но код работает на 2,5% быстрее, чем приведенный тобой.

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

  • rts111 © (26.10.07 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;

 
Конференция "Игры" » Обратная функцыя к RGB() существует? [Delphi, Windows]
Есть новые Нет новых   [134431   +10][b:0][p:0.005]