как разделить изображение и сохранить его в одномерных массивах - PullRequest
0 голосов
/ 19 мая 2019

Я делаю скользящую головоломку, используя изображение.

И в процессе я собираюсь поднять изображения, разделить их на плитки определенного размера и поместить их в одномерные массивы по порядку.

Я зарегистрирую файл изображения в качестве ресурса или импортирую файл изображения, используя функции HBITMAP и LoadImage.

Но я просто не могу представить, как мы собираемся разделить этот файл изображения на определенный размер (прямоугольник) и сохранить его в одномерном массиве.

Можно ли сохранить сегментированные плитки в каждом файле изображения, а затем сохранить путь к файлам в одномерном массиве?

* Примечание: необходимо использовать одномерный массив и двойную буферизацию.

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Вам не нужно для сериализации фрагментов в файлы. Если вы хотите, это отдельная проблема.

Вы можете загрузить изображение как одно изображение и разделить его в памяти. В основном, создайте правильные размеры растровых изображений для кусочных изображений в памяти и раскрасьте часть основного растрового изображения в каждое. Вам также не нужно дурачиться с CreateDIBSection, чтобы сделать это таким образом - вы можете просто сделать все это с совместимыми растровыми изображениями и контекстами устройства.

Что-то вроде следующего (я не проверял это)

std::vector<HBITMAP> SplitBitmap(HBITMAP bmp, int columns, int rows)
{
    // get the bitmap dimensions
    BITMAP bm;
    GetObject(bmp, sizeof(BITMAP), &bm);
    int wd = bm.bmWidth, hgt = bm.bmHeight;
    int piece_wd = wd / columns;
    int piece_hgt = hgt / rows;

    // Select the given bitmap into a device context.
    auto hdcScreen = GetDC(NULL);
    auto hdcBitmap = CreateCompatibleDC(hdcScreen);
    auto hbmOldBmp = SelectObject(hdcBitmap, bmp);

    std::vector<HBITMAP> pieces(columns*rows);
    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < columns; col++) {
            // create a device context for a piece and select an appropriately sized bitmap into it
            auto hdcPiece = CreateCompatibleDC(hdcScreen);
            auto hbmPiece = CreateCompatibleBitmap(hdcScreen, piece_wd, piece_hgt);
            auto hbmOldPiece = SelectObject(hdcPiece, hbmPiece);

            // paint a piece of the whole bitmap into the piece bitmap
            BitBlt(hdcPiece, 0, 0, piece_wd, piece_hgt, hdcBitmap, col * piece_wd, row * piece_hgt, SRCCOPY);

            // cleanup per piece resources we dont need.
            SelectObject(hdcPiece, hbmOldPiece);
            DeleteDC(hdcPiece);

            pieces[row * columns + col] = hbmPiece;
        }
    }

    SelectObject(hdcBitmap, hbmOldBmp);
    DeleteDC(hdcBitmap);
    ReleaseDC(NULL, hdcScreen);

    return pieces;
}

...

auto hbm = (HBITMAP)LoadImage(NULL, L"C:\\work\\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
auto pieces = SplitBitmap(hbm, 4, 4);
0 голосов
/ 20 мая 2019

Вы можете сделать это.

Вот некоторые упрощенные коды для справки.

int Spilt(HWND hWnd)
{
    BYTE* bitPointer;
    HBITMAP g_BitMap = (HBITMAP)LoadImage(NULL, L"C:\\Users\\strives\\Desktop\\timg.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    HDC dc = GetDC(hWnd);
    HDC dc_1 = GetDC(hWnd);
    HDC hdcMemDC = CreateCompatibleDC(dc);
    HDC hdcTemp = CreateCompatibleDC(dc);
    HDC hdcMemDC_1 = GetDC(hWnd);
    BITMAP bmp;
    BITMAP bmp_3;

    GetObject(g_BitMap, sizeof(BITMAP), &bmp);

    static BITMAPINFO bitmap;
    bitmap.bmiHeader.biSize = sizeof(bitmap.bmiHeader);
    bitmap.bmiHeader.biWidth = bmp.bmWidth / 2;
    bitmap.bmiHeader.biHeight = bmp.bmHeight;
    bitmap.bmiHeader.biPlanes = 1;
    bitmap.bmiHeader.biBitCount = 24;
    bitmap.bmiHeader.biCompression = BI_RGB;
    bitmap.bmiHeader.biSizeImage = bmp.bmWidth / 2 * bmp.bmHeight * 4;
    bitmap.bmiHeader.biClrUsed = 0;
    bitmap.bmiHeader.biClrImportant = 0;
    HBITMAP hBitmap2 = CreateDIBSection(hdcTemp, &bitmap, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL);

    HBITMAP bmp_1 = CreateCompatibleBitmap(hdcMemDC_1, bmp.bmWidth / 2, bmp.bmHeight );

    SelectObject(hdcMemDC, g_BitMap);
    SelectObject(hdcTemp, bmp_1);

    BitBlt(hdcTemp, 0, 0, bmp.bmWidth / 2, bmp.bmHeight, hdcMemDC, 0, 0, SRCCOPY);

    GetObject(bmp_1, sizeof(BITMAP), &bmp_3);

    BITMAPFILEHEADER   bmfHeader;
    BITMAPINFOHEADER   bi;      

    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmp_3.bmWidth;
    bi.biHeight = bmp_3.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = 24;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    DWORD dwBmpSize = ((bmp_3.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp_3.bmHeight; 

    // Starting with 24-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
    char *lpbitmap = (char *)GlobalLock(hDIB);

    GetDIBits(hdcMemDC, bmp_1, 0,
        (UINT)bmp_3.bmHeight,
        lpbitmap,   
        (BITMAPINFO *)&bi, 
        DIB_RGB_COLORS);

    // A file is created, this is where we will save the screen capture.
    HANDLE hFile = CreateFile(L"spilt_1.bmp",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);

    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

    bmfHeader.bfSize = dwSizeofDIB;

    bmfHeader.bfType = 0x4D42; //BM   

    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);

    //Unlock and Free the DIB from the heap
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);

    //Close the handle for the file that was created
    CloseHandle(hFile);

    DeleteObject(hdcTemp);
    DeleteObject(hdcMemDC);
    DeleteObject(hBitmap2);
    DeleteObject(bmp_1);

    return 0;
}

Debug

Для удобствапонимая, я делю растровое изображение на две части и сохраняю их как файлы изображений.Наконец, я могу сохранить путь к файлу в одномерном массиве.

Ссылка на код: Захват изображения и консультация @Jonathan Potter advice.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...