Dice painting—–Select a grayscale image and convert it into a painting composed of dice graphics.

#include "Windows.h"
#include "stdio.h"
#include "string.h"
#include "malloc.h"
#include <iostream>
#include "time.h"
#pragma warning(suppress: 4996)
using namespace std;

unsigned char* pBmpBuf;//Pointer to read image data
int bmpWidth;//The width of the image
int bmpHeight;//Height of the image
RGBQUAD* pColorTable;//Color table pointer
int biBitCount;//Image type, bits per pixel

//Dice image: 16*16 two-dimensional array
int touzi1[16][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

int touzi2[16][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 },
{ 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0 },
{ 0, 0, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255, 0, 0 },
{ 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0 },
{ 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

int touzi3[16][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

int touzi4[16][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 },
{ 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0 },
{ 0, 0, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255, 0, 0 },
{ 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0 },
{ 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 },
{ 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0 },
{ 0, 0, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255, 0, 0 },
{ 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0 },
{ 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

int touzi5[16][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

int touzi6[16][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0 },
{ 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

//Character drawing array
char asciiart[72] = "$@B%8 & amp;WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]? -_ + ~<>i!lI;:,"^`'. ";

bool readBmp(char* bmpName)
{
//Open the specified image file in binary reading mode
FILE* fp = fopen(bmpName, "rb");
if (fp == 0) return 0;

//Skip the bitmap file header structure BITMAPFILEHEADER
fseek(fp, sizeof(BITMAPFILEHEADER), 0);
//Define the bitmap information header structure variable, read the bitmap information header into the memory, and store it in the variable head
BITMAPINFOHEADER head;
fread( & amp;head, sizeof(BITMAPINFOHEADER), 1, fp);
//Get image width, height, number of digits per pixel and other information
bmpWidth = head.biWidth;
bmpHeight = head.biHeight;
biBitCount = head.biBitCount;
//Define variables to calculate the number of bytes occupied by each row of pixels in the image (must be a multiple of 4)
int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;
//The grayscale image has a color table, and the color table entry is 256
if (biBitCount == 8) {
//Apply for the space required by the color table and read the color table into memory
pColorTable = new RGBQUAD[256];
fread(pColorTable, sizeof(RGBQUAD), 256, fp);
}
//Apply for the space required for bitmap data and read the bitmap data into memory
pBmpBuf = new unsigned char[lineByte * bmpHeight];
fread(pBmpBuf, 1, lineByte * bmpHeight, fp);
//Close file
fclose(fp);
return 1;
}

bool saveBmp(char* bmpName, unsigned char* imgBuf, int width, int height,
int biBitCount, RGBQUAD* pColorTable)
{
//If the bitmap data pointer is 0, no data is passed in and the function returns
if (!imgBuf)
return 0;
//Color table size, in bytes, grayscale image color table is 1024 bytes, color image color table size is 0
int colorTablesize = 0;
if (biBitCount == 8)
colorTablesize = 1024;
//The number of bytes per line of image data to be stored is a multiple of 4
int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
//Open the file in binary writing mode
FILE* fp = fopen(bmpName, "wb");
if (fp == 0) return 0;
//Apply for the bitmap file header structure variable and fill in the file header information
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42;//bmp type
//bfSize is the sum of the four components of the image file
fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ colorTablesize + lineByte * height;
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;
//bfOffBits is the sum of the space required for the first three parts of the image file
fileHead.bfOffBits = 54 + colorTablesize;
//Write file header into file
fwrite( & amp;fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
//Apply for the bitmap header structure variable and fill in the header information
BITMAPINFOHEADER head;
head.biBitCount = biBitCount;
head.biClrImportant = 0;
head.biClrUsed = 0;
head.biCompression = 0;
head.biHeight = height;
head.biPlanes = 1;
head.biSize = 40;
head.biSizeImage = lineByte * height;
head.biWidth = width;
head.biXPelsPerMeter = 0;
head.biYPelsPerMeter = 0;
//Write bitmap information header into memory
fwrite( & amp;head, sizeof(BITMAPINFOHEADER), 1, fp);
//If the grayscale image has a color table, write it to the file
if (biBitCount == 8)
fwrite(pColorTable, sizeof(RGBQUAD), 256, fp);
//Write bitmap data into file
fwrite(imgBuf, height * lineByte, 1, fp);
//Close file
fclose(fp);
return 1;
}

int main()
{
char inFileName[90] = "D:\OneDrive\Desktop\Data Structure\Dice Image\sss.bmp";
char outFileName[90] = "D:\OneDrive\Desktop\Data Structure\Dice Image\shui3.bmp";
//printf("Please enter the file name of the original bitmap file:");
//scanf("%s", inFileName);
//printf("Please enter the file name of the new bitmap file:");
//scanf("%s", outFileName);
//Read the specified BMP file into memory

readBmp(inFileName);
//Output image information
printf("width=%d,height=%d, biBitCount=%d\
", bmpWidth, bmpHeight, biBitCount);

//Fill in the processing function or code here

int sum = 0;

for (int I = 0; I < bmpWidth / 16; I + + )

{

for (int j = 0; j < bmpHeight / 16; j + + )

{

for (int k = 0; k < 16; k + + )

{

for (int n = 0; n < 16; n + + )

{

sum + = (*(pBmpBuf + (I * 16 + k) * bmpHeight + k + j * 16 + n));

}

}

int average = sum / 256;

if (0 <= average & amp; & amp; average <= 41)

{

for (int k = 0; k < 16; k + + )

for (int n = 0; n < 16; n + + )

pBmpBuf[(I * 16 + k) * bmpHeight + j * 16 + n] = touzi1[k][n];

}

if (41 < average & amp; & amp; average <= 83)

{

for (int k = 0; k < 16; k + + )

for (int n = 0; n < 16; n + + )

pBmpBuf[(I * 16 + k) * bmpHeight + j * 16 + n] = touzi2[k][n];

}

if (83 <= average & amp; & amp; average <= 124)

{

for (int k = 0; k < 16; k + + )

for (int n = 0; n < 16; n + + )

pBmpBuf[(I * 16 + k) * bmpHeight + j * 16 + n] = touzi3[k][n];

}

if (124 < average & amp; & amp; average <= 165)

{

for (int k = 0; k < 16; k + + )

for (int n = 0; n < 16; n + + )

pBmpBuf[(I * 16 + k) * bmpHeight + j * 16 + n] = touzi4[k][n];

}

if (165 < average & amp; & amp; average <= 206)

{

for (int k = 0; k < 16; k + + )

for (int n = 0; n < 16; n + + )

pBmpBuf[(I * 16 + k) * bmpHeight + j * 16 + n] = touzi5[k][n];

}

if (206 < average & amp; & amp; average <= 256)

{

for (int k = 0; k < 16; k + + )

for (int n = 0; n < 16; n + + )

pBmpBuf[(I * 16 + k) * bmpHeight + j * 16 + n] = touzi6[k][n];

}

sum = 0;

}

}

//Save image data to disk
saveBmp(outFileName, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
//Clear the buffer, pBmpBuf and pColorTable are global variables, space applied for when the file is read in
delete[]pBmpBuf;
if (biBitCount == 8)
delete[]pColorTable;
return 0;
}

Select a grayscale image yourself and convert it into a painting composed of dice graphics.

Imageprocess.cpp provides code for reading and writing bmp grayscale images. Use readBmp to read the image. The image data is stored in pBmpBuf (one-dimensional). The value range is 0-255. Find the two-dimensional data of the image and Correspondence between one-dimensional arrays, divide the image into blocks of size 16*16, and calculate the average value of each block of data, Convert to the value corresponding to [1,6], replace the original image data with the corresponding dice image data (touzi1-touzi6 6 arrays), and use the saveBmp function to write the data in the image array to a new image file. You can also try character painting. The characters used can refer to the asciiart array, starting from 0 and arranged from dense to sparse. The corresponding image data can be converted into corresponding characters, which can be output on the screen or written to a txt file.

**Note: The image needs to be converted into a 256-color bmp image in relevant image processing (painting, photoshop, etc.) software in advance.

The replacement image is 16*16 in size, so consider the situation that it is not an integer multiple of 16.

When storing bmp images, the number of bytes in each line is an integer multiple of 4. Any multiples less than 4 are filled with 0, so the width cannot be used directly when looping.

The default bmp bitmap data storage is reversed, that is, the above image data is stored at the end of the data.