使用当前循环更改位图文件的单色图案

时间:2019-04-04 00:59:19

标签: c++ loops bitmap

我正在尝试更改当前位图文件的模式,但是在更改嵌套的for循环来执行此操作时遇到了麻烦。我正在尝试获取具有8个水平条,高32像素,黑白交替的位图文件。我现在得到的是64个垂直条,黑白交替显示。位图图像尺寸为256 x 256像素。

我弄乱了代码中的嵌套for循环,该循环负责在我的多维位数组中存储白色(0x0f)。我注意到,如果将白色更改为黑色(将0x0f更改为0x00),则整个位图文件都会变为黑色。下面是我专注于输出模式的代码部分,在此部分我拥有了完整的代码。

// Build monochrome array of bits in image
    for (int i = 0; i < IMAGE_SIZE; i++) {
        for (int j = 0; j < IMAGE_SIZE / 8; j++) {
            bits[i][j] = 0x0f;
        }
    }
#include <iostream>
#include <fstream>
#include "windows.h"
using namespace std;
// The following defines the size of the square image in pixels.
#define IMAGE_SIZE 256
int main(int argc, char* argv[])
{

    BITMAPFILEHEADER bmfh;

    BITMAPINFOHEADER bmih;

    char colorTable[8] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff };

    // The following defines the array which holds the image.  The row length 
    // (number of columns) is the height divided by 8, since there are 8 bits
    // in a byte.
    char bits[IMAGE_SIZE][IMAGE_SIZE / 8];

    // Define and open the output file. 
    ofstream bmpOut("foo.bmp", ios::out + ios::binary);
    if (!bmpOut) {
        cout << "...could not open file, ending.";
        return -1;
    }
    // Initialize the bit map file header with static values.
    bmfh.bfType = 0x4d42;
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + sizeof(colorTable);
    bmfh.bfSize = bmfh.bfOffBits + sizeof(bits);

    // Initialize the bit map information header with static values.
    bmih.biSize = 40;
    bmih.biWidth = IMAGE_SIZE;
    bmih.biHeight = IMAGE_SIZE;
    bmih.biPlanes = 1;
    bmih.biBitCount = 1;
    bmih.biCompression = 0;
    bmih.biSizeImage = 0;
    bmih.biXPelsPerMeter = 2835;  // magic number, see Wikipedia entry
    bmih.biYPelsPerMeter = 2835;
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;

    // Build monochrome array of bits in image
    for (int i = 0; i < IMAGE_SIZE; i++) {
        for (int j = 0; j < IMAGE_SIZE / 8; j++) {
            bits[i][j] = 0x0f;
        }
    }

    // Write out the bit map.  
    char* workPtr;
    workPtr = (char*)&bmfh;
    bmpOut.write(workPtr, 14);
    workPtr = (char*)&bmih;
    bmpOut.write(workPtr, 40);
    workPtr = &colorTable[0];
    bmpOut.write(workPtr, 8);
    workPtr = &bits[0][0];
    bmpOut.write(workPtr, IMAGE_SIZE*IMAGE_SIZE / 8);
    bmpOut.close();

    // showing result
    system("mspaint foo.bmp");

    // Done.
    return 0;
}

1 个答案:

答案 0 :(得分:0)

您没有正确填充位数组。

您正在创建一个1位(单色)自底向上位图。数组中的每个单独位代表一个不同的像素,其中0位是指颜色表中的第一种颜色,而1位是指颜色表中的第二种颜色。位图图像中的第一行是数组中的 last 行,位图图像中的最后一行是数组中的 first 行。

0x0F十六进制是00001111二进制。您将数组中的每个8位char设置为0x0f,因此您将创建一个交替的模式,该模式由4个0000位,然后每行4个1111位组成,例如:

00001111 00001111 00001111 ... (for 29 more bytes)
00001111 00001111 00001111 ... (for 29 more bytes)
00001111 00001111 00001111 ... (for 29 more bytes)
... (for 253 more rows)

对于256x256位图,它会产生64个交替的垂直条,每条垂直条的宽度均为4个像素。

要获得所需的效果-8个交替的水平条,每个水平条高32像素-您需要将给定行中的每一位都设置为全0或全1,然后您需要将该模式分成一组32个完整的行,例如:

00000000 00000000 00000000 ... (for 29 more bytes)
00000000 00000000 00000000 ... (for 29 more bytes)
00000000 00000000 00000000 ... (for 29 more bytes)
... (for 29 more rows)

