I'm working on a (Universal Windows) c++/cx Directx project, which builds to a dll used in a c# UWP project.
I'm using the DirectX Toolkit to load textures.
I already use it to create a texture from file, but now I need it to create a texture from a byte array that was send from the UWP project. But when trying to use CreateWICTextureFromMemory(), the HRESULT says 0x88982F50:"The component cannot be found"
All I can find about this problem indicates the bytes are not a correct image, but I tested it in the UWP project, there I get the byte array from bingmaps (it's a static map image), and I could make a working image from these bytes.
Does annyone know what I'm doing wrong?
UWP c# download code (to get the bytes):
private async Task DownloadTexture()
{
byte[] buffer = null;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url);
WebResponse response = await request.GetResponseAsync();
using (Stream stream = response.GetResponseStream())
using (MemoryStream ms = new MemoryStream())
{
stream.CopyTo(ms);
buffer = ms.ToArray();
}
}
catch (Exception exception)
{
Logger.Error($"Could not Download Texture: {exception}");
}
_track3D.SetImage(out buffer[0], (ulong)buffer.Length);
}
Directx C++ code (that fails):
void Track3D::SetImage(uint8_t* ddsData, size_t ddsDataSize)
{
HRESULT result = CreateWICTextureFromMemory(_d3dDevice.Get(), _d3dContext.Get(), ddsData, ddsDataSize, nullptr, _Terrain.ReleaseAndGetAddressOf());
//here it goes wrong
//TODO: use the texture
}
UWP C# test code that works (displays image):
private async void setImage(byte[] buffer) //test
{
try
{
BitmapImage bmpImage = new BitmapImage();
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(buffer.AsBuffer());
stream.Seek(0);
await bmpImage.SetSourceAsync(stream);
}
Image image = new Image();
image.Source = bmpImage;
((Grid)Content).Children.Add(image);
}
catch (Exception exception)
{
Logger.Error($"{exception}");
}
}
EDIT:
OK, turns out the first byte in the buffer is different in the C++ code, than it was when sent from UWP. When I change that first byte to the correct value in the C++ code (as a test), the texture is correctly created.
Which raises the question, why did the value of the first byte change? (Or what did I do wrong?)
As requested, The function setImage() looks like this in c#:
[MethodImpl]
public void __ITrack3DPublicNonVirtuals.SetImage(out byte ddsData, [In] ulong ddsDataSize);
(also, I just realised the parameter names still have 'dds' in their name, sorry about that, will change that in my code as it is misleading)
0x88982F50: “The component cannot be found”
This is WINCODEC_ERR_COMPONENTNOTFOUND
which happens whenever WIC can't determine what format codec to use for a file/binary. Your problem is your transfer of the data from managed to native code is wrong.
Your interop method is set to:
[MethodImpl]
public void __ITrack3DPublicNonVirtuals.SetImage(out byte ddsData, [In] ulong ddsDataSize);
With the C++ method signature being:
void Track3D::SetImage(uint8_t* ddsData, size_t ddsDataSize)
Because of the out
your first parameter is being passed as a safe array with the length in the first element.
Instead you should use:
SetImage([In] byte ddsData, [In] ulong ddsDataSize); // C#
void Track3D::SetImage(const uint8_t* ddsData, size_t ddsDataSize); // C++.
User contributions licensed under CC BY-SA 3.0