Отображение растрового изображения в Wpf [дубликат]

Новые кодеры иногда пишут такой код:

my_calculator.button_0 = tkinter.Button(root, text=0) my_calculator.button_1 = tkinter.Button(root, text=1) my_calculator.button_2 = tkinter.Button(root, text=2) ...

Затем кодер остается с кучей именованных переменных с усилием кодирования O (m * n), где m - число именованных переменных, а n - количество раз, к которому необходимо получить доступ к группе переменных (включая создание). Более проницательный новичок отмечает, что единственная разница в каждой из этих строк - это число, которое изменяется на основе правила и решает использовать цикл. Однако они зациклились на том, как динамически создавать эти имена переменных, и могут попробовать что-то вроде этого:

for i in range(10): my_calculator.('button_%d' % i) = tkinter.Button(root, text=i)

Вскоре они обнаруживают, что это не работает.

Если программа требует произвольных переменных «имена», лучше всего подходит словарь, как объясняется в других ответах. Однако, если вы просто пытаетесь создать много переменных, и вы не возражаете ссылаться на них с последовательностью целых чисел, вы, вероятно, ищете list. Это особенно верно, если ваши данные однородны, например, ежедневные показания температуры, еженедельные оценки викторины или сетка графических виджетов.

Это можно собрать следующим образом:

my_calculator.buttons = [] for i in range(10): my_calculator.buttons.append(tkinter.Button(root, text=i))

Этот list также может быть создан в одной строке с пониманием:

my_calculator.buttons = [tkinter.Button(root, text=i) for i in range(10)]

Результат в любом случае - это заполненный list, причем первый элемент имеет доступ к my_calculator.buttons[0], следующий с my_calculator.buttons[1] и т. д. Имя переменной «base» становится именем list, и для доступа к нему используется различный идентификатор.

Наконец, не забудьте другие структуры данных, такие как set - это аналогично словарю, за исключением того, что каждое «имя» не имеет привязанного к нему значения. Если вам просто нужна «сумка» объектов, это может быть отличным выбором. Вместо этого:

keyword_1 = 'apple' keyword_2 = 'banana' if query == keyword_1 or query == keyword_2: print('Match.')

У вас будет следующее:

keywords = {'apple', 'banana'} if query in keywords: print('Match.')

Используйте последовательность list для последовательности похожих объектов, a set для произвольного - помещенный пакет предметов или dict для мешка с именами со связанными значениями.

12
задан Epitouille 9 June 2015 в 08:55
поделиться

2 ответа

Вот метод, который (по моему опыту) по крайней мере в четыре раза быстрее, чем CreateBitmapSourceFromHBitmap.

Требуется установить правильный PixelFormat результирующего BitmapSource.

public BitmapSource Convert(System.Drawing.Bitmap bitmap)
{
    var bitmapData = bitmap.LockBits(
        new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
        System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

    var bitmapSource = BitmapSource.Create(
        bitmapData.Width, bitmapData.Height,
        bitmap.HorizontalResolution, bitmap.VerticalResolution,
        PixelFormats.Bgr24, null,
        bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);

    bitmap.UnlockBits(bitmapData);
    return bitmapSource;
}
28
ответ дан Clemens 20 August 2018 в 23:36
поделиться

Я ответил себе, прежде чем Клеменс ответит:

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

 WriteableBitmap writeableBitmap = new WriteableBitmap(1280, 1024, 96.0, 96.0, PixelFormats.Bgr24, null);
        public MainWindow()
        {
            InitializeComponent();

            ImageTarget.Source = writeableBitmap;

            Messenger.Default.Register<Bitmap>(this, (bmp) =>
            {
                ImageTarget.Dispatcher.BeginInvoke((Action)(() =>
               {
                    BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
                    writeableBitmap.Lock();
                    CopyMemory(writeableBitmap.BackBuffer, data.Scan0,
                        (writeableBitmap.BackBufferStride * bmp.Height));
                    writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, bmp.Width, bmp.Height));
                    writeableBitmap.Unlock();
                    bmp.UnlockBits(data);
                }));
            });
        }

Теперь мое использование процессора составляет около 15%

5
ответ дан Erçin Dedeoğlu 20 August 2018 в 23:36
поделиться
  • 1
    Повторное использование WriteableBitmap даже лучше, чем создание нового. Вероятно, вы также должны показать объявление DllImport для CopyMemory. – Clemens 9 June 2015 в 11:11
  • 2
    И вы пытались, если последовательность Lock / AddDirtyRect / Unlock действительно быстрее, чем WritePixels? По моему опыту это примерно то же самое, и последнее спасет вас от кода и DllImport. – Clemens 9 June 2015 в 11:15
  • 3
    Я тестировал с помощью WritePixel и CopyMemory, это похоже на то же, но WritePixel более читабельна. Я собираюсь перейти к этому решению – Epitouille 9 June 2015 в 12:35
  • 4
    @Epitouille в строке CopyMemory показывает сообщение об ошибке "system.accessviolationexception пытается читать или записывать защищенную память" – Giresh 16 June 2017 в 09:48
Другие вопросы по тегам:

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