How do I save ID2D1Bitmap as a file?

채문석(jim) 41 Reputation points
2024-07-08T05:39:14.6833333+00:00

Bitmap and text were output to DIALOG using Direct2D.

I tried to make this rendered screen into a bitmap and save it as a file.

But, I get D2DERR_WRONG_RESOURCE_DOMAIN.

Is there a way to transform ID2D1Bitmap to IWICBitmap?

My goal is to use GDI+

Bitmap->LockBits(&rect,ImageLockModeRead,PixelFormat32bppARGB,bitmapData);

BYTE *rawData = (BYTE *)bitmapData->Scan0;

The purpose is to obtain memory information of ID2D1Bitmap as shown in the code.

Here my code


// NS_DisplayDlg.h : 헤더 파일
//
#pragma once
#include <d2d1.h>
#include <d2d1_1.h>
#include <dxgi1_2.h>
#include <d3d11.h>
#include <wrl/client.h>
#include <wincodec.h>
#include <dwrite.h>
#include <thread>
#include <atomic>
#include <vector>
#include <string>
#include <atlbase.h>
#include <gdiplus.h>
using namespace Gdiplus;
using Microsoft::WRL::ComPtr;
// CNS_DisplayDlg 대화 상자
class CNS_DisplayDlg : public CDialogEx
{
// 생성입니다.
public:
	CNS_DisplayDlg(CWnd* pParent = NULL);	// 표준 생성자입니다.
	~CNS_DisplayDlg();
// 대화 상자 데이터입니다.
	enum { IDD = IDD_NS_DISPLAY_DIALOG };
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 지원입니다.
public:
	bool m_bBoardUse;
	ULONG_PTR m_gdiplusToken;
public:
	std::thread m_animationThread;
    std::atomic<bool> m_running;
	int m_maxY;
	int m_textPosY;
	int m_textSpeed;
	int m_imagePosY;
	int m_videoFormat;
	BYTE* m_rawData;
public:
	ID2D1Factory* m_pDirect2dFactory;
    ID2D1HwndRenderTarget* m_pRenderTarget;
    ID2D1Bitmap* m_pBitmap;
    IWICImagingFactory* m_pWICFactory;
    IDWriteFactory* m_pDWriteFactory;
    IDWriteTextFormat* m_pTextFormat;
	ID2D1SolidColorBrush* m_pTextBrush;
	
	ID2D1RenderTarget* m_pRenderTarget2;
public:
	HRESULT LoadBitmapFromFile(LPCWSTR uri, ID2D1Bitmap** ppBitmap);
	void AnimationLoop(); // 애니메이션 루프 메서드
	BOOL InitDirect();
	void DrawingRender();
	HRESULT SaveBitmapToFile(PCWSTR uri,ID2D1Bitmap* pBitmap);
	IWICBitmap* m_pWicBitmap;
// 구현입니다.
protected:
	HICON m_hIcon;
	// 생성된 메시지 맵 함수
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnDestroy();
};

//CPP

// NS_DisplayDlg.cpp : 구현 파일
//
#include "stdafx.h"
#include "NS_Display.h"
#include "NS_DisplayDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
int cnt = 0;
// 응용 프로그램 정보에 사용되는 CAboutDlg 대화 상자입니다.
class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();
// 대화 상자 데이터입니다.
	enum { IDD = IDD_ABOUTBOX };
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.
// 구현입니다.
protected:
	DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CNS_DisplayDlg 대화 상자
