Windows10 Image

Windows10 Direct2D で Image を描画します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. Class App1Main に直接 Image を描画するソースコードを書きます。
    Win10 Base を参照して「Windows10 ベースプロジェクト」を構築して下さい。
    ベースプロジェクトが存在するときは、フォルダーごとコピーしてフォルダー名を変更してもOKです。
    プロジェクトの名前は App1 で説明します。
  2. プロジェクトのフォルダー(App1)に画像(ffx2s.jpg)を格納して下さい。
    App1 を選択して[追加][既存の項目]からプロジェクトに追加します。
    画像は ffx2s.jpg に限らず、適当なもので構いません。
    ファイル名が異なるときは L"ffx2s.jpg" を書き替えて下さい。
        DX::ThrowIfFailed(
            m_wicFactory->CreateDecoderFromFilename(
                L"ffx2s.jpg",
                nullptr,
                GENERIC_READ,
                WICDecodeMetadataCacheOnDemand,
                &decoder
                )
            );
    
  3. App1Main.h に Image 関係の領域を定義します。
        Microsoft::WRL::ComPtr<ID2D1DeviceContext1>  m_d2dContext;
        Microsoft::WRL::ComPtr<IWICImagingFactory2>  m_wicFactory;
        Microsoft::WRL::ComPtr<ID2D1Bitmap1>         m_bitmapPerspective;
    
  4. App1Main.cpp に Image を描画するソースコードを書きます。
    App1Main() 関数で Image 領域を初期化して画像を入力します。
        // TODO: これをアプリのコンテンツの初期化で置き換えます。
        m_d2dContext = m_deviceResources->GetD2DDeviceContext();
        m_wicFactory = m_deviceResources->GetWicImagingFactory();
    
        Microsoft::WRL::ComPtr<IWICBitmapDecoder> decoder;
        DX::ThrowIfFailed(
          ・・・
    
    Render() で画像を描画します。
    bool App1Main::Render() 
    {
          ・・・
        // シーン オブジェクトをレンダリングします。
        m_d2dContext->BeginDraw();  
        m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
        m_d2dContext->DrawBitmap(m_bitmapPerspective.Get());
        HRESULT hr = m_d2dContext->EndDraw();
        if (hr != D2DERR_RECREATE_TARGET)
        {   DX::ThrowIfFailed(hr);  }
    
        return true;
    }
    
  5. App1Main.h の全ソースコードです。
    #pragma once
    
    #include "Common\StepTimer.h"
    #include "Common\DeviceResources.h"
    
    // Direct2D および 3D コンテンツを画面上でレンダリングします。
    namespace App1
    {
        class App1Main : public DX::IDeviceNotify
        {
        public:
            App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources);
            ~App1Main();
            void CreateWindowSizeDependentResources();
            void Update();
            bool Render();
    
            // IDeviceNotify
            virtual void OnDeviceLost();
            virtual void OnDeviceRestored();
    
        private:
            // デバイス リソースへのキャッシュされたポインター。
            std::shared_ptr<DX::DeviceResources> m_deviceResources;
    
            // TODO: これを独自のコンテンツ レンダラーで置き換えます。
            Microsoft::WRL::ComPtr<ID2D1DeviceContext1>  m_d2dContext;
            Microsoft::WRL::ComPtr<IWICImagingFactory2>  m_wicFactory;
            Microsoft::WRL::ComPtr<ID2D1Bitmap1>         m_bitmapPerspective;
    
            // ループ タイマーをレンダリングしています。
            DX::StepTimer m_timer;
        };
    }
    
  6. App1Main.cpp の全ソースコードです。
    #include "pch.h"
    #include "App1Main.h"
    #include "Common\DirectXHelper.h"
    
    using namespace App1;
    using namespace Windows::Foundation;
    using namespace Windows::System::Threading;
    using namespace Concurrency;
    
    // アプリケーションの読み込み時にアプリケーション資産を読み込んで初期化します。
    App1Main::App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
        m_deviceResources(deviceResources)
    {
        // デバイスが失われたときや再作成されたときに通知を受けるように登録します
        m_deviceResources->RegisterDeviceNotify(this);
    
        // TODO: これをアプリのコンテンツの初期化で置き換えます。
        m_d2dContext = m_deviceResources->GetD2DDeviceContext();
        m_wicFactory = m_deviceResources->GetWicImagingFactory();
    
        Microsoft::WRL::ComPtr<IWICBitmapDecoder> decoder;
        DX::ThrowIfFailed(
            m_wicFactory->CreateDecoderFromFilename(
                L"ffx2s.jpg",
                nullptr,
                GENERIC_READ,
                WICDecodeMetadataCacheOnDemand,
                &decoder
                )
            );
        Microsoft::WRL::ComPtr<IWICBitmapFrameDecode> frame;
        DX::ThrowIfFailed(
            decoder->GetFrame(0, &frame)
            );
        Microsoft::WRL::ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            );
        DX::ThrowIfFailed(
            converter->Initialize(
                frame.Get(),
                GUID_WICPixelFormat32bppPBGRA,
                WICBitmapDitherTypeNone,
                nullptr,
                0.0f,
                WICBitmapPaletteTypeCustom
                )
            );
        DX::ThrowIfFailed(
            m_d2dContext->CreateBitmapFromWicBitmap(
                converter.Get(),
                nullptr,
                &m_bitmapPerspective
                )
            );
    }
    
    App1Main::~App1Main()
    {
        // デバイスの通知を登録解除しています
        m_deviceResources->RegisterDeviceNotify(nullptr);
    }
    
    //ウィンドウのサイズが変更される (デバイスの方向が変更されるなど) 場合に、 アプリケーションの状態を更新します。
    void App1Main::CreateWindowSizeDependentResources() 
    {
        // TODO: これをアプリのコンテンツのサイズに依存する初期化で置き換えます。
    }
    
    // アプリケーション状態をフレームごとに 1 回更新します。
    void App1Main::Update() 
    {
        // シーン オブジェクトを更新します。
        m_timer.Tick([&]()
        {
            // TODO: これをアプリのコンテンツの更新関数で置き換えます。
        });
    }
    
    // 現在のアプリケーション状態に応じて現在のフレームをレンダリングします。
    // フレームがレンダリングされ、表示準備が完了すると、true を返します。
    bool App1Main::Render() 
    {
        // 初回更新前にレンダリングは行わないようにしてください。
        if (m_timer.GetFrameCount() == 0)
        {   return false;  }
    
        auto context = m_deviceResources->GetD3DDeviceContext();
    
        // ビューポートをリセットして全画面をターゲットとします。
        auto viewport = m_deviceResources->GetScreenViewport();
        context->RSSetViewports(1, &viewport);
    
        // レンダリング ターゲットを画面にリセットします。
        ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
        context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
    
        // バック バッファーと深度ステンシル ビューをクリアします。
        context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
        context->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
    
        // シーン オブジェクトをレンダリングします。
        m_d2dContext->BeginDraw();  
        m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
        m_d2dContext->DrawBitmap(m_bitmapPerspective.Get());
        HRESULT hr = m_d2dContext->EndDraw();
        if (hr != D2DERR_RECREATE_TARGET)
        {   DX::ThrowIfFailed(hr);  }
    
        return true;
    }
    
    // デバイス リソースを解放する必要が生じたことをレンダラーに通知します。
    void App1Main::OnDeviceLost()
    {
    }
    
    // デバイス リソースの再作成が可能になったことをレンダラーに通知します。
    void App1Main::OnDeviceRestored()
    {
        CreateWindowSizeDependentResources();
    }
    

