c++mfcsave-image

How to save image which is specific area that I clicked of picture Control?


Hello I'm studying MFC and I wanna know how to save a specific part of image which is in Picture Control when I click.

Here is the sequence what I want to do

I already make a function that when I click grab button, it shows the image in picture control.

After that, I want to save image when I click specific area.

I attach the image to help understand. picture control

"I want to know how to save the surrounding area as an image when I click a specific part of the picture control as shown above."

It would be easy problem, but I'd appreciate it if you understand because it's my first time doing this.

I tryed to use ScreenToClient function, but I failed.


Solution

  • There are quite a few ways to do this, but the general idea is usually pretty much the same:

    1. Get a DC to the screen or the window's client area (aka DC1).
    2. Create a DC compatible with DC1 (aka DC2).
    3. create a CBitmap compatible with DC1, of the size you want to copy/save.
    4. select the bitmap into DC2.
    5. bitblt the area you care about from DC1 to DC2.
    6. Create a CImage object.
    7. Detach the bitmap from the CBitmap, and attach it to the CImage.
    8. Use CImage::Save to save the bitmap to a file.

    There are variations (e.g., writing the data to a file without using a CImage), but they tend to be tedious, and unless you're willing to put quite a bit of effort into things, fairly limited as well. e.g., writing a .BMP file on your own isn't terribly difficult, but is a bit tedious.If you want to support writing JPEG, TIFF, PNG, etc., you either need to integrate a number of libraries, or else write quite a bit of code for the file formats. CImage is somewhat limited as well, but at least supports a half dozen or so of the most common formats (and most people find just JPEG, PNG and possibly GIF sufficient).

    Here's a bit of tested sample code for saving a 200x200 chunk of whatever's displayed in the current view window into a file named capture.jpg:

    void CPicCapView::OnLButtonDown(UINT nFlags, CPoint point) {
    
        // width and height of area to capture
        static const uint32_t width = 200;
        static const uint32_t height = 200;
    
        CClientDC dc(this);
    
        CDC temp;
        temp.CreateCompatibleDC(&dc);
    
        CBitmap bmp;
        bmp.CreateCompatibleBitmap(&dc, width, height);
        temp.SelectObject(&bmp);
    
        // x-width/2, y-width/2 to get area centered at click point
        temp.BitBlt(0, 0, width, height, &dc, point.x- width/2, point.y-height/2, SRCCOPY);
    
        CImage dest;
        dest.Attach((HBITMAP)bmp.Detach());
    
        // for the moment, just saving to a fixed file name
        dest.Save(L".\\capture.jpg");
    
        CView::OnLButtonDown(nFlags, point);
    }
    

    It might initially seem like you should be able to create the CImage object, use its Create to create a bitmap, and then blit directly from the screen bitmap to the CImage bitmap. Unfortunately, CImage's BitBlt uses the CImage as a source, not a destination, so although there may be some way to get this to work, the obvious method doesn't.