CNS_DisplayDlg::CNS_DisplayDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CNS_DisplayDlg::IDD, pParent), 
	m_pDirect2dFactory(nullptr), m_pRenderTarget(nullptr), m_pBitmap(nullptr), m_pWICFactory(nullptr), m_pDWriteFactory(nullptr), m_pTextFormat(nullptr), m_pTextBrush(nullptr), m_rawData(nullptr),
	m_textPosY(0), m_textSpeed(100), m_imagePosY(10) , m_videoFormat(5),
	m_running(false),m_bBoardUse(false)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
}
CNS_DisplayDlg::~CNS_DisplayDlg()
{
	Gdiplus::GdiplusShutdown(m_gdiplusToken);
	m_running = false;
    if (m_animationThread.joinable())
    {
        m_animationThread.join();
    }
	if(m_rawData)
	{
		delete m_rawData;
		m_rawData = nullptr;
	}
	if(m_pDirect2dFactory) m_pDirect2dFactory->Release();
	if(m_pRenderTarget) m_pRenderTarget->Release();
	if(m_pBitmap) m_pBitmap->Release();
	if(m_pWICFactory) m_pWICFactory->Release();
	if(m_pDWriteFactory) m_pDWriteFactory->Release();
	if(m_pTextFormat) m_pTextFormat-> Release();
	if(m_pTextBrush) m_pTextBrush->Release();
}
void CNS_DisplayDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CNS_DisplayDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
END_MESSAGE_MAP()
// CNS_DisplayDlg 메시지 처리기
BOOL CNS_DisplayDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	// 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다.
	// IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}
	// 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
	//  프레임워크가 이 작업을 자동으로 수행합니다.
	SetIcon(m_hIcon, TRUE);			// 큰 아이콘을 설정합니다.
	SetIcon(m_hIcon, FALSE);		// 작은 아이콘을 설정합니다.
	// TODO: 여기에 추가 초기화 작업을 추가합니다.
	SetWindowPos(nullptr, 0, 0, 1920, 1080, SWP_NOZORDER | SWP_NOMOVE);
	InitDirect();
	return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}