11111111 11111111 11111111 ... (for 29 more bytes)
11111111 11111111 11111111 ... (for 29 more bytes)
11111111 11111111 11111111 ... (for 29 more bytes)
... (for 29 more rows)

... (repeat the above 4 more times)

请尝试以下类似操作:

// Build monochrome array of bits in image
bool isWhite = false;
for (int i = 0; i < IMAGE_SIZE; ) {
    char ch = isWhite ? 0xFF : 0x00;
    int row = (IMAGE_SIZE - 1) - i; // use row = i for a top-down bitmap ...

    for (int col = 0; col < (IMAGE_SIZE / 8); ++col) {
        bits[row][col] = ch;
    }

    // alternatively to the above loop:
    // memset(bits[row], isWhite ? 0xFF : 0x00, IMAGE_SIZE / 8);

    if ((++i % 32) == 0) isWhite = !isWhite;
}

或者:

// Build monochrome array of bits in image
bool isWhite = true;
for (int i = 0; i < IMAGE_SIZE; ++i) {
    if ((i % 32) == 0) isWhite = !isWhite;
    int row = (IMAGE_SIZE - 1) - i; // use row = i for a top-down bitmap ...

    char ch = isWhite ? 0xFF : 0x00;
    for (int col = 0; col < (IMAGE_SIZE / 8); ++col) {
        bits[row][col] = ch;
    }

    // alternatively to the above loop:
    // memset(bits[row], isWhite ? 0xFF : 0x00, IMAGE_SIZE / 8);
}

或者:

// Build monochrome array of bits in image
for (int i = 0; i < IMAGE_SIZE; ++i) {
    char ch = ((i % 64) < 32) ? 0x00 : 0xFF;
    int row = (IMAGE_SIZE - 1) - i; // use row = i for a top-down bitmap ...

    for (int col = 0; col < IMAGE_SIZE / 8; ++col) {
        bits[row][col] = ch;
    }

    // alternatively to the above loop:
    // memset(bits[row], ((i % 64) < 32) ? 0x00 : 0xFF, IMAGE_SIZE / 8);
}

话虽如此,我还是建议对您的其余代码进行一些其他调整:

#include <iostream>
#include <fstream>
#include <windows.h>
//#include <string.h> // if using memset() above...

// The following defines the size of the square image in pixels.
#define IMAGE_SIZE 256

// The following defines the size of each row in bytes.
#define BYTES_PER_ROW (IMAGE_SIZE / sizeof(BYTE))

int main()
{
    // Define and open the output file. 
    std::ofstream bmpOut("foo.bmp", std::ios::binary);
    if (!bmpOut)
    {
        std::cerr << "could not open file, ending.";
        return -1;
    }

    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    RGBQUAD colorTable[2] = { {0x00,0x00,0x00,0x00}, {0xFF,0xFF,0xFF,0x00} };

    // The following defines the array which holds the image bits.  The row length 
    // (number of columns) is the height divided by 8, since there are 8 bits
    // in a byte.
    BYTE bits[IMAGE_SIZE][BYTES_PER_ROW];

    // Initialize the bitmap file header with static values.
    bmfh.bfType = 0x4d42;
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + sizeof(colorTable);
    bmfh.bfSize = bmfh.bfOffBits + sizeof(bits);

    // Initialize the bitmap information header with static values.
    bmih.biSize = sizeof(bmih);
    bmih.biWidth = IMAGE_SIZE;
    bmih.biHeight = IMAGE_SIZE; // positive for bottom-up, negative for top-down
    bmih.biPlanes = 1;
    bmih.biBitCount = 1;
    bmih.biCompression = BI_RGB;
    bmih.biSizeImage = 0;
    bmih.biXPelsPerMeter = 2835;  // magic number, see Wikipedia entry
    bmih.biYPelsPerMeter = 2835;
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;

    // Build monochrome array of bits in image, see above...

    // Write out the bitmap.  
    bmpOut.write(reinterpret_cast<char*>(&bmfh), sizeof(bmfh));
    bmpOut.write(reinterpret_cast<char*>(&bmih), sizeof(bmih));
    bmpOut.write(reinterpret_cast<char*>(&colorTable), sizeof(colorTable));
    bmpOut.write(reinterpret_cast<char*>(&bits), sizeof(bits));

    if (!bmpOut)
    {
        std::cerr << "could not write file, ending.";
        return -1;
    }

    bmpOut.close();

    // showing result
    ShellExecuteA(NULL, NULL, "foo.bmp", NULL, NULL, SW_SHOW);

    // Done.
    return 0;
}