2016-06-29 20 views
-3

저는 "what is a Creel?"의 직접 2d 튜토리얼을 따라 왔습니다. 나는 튜토리얼 8 : '이미지로드'에 도착했다. 나는이객체가 Graphics 객체에 대한 포인터를 저장하지 않았기 때문에이 버전의 Visual Studio에서 문제가 발생하므로 호출해야 할 필요가있을 때마다 전달됩니다. 요점 : "What 's a Creel?"튜토리얼 : Visual Studio에서 IWICBitmapDecoder를 만들 수 없습니다. 2015

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

과 자동차의

내가 얻을 :

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

코드이되는 : 나는 wicfactory->CreateDecoderFromFile() 방법으로 IWICBitmapDecoder을 만들 때, 나는 다음과 같은 오류가 발생합니다

#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 객체를 선언/초기화하는 방법에 대한 좋은 예가 나와 있습니다.) DX12의 Microsoft 설명서도 최신 버전이 아니지만 여기서 설명 하겠습니다.

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입니다. 문서 및 자습서 중 일부는 오히려 분해되고 테스트되지 않았지만, 충분히 길게 보면 게임을 만들 수 있습니다. C#으로 작성된 설치 프로그램의 일부로 x86/x64 재배포 가능 패키지를 실행하는 것을 잊지 마십시오. (왜냐하면 C++은 Windows에서 더 이상 실행되지 않고 C#은 절반 만 빠르기 때문입니다) 그리고 C++ 프로그램이 필요할 때 실행됩니다 .