void CNS_DisplayDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}
// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
//  아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
//  프레임워크에서 이 작업을 자동으로 수행합니다.
void CNS_DisplayDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.
		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
		// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;
		// 아이콘을 그립니다.
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		//CDialogEx::OnPaint();
		DrawingRender();
		//ProcessRawData();
		//DrawingRenderAJABoard();
	}
}
// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서
//  이 함수를 호출합니다.
HCURSOR CNS_DisplayDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}
void CNS_DisplayDlg::OnDestroy()
{
	CDialogEx::OnDestroy();
	// TODO: 여기에 메시지 처리기 코드를 추가합니다.
}
BOOL CNS_DisplayDlg::InitDirect()
{
	HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pDirect2dFactory);
    if (FAILED(hr))
    {
        MessageBox(L"Direct2D Factory 생성 실패", L"오류", MB_OK);
        return FALSE;
    }
    hr = CoInitialize(nullptr);
    if (FAILED(hr))
    {
        MessageBox(L"COM 라이브러리 초기화 실패", L"오류", MB_OK);
        return FALSE;
    }
    hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pWICFactory));
    if (FAILED(hr))
    {
        MessageBox(L"WIC Factory 생성 실패", L"오류", MB_OK);
        return FALSE;
    }
    // 렌더 타겟 생성
    RECT rc;
    GetClientRect(&rc);
    D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
    hr = m_pDirect2dFactory->CreateHwndRenderTarget(
        D2D1::RenderTargetProperties(),
        D2D1::HwndRenderTargetProperties(m_hWnd, size),
        &m_pRenderTarget);
	
    if (FAILED(hr))
    {
        MessageBox(L"Direct2D 렌더 타겟 생성 실패", L"오류", MB_OK);
        return FALSE;
    }
	if (FAILED(hr))
    {
        MessageBox(L"Direct2D 렌더 타겟 생성 실패", L"오류", MB_OK);
        return FALSE;
    }
	hr = LoadBitmapFromFile(L"..\\Debug\\test.png", &m_pBitmap);
    if (FAILED(hr))
    {
        MessageBox(L"이미지 로드 실패", L"오류", MB_OK);
        return FALSE;
    }
	
	 // DirectWrite 팩토리 생성
    hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&m_pDWriteFactory));
    if (FAILED(hr))
    {
        MessageBox(L"DirectWrite Factory 생성 실패", L"오류", MB_OK);
        return FALSE;
    }
    // 텍스트 형식 생성
    hr = m_pDWriteFactory->CreateTextFormat(
        L"Arial",                // 폰트 이름
        nullptr,
        DWRITE_FONT_WEIGHT_NORMAL,
        DWRITE_FONT_STYLE_NORMAL,
        DWRITE_FONT_STRETCH_NORMAL,
        24.0f,
        L"en-us",
        &m_pTextFormat);
    if (FAILED(hr))
    {
        MessageBox(L"텍스트 형식 생성 실패", L"오류", MB_OK);
        return FALSE;
    }
	// 텍스트 브러시 생성
	hr = m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &m_pTextBrush);
    if (FAILED(hr))
    {
        MessageBox(L"텍스트 브러시 생성 실패", L"오류", MB_OK);
        return FALSE;
    }
	 // 화면의 가장 아래의 Y 값(m_maxY) 구하기
    m_imagePosY = m_textPosY = m_maxY = rc.bottom - 10; // 여유 공간을 둬서 화면의 가장 아래에 위치하도록 설정
	
	m_running = true;
    m_animationThread = std::thread(&CNS_DisplayDlg::AnimationLoop, this);
	return TRUE;
}
HRESULT CNS_DisplayDlg::LoadBitmapFromFile(LPCWSTR uri, ID2D1Bitmap** ppBitmap)
{
	IWICBitmapDecoder* pDecoder = nullptr;
    IWICBitmapFrameDecode* pFrame = nullptr;
    IWICFormatConverter* pConverter = nullptr;
    HRESULT hr = m_pWICFactory->CreateDecoderFromFilename(uri, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder);
    if (FAILED(hr))
    {
        MessageBox(L"WIC 디코더 생성 실패", L"오류", MB_OK);
        return hr;
    }
    hr = pDecoder->GetFrame(0, &pFrame);
    if (FAILED(hr))
    {
        MessageBox(L"WIC 프레임 디코딩 실패", L"오류", MB_OK);
        pDecoder->Release();
        return hr;
    }
	
    hr = m_pWICFactory->CreateFormatConverter(&pConverter);
    if (FAILED(hr))
    {
        MessageBox(L"WIC 포맷 변환기 생성 실패", L"오류", MB_OK);
        pFrame->Release();
        pDecoder->Release();
        return hr;
    }
    hr = pConverter->Initialize(
        pFrame,
        GUID_WICPixelFormat32bppPBGRA,
        WICBitmapDitherTypeNone,
        nullptr,
        0.f,
        WICBitmapPaletteTypeMedianCut);
    if (FAILED(hr))
    {
        MessageBox(L"WIC 포맷 변환기 초기화 실패", L"오류", MB_OK);
        pConverter->Release();
        pFrame->Release();
        pDecoder->Release();
        return hr;
    }
    // 이 부분에서 Direct2D 렌더 타겟이 유효한지 확인
    if (!m_pRenderTarget)
    {
        MessageBox(L"Direct2D 렌더 타겟이 유효하지 않습니다.", L"오류", MB_OK);
        pConverter->Release();
        pFrame->Release();
        pDecoder->Release();
        return E_FAIL;
    }
    hr = m_pRenderTarget->CreateBitmapFromWicBitmap(pConverter, nullptr, ppBitmap);
	
    if (FAILED(hr))
    {
        MessageBox(L"Direct2D 비트맵 생성 실패", L"오류", MB_OK);
    }
    pConverter->Release();
    pFrame->Release();
    pDecoder->Release();
    return hr;
}
void CNS_DisplayDlg::AnimationLoop()
{
    while (m_running)
    {
        // 텍스트 위치 업데이트
        m_textPosY -= m_textSpeed / 100; // 100 픽셀을 1초에 이동 (100ms 마다 10씩 이동)
        if (m_textPosY < -50) {
            m_textPosY = m_maxY; // 화면 아래에서 위로 이동할 때 화면 아래로 이동
        }
        // 이미지 위치 업데이트 (텍스트와 같은 속도로 이동)
        m_imagePosY -= m_textSpeed / 100;
        if (m_imagePosY < -50) {
            m_imagePosY = m_maxY; // 화면 아래에서 위로 이동할 때 화면 아래로 이동
        }
        // 화면 다시 그리기 요청
        Invalidate(FALSE);
        // 100ms 대기
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}
void CNS_DisplayDlg::DrawingRender()
{
	HRESULT hr = S_OK;
	if (m_pRenderTarget == nullptr)
    {
        RECT rc;
        GetClientRect(&rc);
        D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
        // Create render target
        hr = m_pDirect2dFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(m_hWnd, size),
            &m_pRenderTarget);
        
        if (FAILED(hr))
        {
            MessageBox(L"Failed to create render target", L"Error", MB_OK);
            return ;
        }
    }
	m_pRenderTarget->BeginDraw();
	m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black));
	
	if (m_pBitmap)
    {
        D2D1_SIZE_F imageSize = m_pBitmap->GetSize();
        m_pRenderTarget->DrawBitmap(m_pBitmap, D2D1::RectF(10, m_imagePosY, 10 + imageSize.width, m_imagePosY + imageSize.height));
    }
	// Draw text
    static const WCHAR sc_helloWorld[] = L"Hello, World!";
    D2D1_RECT_F layoutRect = D2D1::RectF(20, static_cast<float>(m_textPosY), 300, static_cast<float>(m_textPosY + 50));
    m_pRenderTarget->DrawText(sc_helloWorld, ARRAYSIZE(sc_helloWorld) - 1, m_pTextFormat, &layoutRect, m_pTextBrush);
	hr = m_pRenderTarget->EndDraw();
	if (FAILED(hr))
    {
        MessageBox(L"Rendering failed", L"Error", MB_OK);
    }
	//ID2D1Factory::CreateWicBitmapRenderTarget(pWicBitmap,
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Create bitmap render target
	ComPtr<ID2D1BitmapRenderTarget> pBitmapRenderTarget;
    hr = m_pRenderTarget->CreateCompatibleRenderTarget(&pBitmapRenderTarget);
    if (FAILED(hr))
    {
        MessageBox(L"Failed to create bitmap render target", L"Error", MB_OK);
        return;
    }
	pBitmapRenderTarget->BeginDraw();
    pBitmapRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black));
    if (m_pBitmap)
    {
        D2D1_SIZE_F imageSize = m_pBitmap->GetSize();
        pBitmapRenderTarget->DrawBitmap(m_pBitmap, D2D1::RectF(10, m_imagePosY, 10 + imageSize.width, m_imagePosY + imageSize.height));
    }
    // Draw text
    static const WCHAR sc_helloWorld2[] = L"Hello, World!";
    D2D1_RECT_F layoutRect2 = D2D1::RectF(20, static_cast<float>(m_textPosY), 300, static_cast<float>(m_textPosY + 50));
    pBitmapRenderTarget->DrawText(sc_helloWorld2, ARRAYSIZE(sc_helloWorld2) - 1, m_pTextFormat, &layoutRect2, m_pTextBrush);
    hr = pBitmapRenderTarget->EndDraw();
	if (FAILED(hr))
    {
        MessageBox(L"Rendering failed", L"Error", MB_OK);
    }
    //ComPtr<ID2D1Bitmap> pBitmap;
	ID2D1Bitmap* pBitmap;
    hr = pBitmapRenderTarget->GetBitmap(&pBitmap);
	
	D2D1_SIZE_U sizet = pBitmap->GetPixelSize();
    if (FAILED(hr))
    {
        MessageBox(L"Failed to get bitmap", L"Error", MB_OK);
        return;
    }
	CString str = L"";
	//str.Format(L"D:\\1. workspace\\1. source\\12. vs2012\\NS_Display\\Debug\\TEST%d.png",cnt);
	str.Format(L"..\\Debug\\TEST%d.png",cnt);
	IWICBitmap* ppWICBitmap;
	//SaveD2DBitmapToFile(pBitmap, &ppWICBitmap,str);
	
	SaveBitmapToFile(str,pBitmap);
	cnt++;
	pBitmap->Release();
}
HRESULT CNS_DisplayDlg::SaveBitmapToFile(PCWSTR uri,ID2D1Bitmap* pBitmap)
{
	HRESULT hr = S_OK;
	//ID2D1Factory *pD2DFactory = NULL;
	IWICBitmap *pWICBitmap = NULL;
	ID2D1RenderTarget *pRT = NULL;
	IWICBitmapEncoder *pEncoder = NULL;
	IWICBitmapFrameEncode *pFrameEncode = NULL;
	IWICStream *pStream = NULL;
	
	//
	// Create IWICBitmap and RT
	//
	UINT sc_bitmapWidth = pBitmap->GetSize().width;
	UINT sc_bitmapHeight = pBitmap->GetSize().height;
	if (SUCCEEDED(hr))
	{
		hr = m_pWICFactory->CreateBitmap(
			sc_bitmapWidth,
			sc_bitmapHeight,
		GUID_WICPixelFormat32bppPBGRA,
			WICBitmapCacheOnLoad,
			&pWICBitmap
			);
	}
	if (SUCCEEDED(hr))
	{
		D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties();
		rtProps.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
		rtProps.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
		rtProps.usage = D2D1_RENDER_TARGET_USAGE_NONE;
		//auto rtProps = D2D1::RenderTargetProperties();
		//rtProps.type = D2D1_RENDER_TARGET_TYPE_SOFTWARE;
		//rtProps.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
		hr = m_pDirect2dFactory->CreateWicBitmapRenderTarget(
			pWICBitmap,
		rtProps,
			&pRT
			);
	}
	if (SUCCEEDED(hr))
	{
		//
		// Render into the bitmap
		//
		pRT->BeginDraw();
		
		pRT->Clear(D2D1::ColorF(D2D1::ColorF::Black));
		if (m_pBitmap)
		{
			D2D1_SIZE_F imageSize = m_pBitmap->GetSize();
			pRT->DrawBitmap(m_pBitmap, D2D1::RectF(10, m_imagePosY, 10 + imageSize.width, m_imagePosY + imageSize.height));
		}
		// Draw text
		static const WCHAR sc_helloWorld[] = L"Hello, World!";
		D2D1_RECT_F layoutRect = D2D1::RectF(20, static_cast<float>(m_textPosY), 300, static_cast<float>(m_textPosY + 50));
		pRT->DrawText(sc_helloWorld, ARRAYSIZE(sc_helloWorld) - 1, m_pTextFormat, &layoutRect, m_pTextBrush);
		//pRT->DrawBitmap(pBitmap);
		hr = pRT->EndDraw();
	}
	if (SUCCEEDED(hr))
	{
		//
		// Save image to file
		//
		hr = m_pWICFactory->CreateStream(&pStream);
	}
	WICPixelFormatGUID format = GUID_WICPixelFormat32bppPBGRA;
	if (SUCCEEDED(hr))
	{
		hr = pStream->InitializeFromFilename(uri, GENERIC_WRITE);
	}
	if (SUCCEEDED(hr))
	{
		hr = m_pWICFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder);
	}
	if (SUCCEEDED(hr))
	{
		hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache);
	}
	if (SUCCEEDED(hr))
	{
		hr = pEncoder->CreateNewFrame(&pFrameEncode, NULL);
	}
	if (SUCCEEDED(hr))
	{
		hr = pFrameEncode->Initialize(NULL);
	}
	if (SUCCEEDED(hr))
	{
		hr = pFrameEncode->SetSize(sc_bitmapWidth, sc_bitmapHeight);
	}
	if (SUCCEEDED(hr))
	{
		hr = pFrameEncode->SetPixelFormat(&format);
	}
	if (SUCCEEDED(hr))
	{
		hr = pFrameEncode->WriteSource(pWICBitmap, NULL);
	}
	if (SUCCEEDED(hr))
	{
		hr = pFrameEncode->Commit();
	}
	if (SUCCEEDED(hr))
	{
		hr = pEncoder->Commit();
	}
	if(pWICBitmap) pWICBitmap->Release();
	if(pRT) pRT->Release();
	if(pEncoder) pEncoder->Release();
	if(pStream)pStream->Release();
return hr;
}



Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,649 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,755 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Castorix31 85,706 Reputation points
    2024-07-08T07:07:42.08+00:00
    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.