Seer
Seer

Reputation: 45

Transfer an image from CDC to CBitmap

How can I transfer an image from CDC to CBitmap? The problem in whole: I have a big image into CBitmap A. I need to transfer parts of this image to a number of CBitmap for the storage into a vector, because I can't use a number of CDC for this :) I make a prepared CDC into a cycle (get a neccessary part of CBitmap A) and then I need to transfer it to CBitmap x. How can I do it?

Here's my code:

m_bitmaps.clear();
m_bitmaps.reserve(4);

CDC SourceDC, destDC;
SourceDC.CreateCompatibleDC(pMainDC);
destDC.CreateCompatibleDC(pMainDC);

CBitmap bmpWhole; // bmp 200*200
bmpWhole.LoadBitmap(IDB_TEST_BITMAP);
SourceDC.SelectObject(&bmpWhole);

//pMainDC->BitBlt(0,0,200,200,&SourceDC,0,0,SRCCOPY);

// It's OK - I got a source picture

for (int x=100; x>=0; x-=100)
    for (int y=100; y>=0; y-=100)
    {
        CBitmap *destBitmap = new CBitmap();
        destBitmap->CreateCompatibleBitmap(&destDC, 100, 100);

        CBitmap *oldBitmap = destDC.SelectObject(destBitmap);

        destDC.BitBlt(0,0,100,100,&SourceDC,x,y,SRCCOPY);

        pMainDC->BitBlt(x*1.1,y*1.1,100,100,&destDC,0,0,SRCCOPY);

// I got black squares here! - something wrong with previous code

        m_bitmaps.push_back(destBitmap);

        destDC.SelectObject(oldBitmap);
    }

bmpWhole.DeleteObject();
destDC.DeleteDC();
SourceDC.DeleteDC();

// And later CBitmaps are black squares


I found the solution!

Parsing the CBitmap and initializing the vector

m_bitmaps.clear();
m_bitmaps.reserve(4);

CDC SourceDC, destDC;
SourceDC.CreateCompatibleDC(pMainDC);

CBitmap bmpWhole;
bmpWhole.LoadBitmap(IDB_TEST_BITMAP);
SourceDC.SelectObject(&bmpWhole);

for (int x=100; x>=0; x-=100)
    for (int y=100; y>=0; y-=100)
    {
        CImage *destImage = new CImage();
        destImage->Create(100, 100, 24);

        destDC.Attach(destImage->GetDC());
        destDC.BitBlt(0,0,100,100,&SourceDC,x,y,SRCCOPY);
        destDC.Detach();
        destImage->ReleaseDC();

        m_bitmaps.push_back(destImage);
    }

bmpWhole.DeleteObject();
destDC.DeleteDC();
SourceDC.DeleteDC();

Draw:

WORD nShift=0;
for (auto iter = m_bitmaps.begin(); iter != m_bitmaps.end(); ++iter, nShift+=110)
{
    CBitmap* pBitmap = CBitmap::FromHandle((*iter)->operator HBITMAP());

    CDC memDC;
    memDC.CreateCompatibleDC(pMainDC);
    memDC.SelectObject(pBitmap);
    pMainDC->BitBlt(nShift, 0, 100, 100, &memDC, 0, 0, SRCCOPY);
}

Upvotes: 2

Views: 5883

Answers (1)

Captain Obvlious
Captain Obvlious

Reputation: 20103

Create another device context and one by one create and select your target bitmaps into it and use BitBlt to copy portions of the source bitmap into them. Below is an example of how you might do this.

// Create a DC compatible with the display
// this is used to copy FROM the source bitmap
sourceDC.CreateDC(NULL); 
sourceDC.SelectObject(&sourceBitmap);

// Create another device context for the destination bitmap
destDC.CreateCompatibleDC(&sourceDC);
for(int i = 0; i < numBitmaps; i++)
{
    // Determine the x, y, sourceX, sourceY, with and height here
    // ...

    // create a new bitmap
    CBitmap *destBitmap = new CBitmap();
    destBitmap->CreateCompatibleBitmap(&destDC, width, height);
    // Select the bitmap into the destination device context
    CBitmap *oldBitmap = destDC.SelectObject(destBitmap);

    // copy the bitmap
    destDC.BitBlt(x, y, width, height, &sourceDC, sourceX, sourceY, SRCCOPY);

    // add it to the vector    
    bitmapVector.push_back(destBitmap);

    // Clean up
    destDC.SelectObject(oldBitmap);
}

I omitted error checking for simplicity. If you are using C++11 or Boost I recommend using unique_ptr to manage the lifetime of the bitmap object. Otherwise you need to delete it at the appropriate place such as the destructor.

Upvotes: 1

Related Questions