2016-10-03 14 views
1

Я пытаюсь использовать WIC для загрузки изображения из файла и отображения его на экране с помощью Direct2D. Я следую за MSDN example, но у меня возникла проблема с функцией CreateBitmapFromWicBitmap().ID2D1HwndRenderTarget :: CreateBitmapFromWicBitmap()

Независимо от того, какая комбинация pixel formats я использую при создании ID2D1HwndRenderTarget и IWICFormatConverter::Initialize() вызова функции, не функционирует CreateBitmapFromWicBitmap() возвращается 0x88982f80 ошибок (WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT).

Я вызываю функцию, используя тот же ID2D1HwndRenderTarget, который я использую для рисования. Должен ли я создать другую цель рендеринга?

В разделе комментариев в этом link кто-то написал, что CreateBitmapFromWicBitmap() должен быть вызван объектом визуализации поверхности DXGI. Означает ли это, что эта функция просто не может использоваться с ID2D1HwndRenderTarget?

EDIT:

void LoadBitmapFromFile(ID2D1HwndRenderTarget* target, ID2D1Bitmap** ppBitmap) 
{ 
    IWICImagingFactory* factory; 
    IWICBitmapDecoder* decoder; 
    IWICBitmapFrameDecode* frame; 
    IWICFormatConverter* converter; 

    CoInitializeEx(0, COINIT_MULTITHREADED); 
    CoCreateInstance(CLSID_WICImagingFactory1, 
        NULL, 
        CLSCTX_INPROC_SERVER, 
        IID_IWICImagingFactory, 
        reinterpret_cast<void**>(&factory)); 

    factory->CreateDecoderFromFilename(L".png", 
             NULL, 
             GENERIC_READ, 
             WICDecodeMetadataCacheOnLoad, 
             &decoder); 

    decoder->GetFrame(0, &frame); 

    factory->CreateFormatConverter(&converter); 

    converter->Initialize(frame, 
          GUID_WICPixelFormat32bppPBGRA, 
          WICBitmapDitherTypeNone, 
          NULL, 
          0.f, 
          WICBitmapPaletteTypeMedianCut); 

    target->CreateBitmapFromWicBitmap(frame, 0, ppBitmap); 
} 

ID2D1HwndRenderTarget создается так:

ID2D1Factory* factory; 
ID2D1HwndRenderTarget* target; 

D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory); 

factory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_HARDWARE, 
           D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)), 
    D2D1::HwndRenderTargetProperties(hwnd, D2D1::SizeU(width, height)), 
    &target); 
+0

Просьба показать код в [MCVE] (http://stackoverflow.com/help/mcve) образом. –

ответ

2

CreateBitmapFromWicBitmap ожидает converter в качестве первого параметра, не frame.

Использовать CLSID_WICImagingFactory вместо CLSID_WICImagingFactory1. Компилятор выберет правильное значение. В моем случае он выбирает CLSID_WICImagingFactory2

Имя переменной для IWICImagingFactory* factory скрывает глобальную переменную с тем же именем. Вероятно, это не вызвало ошибку, но лучше ее изменить ...

Ручки необходимо освободить.

HRESULT LoadBitmapFromFile(const wchar_t *filename, ID2D1HwndRenderTarget* target, ID2D1Bitmap** pBitmap) 
{ 
    HRESULT hr = S_FALSE; 
    IWICImagingFactory* wic_factory = NULL; 
    IWICBitmapDecoder* decoder = NULL; 
    IWICBitmapFrameDecode* frame = NULL; 
    IWICFormatConverter* converter = NULL; 

    hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void**>(&wic_factory)); 
    if FAILED(hr) goto clenaup; 

    hr = wic_factory->CreateDecoderFromFilename(filename, NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder); 
    if FAILED(hr) goto clenaup; 

    hr = decoder->GetFrame(0, &frame); 
    if FAILED(hr) goto clenaup; 

    hr = wic_factory->CreateFormatConverter(&converter); 
    if FAILED(hr) goto clenaup; 

    hr = converter->Initialize(frame, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut); 
    if FAILED(hr) goto clenaup; 

    hr = target->CreateBitmapFromWicBitmap(converter, 0, pBitmap); 
    if FAILED(hr) goto clenaup; 

clenaup: 
    safe_release(decoder); 
    safe_release(converter); 
    safe_release(frame); 
    safe_release(wic_factory); 
    return hr; 
} 

CoInitializeEx(0, COINIT_MULTITHREADED) можно вызвать один раз при инициализации.

ID2D1Factory* factory; 
ID2D1HwndRenderTarget* target; 

void initialize(HWND hwnd) 
{ 
    CoInitializeEx(0, COINIT_MULTITHREADED); 

    RECT rc; 
    GetClientRect(hwnd, &rc); 

    D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory); 
    factory->CreateHwndRenderTarget(
     D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_HARDWARE, 
     D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)), 
     D2D1::HwndRenderTargetProperties(hwnd, D2D1::SizeU(rc.right, rc.bottom)), 
     &target); 
} 

void on_render() 
{ 
    target->BeginDraw(); 
    target->Clear(D2D1::ColorF(D2D1::ColorF::White)); 

    ID2D1Bitmap* pBitmap = NULL; 
    if (SUCCEEDED(LoadBitmapFromFile(L"filename.png", target, &pBitmap))) 
    { 
     D2D1_SIZE_F size = pBitmap->GetSize(); 
     target->DrawBitmap(pBitmap, D2D1::RectF(0, 0, size.width, size.height)); 
     safe_release(pBitmap); 
    } 

    target->EndDraw(); 
} 
+0

Большое спасибо за то, что заметили эту проблему в CreateBitmapFromWicBitmap(). Я бы никогда не нашел его. Но я нашел другую вещь. Когда я изменяю CLSID_WICImagingFactory1 на CLSID_WICImagingFactory, CoCreateInstance() возвращает REGDB_E_CLASSNOTREG. – Avert

+0

Я вижу. Здесь есть дополнительная информация о 'CLSID_WICImagingFactory' [ссылка] (http://stackoverflow.com/a/16699299/4603670). Я в VS2015 на Windows 10, и оба 'CLSID_WICImagingFactory1' и' CLSID_WICImagingFactory2' работают нормально. –

 Смежные вопросы

  • Нет связанных вопросов^_^