2016-06-29 16 views
-3

Я слежу за учебником «Что такое Creel?» Для прямого 2d. Я получил учебное пособие 8: «Загрузка изображения». У меня не было объекта spritesheet, сохраняя указатель на объект Graphics, так как это вызвало проблемы с этой версией визуальной студии, поэтому оно передается каждый раз, когда что-то требует его вызова. Главное: когда я пытаюсь создать IWICBitmapDecoder с помощью метода wicfactory->CreateDecoderFromFile(), я получаю следующее сообщение об ошибке:, следующий за инструкцией «Что такое Creel?»: Невозможно создать IWICBitmapDecoder, в visual studio 2015

Exception thrown at 0x008C70A7 in Project8.exe: 0xC0000005: Access violation reading location 0x00000000.

и в Autos я получаю:

hr | E_NOINTERFACE No such interface supported. this | 0x00c1a5c8 {bmp=0x00000000 <NULL> } spritesheet * wicfactory | 0x00000000<NULL> wicdecoder | 0xcccccccc{...}

код был это:

#pragma once 

#include <wincodec.h> //include windowscodecs.lib in the linker input 
#include "Graphics.h" 
#include <d2d1.h> 
#include<string> 

class spritesheet { 
public: 

    ID2D1Bitmap* bmp; 
    spritesheet() {} 

    spritesheet(LPCWSTR file, graphics* gfx) { 
     //this->gfx = gfx; 
     //bmp = NULL; 
     HRESULT hr; 
     //create an image factory 
     IWICImagingFactory *wicFactory; 
     hr = CoCreateInstance(
      CLSID_WICImagingFactory, 
      NULL, 
      CLSCTX_INPROC_SERVER, 
      CLSID_WICImagingFactory, 
      (LPVOID*)&wicFactory 
      ); 

     //create a decoder 
     IWICBitmapDecoder *wicdecoder; 
     hr = wicFactory->CreateDecoderFromFilename(
      file, 
      NULL, 
      GENERIC_READ, 
      WICDecodeMetadataCacheOnLoad, 
      &wicdecoder 
      ); 
     IWICBitmapFrameDecode* wicframe = NULL; 
     hr = wicdecoder->GetFrame(0, &wicframe); 

     IWICFormatConverter *wicconverter = NULL; 
     hr = wicFactory->CreateFormatConverter(&wicconverter); 

     hr = wicconverter->Initialize(
      wicframe, 
      GUID_WICPixelFormat32bppPBGRA, 
      WICBitmapDitherTypeNone, 
      NULL, 
      0.0, 
      WICBitmapPaletteTypeCustom 
      ); 

     gfx->gettarget()->CreateBitmapFromWicBitmap(
      wicconverter, 
      NULL, 
      &bmp 
      ); 

     if (wicdecoder) wicdecoder->Release(); 
     if (wicFactory) wicFactory->Release(); 
     if (wicconverter) wicconverter->Release(); 
     if (wicframe) wicframe->Release(); 

    } 

    void init(wchar_t * file, graphics * gfx) { 
     //this->gfx = gfx; 
     //bmp = NULL; 
     HRESULT hr; 
     //create an image factory 
     IWICImagingFactory* wicFactory; 
     hr = CoCreateInstance(
      CLSID_WICImagingFactory, 
      NULL, 
      CLSCTX_INPROC_SERVER, 
      CLSID_WICImagingFactory, 
      (LPVOID*)&wicFactory 
      ); 

     //create a decoder 
     IWICBitmapDecoder* wicdecoder; 
     hr = wicFactory->CreateDecoderFromFilename(
      file, 
      NULL, 
      GENERIC_READ, 
      WICDecodeMetadataCacheOnLoad, 
      &wicdecoder 
      ); 

     IWICBitmapFrameDecode* wicframe = NULL; 
     hr = wicdecoder->GetFrame(0, &wicframe); 

     IWICFormatConverter *wicconverter = NULL; 
     hr = wicFactory->CreateFormatConverter(&wicconverter); 

     hr = wicconverter->Initialize(
      wicframe, 
      GUID_WICPixelFormat32bppPBGRA, 
      WICBitmapDitherTypeNone, 
      NULL, 
      0.0, 
      WICBitmapPaletteTypeCustom 
      ); 

     gfx->rendertarget->CreateBitmapFromWicBitmap(
      wicconverter, 
      NULL, 
      &bmp 
      ); 

     if (wicdecoder) wicdecoder->Release(); 
     if (wicFactory) wicFactory->Release(); 
     if (wicconverter) wicconverter->Release(); 
     if (wicframe) wicframe->Release(); 

     gfx->rendertarget->DrawBitmap(
      bmp, 
      D2D1::RectF(0.0f, 0.0f, 10, 10),  //dest rect 
      1.0f, 
      D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, //effect for scaling 
     D2D1::RectF(0, 0, 10, 10));    //scource rect 


} 


void draw(graphics *gfx) { 
    gfx->rendertarget->DrawBitmap(
     bmp, 
     D2D1::RectF(0.0f, 0.0f, 10, 10),  //dest rect 
     1.0f, 
     D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, //effect for scaling 
     D2D1::RectF(0, 0, 10, 10));    //scource rect 

    } 
}; 