LoadBitmapFile() 関数を使う

  1. プロジェクトに組み込んだ画像を Load するソースコードは、結構長くて面倒です。
    そこで LoadBitmapFile() 関数として定義してみました。
    詳細は Image Load を参照して下さい。
  2. プロトタイプ宣言が無くても参照出来るように using の直後に LoadBitmapFile() 関数を置きます。
    // ★LoadBitmapFile 関数  前田 稔
    Microsoft::WRL::ComPtr<ID2D1Bitmap1> LoadBitmapFile(
        Microsoft::WRL::ComPtr<ID2D1DeviceContext>  d2dContext,
        Microsoft::WRL::ComPtr<IWICImagingFactory2> wicFactory,
        PCWSTR          uri)
    {
        Microsoft::WRL::ComPtr<ID2D1Bitmap1>    bitmapPerspective;
        Microsoft::WRL::ComPtr<IWICBitmapDecoder> decoder;
        DX::ThrowIfFailed(
            wicFactory->CreateDecoderFromFilename(
                uri, nullptr, GENERIC_READ,
                WICDecodeMetadataCacheOnDemand, &decoder));
        Microsoft::WRL::ComPtr<IWICBitmapFrameDecode> frame;
        DX::ThrowIfFailed(decoder->GetFrame(0, &frame));
        Microsoft::WRL::ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(wicFactory->CreateFormatConverter(&converter));
        DX::ThrowIfFailed(
            converter->Initialize(
                frame.Get(), GUID_WICPixelFormat32bppPBGRA,
                WICBitmapDitherTypeNone, nullptr, 0.0f,
                WICBitmapPaletteTypeCustom));
    
        DX::ThrowIfFailed(
            d2dContext->CreateBitmapFromWicBitmap(
                converter.Get(), nullptr,
                &bitmapPerspective));
        return bitmapPerspective;
    }
    
  3. 画像の Load は次のようになります。
        // TODO: これをアプリのコンテンツの初期化で置き換えます。
        m_d2dContext = m_deviceResources->GetD2DDeviceContext();
        m_wicFactory = m_deviceResources->GetWicImagingFactory();
    
        m_bitmapPerspective = LoadBitmapFile(m_d2dContext, m_wicFactory, L"ffx2s.jpg");
    

超初心者のプログラム入門(DirectX Store)