debugging C++:当使用位集数组(正确地!)代替位集变量时,程序似乎不工作

mftmpeh8  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(100)

我在调试一些代码时遇到了一个非常特殊的问题。在这个程序的第一次迭代中,我使用了几个位集变量,而不是制作一个位集数组。
我试图弄清楚为什么数组只对任何事情的第一种情况起作用,而不是其余的情况(输出是一系列图像)
请注意,当使用变量时,它确实工作得很好。
任何输入都将受到赞赏。本质上,麻烦要么来自bmp_split函数,要么来自保存_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();
}
u4vypkhs

u4vypkhs1#

我不太清楚为什么需要将8bpp图像分割为单色图像,但是如果将保存_bmp函数更改为以下内容,它至少会生成“有效”的图像

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); 
    unsigned char * b = pack(image);
    fwrite(b,N/8,1,file_ptr);
    delete[] b;

    fclose(file_ptr); 
}

bitset是一个对象而不是一个缓冲区。因为你已经有了一个pack函数来把bitset打包到一个缓冲区中,所以使用它来代替试图把一个对象写到一个文件中似乎是很自然的。

相关问题