сейчас, чтобы проверить вещи, я поставил ID2D1Bitmap* bmp; в начале каждого метода, чтобы увидеть, где все получилось, но сообщение об ошибке wicdecoder просто изменилось на случайное место в памяти.

+1

Вы не используете CoCreateInstance() правильно. Используйте правильный интерфейс guid, IID_IWICImagingFactory. И добавьте проверку ошибок, чтобы вы не просто продолжали пахать, пока не упали со случайным исключением. –

+0

Можете ли вы привести пример того, как я буду использовать CoCreateInstance() в этом контексте? я немного новичок в этом, и мне было интересно, как ветеран будет его реализовывать – mrsamsir

ответ

0

Обнаружили проблему. реализация CoCreateInstance() была прекрасной, но было несколько проблем с его кодом, связанным с тем, что он устарел.

сейчас, прежде чем я начну, я должен сказать, что это был ЧАСТИЧНО взят из: https://msdn.microsoft.com/en-us/library/windows/desktop/dd756686(v=vs.85).aspx

реализации здесь до сих пор не дает полезной реализации CoCreateInstance(), (а также требует, чтобы иметь шаблонный код this учебника. Кроме того, код учебника с 2008 года, и архитектура расширяет объем памяти, которую приложение использует каждый раз, когда вы изменяете размер окна ... но я отвлекаюсь. Главное: НЕ используйте этот пример программы учебника в качестве модели для собственных программ , но он дает хороший пример того, как объявлять/инициализировать соответствующие объекты WIC и D2D), документация Microsoft для DX12 также устарела, но это то, что я поясню здесь.

правильная реализация CoCreateInstance() и правильный способ загрузить изображение является:

void spritesheet::load(PCWSTR uri, ID2D1HwndRenderTarget * gfx) { 

    IWICBitmapDecoder *pDecoder = NULL; 
    IWICBitmapFrameDecode *pSource = NULL; 
    IWICStream *pStream = NULL; 
    IWICFormatConverter *pConverter = NULL; 
    IWICBitmapScaler *pScaler = NULL; 


    IWICImagingFactory *wicFactory = NULL; 

    CoCreateInstance(
     CLSID_WICImagingFactory, 
     NULL, 
     CLSCTX_INPROC_SERVER, 
     IID_IWICImagingFactory, 
     (LPVOID*)&wicFactory); 

    HRESULT hr = wicFactory->CreateDecoderFromFilename(
     uri, 
     NULL, 
     GENERIC_READ, 
     WICDecodeMetadataCacheOnLoad, 
     &pDecoder 
     ); 


    if (SUCCEEDED(hr)) { 
     // Create the initial frame. 
     hr = pDecoder->GetFrame(0, &pSource); 
    } 


    if (SUCCEEDED(hr)) { 

     // Convert the image format to 32bppPBGRA 
     // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED). 
     hr = wicFactory->CreateFormatConverter(&pConverter); 

    } 


    if (SUCCEEDED(hr)) { 
     hr = pConverter->Initialize(
      pSource, 
      GUID_WICPixelFormat32bppPBGRA, 
      WICBitmapDitherTypeNone, 
      NULL, 
      0.f, 
      WICBitmapPaletteTypeMedianCut 
      ); 
    } 
    if (SUCCEEDED(hr)) 
    { 

     // Create a Direct2D bitmap from the WIC bitmap. 
     hr = gfx->CreateBitmapFromWicBitmap(
      pConverter, 
      NULL, 
      &bmp 
      ); 
    } 

    if (pDecoder) { 
     pDecoder->Release(); 
    } 
    if (pSource) { 
     pSource->Release(); 

    } 
    if (pConverter) { 
     pConverter->Release(); 
    } 
} 

Примечание: URI просто быть имя файла в формате PCWSTR, заявленный как L"name.bmp" при переходе к функции ,

правильный способ сделать изображение является:

void spritesheet::draw(ID2D1HwndRenderTarget * gfx, float bx, float by, float rx, float ry, float dx, float dy) { 

    D2D1_SIZE_F size = bmp->GetSize(); 
    D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(dx, dy); 

    gfx->DrawBitmap(
     bmp, 
     D2D1::RectF(
      upperLeftCorner.x, 
      upperLeftCorner.y, 
      upperLeftCorner.x + rx, 
      upperLeftCorner.y + ry), 
     1, 
     D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, 
     D2D1::RectF(
      bx, 
      by, 
      rx, 
      ry) 
     ); 
} 

Теперь, остальная часть документации D2D не в курсе, но все еще дает хороший пример того, что там использовать. Некоторые из объектов больше не существуют, например, D2D1::Rect, и теперь у вас есть только: D2D1::RectF, некоторые из документации и учебников довольно разрознены и непроверены, но если вы копаете достаточно долго, вы можете создать игру. просто помните, что распространяемые пакеты x86/x64 выполняются как часть вашего установщика, написанного на C# (поскольку C++ больше не будет запускаться изначально в окнах, а C# - наполовину быстрее), а ваша программа на C++ будет работать там, где вам это нужно ,