Библиотеки графического изображения Python [закрываются]

Да, это слишком медленно.

Я столкнулся с этой проблемой несколько лет назад во время разработки Paint.NET (с самого начала, и это было довольно сложно!). Производительность рендеринга была ужасной, так как она всегда была пропорциональна размеру растрового изображения, а не размеру области, которую было сказано перерисовать. То есть частота кадров уменьшалась по мере увеличения размера растрового изображения, а частота кадров никогда не увеличивалась, поскольку размер недопустимой области / области перерисовки уменьшался при реализации OnPaint () и вызове Graphics.DrawImage (). Небольшое растровое изображение, скажем, 800x600, всегда работало нормально, но большие изображения (например, 2400x1800) были очень медленными. (В любом случае, вы можете предположить, что в предыдущем абзаце ничего лишнего не происходило, например, масштабирование с помощью какого-нибудь дорогого бикубического фильтра, что могло бы негативно повлиять на производительность.)

Можно заставить WinForms использовать GDI вместо GDI + и избегайте даже создания объекта Graphics за кулисами, после чего вы можете наложить поверх него еще один инструментарий рендеринга (например, Direct2D). Однако это не просто. Я делаю это в Paint.NET, и вы можете увидеть, что требуется, используя что-то вроде Reflector в классе с именем GdiPaintControl в DLL-библиотеке SystemLayer, но для того, что вы делаете, я бы посчитал это последним средством.

Однако используемый вами размер растрового изображения (800x1200) все равно должен работать достаточно хорошо в GDI +, не прибегая к расширенному взаимодействию, если только вы не нацеливаетесь на что-то столь же низкое, как Pentium II с 300 МГц. Вот несколько советов, которые могут помочь:

  • Если вы используете непрозрачное растровое изображение (без альфа / прозрачности) в вызове Graphics.DrawImage(), и особенно если это 32-разрядное растровое изображение с альфа-канал (но вы знаете , что он непрозрачный, или вам все равно), затем установите Graphics.CompositingMode в CompositingMode.SourceCopy перед вызовом DrawImage() (обязательно установите его обратно в исходное значение после, в противном случае обычные рисунки примитивов будут выглядеть очень некрасиво). Это пропускает много дополнительных математических вычислений на пиксель.
  • Убедитесь, что Graphics.InterpolationMode не настроен на что-то вроде InterpolationMode.HighQualityBicubic. Использование NearestNeighbor будет самым быстрым, хотя, если есть какое-либо растяжение, оно может выглядеть не очень хорошо (если только оно не растягивается ровно в 2, 3, 4 раза и т. Д.) Bilinear обычно является хорошим компромиссом. Вы никогда не должны использовать ничего, кроме NearestNeighbor, если размер растрового изображения соответствует области, в которую вы рисуете, в пикселях.
  • Всегда используйте объект Graphics, данный вам в OnPaint().
  • Всегда делайте свой рисунок в OnPaint. Если вам нужно перерисовать область, позвоните по номеру Invalidate(). Если вам нужно, чтобы розыгрыш произошел прямо сейчас, позвоните Update() после Invalidate(). Это разумный подход, поскольку сообщения WM_PAINT (что приводит к вызову OnPaint()) являются сообщениями с «низким приоритетом». Любая другая обработка, выполняемая оконным менеджером, будет выполняться в первую очередь, и, в противном случае, вы можете получить много пропущенных и пропущенных кадров.
  • Использование System.Windows.Forms.Timer в качестве частоты кадров / таймера не очень хорошо работает. Они реализованы с использованием Win32 SetTimer и приводят к сообщениям WM_TIMER, которые затем приводят к возникновению события Timer.Tick, а WM_TIMER - другое сообщение с низким приоритетом, которое отправляется только тогда, когда очередь сообщений пуста. Вам лучше использовать System.Threading.Timer, а затем использовать Control.Invoke() (чтобы убедиться, что вы на правильном пути!) И вызывать Control.Update().
  • Как правило, не используйте Control.CreateGraphics(). (следствие «всегда рисовать в OnPaint()» и «всегда использовать Graphics, данное вам OnPaint()»)
  • Я рекомендую не использовать обработчик событий Paint. Вместо этого реализуйте OnPaint() в классе, который вы пишете, который должен быть получен из Control. Производные от другого класса, например PictureBox или UserControl, либо не добавят никакой ценности для вас, либо добавят дополнительные издержки. (КСТАТИ PictureBox часто неправильно понимают. Вы, вероятно, почти никогда не захотите его использовать.)

Надежда, которая помогает.

48
задан 5 revs, 2 users 56% 14 December 2010 в 15:37
поделиться

3 ответа

Вы всегда можете использовать объектно-ориентированную структуру для Matplotlib вместо интерфейса pylab.

28
ответ дан 26 November 2019 в 18:37
поделиться

Я использовал Gnuplot.py с большим успехом.

3
ответ дан 26 November 2019 в 18:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: