Конференция "Media" » Работа с пикселями TBitmap [D7, WinXP]
 
  • kaldirishe (11.02.13 22:38) [0]
    Здравствуйте уважаемые форумчане)
    Занялся на досуге оптимизацией кода копирования битмапа на битмап(в процедуре прямоугольник на прямоугольник, но не суть). Решил попробовать процедуру move, получил ацкое ускорение и забыл) Однако вернувшись к ней снова меня стали терзать смутные сомнения… А не копирую ли я массив указателей? Что будет если по адресу убитого первого битмапа запишется что то иное. Или мои сомнения беспочвенны и так сделать можно?
     
    Собственно код:
    TColor32 = packed record
         b, g, r, a: Byte;
       end;

       TLine32 = array[Word] of TColor32;
       PLine32 = ^TLine32;

    function DrawAlpha(Source, Dest: TBitmap; SourceRect, DestRect: TRect): Boolean;
    var
     x0, y0, y, temp_y, AWidth: Integer;
     x1, y1, x2, y2: Integer;
     x3, y3, x4, y4: Integer;
     SourceLine, DestLine: PLine32;
    begin
     Result := (Source.PixelFormat = pf32bit) and (Dest.PixelFormat = pf32bit);
     if Result then
       try
         with Source do
         begin
           x1 := SourceRect.Left;
           if SourceRect.Left < 0 then x1 := 0
           else if SourceRect.Left >= Width - 1 then x1 := Width - 1;
           x2 := SourceRect.Right;
           if SourceRect.Right < 0 then x2 := 0
           else if SourceRect.Right >= Width - 1 then x2 := Width - 1;

           y1 := SourceRect.Top;
           if SourceRect.Top < 0 then y1 := 0
           else if SourceRect.Top >= Height - 1 then y1 := Height - 1;
           y2 := SourceRect.Bottom;
           if SourceRect.Bottom < 0 then y2 := 0
           else if SourceRect.Bottom >= Height - 1 then y2 := Height - 1;
         end;

         with Dest do
         begin
           x3 := DestRect.Left;
           if DestRect.Left < 0 then x3 := 0
           else if DestRect.Left >= Width - 1 then x3 := Width - 1;
           x4 := DestRect.Right;
           if DestRect.Right < 0 then x4 := 0
           else if DestRect.Right >= Width - 1 then x4 := Width - 1;

           y3 := DestRect.Top;
           if DestRect.Top < 0 then y3 := 0
           else if DestRect.Top >= Height - 1 then y3 := Height - 1;
           y4 := DestRect.Bottom;
           if DestRect.Bottom < 0 then y4 := 0
           else if DestRect.Bottom >= Height - 1 then y4 := Height - 1;
         end;

         if x2 - x1 > x4 - x3 then x0 := x4 - x3
         else x0 := x2 - x1;
         if y2 - y1 > y4 - y3 then y0 := y4 - y3
         else y0 := y2 - y1;

         temp_y := y3 - y1;
         AWidth := x0 * 4;
         for y := y1 to y1 + y0 do
         begin
           SourceLine := Source.ScanLine[y];
           DestLine := Dest.ScanLine[temp_y + y];
           Move(SourceLine[x1],  DestLine[x3],  AWidth);
         end;
       except
         Result := False;
       end;
    end;


  • MBo © (11.02.13 23:18) [1]
    >А не копирую ли я массив указателей?
    Нет, сами данные
  • kaldirishe (12.02.13 08:48) [2]
    Пасиб
  • kaldirishe (13.02.13 23:01) [3]
    Добрый вечер!
    Ну раз пошла такая пьянка), позвольте спросить еще об одном, попробую сформулировать… Я масштабирую изображение формата bmp 32 бита, средствами gdi+. Алгоритм может вызвать недоумение, но опытным путем проверено, что прямая загрузка\выгрузка через поток-потеря прозрачности.. короче это работает, проверено.  Далее изображение выводится через  AlphaBlend на конечный битмап. Прошу прощения за много букф, перехожу к главному… Столкнулся с непонятной для себя ситуевиной, на семерке, при увеличении, получаю цветную каемку на изображении, на xp, все нормально( Может кто нибудь это объяснить и посоветовать как с этим бороться?

    http://layerform.net/w7_n.png под семеркой
    http://layerform.net/w_xp_n.png xp, виртуалка

    код масштабирования, после выводим на конечный битмап и UpdateLayeredWindow
    function StretchBitmap(ASource, ADest: TBitmap; AWidth, AHeight: Integer): Boolean;
    var
     AGPSource, AGPDest: TGPBitmap;
     AW: Integer;
     ABitmapData: TBitmapData;
     AScanline: PByte;
     ABitmapLine: PLine32;
     AStride, Y: integer;
     ADestColor: PRGBQuad;
    begin
     Result := ASource.PixelFormat = pf32bit;
     if Result then
       try
         with ASource do
         begin
           ADest.Width := AWidth;
           ADest.Height := AHeight;
           ADest.PixelFormat := pf32bit;

           AGPSource := TGPbitmap.Create(Width, Height, PixelFormat32bppARGB);
           AGPDest := TGPbitmap.Create(AWidth, AHeight, PixelFormat32bppARGB);
           try
             AGPSource.LockBits(MakeRect(0, 0, Width, Height), ImageLockModeWrite, PixelFormat32bppARGB, ABitmapData);
             try
               AScanline := ABitmapData.Scan0;
               AStride := ABitmapData.Stride;

               AW := Width shl 2;
               for Y := 0 to Height - 1 do
               begin
                 ABitmapLine := ScanLine[Y];
                 ADestColor := PRGBQuad(AScanline);
                 Move(ABitmapLine[0], ADestColor^, AW);
                 inc(AScanline, AStride);
               end;
             finally
               AGPSource.UnlockBits(ABitmapData)
             end;
             with TGPGraphics.Create(AGPDest) do
               try
                 SetInterpolationMode(InterpolationModeHighQualityBicubic);
                 SetSmoothingMode(SmoothingModeAntiAlias);
                 DrawImage(AGPSource, MakeRect(0, 0, AWidth, AHeight), 0, 0, Width, Height, UnitPixel);
               finally
                 Free;
               end;
             AGPDest.LockBits(MakeRect(0, 0, AWidth, AHeight), ImageLockModeRead, PixelFormat32bppARGB, ABitmapData);
             try
               AScanline := ABitmapData.Scan0;
               AStride := ABitmapData.Stride;
               with ADest do
               begin
                 AW := Width shl 2;
                 for Y := 0 to Height - 1 do
                 begin
                   ABitmapLine := ScanLine[Y];
                   ADestColor := PRGBQuad(AScanline);
                   Move(ADestColor^, ABitmapLine[0], AW);
                   inc(AScanline, AStride);
                 end;
               end;
             finally
               AGPDest.UnlockBits(ABitmapData)
             end;
           finally
             AGPDest.Free;
             AGPSource.Free;
           end;
         end;
     except
       Result := False;
     end;
    end;
  • MBo © (14.02.13 06:31) [4]
    >на семерке, при увеличении, получаю цветную каемку на изображении, на xp, все нормально
    Возможно, по-разному работают алгоритмы интерполяции цветов при изменении размера
  • Eraser © (14.02.13 07:21) [5]

    > kaldirishe   (11.02.13 22:38) 

    лучше использовать bitblt и ее производные, быстрее будет наверняка.
  • kaldirishe (14.02.13 08:52) [6]

    > Возможно, по-разному работают алгоритмы интерполяции цветов
    > при изменении размера


    Как то странно это выглядит( Разные библиотеки для разных версий с одинаковыми заголовками( Кстати, только сейчас обратил внимание-форма в виде рисунка тоже различается на приведенных картинках. А ее я gdi+ не мучал, только AlphaBlend и UpdateLayeredWindow. Надо сильно подумать(


    > лучше использовать bitblt и ее производные, быстрее будет
    > наверняка.


    Я попробовал gdi+ из-за сглаживания.
  • kaldirishe (14.02.13 09:13) [7]
    Ложная тревога, сейчас на работе посмотрел как выглядит у сослуживца на семерке… Все ок. Значит «проблемы» с домашним ноутом, на котором идет борьба за производительность, хотя глубина цвета у него та же, 32.
  • Eraser © (14.02.13 19:16) [8]

    > kaldirishe   (14.02.13 08:52) [6]

    для bitblt сглаживание смысла не имеет по определению, а для stretchblt его можно включить.
  • antonn © (25.02.13 20:25) [9]

    > лучше использовать bitblt и ее производные, быстрее будет
    > наверняка.

    собственно stretchblt и может давать каемку, т.к. использует "аппаратное" сглаживание
  • kaldirishe (27.02.13 17:28) [10]
    Отчитываюсь), мой сайт (я его правда на буржуйском языке сделал) http://layerform.net/, раздел “Download”, пример “This example shows how to create a desktop with TStretchButtonLayerControl of the "three steps"
    (for ver 2.0)”. Масштабирование выполнено средствами GDI+, хотя как масштабирует Photopaint мне нравится больше.
 
Конференция "Media" » Работа с пикселями TBitmap [D7, WinXP]
Есть новые Нет новых   [118380   +18][b:0.001][p:0.001]