#c #loops #bitmap
#c #циклы #растровое изображение
Вопрос:
Я пытаюсь изменить шаблон текущего файла растрового изображения, но у меня возникли проблемы с изменением моего вложенного цикла for для этого. Я пытаюсь получить файл растрового изображения с 8 горизонтальными полосами высотой 32 пикселя, чередующимися черным и белым. В настоящее время я получаю 64 вертикальных полосы, чередующиеся с черными и белыми. Размеры растрового изображения составляют 256 пикселей на 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*)amp;bmfh;
bmpOut.write(workPtr, 14);
workPtr = (char*)amp;bmih;
bmpOut.write(workPtr, 40);
workPtr = amp;colorTable[0];
bmpOut.write(workPtr, 8);
workPtr = amp;bits[0][0];
bmpOut.write(workPtr, IMAGE_SIZE*IMAGE_SIZE / 8);
bmpOut.close();
// showing result
system("mspaint foo.bmp");
// Done.
return 0;
}
Ответ №1:
Вы неправильно заполняете свой массив битов.
Вы создаете 1-битное (монохромное) растровое изображение снизу вверх. Каждый отдельный бит в вашем массиве представляет отдельный пиксель, где 0
бит относится к первому цвету, а 1
бит относится ко второму цвету в вашей таблице цветов. И первая строка в растровом изображении является последней строкой в массиве, а последняя строка в растровом изображении является первой строкой в массиве.
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)
Для растрового изображения размером 256×256 получается 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*>(amp;bmfh), sizeof(bmfh));
bmpOut.write(reinterpret_cast<char*>(amp;bmih), sizeof(bmih));
bmpOut.write(reinterpret_cast<char*>(amp;colorTable), sizeof(colorTable));
bmpOut.write(reinterpret_cast<char*>(amp;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;
}