Delphi медленный битблт с очень большой битмап

Я создаю компонент, в котором можно создавать таблицы с помощью перетаскивания.

Мне удалось написать часть перетаскивания и рендеринга таблицы, но у меня есть проблема.

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

шаги:

  1. Нарисуйте таблицу в растровое изображение в памяти (это может быть очень большим, вплоть до максимума).
  2. частичное содержимое растрового изображения в памяти на холсте элемента управления.

Проблема в том, что чем больше растровое изображение в памяти, тем медленнее будет (очевидно) операция bitblt.

Мой вопрос:

  • Как улучшить производительность этого? Я тоже заинтересован в альтернативных решениях.

Код:

procedure TCustomGraphicScrollControl.Paint;
var 
    x,y: Integer;
begin
  inherited;

  // Rendering is done in the child class. FRender is a 4-bit color depth 
  // in-memory bitmap. 

  if HorzScrollBar.Visible then x := HorzScrollBar.Position else x:=0;
  if VertScrollBar.Visible then y := VertScrollBar.Position else y:=0;

  // We will create a second in-memory bitmap, with the same dimensions as the control
  // and the same color depth as FRender. This way BitBlt will be a little faster, as it won't be needed to do any conversion.

  // bitblt part of the large in-memory bitmap to screen
  BitBlt(
    FCanvas.Handle,
    0,
    0,
    Width,
    Height,
    FRender.Canvas.Handle,
    x,
    y,
    SRCCOPY
  );
end;

Обновить:

Удалены "Тройная буферизация" и UpdateScrollBars из кода и вопроса.

1 ответ

Решение
  1. Нарисуйте таблицу в растровое изображение в памяти (это может быть очень большим, вплоть до максимума).
  2. Blit частичное содержимое растрового изображения в памяти на холсте элемента управления.

Проблема в том, что чем больше растровое изображение в памяти, тем медленнее будет (очевидно) операция bitblt.

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

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

Другие вопросы по тегам