#include "Surface.h" IWICImagingFactory* Surface::wicFactory = nullptr; int Surface::totalSlot = 0; BYTE** imageData = nullptr; DXGI_FORMAT Surface::GetDXGIFormatFromWICFormat(WICPixelFormatGUID& wicFormatGUID) { if (wicFormatGUID == GUID_WICPixelFormat128bppRGBAFloat) return DXGI_FORMAT_R32G32B32A32_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBAHalf) return DXGI_FORMAT_R16G16B16A16_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBA) return DXGI_FORMAT_R16G16B16A16_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBA) return DXGI_FORMAT_R8G8B8A8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppBGRA) return DXGI_FORMAT_B8G8R8A8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppBGR) return DXGI_FORMAT_B8G8R8X8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBA1010102XR) return DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBA1010102) return DXGI_FORMAT_R10G10B10A2_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat16bppBGRA5551) return DXGI_FORMAT_B5G5R5A1_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat16bppBGR565) return DXGI_FORMAT_B5G6R5_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppGrayFloat) return DXGI_FORMAT_R32_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat16bppGrayHalf) return DXGI_FORMAT_R16_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat16bppGray) return DXGI_FORMAT_R16_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat8bppGray) return DXGI_FORMAT_R8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat8bppAlpha) return DXGI_FORMAT_A8_UNORM; else return DXGI_FORMAT_UNKNOWN; }; WICPixelFormatGUID Surface::GetConvertToWICFormat(WICPixelFormatGUID& wicFormatGUID) { if (wicFormatGUID == GUID_WICPixelFormatBlackWhite) return GUID_WICPixelFormat8bppGray; else if (wicFormatGUID == GUID_WICPixelFormat1bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat2bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat4bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat8bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat2bppGray) return GUID_WICPixelFormat8bppGray; else if (wicFormatGUID == GUID_WICPixelFormat4bppGray) return GUID_WICPixelFormat8bppGray; else if (wicFormatGUID == GUID_WICPixelFormat16bppGrayFixedPoint) return GUID_WICPixelFormat16bppGrayHalf; else if (wicFormatGUID == GUID_WICPixelFormat32bppGrayFixedPoint) return GUID_WICPixelFormat32bppGrayFloat; else if (wicFormatGUID == GUID_WICPixelFormat16bppBGR555) return GUID_WICPixelFormat16bppBGRA5551; else if (wicFormatGUID == GUID_WICPixelFormat32bppBGR101010) return GUID_WICPixelFormat32bppRGBA1010102; else if (wicFormatGUID == GUID_WICPixelFormat24bppBGR) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat24bppRGB) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat32bppPBGRA) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat32bppPRGBA) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat48bppRGB) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat48bppBGR) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppBGRA) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppPRGBA) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppPBGRA) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat48bppRGBFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat48bppBGRFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBAFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppBGRAFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBHalf) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat48bppRGBHalf) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat128bppPRGBAFloat) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat128bppRGBFloat) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat128bppRGBAFixedPoint) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat128bppRGBFixedPoint) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBE) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat32bppCMYK) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppCMYK) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat40bppCMYKAlpha) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat80bppCMYKAlpha) return GUID_WICPixelFormat64bppRGBA; #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) else if (wicFormatGUID == GUID_WICPixelFormat32bppRGB) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGB) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppPRGBAHalf) return GUID_WICPixelFormat64bppRGBAHalf; #endif else return GUID_WICPixelFormatDontCare; }; int Surface::GetDXGIFormatBitsPerPixel(DXGI_FORMAT& dxgiFormat) { if (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT) return 128; else if (dxgiFormat == DXGI_FORMAT_R16G16B16A16_FLOAT) return 64; else if (dxgiFormat == DXGI_FORMAT_R16G16B16A16_UNORM) return 64; else if (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_B8G8R8A8_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_B8G8R8X8_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_R10G10B10A2_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_B5G5R5A1_UNORM) return 16; else if (dxgiFormat == DXGI_FORMAT_B5G6R5_UNORM) return 16; else if (dxgiFormat == DXGI_FORMAT_R32_FLOAT) return 32; else if (dxgiFormat == DXGI_FORMAT_R16_FLOAT) return 16; else if (dxgiFormat == DXGI_FORMAT_R16_UNORM) return 16; else if (dxgiFormat == DXGI_FORMAT_R8_UNORM) return 8; else if (dxgiFormat == DXGI_FORMAT_A8_UNORM) return 8; }; UINT Surface::GetHeight() { return this->height; }; UINT Surface::GetWidth() { return this->width; }; DXGI_FORMAT Surface::GetDxgiFormat() { return this->dxgiFormat; }; UINT Surface::GetBytesPerRow() { return this->bytesPerRow; }; BYTE* Surface::GetImageData() { return this->imageData; }; UINT Surface::GetCurrSlot() { return this->currSlot; }; /************************************ * Texture 01 * Load the data from the image file * and decrypt it to a bitmap format * compatible with DXGI formats (rgba) ************************************/ void Surface::LoadImageFromFile( Microsoft::WRL::ComPtr dev, Microsoft::WRL::ComPtr devcon, std::string imageFile) { // reset decoder, frame and converter since these will be different for each image we load IWICBitmapDecoder* wicDecoder = NULL; IWICBitmapFrameDecode* wicFrame = NULL; IWICFormatConverter* wicConverter = NULL; HRESULT hr; std::wstring wsImageFile = std::wstring(imageFile.begin(), imageFile.end()); /************************************ * 1 Initialize the COM library ************************************/ if (wicFactory == nullptr) { hr = CoInitialize(wicFactory); } /************************************ * 2 Create WIC Factory ************************************/ hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&wicFactory)); /************************************ * 3 Create the Bitmap Decoder ************************************/ hr = wicFactory->CreateDecoderFromFilename( wsImageFile.c_str(), // Image we want to load in NULL, // This is a vendor ID, we do not prefer a specific one so set to null GENERIC_READ, // We want to read from this file WICDecodeMetadataCacheOnLoad, // We will cache the metadata right away, rather than when needed, which might be unknown &wicDecoder // the wic decoder to be created) ); /************************************ * 4 Grab the first frame in the image ************************************/ hr = wicDecoder->GetFrame(0, &wicFrame); /************************************ * 5 Get WIC Pixel Format From Frame ************************************/ WICPixelFormatGUID pixelFormat; hr = wicFrame->GetPixelFormat(&pixelFormat); /************************************ * 6 Get Size of the image ************************************/ hr = wicFrame->GetSize(&width, &height); /************************************ * 7 Get Compatible DXGI Format ************************************/ // convert wic pixel format to dxgi pixel format DXGI_FORMAT dxgiFormat = GetDXGIFormatFromWICFormat(pixelFormat); /************************************ * 8 Convert image to DXGI format if necessary ************************************/ bool imageConverted = false; // if the format of the image is not a supported dxgi format, try to convert it if (dxgiFormat == DXGI_FORMAT_UNKNOWN) { // get a dxgi compatible wic format from the current image format WICPixelFormatGUID convertToPixelFormat = GetConvertToWICFormat(pixelFormat); // return if no dxgi compatible format was found //if (convertToPixelFormat == GUID_WICPixelFormatDontCare) return 0; // set the dxgi format dxgiFormat = GetDXGIFormatFromWICFormat(convertToPixelFormat); // create the format converter hr = wicFactory->CreateFormatConverter(&wicConverter); //if (FAILED(hr)) return 0; // make sure we can convert to the dxgi compatible format BOOL canConvert = FALSE; hr = wicConverter->CanConvert(pixelFormat, convertToPixelFormat, &canConvert); //if (FAILED(hr) || !canConvert) return 0; // do the conversion (wicConverter will contain the converted image) hr = wicConverter->Initialize(wicFrame, convertToPixelFormat, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); //if (FAILED(hr)) return 0; // this is so we know to get the image data from the wicConverter (otherwise we will get from wicFrame) imageConverted = true; } /************************************ * 9 Get image size information ************************************/ int bitsPerPixel = GetDXGIFormatBitsPerPixel(dxgiFormat); // number of bits per pixel bytesPerRow = (width * bitsPerPixel) / 8; // number of bytes in each row of the image data int imageSize = bytesPerRow * height; // total image size in bytes /************************************ * 10 Get the pixel data (CopyPixel) ************************************/ // allocate enough memory for the raw image data, and set imageData to point to that memory imageData = (BYTE*)malloc(imageSize); // copy (decoded) raw image data into the newly allocated memory (imageData) if (imageConverted) { // if image format needed to be converted, the wic converter will contain the converted image hr = wicConverter->CopyPixels(0, bytesPerRow, imageSize, imageData); //if (FAILED(hr)) return 0; } else { // no need to convert, just copy data from the wic frame hr = wicFrame->CopyPixels(0, bytesPerRow, imageSize, imageData); //if (FAILED(hr)) return 0; } /************************************ * 11 Create Texture Resource ************************************/ // create texture resource D3D11_TEXTURE2D_DESC textureDesc = {}; textureDesc.Width = width; textureDesc.Height = height; textureDesc.MipLevels = 1; textureDesc.ArraySize = 1; textureDesc.Format = dxgiFormat; textureDesc.SampleDesc.Count = 1; textureDesc.SampleDesc.Quality = 0; textureDesc.Usage = D3D11_USAGE_DEFAULT; textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA sd = {}; sd.pSysMem = imageData; // s.GetBufferPtr(); sd.SysMemPitch = bytesPerRow; // s.GetWidth() * sizeof(Surface::Color); sd.SysMemSlicePitch = bytesPerRow * height; // wrl::ComPtr pTexture; ID3D11Texture2D* pTexture2D = nullptr; hr = dev->CreateTexture2D(&textureDesc, &sd, &pTexture2D); /************************************ * 12 Create the resource view on the texture ************************************/ ID3D11ShaderResourceView* pTextureView = nullptr; if (hr == S_OK) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Format = textureDesc.Format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = 1; hr = dev->CreateShaderResourceView(pTexture2D, &srvDesc, &pTextureView); } /************************************ * 13 Bind shader resource view to pipeline ************************************/ currSlot = (++totalSlot) - 1; devcon->PSSetShaderResources(currSlot, 1, &pTextureView); };