Как к рендерингу имитатором Picasa уменьшенного качества отображают для ускорения рисунка

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

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

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

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

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

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

7
задан Community 23 May 2017 в 12:30
поделиться

1 ответ

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

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

Пример кода, который я использую в приложении, делающем нечто подобное (эффект увеличения, который изменяет размер окна, в котором может быть 100 объектов - выглядит как демонстрация на 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 во время перетаскивания мыши, если не изменен размер.

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

3
ответ дан 7 December 2019 в 16:38
поделиться