C ++ WinRT - CanvasBitmap, как динамически создать растровое изображение, нарисовать на нем пиксель, а затем отобразить на экране? - PullRequest
0 голосов
/ 05 июня 2019

Как:

  1. Динамически создать растровое изображение размером 512x512.

  2. Нарисуйте пиксель с цветом, таким как SetPixel (x, y, color) на растровом изображении;

  3. Показать это растровое изображение, созданное на экране панели?

Из Win2D Github, автор посоветовал использовать CanvasBitmap.SetPixelBytes, очевидно, очень трудно найти рабочий образец в C ++ WinRT, загруженный исходный код Win2D Gallery и его исходный код были только на C #, и я должен перевести его на C ++ и нет функции записи в один пиксель.

Может быть, я старый народный и унаследованный программист, со старым способом кодирования, который называется «Записать прямо на экран», и я обнаружил, что многие спрашивали об этом, но не могут найти полное решение, не говоря уже о примере исходного кода в C ++ WinRT.

Я не хочу сейчас вдаваться в Win2D, DirectX, Unity или любые другие причины, связанные с GPU или CPU. Более того, мои знания COM еще не получены и, глядя на источник шаблонов DirectX, меня уже напугали, хотя я уже писал в DirectX 2D в Win32.

Я новичок в C ++ WinRT, просто хочу простой кристально чистый пример кода на C ++ WinRT с XAML для UWP, написанного на основе 3 приведенных выше операторов.

Как только она будет решена, я легко перенесу свои знания в области 3D на платформу WinRT UWP.

Любая идея или ссылка с благодарностью.

Пожалуйста, сообщите.

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

Как уже отмечалось, WriteableBitmap может использоваться для рендеринга в растровое изображение в памяти.

Для полного рабочего примера начните с "Blank App (C ++ /WinRT) " шаблон (назовите его " WriteableBitmapSample ").Это дает вам хорошую отправную точку, полное приложение с одной страницей.

Чтобы настроить MainPage, чтобы освободить место для растрового изображения, используйте следующий код внутри сгенерированного MainPage.xaml file:

<Page
    ...

    <StackPanel Orientation="Vertical">
        <Button x:Name="myButton" Click="ClickHandler" HorizontalAlignment="Stretch">Generate bitmap</Button>
        <Image x:Name="myBitmap" Width="512" Height="512" />
    </StackPanel>
</Page>

Удалите все, что не нужно, из сгенерированного MainPage.idl :

namespace WriteableBitmapSample
{
    [default_interface]
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
    }
}

Теперь перейдем к реализации (внутри MainPage.cpp ).Большая часть этого реализована в ClickHandler с глобальным SetPixel помощником:

#include "pch.h"

#include "MainPage.h"

#include "MainPage.g.cpp"

#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.UI.Xaml.Media.Imaging.h>
#include <winrt/Windows.UI.h>

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::UI;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Media::Imaging;

namespace
{
void SetPixel(WriteableBitmap const& bitmap, int32_t const x, int32_t const y, Color const col)
{
    auto w { bitmap.PixelWidth() };
    // Get pointer to in-memory buffer
    auto p { bitmap.PixelBuffer().data() };
    // Calculate memory offset (4 bytes per pixel)
    auto offset { w * y * 4 + x * 4 };
    // Write pixel
    auto pixel_address { p + offset };
    *(pixel_address + 0) = col.B;
    *(pixel_address + 1) = col.G;
    *(pixel_address + 2) = col.R;
    *(pixel_address + 3) = col.A;
}
} // namespace

namespace winrt::WriteableBitmapSample::implementation
{
MainPage::MainPage() { InitializeComponent(); }

void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    // Create bitmap
    auto const width { 512 };
    auto const height { 512 };
    auto bitmap { WriteableBitmap(width, height) };

    // Construct gradient bitmap
    for (int32_t x = 0; x < width; ++x)
    {
        for (int32_t y = 0; y < height; ++y)
        {
            SetPixel(bitmap, x, y, ColorHelper::FromArgb(255, 255, x / 2, y / 2));
        }
    }

    // Set image source for the XAML interface
    myBitmap().Source(bitmap);
}
} // namespace winrt::WriteableBitmapSample::implementation

Обратите особое внимание, что реализация SetPixel намного медленнее, чем кажется.Вызов члена data() на PixelBuffer вызывает вызов QueryInterface, AddRef и Release.Для каждого пикселя.

В идеале это следует вызывать из асинхронного обработчика, но я не смог манипулировать WriteableBitmap из потока, отличного от потока пользовательского интерфейса.Похоже, что это ограничение DependencyObject (см. DependencyObject.Dispatcher ), из которого WriteableBitmap происходит.

0 голосов
/ 05 июня 2019

Проверьте класс WritableBitmap, вы можете манипулировать пикселями растрового изображения непосредственно через свойство WritableBitmap.PixelBuffer .

На странице есть образец.в правом верхнем углу страницы выберите нужный язык как C++/WinRT.

...