示例#1
0
HRESULT D3DWCubeMap::Create(
  ID3DWTexture *posX,
  ID3DWTexture *negX,
  ID3DWTexture *posY,
  ID3DWTexture *negY,
  ID3DWTexture *posZ,
  ID3DWTexture *negZ,
  D3DWContext *ctx,
  D3DWCubeMap **oCubeMap)
{
  if(!oCubeMap)
    return E_POINTER;
  *oCubeMap = NULL;
  ComObject<D3DWCubeMap> *cubeMap = new (std::nothrow) ComObject<D3DWCubeMap>();
  if(!cubeMap)
    return E_OUTOFMEMORY;
  HRESULT hr = cubeMap->Initialize(posX, negX, posY, negY, posZ, negZ, ctx);
  if(FAILED(hr))
  {
    SafeDelete(cubeMap);
    return hr;
  }
  cubeMap->AddRef();
  *oCubeMap = cubeMap;
  return S_OK;
}
//----------------------------------------------------------------------------
Texture2* WICFileIO::Load(std::string const& filename, bool wantMipmaps)
{
    // Start COM and create WIC.
    ComInitializer comInitializer;
    if (!comInitializer.IsInitialized())
    {
        LogError("Unable to initialize COM for WIC.");
        return nullptr;
    }

    // Create a WIC imaging factory.
    ComObject<IWICImagingFactory> wicFactory;
    HRESULT hr = ::CoCreateInstance(CLSID_WICImagingFactory, nullptr,
        CLSCTX_INPROC_SERVER, IID_IWICImagingFactory,
        reinterpret_cast<LPVOID*>(&wicFactory));
    if (FAILED(hr))
    {
        LogError("Unable to create WIC imaging factory.");
        return nullptr;
    }

    // Create a decoder based on the file name.
    std::wstring wfilename = Environment::Convert(filename);
    ComObject<IWICBitmapDecoder> wicDecoder;
    hr = wicFactory->CreateDecoderFromFilename(wfilename.c_str(),
        nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &wicDecoder);
    if (FAILED(hr))
    {
        LogError("wicFactory->CreateDecoderFromFilename failed (" +
            filename + ").");
        return nullptr;
    }

    // Create a WIC decoder.
    ComObject<IWICBitmapFrameDecode> wicFrameDecode;
    hr = wicDecoder->GetFrame(0, &wicFrameDecode);
    if (FAILED(hr))
    {
        LogError("wicDecoder->GetFrame failed.");
        return nullptr;
    }

    // Get the pixel format of the image.
    WICPixelFormatGUID wicSourceGUID;
    hr = wicFrameDecode->GetPixelFormat(&wicSourceGUID);
    if (FAILED(hr))
    {
        LogError("wicFrameDecode->GetPixelFormat failed.");
        return nullptr;
    }

    // Find the supported WIC input pixel format that matches a Texture2
    // format.  If a matching format is not found, the returned texture
    // is an R8G8B8A8 format with texels converted from the source format.
    WICPixelFormatGUID wicConvertGUID = GUID_WICPixelFormat32bppRGBA;
    DFType gtformat = DF_R8G8B8A8_UNORM;
    for (int i = 0; i < NUM_LOAD_FORMATS; ++i)
    {
        if (IsEqualGUID(wicSourceGUID, *msLoadFormatMap[i].wicInputGUID))
        {
            // Determine whether there is a conversion format.
            if (msLoadFormatMap[i].wicConvertGUID)
            {
                wicConvertGUID = *msLoadFormatMap[i].wicConvertGUID;
            }
            else
            {
                wicConvertGUID = *msLoadFormatMap[i].wicInputGUID;
            }
            gtformat = msLoadFormatMap[i].gtFormat;
            break;
        }
    }

    // The wicFrameDecode value is used for no conversion.  If the decoder
    // does not support the format in the texture, then a conversion is
    // required.
    IWICBitmapSource* wicBitmapSource = wicFrameDecode;
    ComObject<IWICFormatConverter> wicFormatConverter;
    if (!IsEqualGUID(wicSourceGUID, wicConvertGUID))
    {
        // Create a WIC format converter.
        hr = wicFactory->CreateFormatConverter(&wicFormatConverter);
        if (FAILED(hr))
        {
            LogError("wicFactory->CreateFormatConverter failed.");
            return false;
        }

        // Initialize format converter to convert the input texture format
        // to the nearest format supported by the decoder.
        hr = wicFormatConverter->Initialize(wicFrameDecode, wicConvertGUID,
            WICBitmapDitherTypeNone, nullptr, 0.0,
            WICBitmapPaletteTypeCustom);
        if (FAILED(hr))
        {
            LogError("wicFormatConverter->Initialize failed.");
            return false;
        }

        // Use the format converter.
        wicBitmapSource = wicFormatConverter;
    }

    // Get the image dimensions.
    UINT width, height;
    hr = wicBitmapSource->GetSize(&width, &height);
    if (FAILED(hr))
    {
        LogError("wicBitmapSource->GetSize failed.");
        return nullptr;
    }

    // Create the 2D texture and compute the stride and image size.
    std::unique_ptr<Texture2> texture(new Texture2(gtformat, width,
        height, wantMipmaps));
    UINT const stride = width * texture->GetElementSize();
    UINT const imageSize = stride * height;

    // Copy the pixels from the decoder to the texture.
    hr = wicBitmapSource->CopyPixels(nullptr, stride, imageSize,
        texture->Get<BYTE>());
    if (FAILED(hr))
    {
        LogError("wicBitmapSource->CopyPixels failed.");
        return nullptr;
    }

    return texture.release();
}
//----------------------------------------------------------------------------
bool WICFileIO::SaveToPNG(std::string const& filename, Texture2* texture)
{
    if (!texture || !texture->GetData())
    {
        LogError("The texture and its data must exist.");
        return false;
    }

    // Select the WIC format that matches the input texture format.
    WICPixelFormatGUID wicSourceGUID = GUID_WICPixelFormatUndefined;
    for (int i = 0; i < NUM_SAVE_FORMATS; ++i)
    {
        if (msSaveFormatMap[i].gtFormat == texture->GetFormat())
        {
            wicSourceGUID = *msSaveFormatMap[i].wicOutputGUID;
            break;
        }
    }
    if (IsEqualGUID(wicSourceGUID, GUID_WICPixelFormatUndefined))
    {
        LogError("Format " +
            DataFormat::GetName(texture->GetFormat()) +
            "cannot be saved to PNG.");
        return false;
    }

    // Start COM and create WIC.
    ComInitializer comInitializer;
    if (!comInitializer.IsInitialized())
    {
        LogError("Unable to initialize COM for WIC.");
        return false;
    }

    // Create a WIC imaging factory.
    ComObject<IWICImagingFactory> wicFactory;
    HRESULT hr = ::CoCreateInstance(CLSID_WICImagingFactory, nullptr,
        CLSCTX_INPROC_SERVER, IID_IWICImagingFactory,
        reinterpret_cast<LPVOID*>(&wicFactory));
    if (FAILED(hr))
    {
        LogError("Unable to create WIC imaging factory.");
        return false;
    }

    // Create a WIC stream for output.
    ComObject<IWICStream> wicStream;
    hr = wicFactory->CreateStream(&wicStream);
    if (FAILED(hr))
    {
        LogError("wicFactory->CreateStream failed.");
        return false;
    }

    std::wstring wfilename = Environment::Convert(filename);
    hr = wicStream->InitializeFromFilename(wfilename.c_str(), GENERIC_WRITE);
    if (FAILED(hr))
    {
        LogError("wicStream->InitializeFromFilename failed (" +
            filename + ").");
        return false;
    }

    // Create a WIC PNG encoder.
    ComObject<IWICBitmapEncoder> wicEncoder;
    hr = wicFactory->CreateEncoder(GUID_ContainerFormatPng, nullptr,
        &wicEncoder);
    if (FAILED(hr))
    {
        LogError("wicFactory->CreateEncoder failed.");
        return false;
    }

    hr = wicEncoder->Initialize(wicStream, WICBitmapEncoderNoCache);
    if (FAILED(hr))
    {
        LogError("wicEncoder->Initialize failed.");
        return false;
    }

    // Create a new frame and a property bag for encoder options.
    ComObject<IWICBitmapFrameEncode> wicFrameEncode;
    ComObject<IPropertyBag2> wicPropertyBag;
    hr = wicEncoder->CreateNewFrame(&wicFrameEncode, &wicPropertyBag);
    if (FAILED(hr))
    {
        LogError("wicEncoder->CreateNewFrame failed.");
        return false;
    }

    // Set the options for the PNG encoder.
    PROPBAG2 option = { 0 };
    VARIANT varValue;

    // Disable interlacing.
    option.pstrName = L"InterlaceOption";
    VariantInit(&varValue);
    varValue.vt = VT_BOOL;
    varValue.boolVal = FALSE;
    hr = wicPropertyBag->Write(1, &option, &varValue);
    if (FAILED(hr))
    {
        LogError("wicPropertyBag->Write failed for InterlaceOption.");
        return false;
    }

    // Disable filtering.
    option.pstrName = L"FilterOption";
    VariantInit(&varValue);
    varValue.vt = VT_UI1;
    varValue.bVal = WICPngFilterNone;
    hr = wicPropertyBag->Write(1, &option, &varValue);
    if (FAILED(hr))
    {
        LogError("wicPropertyBag->Write failed for FilterOption.");
        return false;
    }

    // Initialize the encoder.
    hr = wicFrameEncode->Initialize(wicPropertyBag);
    if (FAILED(hr))
    {
        LogError("wicFrameEncode->Initialize failed.");
        return false;
    }

    // Set the image size.
    UINT width = texture->GetWidth();
    UINT height = texture->GetHeight();
    hr = wicFrameEncode->SetSize(width, height);
    if (FAILED(hr))
    {
        LogError("wicFrameEncode->SetSize failed.");
        return false;
    }

    // Set the image format.
    WICPixelFormatGUID wicTargetGUID = wicSourceGUID;
    hr = wicFrameEncode->SetPixelFormat(&wicTargetGUID);
    if (FAILED(hr))
    {
        LogError("wicFrameEncode->SetPixelFormat failed.");
        return false;
    }

    // Compute the stride and image size.
    UINT const stride = width * texture->GetElementSize();
    UINT const imageSize = stride * height;

    // Create a WIC bitmap to wrap the texture image data.
    ComObject<IWICBitmap> wicTextureBitmap;
    hr = wicFactory->CreateBitmapFromMemory(width, height,
        wicSourceGUID, stride, imageSize, texture->Get<BYTE>(),
        &wicTextureBitmap);
    if (FAILED(hr))
    {
        LogError("wicFactory->CreateBitmapFromMemory failed.");
        return false;
    }

    // The wicTextureBitmap value is used for no conversion.  If the encoder
    // does not support the format in the texture, then a conversion is
    // required.
    IWICBitmapSource* wicBitmapSource = wicTextureBitmap;
    ComObject<IWICFormatConverter> wicFormatConverter;
    if (!IsEqualGUID(wicSourceGUID, wicTargetGUID))
    {
        // Create a WIC format converter.
        hr = wicFactory->CreateFormatConverter(&wicFormatConverter);
        if (FAILED(hr))
        {
            LogError("wicFactory->CreateFormatConverter failed.");
            return false;
        }

        // Initialize the format converter to convert to the nearest format
        // supported by the encoder.
        hr = wicFormatConverter->Initialize(wicTextureBitmap, wicTargetGUID,
            WICBitmapDitherTypeNone, nullptr, 0.0,
            WICBitmapPaletteTypeCustom);
        if (FAILED(hr))
        {
            LogError("wicFormatConverter->Initialize failed.");
            return false;
        }

        // Use the format converter.
        wicBitmapSource = wicFormatConverter;
    }

    // Send the pixels to the encoder.
    hr = wicFrameEncode->WriteSource(wicBitmapSource, nullptr);
    if (FAILED(hr))
    {
        LogError("wicFrameEncode->WriteSource failed.");
        return false;
    }

    // Commit the frame.
    hr = wicFrameEncode->Commit();
    if (FAILED(hr))
    {
        LogError("wicFrameEncode->Commit failed.");
        return false;
    }

    // Commit the encoder.
    hr = wicEncoder->Commit();
    if (FAILED(hr))
    {
        LogError("wicEncoder->Commit failed.");
        return false;
    }

    return true;
}