Как имитировать рендеринг изображения низкого качества в Picasa для ускорения рисования - PullRequest
7 голосов
/ 23 июня 2010

У меня есть нарисованный владельцем элемент управления, где производительность возникает во время быстрых перерисовок, таких как перетаскивание объектов, изменение размера и рисование квадрата селектора. я заметил, что несколько других приложений, включая Picasa , временно нарисуют изображение низкого качества во время сценариев быстрой перерисовки, а затем обновят изображение с более высоким качественная версия, когда пользовательский интерфейс «успокаивается».

Как я могу (могу ли я) создать изображение низкого качества для рисования, когда происходит много быстрых перерисовок? Существуют ли другие стратегии, подобные этой, которые я могу использовать для повышения производительности (или фальсификации увеличения производительности)?

Дополнительная информация:

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

Я использую метод DrawImageUnscaled GDI + для рисования изображений, который должен быть намного более эффективным, чем DrawImage, но профилирование производительности показывает, что DrawImageUnscaled все еще является узким местом. Я думаю, что мой единственный выход - найти умные способы рисовать меньше.

P.S. Предыдущий вопрос, связанный с этой проблемой, принес мне значок Tumbleweed, поэтому я использую другой подход: Как повысить производительность по сравнению с DrawImage GDI (Unscaled)?

1 Ответ

3 голосов
/ 24 июня 2010

Подождите - вы пропустили здесь кусочек низко висящих фруктов. Они, вероятно, не перерисовывают изображение вообще во время операций изменения размера. Они могут изменять размер существующего изображения в видео-плеере с помощью StretchBlt, который может быть оптимизирован с помощью видеодрайвера / аппаратного обеспечения, чтобы быть очень очень быстрым, быстрее, чем вы могли бы «перерисовать изображение пониженного качества».

Стратегия
-изображения объектов имеют переменную-член для последней позиции / размера (прямоугольник)
перекраска изображения объекта рисует в полном объеме
перерисовка обновлений изображения последней позиции
во время перетаскивания сделайте следующее:
* StrechBlt от последней позиции / размера до текущей позиции / размера
* Обновить последнюю позицию / размер
* Если более нескольких секунд. рисования и / или> .2s с момента последнего перемещения мыши, вызовите перекрашивание (а не просто сделайте недействительным - вы хотите СЕЙЧАС), чтобы получить новое полноразмерное изображение. Также сделайте, если вы обнаружите перекрытия от других объектов (тоже получит StrechBlt'd)

Пример кода, который я использую в приложении, которое делает что-то похожее (эффект увеличения масштаба, который изменяет размеры окна, в котором могут быть сотни объектов - это выглядит как более плавная демонстрация ipad):

Declare Function StretchBlt Lib "gdi32.dll" _
   (ByVal hdcDest As IntPtr, _
    ByVal nXOriginDest As Integer, _
    ByVal nYOriginDest As Integer, _
    ByVal nWidthDest As Integer, _
    ByVal nHeightDest As Integer, _
    ByVal hdcSrc As IntPtr, _
    ByVal nXOriginSrc As Integer, _
    ByVal nYOriginSrc As Integer, _
    ByVal nWidthSrc As Integer, _
    ByVal nHeightSrc As Integer, _
    ByVal dwRop As Int32) As Boolean

    Using g As Graphics = f.pb.CreateGraphics
        ' parm of True says draw plain view - no text = looks bad Zooming.
        f.DrawAll(g, True)
        For i As Integer = iSteps To 1 Step -1
            Dim HDC1 As IntPtr = g.GetHdc
            Try
                ' Size of bite will not be right, but by re-adjusting 
                ' with each iteration, it will make it to full-screen.
                ' Looks as good as having it right to start with, only much easier.
                TopBite = objTop \ i
                BottomBite = h - ((h - objBottom) \ i)
                ' Stretch/move the stuff.
                StretchBlt(HDC1, 0, 0, w - LeftBite, h, _
                  HDC1, LeftBite, TopBite, w - LeftBite, BottomBite - TopBite, 13369376)
                ' Calculate where MyEntry would be after each stretch. Then the Bite 
                ' size calcs above will ensure its closer next time. 
                SimulateStretch(objTop, objBottom, TopBite, BottomBite, h)
            Finally
                g.ReleaseHdc(HDC1)
            End Try
            ' Clear exposed/invalid area to the right.
            g.FillRectangle(br, w - LeftBite, 0, LeftBite, h)
            ' Sleep will make Swells close in duration between small/big window.
            ' (Can I actually sleep this short of a time?)
            System.Threading.Thread.Sleep(5)
        Next
    End Using

Конечно, если кто-то измерит его крошечное изображение, а затем создаст резервную копию, оно будет очень низкокачественным и с пикселизацией - так что вы можете использовать более умный алгоритм, чтобы иногда запускать настоящую onpaint во время mousedrag, если не изменяете размер.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...