我在调试某些代码时遇到了一个非常特殊的问题。在这个程序的第一次迭代中,我使用了几个位集变量,而不是制作一个位集数组。
我试图弄清楚为什么数组只适用于任何事情的第一种情况,而不适用于其他情况(输出是一系列图像)
请注意,当使用变量时,它确实运行良好。
任何意见都将不胜感激。从本质上讲,问题要么来自bmp_split函数,要么来自save_bmp函数,但我的钱花在了后者上。
#include <iostream>
#include <sstream>
#include <string.h>
#include <string>
#include <cstdlib>
#include <Windows.h>
#include <bitset>
using namespace std;
char *file_name = "grayImage.bmp";
#define X 1024
#define Y 768
#define N X*Y
//Function prototypes
FILE* load_bmp(char *fname);
BITMAPFILEHEADER read_header(FILE *f_ptr);
BITMAPINFOHEADER read_info(FILE *f_ptr);
BYTE* read_imagedata(FILE *f_ptr, BITMAPFILEHEADER *h_ptr);
void new_split(BYTE* pixel, bitset<N> planes[]);
void bmp_split(BYTE *pixel, bitset<N> *p1, bitset<N> *p2, bitset<N> *p3,
bitset<N> *p4, bitset<N> *p5, bitset<N> *p6, bitset<N> *p7, bitset<N> *p8);
BITMAPFILEHEADER create_header();
BITMAPINFOHEADER create_info(BITMAPINFOHEADER *i_ptr);
RGBQUAD create_palette(BYTE R, BYTE G, BYTE B);
void save_bmp(char *fname, BITMAPFILEHEADER *header, BITMAPINFOHEADER *info,
std::bitset<N> *image);
unsigned char char_converter(std::bitset<8> *bin);
unsigned char *pack(std::bitset<N> *bin_plane);
string converInt(int number);
int main()
{
/* bitset array */
bitset<N> * plane_holder[8];
for (int i = 0; i<8; i++)
{
plane_holder[i] = new bitset<N>;
}
bitset<N> plane1;
bitset<N> plane2;
bitset<N> plane3;
bitset<N> plane4;
bitset<N> plane5;
bitset<N> plane6;
bitset<N> plane7;
bitset<N> plane8;
FILE *bmp_ptr;
BITMAPFILEHEADER header_ptr, new_header;
BITMAPINFOHEADER info_ptr, new_info;
RGBQUAD new_palette1, new_palette2;
BYTE *image_ptr;
/*unsigned char pointer array replacing 8 char variables!
unsigned char * buffer[8];*/
unsigned char *buf1, *buf2, *buf3, *buf4, *buf5, *buf6, *buf7, *buf8;
//Load the input 8bpp image
cout << file_name << endl;
//system("PAUSE");
bmp_ptr = load_bmp(file_name);
header_ptr = read_header(bmp_ptr);
info_ptr = read_info(bmp_ptr);
if(info_ptr.biBitCount != 8)
{
cout << "This program is only for 8bpp images" << endl;
system("PAUSE");
return 0;
}
image_ptr = read_imagedata(bmp_ptr, &header_ptr);
fclose(bmp_ptr);
//Split the 8bpp image into eight 1bpp images
//new_split(image_ptr, plane_holder);
bmp_split(image_ptr, plane_holder[0], plane_holder[1], plane_holder[2], plane_holder[3], plane_holder[4],
plane_holder[5], plane_holder[6], plane_holder[7]);
delete[] image_ptr;
//Saving the planes
new_header = create_header();
new_info = create_info(&info_ptr);
save_bmp("Picture1.bmp", &new_header, &new_info, plane_holder[0]);
save_bmp("Picture2.bmp", &new_header, &new_info, plane_holder[1]);
save_bmp("Picture3.bmp", &new_header, &new_info, plane_holder[2]);
save_bmp("Picture4.bmp", &new_header, &new_info, plane_holder[3]);
save_bmp("Picture5.bmp", &new_header, &new_info, plane_holder[4]);
save_bmp("Picture6.bmp", &new_header, &new_info, plane_holder[5]);
save_bmp("Picture7.bmp", &new_header, &new_info, plane_holder[6]);
save_bmp("Picture8.bmp", &new_header, &new_info, plane_holder[7]);
//Pack the eight 1bpp images
buf1 = pack(plane_holder[0]);
buf2 = pack(plane_holder[1]);
buf3 = pack(plane_holder[2]);
buf4 = pack(plane_holder[3]);
buf5 = pack(plane_holder[4]);
buf6 = pack(plane_holder[5]);
buf7 = pack(plane_holder[6]);
buf8 = pack(plane_holder[7]);
delete[] buf1;
delete[] buf2;
delete[] buf3;
delete[] buf4;
delete[] buf5;
delete[] buf6;
delete[] buf7;
delete[] buf8;
for (int i = 0; i<8; i++)
{
delete plane_holder[i];
}
system("PAUSE");
return 0;
}
/* This function downloads a bmp file. The parameter is the name of the
bmp file. Returns the pointer to the bmp file.
*/
FILE* load_bmp(char *fname)
{
FILE *bmp;
bmp=fopen(fname, "rb");
if(bmp == NULL)
{
cout << "File opening fail\n";
system("PAUSE");
return 0;
}
return bmp;
}
/* This function reads the info header in the input bmp. The parameter is
the pointer to the input bmp. Returns pointer to the file header of the
input bmp.
*/
BITMAPFILEHEADER read_header(FILE *f_ptr)
{
BITMAPFILEHEADER bmfh;
fread(&bmfh, sizeof(BITMAPFILEHEADER), 1, f_ptr);
return bmfh;
}
/* This function reads the info header in the input bmp. The parameter is
the pointer to the input bmp. Returns pointer to the info header of the
input bmp.
*/
BITMAPINFOHEADER read_info(FILE *f_ptr)
{
BITMAPINFOHEADER bmih;
fread(&bmih, sizeof(BITMAPINFOHEADER), 1, f_ptr);
return bmih;
}
/* This function reads the image array in the input bmp. The parameters are
two pointer to the input bmp and its file header. Returns pointer to
the images array o fthe input bmp.
*/
BYTE* read_imagedata(FILE *f_ptr, BITMAPFILEHEADER *h_ptr)
{
DWORD size;
BYTE *tempPixelData;
size = (*h_ptr).bfSize - (*h_ptr).bfOffBits;
tempPixelData = new BYTE[size];
if(tempPixelData == NULL)
{
fclose(f_ptr);
cout << "image extraction fail\n";
return 0;
}
fread(tempPixelData,sizeof(BYTE),size,f_ptr);
return tempPixelData;
}
/* This function splits each pixel in the original 8bpp bmp into eight bits and
appends each bit to different bitset arrays. The parameters are the image array
of the original bmp, and eight bitset arrays which represents eight bitplanes.
*/
void bmp_split(BYTE *pixel, bitset<N> *p1, bitset<N> *p2, bitset<N> *p3,
bitset<N> *p4, bitset<N> *p5, bitset<N> *p6, bitset<N> *p7, bitset<N> *p8)
{
int i, dec;
BYTE *temp = pixel;
for(i=0; i<N; i++)
{
dec = (int)*temp;
(*p1)[i] = dec % 2;
dec /= 2;
(*p2)[i] = dec % 2;
dec /= 2;
(*p3)[i] = dec % 2;
dec /= 2;
(*p4)[i] = dec % 2;
dec /= 2;
(*p5)[i] = dec % 2;
dec /= 2;
(*p6)[i] = dec % 2;
dec /= 2;
(*p7)[i] = dec % 2;
dec /= 2;
(*p8)[i] = dec % 2;
temp++;
}
}
void new_split(BYTE* pixel, bitset<N> planes[])
{
int i, dec;
BYTE *temp = pixel;
for(i=0; i<N; i++)
{
dec = (int)*temp;
planes[0][i] = dec%2;
dec /= 2;
planes[1][i] = dec%2;
dec /= 2;
planes[2][i] = dec%2;
dec /= 2;
planes[3][i] = dec%2;
dec /= 2;
planes[4][i] = dec%2;
dec /= 2;
planes[5][i] = dec%2;
dec /= 2;
planes[6][i] = dec%2;
dec /= 2;
planes[7][i] = dec%2;
dec /= 2;
temp++;
}
}
/* This function creates an file header for a 1bpp bmp file.
All the features corresponds to the original 8bpp bmp file except for bpp.
Returns the file header.
*/
BITMAPFILEHEADER create_header()
{
BITMAPFILEHEADER header;
header.bfType = 'B'+('M' << 8);
header.bfReserved1 = 0;
header.bfReserved2 = 0;
header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD)*2;
header.bfSize = header.bfOffBits + N/8;
return header;
}
/* This function creates an info header for a 1bpp bmp file.
All the features corresponds to the original 8bpp bmp file except for bpp.
Returns the info header.
*/
BITMAPINFOHEADER create_info(BITMAPINFOHEADER *i_ptr)
{
BITMAPINFOHEADER info;
info.biSize = sizeof(BITMAPINFOHEADER);
info.biWidth = X;
info.biHeight = Y;
info.biPlanes = 1;
info.biBitCount = 1;
info.biCompression = 0;
info.biSizeImage = X*Y/8;
info.biXPelsPerMeter = (*i_ptr).biXPelsPerMeter;
info.biYPelsPerMeter = (*i_ptr).biYPelsPerMeter;
info.biClrUsed = 0;
info.biClrImportant = 0;
return info;
}
/* This function creates colour definition.
The parameters are the degree of red, green, and blue.
Returns the colour definition.
*/
RGBQUAD create_palette(BYTE R, BYTE G, BYTE B)
{
RGBQUAD palette;
palette.rgbBlue = R;
palette.rgbGreen = G;
palette.rgbRed = B;
return palette;
}
/* This function saves a pure black and white bitmap file of 1bpp.
The parameters are the desired file name, file header, info header,
and the image array.
*/
void save_bmp(char *fname, BITMAPFILEHEADER *header, BITMAPINFOHEADER *info,
std::bitset<N> *image)
{
FILE *file_ptr = fopen(fname, "wb");
fwrite(header, sizeof(BITMAPFILEHEADER), 1, file_ptr);
fwrite(info, sizeof(BITMAPINFOHEADER), 1, file_ptr);
fwrite(&create_palette(0,0,0), sizeof(RGBQUAD), 1, file_ptr);
fwrite(&create_palette(255,255,255), sizeof(RGBQUAD), 1, file_ptr);
fwrite(image, N, 1, file_ptr);
fclose(file_ptr);
}
/* This function converts a 8 digit binary number into a decimal number.
Given bitset of size 8, it returns single unsigned char variable.
*/
unsigned char char_converter(bitset<8> *bin)
{
int c = 0;
c = (*bin)[7]*128+(*bin)[6]*64+(*bin)[5]*32+(*bin)[4]*16+(*bin)[3]*8
+(*bin)[2]*4+(*bin)[1]*2+(*bin)[0]*1;
return (unsigned char)c;
}
/* This function packs 8 consecutive elements of 1bpp image array,
which represents 8 digit binary number into array of decimal
number of type unsigned char. Returns dynamically allocated
unsigned char array of size N/8.
*/
unsigned char *pack(bitset<N> *bin_plane)
{
bitset<8> bin;
int i = N-1, j = 7, k = 0;
unsigned char c, *buffer;
buffer = new unsigned char[N/8];
while(i>=0)
{
bin[j] = (*bin_plane)[i];
if(j == 0)
{
j = 8;
c = char_converter(&bin);
buffer[k] = c;
k++;
}
--i;
--j;
}
return buffer;
}
string convertInt (int number)
{
stringstream ss;
ss<<number;
return ss.str();
}