Конференция "Media" » Качественное и быстрое масштабирование картинки [D6, WinXP]
 
  • DVM © (15.10.07 16:15) [80]
    В FastDIB вообще нет функций для быстрого уменьшения в 2xN раз. Там есть функции для такого увеличения. Только они, вроде бы без билинейной фильтрации. Но можно дописать.

    Меня больше теперь интересует, результаты алгоритмов билинейной фильтрации должны быть одинаковы или нет?
  • homm © (15.10.07 16:17) [81]
    > [80] DVM ©   (15.10.07 16:15)
    > Меня больше теперь интересует, результаты алгоритмов билинейной
    > фильтрации должны быть одинаковы или нет?

    Должны. Ты же сам видишь, то, что получается в FastDIB, или в Pain.NET — кака полная.
  • DVM © (15.10.07 16:20) [82]

    > Ты же сам видишь, то, что получается в FastDIB, или в Pain.
    > NET — кака полная.

    Почему у всех, даже известных и вызывающих доверие программ они разные?

    Почему у Photoshop, Macromedia Fireworks, Intel OpenCV разные результаты?
    И у кого из них правильный?
  • homm © (15.10.07 16:35) [83]
    Ок, пусть будут разные, но не такие говенные как у Pain.NET и FastDIB.

    Можешь сделать общий png, на котором бы были представлены уменьшеные в 4 раза в Photoshop, Macromedia Fireworks, Intel OpenCV? у меня ни второго не третьего.
  • homm © (15.10.07 16:36) [84]
    > [82] DVM ©   (15.10.07 16:20)
    > И у кого из них правильный?

    У меня. И я кстати, не шучу. Суть метода — сложить и поделить. Т.к. у меня довольно частный случай в алгоритмах, определить что именно нужно сложить и на что поделить — проще всего.
  • DVM © (15.10.07 16:38) [85]

    > Можешь сделать общий png,

    Сделаю. Но вечером, на работе у меня вообще ничего из перечисленного нет.
  • Sapersky (15.10.07 17:24) [86]
    В FastDIB вообще нет функций для быстрого уменьшения в 2xN раз.

    Уменьшение в 2 раза:
    http://sapersky.narod.ru/files/FastSizeEx.rar
    Также там имеется вариант SmoothResize, работающий примерно в 2 раза быстрее. Но SmoothResize - всё-таки скорее качественная, чем быстрая фильтрация. Сама функция рассчитана в большей степени на сложные фильтры вроде Lancros (и что немаловажно - на фильтры РАЗНОЙ длины, что вынуждает крутить "внутренний" цикл для каждого пикселя).

    А Bilinear, ИМХО, это неплохой компромисс между скоростью и качеством. Если кому-то не нравится - не используйте, нам больше достанется :)
  • Sapersky (15.10.07 19:27) [87]
    Кстати, непонятно, какой смысл сравнивать с Photoshop. Он рекордов скорости ставить не собирается и может применить медленный, но качественный метод вроде SmoothResize c rfBilinear.
    Сравнивать нужно с кодом homm, который работает с любым коэффициентом  масштабирования, быстрее Bilinear и даёт более качественный результат.
    Кстати, где он? Я что-то пропустил? :)
  • homm © (15.10.07 21:15) [88]
    > [87] Sapersky   (15.10.07 19:27)
    > Сравнивать нужно с кодом homm, который работает с любым
    > коэффициентом  масштабирования, быстрее Bilinear и даёт
    > более качественный результат.

    Еше не написан такой.


    > Также там имеется вариант SmoothResize, работающий примерно
    > в 2 раза быстрее. Но SmoothResize - всё-таки скорее качественная,
    > чем быстрая фильтрация.

    Какое-то противоречие.


    > Кстати, непонятно, какой смысл сравнивать с Photoshop. Он
    > рекордов скорости ставить не собирается и может применить
    > медленный, но качественный метод вроде SmoothResize c rfBilinear.

    Он и применяет качественный фильтр, результат использования которого равен моему результату, и он же, собственно и есть самый настоящий билинеар.
  • DVM © (15.10.07 21:44) [89]
    Вот некоторые сравнения:

    http://dvmuratov.narod.ru/psvsfw.png

    1) Fireworks 4
    2) Photoshop 8
    3) Разница есть (FW заметно проигрывает Photoshop)

    http://dvmuratov.narod.ru/psvsulead.png

    1) Ulead PhotoImpact 11
    2) Photoshop 8
    3) Разница есть (небольшая но есть)

    http://dvmuratov.narod.ru/1.bmp - исходный файл

    Сейчас еще другие сравнения сделаю наверное
  • homm © (15.10.07 21:52) [90]
    > [89] DVM ©   (15.10.07 21:44)
    > 3) Разница есть (небольшая но есть)

    Ну это уже небольшие нюансы в построении… По скрину видно, что строится верно, как минимум не хуже билинейного.
  • homm © (15.10.07 23:59) [91]
    > [72] antonn ©   (14.10.07 22:56)
    > а есть на асме блитинг (с альфой или просто "прозрачный
    > цвет") двух битмапов (либо просто массивов)?


    Наваял без асма пока. Поучается примерно 100 кадров в секунду для 1024*768.

    procedure TForm1.Button1Click(Sender: TObject);
    type
     ARGBQuad = array [0..0] of TRGBQuad;
     PARGBQuad = ^ARGBQuad;
     AByte = array [0..0] of Byte;
     PAByte = ^AByte;
    var
     BMP1: TBitmap;
     BMP2: TBitmap;

     SL1, SL2: PARGBQuad;
     V1, V2: TRGBQuad;
     R: ^TRGBQuad;
     i, j: Integer;
     A_1, A: Integer;
     Delta: DWORD;

     T: DWORD;

    begin
     BMP1 := TBitmap.Create;
     BMP1.LoadFromFile('C:\1.bmp');
     BMP2 := TBitmap.Create;
     BMP2.LoadFromFile('C:\2.bmp');
     
    T := GetTickCount;

     SL1 := BMP1.ScanLine[0];
     SL2 := BMP2.ScanLine[0];
     Delta := DWORD(BMP1.ScanLine[1]) - DWORD(SL1);
     for i := 0 to BMP1.Height-1 do begin
       for j := 0 to BMP1.Width-1 do begin
         V1 := SL1[j];
         V2 := SL2[j];
         A := V2.rgbReserved;
         A_1 := 255-V2.rgbReserved;
         R := @SL1[j];
         R.rgbBlue := (V2.rgbBlue*A_1+V1.rgbBlue*A) shr 8;
         R.rgbGreen := (V2.rgbGreen*A_1+V1.rgbGreen*A) shr 8;
         R.rgbRed := (V2.rgbRed*A_1+V1.rgbRed*A) shr 8;
       end;
       SL1 := Pointer(DWORD(SL1) + Delta);
       SL2 := Pointer(DWORD(SL2) + Delta);
     end;

    ShowMessage(IntToStr(GetTickCount - T));

     Image1.Canvas.StretchDraw(Rect(0, 0, 1024, 768), BMP1);
     BMP1.Free;
     BMP2.Free;
    end;



    Обе картинки болжны быть 32-х битные, причем вторая должна в резервном бите содержать альфаканал (легко сделать в фотошопе).
  • antonn © (16.10.07 01:07) [92]
    я наверное щас совсем оборзею, но можно попросить о помощи? :)
    битмапы храню в массиве dword (так по идее доступ еще быстрее, и почка для асма:))
    немножко велосипеда:
    const
     MaxBTCount = MaxInt div SizeOf(dword);
    type
     BTElement = dword;
     TBTArray = array[0..MaxBTCount-1] of BTElement;

     PxlByte = array [0..2] of byte;

     LongAS = packed record
       DW: array [0..3] of dword;
     end;

     pPRBT= ^TPRBT; //для 4х уменьшения
     TPRBT = record
       b1,b2,b3,b4:dword;
     end;
     pPRBD= ^TPRBD; //это для 2х уменьшения
     TPRBD = record
       b1,b2:dword;
     end;

     TBT = Class
       private
        procedure setarrays(x,y:integer);
       public
        DIBWidth     : integer;
        DIBHeight    : integer;
        P: ^TBTArray;
        constructor Create;
        destructor Destroy; override;
        procedure loadbitmap(bitmap:tbitmap);
        procedure savebitmap2file(filename:string);
        procedure set_widthheight(w,h:integer);
     end;

    implementation

    constructor TBT.Create;
    begin
    inherited;
    DIBWidth:=0;
    DIBHeight:=0;
    end;

    destructor TBT.Destroy;
    begin
    FreeMem(P, DIBWidth*DIBHeight*SizeOf(BTElement));
    inherited;
    end;

    procedure TBT.setarrays(x,y:integer);
    begin
    FreeMem(P, DIBWidth*DIBHeight*SizeOf(BTElement));

    DIBWidth:=x;
    DIBHeight:=y;
    P:=AllocMem(DIBWidth*DIBHeight * SizeOf(BTElement));
    end;

    procedure TBT.set_widthheight(w,h:integer);
    begin
    setarrays(w,h);
    end;

    procedure TBT.loadbitmap(bitmap:tbitmap);
    var x,y,cou,n: Integer;  Row2:PRGBAArray;
    begin
    cou:=0;
    setarrays(bitmap.Width,bitmap.Height);

    for Y:=0 to bitmap.Height-1 do begin
       Row2:=bitmap.ScanLine[y];
        for x:=0 to bitmap.Width-1 do begin

          if((Row2[x].rgbRed=255) and (Row2[x].rgbGreen=0) and (Row2[x].rgbBlue=0)) then
           Row2[x].rgbReserved:=0 else
           Row2[x].rgbReserved:=255;

           P^[ y*DIBWidth+x ]:=(Row2[x].rgbRed or (Row2[x].rgbGreen shl 8) or (Row2[x].rgbBlue shl 16) or (Row2[x].rgbReserved shl 24));
        end;
     end;
    end;

    procedure TBT.savebitmap2file(filename:string);
    var bb:tbitmap; x,y,cou: Integer;  Row2:PRGBAArray; fd:dword;
    begin
    bb:=tbitmap.Create;
    try
     bb.PixelFormat:=pf32bit;
     bb.Width:=DIBWidth;
     bb.Height:=DIBHeight;
      for Y:=0 to bb.Height-1 do begin
        Row2:=bb.ScanLine[y];
        for x:=0 to bb.Width-1 do begin
          fd:=P^[ y*DIBWidth+x ];
          Row2[x].rgbBlue:=Byte(fd shr 16);
          Row2[x].rgbGreen:=Byte(fd shr 8);
          Row2[x].rgbRed:=Byte(fd);
          Row2[x].rgbReserved:=Byte(fd shr 24);
        end;
      end;
      bb.SaveToFile(filename);
    finally
     bb.Free;
    end;
    end;


    небольшой класс, грузящий битмап в массив и сохранающий как битмап. Оптимизаций загрузки/сохранения не делал, потом.
    Так вот, в асме я дуб, но хочется быстрее, выше и сильнее, особенно если с ММХ/SSE и тп:)
    кстати, код для уменьшения:)
    procedure antialias_x2(var BTSourc,BTDest:TBT);
    var x,y,cou,num,i,cxi,cx,wi,hi: Integer;  Row2:PRGBAArray; fd:dword;
      y1,y2,totr,totg,totb,tota:integer;
     yy1,yy2:pPRBD;
     wii,hii:integer;
    begin
     wii:=BTSourc.DIBWidth div 2;
     hii:=BTSourc.DIBHeight div 2;

      for Y:=0 to hii-1 do begin

        y1:=y*2*BTSourc.DIBWidth;
        y2:=y1+BTSourc.DIBWidth;

        for x:=0 to wii-1 do begin
          cx:=x*2;

          yy1:=pPRBD(@(BTSourc.P^[ y1+cx ]));
          yy2:=pPRBD(@(BTSourc.p^[ y2+cx ]));

          totb:=LongRec(yy1.b1).Bytes[2] + LongRec(yy2.b1).Bytes[2] ;
          totb:=totb+LongRec(yy1.b2).Bytes[2] + LongRec(yy2.b2).Bytes[2] ;

          totg:=LongRec(yy1.b1).Bytes[1] + LongRec(yy2.b1).Bytes[1] ;
          totg:=totg+LongRec(yy1.b2).Bytes[1] + LongRec(yy2.b2).Bytes[1] ;

          totr:=LongRec(yy1.b1).Bytes[0] + LongRec(yy2.b1).Bytes[0] ;
          totr:=totr+LongRec(yy1.b2).Bytes[0] + LongRec(yy2.b2).Bytes[0];

          tota:=LongRec(yy1.b1).Bytes[3] + LongRec(yy2.b1).Bytes[3] ;
          tota:=tota+LongRec(yy1.b2).Bytes[3] + LongRec(yy2.b2).Bytes[3] ;

          BTDest.P^[ y*wii+x ]:=((totr Shr 2) or ((totg Shr 2) shl 8) or ((totb Shr 2)  shl 16)or ((tota Shr 2) shl 24));

        end;
      end;
    end;



    альфаблитинг (с проверками на границы и произольным началом вывода):
    procedure AlfaBliting(var BTPic,BTBack:TBT; _x,_y:integer);
    var x, y,xd,yd,yyd: Integer; _r,_b,_g:integer;
       w_out,h_out,tmp,x_cor,y_cor,x_corS,y_corS: Integer;
       _d,_dd:double;
       fd,fs,fr:dword;
    begin
    w_out:=BTBack.DIBWidth;
    h_out:=BTBack.DIBHeight;
    if (_x)>w_out-1 then exit; if (_x+w_out)<0 then exit;
    if (_y)>h_out-1 then exit; if (_y+h_out)<0 then exit;
    if _x<0 then x_corS:=abs(_x) else x_corS:=0;
    if _y<0 then y_corS:=abs(_y) else y_corS:=0;
    if (_x+BTPic.DIBWidth)>w_out then x_cor:=_x+BTPic.DIBWidth-w_out else x_cor:=0;
    if (_y+BTPic.DIBHeight)>h_out then y_cor:=_y+BTPic.DIBHeight-h_out else y_cor:=0;
     y_cor:=BTPic.DIBHeight-1-y_cor;
     tmp:=BTPic.DIBWidth-1-x_cor; _dd:=(100/255)/100;
     for y:=y_corS to y_cor do begin
        yd:=y*BTPic.DIBWidth;
        yyd:=(y+_y)*BTBack.DIBWidth;
       for x:=x_corS to tmp do begin
         fd:=BTPic.P^[ yd+x ];
         if(LongRec(fd).Bytes[3]>0)then begin
             xd:=x+_x;
             fs:=BTBack.P^[ yyd +xd ];

             _d:=LongRec(fd).Bytes[3]*_dd;

            _r:= LongRec(fs).Bytes[0]+round((LongRec(fd).Bytes[0]-LongRec(fs).Bytes[0])*_d);
            if _r>255 then _r:=255 else if _r<0 then _r:=0;

            _g:= LongRec(fs).Bytes[1]+round((LongRec(fd).Bytes[1]-LongRec(fs).Bytes[1])*_d);
            if _g>255 then _g:=255 else if _g<0 then _g:=0;

            _b:= LongRec(fs).Bytes[2]+round((LongRec(fd).Bytes[2]-LongRec(fs).Bytes[2])*_d);
            if _b>255 then _b:=255 else if _b<0 then _b:=0;

          if LongRec(fs).Bytes[3]<LongRec(fd).Bytes[3] then
            BTBack.P^[ yyd +xd ]:=(_r or (_g shl 8) or (_b  shl 16)or (LongRec(fd).Bytes[3] shl 24))
          else
            BTBack.P^[ yyd +xd ]:=(_r or (_g shl 8) or (_b  shl 16)or (LongRec(fs).Bytes[3] shl 24));

           end;

     end; end;

    end;



    и "обычный" блит с "прозрачным каналом" (прозрачный канал - это альфа с значением 0):
    procedure Bliting(var BTPic,BTBack:TBT; _x,_y:integer);
    var x, y,yd,yyd: Integer;
       w_out,h_out,tmp,x_cor,y_cor,x_corS,y_corS: Integer;
    begin
    w_out:=BTBack.DIBWidth;
    h_out:=BTBack.DIBHeight;
    if (_x)>w_out-1 then exit; if (_x+w_out)<0 then exit;
    if (_y)>h_out-1 then exit; if (_y+h_out)<0 then exit;
    if _x<0 then x_corS:=abs(_x) else x_corS:=0;
    if _y<0 then y_corS:=abs(_y) else y_corS:=0;
    if (_x+BTPic.DIBWidth)>w_out then x_cor:=_x+BTPic.DIBWidth-w_out else x_cor:=0;
    if (_y+BTPic.DIBHeight)>h_out then y_cor:=_y+BTPic.DIBHeight-h_out else y_cor:=0;
     y_cor:=BTPic.DIBHeight-1-y_cor;
     tmp:=BTPic.DIBWidth-1-x_cor;
     for y:=y_corS to y_cor do begin
        yd:=y*BTPic.DIBWidth;
        yyd:=(y+_y)*BTBack.DIBWidth;
       for x:=x_corS to tmp do begin
         if(LongRec(BTPic.P^[ yd+x ]).Bytes[3]>0)then
            BTBack.P^[ yyd+x+_x ]:=BTPic.P^[ yd+x ];
       end;
     end;
    end;



    так вот, я понимаю, что выгрузил тут много всякого, не поможите оптимизировать? :)
  • Sapersky (16.10.07 02:45) [93]
    Еше не написан такой.

    Так вот сначала напиши, а потом советуй выбросить FastDIB.

    > Также там имеется вариант SmoothResize, работающий примерно
    > в 2 раза быстрее. Но SmoothResize - всё-таки скорее качественная,
    > чем быстрая фильтрация.

    Какое-то противоречие.


    Я имел в виду - быстрее, чем тот вариант SmoothResize, который в составе FastLib 3.9.9. Но медленнее, чем Bilinear.

    > Кстати, непонятно, какой смысл сравнивать с Photoshop. Он
    > рекордов скорости ставить не собирается и может применить
    > медленный, но качественный метод вроде SmoothResize c rfBilinear.

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


    Против Фотошопа FastLib'у есть что выставить - у SmoothResize качество ничуть не хуже, и скорость скорее всего тоже.
    Но Bilinear - это специально оптимизированная на скорость (ценой некоторой потери качества) функция. Поэтому не стоит сравнивать её с меланхоличным Фотошопом. С BitmapAntialias2X тоже не стоит, уж неловко напоминать почему. С чем стоит - уже писал :)

    Теперь о том, почему совмешение скорости с качеством маловероятно. Причина высокого качества, которое даёт SmoothResize - переменная длина фильтра, которая зависит не только от типа фильтра, но и от коэффициента масштабирования. И эта же переменная (и бОльшая по величине) длина, как я уже писал в [86] (а не "вызов f для каждого пикселя") - причина тормознутости функции. Ну и в какой-то степени обработка в 2 прохода (приходится создавать промежуточный буфер).
    Т.е. можно, конечно, создать некий гибрид SmoothResize/Bilinear, и он будет даже несколько быстрее первой (за счёт фиксированной функции, обработки в 1 проход и т.п.), но до 2-й по скорости всё равно не дотянет.
    Не проще ли тогда господам эстетам просто вызывать SmoothResize при K < 0.5, а в остальных случаях Bilinear?
  • Sapersky (16.10.07 02:46) [94]
    antonn ©   (16.10.07 01:07) [92]

    См. SpriteUtils-2.
  • homm © (16.10.07 06:33) [95]
    > Так вот сначала напиши, а потом советуй выбросить FastDIB.

    Мне незачем искать, я и так знаю, что еше нет «кода, написаного, homm (мной), который работает с любым коэффициентом  масштабирования, быстрее Bilinear и даёт более качественный результат».

    > Против Фотошопа FastLib'у есть что выставить - у SmoothResize
    > качество ничуть не хуже, и скорость скорее всего тоже.

    Просто делать делать необоснованные утверждения? Photoshop — 532 ms, SmoothResize — 2312ms.


    > Но Bilinear - это специально оптимизированная на скорость
    > (ценой некоторой потери качества) функция.

    «ИМХО» забыл добавить.


    > Поэтому не стоит сравнивать её с меланхоличным Фотошопом.

    «меланхоличным Фотошопом» это как понять?
  • homm © (16.10.07 07:03) [96]
    2 antonn

    procedure BitmapAntialias2X(SrcBitmap, DstBitmap: TBt);
    type    AGRBQuad = array [0..0] of TRGBQuad;
         PAGRBQuad = ^AGRBQuad;
    var     yDest: integer;
         xDest: integer;
         xSrc: integer;
         i: integer;
         R: integer;
         G: integer;
         B: integer;
         rowDest: PAGRBQuad;
         rowSrc: array [0..3] of PAGRBQuad;
         _rowSrc: PAGRBQuad;
         SrcBits: DWORD;
         DstBits: DWORD;
         dHeight: DWORD;
         dWidth: DWORD;
         Delta: DWORD;
    begin
     if CPUisMMX then begin
         SrcBits := DWORD(SrcBitmap.P);
         DstBits := DWORD(DstBitmap.P);
         dHeight := DstBitmap.DIBHeight;
         dWidth := DstBitmap.DIBWidth;
         Delta := SrcBitmap.DIBWidth*SizeOf(BTElement);//ScanLineSize(SrcBitmap);
         asm
             pushad
             mov esi, SrcBits
             mov edi, DstBits
             //pxor mm2, mm2
             db $0f, $ef, $d2

             mov eax, dHeight
    @LM1:       push eax

             mov eax, dWidth
    @LM2:       /////////
             mov ecx, esi

             //movd mm1, [ecx]
             db $0f, $6e, $09
             //punpcklbw mm1, mm2
             db $0f, $60, $ca
             //movd mm3, [ecx+4]
             db $0f, $6e, $59, $04
             //punpcklbw mm3, mm2
             db $0f, $60, $da
             //paddusw mm1, mm3
             db $0f, $dd, $cb

             add ecx, Delta

             //movd mm3, [ecx]
             db $0f, $6e, $19
             //punpcklbw mm3, mm2
             db $0f, $60, $da
             //paddusw mm1, mm3
             db $0f, $dd, $cb
             //movd mm3, [ecx+4]
             db $0f, $6e, $59, $04
             //punpcklbw mm3, mm2
             db $0f, $60, $da
             //paddusw mm1, mm3
             db $0f, $dd, $cb

             //psrlw mm1, 2
             db $0f, $71, $d1, $02
             //packuswb mm1, mm2
             db $0f, $67, $ca
             //movd [edi], mm1
             db $0f, $7e, $0f
             /////////

             add edi, 4
             add esi, 8

             sub eax, 1
       jnz @LM2

             add esi, Delta

             pop eax
             sub eax, 1
       jnz @LM1

             //emms
             db $0f, $77

             popad
         end;
     end else
     {for yDest := 0 to DstBitmap.DIBHeight -1 do begin
         rowDest := DstBitmap.ScanLine[yDest];
         for i := 0 to 1 do
             rowSrc[i] := SrcBitmap.ScanLine[yDest*2+i];
         for xDest := 0 to DstBitmap.Width-1 do begin
             xSrc := xDest*2;
             R:=0; G:=0; B:=0;
             for i := 0 to 1 do begin
                 _rowSrc := rowSrc[i];
                 R:= R+_rowSrc[xSrc+0].rgbRed
                     + _rowSrc[xSrc+1].rgbRed;
                 G:= G+_rowSrc[xSrc+0].rgbGreen
                     + _rowSrc[xSrc+1].rgbGreen;
                 B:= B+_rowSrc[xSrc+0].rgbBlue
                     + _rowSrc[xSrc+1].rgbBlue;
             end;
             DWORD(rowDest[xDest]) := ((R and $03fc) shl 14) or ((G and $03fc) shl 6) or (B shr 2);
         end;
     end;  }

    end;



    получилось 219мс супротив 657 с antialias_x2.
    BitmapAntialias4X преобразуется точно так-же, ни одна асмовская строчка не затрагивается :)

    Паскалевскую версию закоментировал, надеюсь ты сам с ней разберешся :)
    А вообще лучше бы оптимизировал загрузку изображений, толку было бы больше.
  • homm © (16.10.07 07:09) [97]
    > [95] homm ©   (16.10.07 06:33)
    > > Так вот сначала напиши, а потом советуй выбросить FastDIB.
    >
    > Мне незачем искать

    Прошу прощения, прочлось как «сначала поищи».
  • homm © (16.10.07 08:52) [98]
    > [92] antonn ©   (16.10.07 01:07)
    > if((Row2[x].rgbRed=255) and (Row2[x].rgbGreen=0) and (Row2[x].rgbBlue=0) ) then

    if ((DWORD(Row2[x]) AND $ffffff)=$ff0000) then




    > P^[ y*DIBWidth+x ]:=(Row2[x].rgbRed or (Row2[x].rgbGreen
    > shl 8) or (Row2[x].rgbBlue shl 16) or (Row2[x].rgbReserved
    > shl 24));

    P[ y*DIBWidth+x ] := DWORD(Row2[x]);
  • homm © (16.10.07 09:19) [99]
    > if((Row2[x].rgbRed=255) and (Row2[x].rgbGreen=0) and (Row2[x].rgbBlue=0)) then
    >       Row2[x].rgbReserved:=0 else
    >       Row2[x].rgbReserved:=255;

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

    Row2[x].rgbReserved := Byte(boolean( (DWORD(Row2[x]) AND $ffffff) xor $ff0000) )*$ff;



    Слабо верится, что Дельфи поймет, что я тут хотел сказать, но вдруг :)
 
Конференция "Media" » Качественное и быстрое масштабирование картинки [D6, WinXP]
Есть новые Нет новых   [120120   +95][b:0.001][p:0.008]