aboutsummaryrefslogtreecommitdiff
path: root/src/win/graphics/direct/ImageFactory.cpp
blob: dc43a9b992ef2fdbe6776e14ec1cc6c6c2c0c1a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "cru/win/graphics/direct/ImageFactory.hpp"
#include "cru/win/graphics/direct/Exception.hpp"
#include "cru/win/graphics/direct/Factory.hpp"
#include "cru/win/graphics/direct/Image.hpp"

#include <wincodec.h>

namespace cru::platform::graphics::win::direct {
WinImageFactory::WinImageFactory(DirectGraphicsFactory* graphics_factory)
    : DirectGraphicsResource(graphics_factory) {
  HRESULT hr =
      CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
                       IID_PPV_ARGS(&wic_imaging_factory_));
  ThrowIfFailed(hr);
}

WinImageFactory::~WinImageFactory() {}

std::unique_ptr<IImage> WinImageFactory::DecodeFromStream(io::Stream* stream) {
  // TODO: The correct way to do this is to implement a IStream wrapper.

  auto buffer = stream->ReadAll();

  HRESULT hr;

  Microsoft::WRL::ComPtr<IWICStream> wic_stream;
  hr = wic_imaging_factory_->CreateStream(&wic_stream);
  ThrowIfFailed(hr);

  hr = wic_stream->InitializeFromMemory(
      reinterpret_cast<unsigned char*>(buffer.data()), buffer.size());
  ThrowIfFailed(hr);

  Microsoft::WRL::ComPtr<IWICBitmapDecoder> wic_bitmap_decoder;
  hr = wic_imaging_factory_->CreateDecoderFromStream(
      wic_stream.Get(), NULL, WICDecodeMetadataCacheOnDemand,
      &wic_bitmap_decoder);
  ThrowIfFailed(hr);

  Microsoft::WRL::ComPtr<IWICBitmapFrameDecode> wic_bitmap_frame_decode;
  hr = wic_bitmap_decoder->GetFrame(0, &wic_bitmap_frame_decode);
  ThrowIfFailed(hr);

  auto d2d_context = graphics_factory_->GetDefaultD2D1DeviceContext();

  ID2D1Bitmap* d2d_image;
  d2d_context->CreateBitmapFromWicBitmap(wic_bitmap_frame_decode.Get(), NULL,
                                         &d2d_image);

  return std::make_unique<Direct2DImage>(graphics_factory_, d2d_image, true);
}
}  // namespace cru::platform::graphics::win::direct