windows WIC RGB32转Jpeg

最近运用 windows 下 WIC IWICBitmapFrameEncode 将 RGB32转Jpeg,遇到一个问题,转出来的Jpeg,显示不对:1、画面灰色,有白条纹;2、画面是倒的(从opengl纹理读到的),如下:

 而RGB24直接转jpeg是正常的,通过MSDN相关资料发现,jpeg编解码器只支持RGB24格式

本机像素格式概述 - Win32 apps | Microsoft Docs

两步解决以上问题: 

1、需要采用IWICFormatConverter,将RGB32转为RGB24

  hr = piFactory->CreateBitmapFromMemory(
      width, height, GUID_WICPixelFormat32bppRGBA, width * 4,
      height * width * 4, buffer, &piBitmapSrc);

  // Create the flip / rotator.
  if (SUCCEEDED(hr)) {
    hr = piFactory->CreateFormatConverter(&piFormatConverter);
  }

  // Initialize the format converter.
  if (SUCCEEDED(hr)) {
    hr = piFormatConverter->Initialize(
        piBitmapSrc,                  // Input source to convert
        GUID_WICPixelFormat24bppBGR,  // Destination pixel format
        WICBitmapDitherTypeNone,      // Specified dither pattern
        NULL,                         // Specify a particular palette
        0.f,                          // Alpha threshold
        WICBitmapPaletteTypeCustom    // Palette translation type
    );
  }

2、运用Jpeg编码器的选项 BitmapTransform,将画面旋转180度,该选项还支持其他变换,详见以下链接

JPEG 格式概述 - Win32 apps | Microsoft Docs


  if (SUCCEEDED(hr)) {
    PROPBAG2 option = {0};
    option.pstrName = L"BitmapTransform";
    VARIANT varValue;
    VariantInit(&varValue);
    varValue.vt = VT_UI1;
    varValue.bVal = WICBitmapTransformRotate180;
    hr = pPropertybag->Write(1, &option, &varValue);
    if (SUCCEEDED(hr)) {
      hr = piBitmapFrame->Initialize(pPropertybag);
    }
  }

具体实现代码如下:

int RGB32BufferToJpeg(uint8_t* buffer, int width, int height, const std::wstring& filePath)
{
  IWICImagingFactory* piFactory = NULL;
  IWICBitmapEncoder* piEncoder = NULL;
  IWICBitmapFrameEncode* piBitmapFrame = NULL;
  IWICStream* piStream = NULL;
  IWICBitmap* piBitmapSrc = NULL;
  IWICFormatConverter* piFormatConverter = NULL;
  IWICBitmapSource* piBitmapTmp = NULL;
  IPropertyBag2* pPropertybag = NULL;

  CoInitialize(NULL);
  HRESULT hr =
      CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
                       IID_IWICImagingFactory, (LPVOID*)&piFactory);
  if (SUCCEEDED(hr)) {
    hr = piFactory->CreateStream(&piStream);
  }
  if (SUCCEEDED(hr)) {
    LPCWSTR tmp = reinterpret_cast<LPCWSTR>(filePath.c_str());
    hr = piStream->InitializeFromFilename(tmp, GENERIC_WRITE);
  }
  if (SUCCEEDED(hr)) {
    hr = piFactory->CreateEncoder(GUID_ContainerFormatJpeg, NULL, &piEncoder);
  }
  if (SUCCEEDED(hr)) {
    hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache);
  }
  if (SUCCEEDED(hr)) {
    hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
  }

  if (SUCCEEDED(hr)) {
    PROPBAG2 option = {0};
    option.pstrName = L"BitmapTransform";
    VARIANT varValue;
    VariantInit(&varValue);
    varValue.vt = VT_UI1;
    varValue.bVal = WICBitmapTransformRotate180;
    hr = pPropertybag->Write(1, &option, &varValue);
    if (SUCCEEDED(hr)) {
      hr = piBitmapFrame->Initialize(pPropertybag);
    }
  }
  if (SUCCEEDED(hr)) {
    hr = piBitmapFrame->SetSize(width, height);
  }

  hr = piFactory->CreateBitmapFromMemory(
      width, height, GUID_WICPixelFormat32bppRGBA, width * 4,
      height * width * 4, buffer, &piBitmapSrc);

  // Create the flip / rotator.
  if (SUCCEEDED(hr)) {
    hr = piFactory->CreateFormatConverter(&piFormatConverter);
  }

  // Initialize the format converter.
  if (SUCCEEDED(hr)) {
    hr = piFormatConverter->Initialize(
        piBitmapSrc,                  // Input source to convert
        GUID_WICPixelFormat24bppBGR,  // Destination pixel format
        WICBitmapDitherTypeNone,      // Specified dither pattern
        NULL,                         // Specify a particular palette
        0.f,                          // Alpha threshold
        WICBitmapPaletteTypeCustom    // Palette translation type
    );
  }

  if (SUCCEEDED(hr))
    piFormatConverter->QueryInterface(IID_IWICBitmapSource,
                                      reinterpret_cast<void**>(&piBitmapTmp));

  if (SUCCEEDED(hr)) {
    hr = piBitmapFrame->WriteSource(piBitmapTmp, NULL);
  }

  if (SUCCEEDED(hr)) {
    hr = piBitmapFrame->Commit();
  }

  if (SUCCEEDED(hr)) {
    hr = piEncoder->Commit();
  }

  if (piBitmapTmp) {
    piBitmapTmp->Release();
  }

  if (piFormatConverter) {
    piFormatConverter->Release();
  }

  if (piBitmapSrc) {
    piBitmapSrc->Release();
  }

  if (piEncoder) {
    piEncoder->Release();
  }

  if (piBitmapFrame) {
    piBitmapFrame->Release();
  }

  if (pPropertybag) {
    pPropertybag->Release();
  }

  if (piStream) {
    piStream->Release();
  }

  if (piFactory) {
    piFactory->Release();
  }

  return SUCCEEDED(hr) ? 0 : -1;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值