gldhnchn
gldhnchn

Reputation: 344

How to draw a image with effects that rescales with it's window in direct2d

I created a Direct2D application following this example: https://github.com/microsoft/Windows-classic-samples/tree/master/Samples/Win7Samples/multimedia/Direct2D/SimpleDirect2DApplication

I managed to show a bitmap in the applications window and the bitmap also rescales when rescaling the window. But now I wanted to apply effects on the bitmap and here comes my problem. The effect is applied like this

hr = m_pRenderTarget->QueryInterface( __uuidof(ID2D1DeviceContext), (void**)&m_pDeviceContext );
m_pDeviceContext->CreateEffect( CLSID_D2D1GammaTransfer, &gammaTransferEffect );
gammaTransferEffect->SetInput( 0, m_pBitmap );
gammaTransferEffect->SetValue( D2D1_GAMMATRANSFER_PROP_RED_AMPLITUDE, 4.0f );

The problem is that after applying the effect, the image data is now in the format of ID2D1Effect. This can be drawn with DrawImage like this:

m_pDeviceContext->DrawImage(gammaTransferEffect);

But I did the rescaling with destinationRectangle in the function DrawBitmap and there is no equivalent to destinationRectangle in DrawImage.

m_pDeviceContext->DrawBitmap(
            m_pBitmap,
            D2D1::RectF(
                0,
                0,
                renderTargetSize.width,
                renderTargetSize.height),
            1.0f,
            D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
        );

So how can I rescale the bitmap after applying the effect when rescaling the render target? I had some ideas about this, but none led me to a solution.

  1. Rescale the device context. I didn't find a method like Resize for the rendert target.
  2. Make a bitmap from the effects output to use DrawBitmap again. I found no possibility to do this.
  3. Rescaling the bitmap before applying effects on it. I found no way to do this.

Somebody an idea what could be a solution here?

Upvotes: 0

Views: 1181

Answers (2)

JimDill
JimDill

Reputation: 1

Thank you gldhnchn. I had the same problem. In fact I encounter it even without the effect -- RenderTarget->DrawBitmap scales the image as desired, but DeviceContext->DrawImage does not, as demonstrated below. Your fix does the trick.

IMPLEMENT_DYNAMIC(CMyImageCtrl, CStatic)

CMyImageCtrl::CMyImageCtrl()
{
    EnableD2DSupport();

    CImage image; 
    image.Load("test_bmap.jpg");
    m_pBitmap = new CD2DBitmap(GetRenderTarget(), image.Detach());
}

afx_msg LRESULT CMyImageCtrl::OnDraw2D(WPARAM wParam, LPARAM lParam)
{
    CHwndRenderTarget* pRenderTarget = (CHwndRenderTarget*)lParam;

    CRect rect;
    GetClientRect(rect);
    CD2DRectF rectD(rect);

    bool bUseRenderTarget = true;
    if (bUseRenderTarget) {

        // here image scales to fit client
        pRenderTarget->DrawBitmap(m_pBitmap, rectD);

    } else {

        // here image is drawn full native size, does not scale to rect
        CComQIPtr<ID2D1DeviceContext> spDeviceContext = pRenderTarget->GetRenderTarget();

        spDeviceContext->DrawImage(m_pBitmap->Get(), D2D1::Point2F(0., 0.), rectD);
    }
}

Upvotes: 0

gldhnchn
gldhnchn

Reputation: 344

One solution to my problem is to rescale the render target:

// Retrieve the size of the render target.
D2D1_SIZE_F renderTargetSize = m_pRenderTarget->GetSize();
// calculate scale factors
float scale_x = renderTargetSize.width / _bitmapSource.width;
float scale_y = renderTargetSize.height / _bitmapSource.height;
// scale render target
m_pRenderTarget->SetTransform(
    D2D1::Matrix3x2F::Scale(
        D2D1::Size( scale_x, scale_y ),
        D2D1::Point2F( 0.0f, 0.0f ))
);
hr = m_pRenderTarget->QueryInterface( __uuidof(ID2D1DeviceContext), (void**)&m_pDeviceContext );
m_pDeviceContext->CreateEffect( CLSID_D2D1GammaTransfer, &gammaTransferEffect );
gammaTransferEffect->SetInput( 0, m_pBitmap );
gammaTransferEffect->SetValue( D2D1_GAMMATRANSFER_PROP_RED_AMPLITUDE, 4.0f );
m_pDeviceContext->DrawImage(gammaTransferEffect);

Additionally I had to remove my resize function from the WM_SIZE message, otherwise my painted bitmap didn't rescale with its window. That was a bit counter intuitive to me, but yay it works.

Upvotes: 0

Related Questions