以下 "What's a Creel?" 教程:无法在 visual studio 2015 年创建 IWICBitmapDecoder
following "What's a Creel?"s tutorial: Can't create a IWICBitmapDecoder, in visual studio 2015
我一直在关注 "what's a Creel?" 的直接 2d 教程。我学习了教程 8:'Loading an image'。我没有让 spritesheet
对象保存指向 Graphics
对象的指针,因为这会导致此版本的 visual studio 出现问题,因此每次调用需要它的东西时都会传递它。要点:当我尝试使用 wicfactory->CreateDecoderFromFile()
方法创建 IWICBitmapDecoder
时,出现以下错误:
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{...}
代码是这样的:
#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
错误消息只是更改为随机位置内存。
发现问题。 CoCreateInstance()
的实现很好,但是他的代码有一些问题,与它已经过时有关。
现在,在我开始之前,我必须说,这部分摘自:https://msdn.microsoft.com/en-us/library/windows/desktop/dd756686(v=vs.85).aspx
这里的实现仍然没有提供 CoCreateInstance()
的可用实现,(还需要你有 this 教程的样板代码。另外,教程的代码来自 2008 年,架构扩展每次调整 window 大小时应用程序使用的内存量...但我离题了。要点:不要使用该教程的程序示例作为您自己程序的模型,但它确实提供了一个很好的示例关于如何 declare/initialize 正确的 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
,一些文档和教程相当脱节和未经测试,但如果你挖掘的时间足够长,你可以创建一个游戏。只记得将 x86/x64 可再分发包 运行 作为用 c# 编写的安装程序的一部分(因为 c++ 不再 运行 本机在 windows 中,而 c# 是它的一半快),你的 C++ 程序将 运行 在你需要它的地方。
我正在尝试执行您在此处提供的解决方案,但运气不佳,wicFactory 仍然为空。
D2DGauge* d2dg = reinterpret_cast<D2DGauge*>(args);
HRESULT hr;
bmp = nullptr;
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pSource = NULL;
IWICFormatConverter *pConverter = NULL;
//Creating a factory
IWICImagingFactory *wicFactory = NULL;
CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&wicFactory);
MessageBox(NULL, (LPCWSTR)wicFactory, NULL, MB_OK);
//Creating a decoder
hr = wicFactory->CreateDecoderFromFilename(
filename,
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&pDecoder);
//Read Frame from image
if (SUCCEEDED(hr)) {
// Create the initial frame.
hr = pDecoder->GetFrame(0, &pSource);
}
//Creating a Converter
if (SUCCEEDED(hr)) {
// Convert the image format to 32bppPBGRA
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
hr = wicFactory->CreateFormatConverter(&pConverter);
}
//Setup the converter
if (SUCCEEDED(hr)) {
hr = pConverter->Initialize(
pSource,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.f,
WICBitmapPaletteTypeMedianCut
);
}
//Use the converter to create an D2D1Bitmap
//ID2D1Bitmap* bmp;
if (SUCCEEDED(hr))
{
hr = d2dg->pRT->CreateBitmapFromWicBitmap(
pConverter,
NULL,
&bmp
);
}
if (wicFactory)wicFactory->Release();
if (pDecoder)pDecoder->Release();
if (pConverter)pConverter->Release();
if (pSource)pSource->Release();
我怎样才能让它不是 nullptr?
我一直在关注 "what's a Creel?" 的直接 2d 教程。我学习了教程 8:'Loading an image'。我没有让 spritesheet
对象保存指向 Graphics
对象的指针,因为这会导致此版本的 visual studio 出现问题,因此每次调用需要它的东西时都会传递它。要点:当我尝试使用 wicfactory->CreateDecoderFromFile()
方法创建 IWICBitmapDecoder
时,出现以下错误:
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{...}
代码是这样的:
#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
错误消息只是更改为随机位置内存。
发现问题。 CoCreateInstance()
的实现很好,但是他的代码有一些问题,与它已经过时有关。
现在,在我开始之前,我必须说,这部分摘自:https://msdn.microsoft.com/en-us/library/windows/desktop/dd756686(v=vs.85).aspx
这里的实现仍然没有提供 CoCreateInstance()
的可用实现,(还需要你有 this 教程的样板代码。另外,教程的代码来自 2008 年,架构扩展每次调整 window 大小时应用程序使用的内存量...但我离题了。要点:不要使用该教程的程序示例作为您自己程序的模型,但它确实提供了一个很好的示例关于如何 declare/initialize 正确的 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
,一些文档和教程相当脱节和未经测试,但如果你挖掘的时间足够长,你可以创建一个游戏。只记得将 x86/x64 可再分发包 运行 作为用 c# 编写的安装程序的一部分(因为 c++ 不再 运行 本机在 windows 中,而 c# 是它的一半快),你的 C++ 程序将 运行 在你需要它的地方。
我正在尝试执行您在此处提供的解决方案,但运气不佳,wicFactory 仍然为空。
D2DGauge* d2dg = reinterpret_cast<D2DGauge*>(args);
HRESULT hr;
bmp = nullptr;
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pSource = NULL;
IWICFormatConverter *pConverter = NULL;
//Creating a factory
IWICImagingFactory *wicFactory = NULL;
CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&wicFactory);
MessageBox(NULL, (LPCWSTR)wicFactory, NULL, MB_OK);
//Creating a decoder
hr = wicFactory->CreateDecoderFromFilename(
filename,
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&pDecoder);
//Read Frame from image
if (SUCCEEDED(hr)) {
// Create the initial frame.
hr = pDecoder->GetFrame(0, &pSource);
}
//Creating a Converter
if (SUCCEEDED(hr)) {
// Convert the image format to 32bppPBGRA
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
hr = wicFactory->CreateFormatConverter(&pConverter);
}
//Setup the converter
if (SUCCEEDED(hr)) {
hr = pConverter->Initialize(
pSource,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.f,
WICBitmapPaletteTypeMedianCut
);
}
//Use the converter to create an D2D1Bitmap
//ID2D1Bitmap* bmp;
if (SUCCEEDED(hr))
{
hr = d2dg->pRT->CreateBitmapFromWicBitmap(
pConverter,
NULL,
&bmp
);
}
if (wicFactory)wicFactory->Release();
if (pDecoder)pDecoder->Release();
if (pConverter)pConverter->Release();
if (pSource)pSource->Release();
我怎样才能让它不是 nullptr?