如何加速我的.bmp类

How to speed up my .bmp class?

本文关键字:我的 bmp 加速 何加速      更新时间:2023-10-16

向大家致以良好的问候:)

几天前,我终于创建了一个函数式C++类来制作.bmp图像。尽管它是功能性的(还没有错误),但在速度方面(在我看来)效率并不高。做了一些测试,看看写不同大小的图像需要多少时间,我最终得到了以下结果:

Image Dimensions   Time taken(in seconds)     Comparison to the 1000x1000 image
10x100             0.0491                     x 1000 = 49.1 seconds
100x100            0.2471                     x 100  = 24.7 seconds
100x1000           2.3276                     x 10   = 23.3 seconds
1000x1000          22.515                     x 1    = 22.5 seconds
1000x10000         224.76                      10   = 22.4 seconds

例如,10x100图像有1000个像素(每个像素有一个ARGB通道[32位或4个字节])加上标题的54个字节,写入4054个字节(char)需要0.05秒。

我觉得这太慢了,因为我的电脑可以在一两秒钟内复制一个~85MB的文件。我正在使用fstream向磁盘进行写入,任何能让课程更快进行的帮助都将不胜感激。非常感谢。

我的类名为SimpleBMP,它就在这里(我只放了相关函数):

#include <fstream>

class SimpleBMP{
    struct PIXEL{
        unsigned char A, R, G, B;
    }*PixelArray;
    unsigned char *BMPHEADER, *BMPINFOHEADER;
    std::string DATA;
    unsigned int Size_Of_BMP, Size_Of_PixelArray;
    int BMP_Width, BMP_Height;
public:
void SetPixel(int Column, int Row, unsigned char A, unsigned char R, unsigned char G, unsigned char B){
    PixelArray[(Row*BMP_Width)+Column].A = A;
    PixelArray[(Row*BMP_Width)+Column].R = R;
    PixelArray[(Row*BMP_Width)+Column].G = G;
    PixelArray[(Row*BMP_Width)+Column].B = B;
};
bool MakeImage(std::string Name){
    Name.append(".bmp");
    std::ofstream OffFile(Name, std::ios::out|std::ios::binary);
    if(OffFile.is_open()){
        DATA.clear();
        for(int temp = 0; temp < 14; temp++){
            BMPHEADER[temp] = 0x00;
        };
        BMPHEADER[0] = 'B';
        BMPHEADER[1] = 'M';
        BMPHEADER[2] = Size_Of_BMP;
        BMPHEADER[3] = (Size_Of_BMP >> 8);
        BMPHEADER[4] = (Size_Of_BMP >> 16);
        BMPHEADER[5] = (Size_Of_BMP >> 24);
        BMPHEADER[10] = 0x36;

        for(int temp = 0; temp < 40; temp++){
            BMPINFOHEADER[temp] = 0x00;
        };
        BMPINFOHEADER[0] = 0x28;
        for(int temp = 0; temp < 4; temp++){
            BMPINFOHEADER[temp+4] = (BMP_Width >> (temp*8));
        };
        for(int temp = 0; temp < 4; temp++){
            BMPINFOHEADER[temp+8] = (BMP_Height >> (temp*8));
        };  
        BMPINFOHEADER[12] = 0x01;
        BMPINFOHEADER[14] = 0x20;
        for(int temp = 0; temp < 4; temp++){
            BMPINFOHEADER[temp+20] = (Size_Of_PixelArray >> (temp*8));
        };
        BMPINFOHEADER[24] = 0x13;
        BMPINFOHEADER[25] = 0x0b;
        BMPINFOHEADER[28] = 0x13;
        BMPINFOHEADER[29] = 0x0b;

        for(int temp = 0; temp < 14; temp++){
            DATA.push_back(BMPHEADER[temp]);
        };
        for(int temp = 0; temp < 40; temp++){
            DATA.push_back(BMPINFOHEADER[temp]);
        };
        for(int temp = 0; temp < (Size_Of_PixelArray/4); temp++){
            DATA.push_back(PixelArray[temp].B);
            DATA.push_back(PixelArray[temp].G);
            DATA.push_back(PixelArray[temp].R);
            DATA.push_back(PixelArray[temp].A);
        };  
        OffFile.write(DATA.c_str(), Size_Of_BMP);
        OffFile.close();
        return true;
    }
    else
        return false;
};

};

运行测试时,应以版本模式编译项目Debug模式在大多数环境中引入了额外的检查和代码。链接的调试库还可以包括其他检查,如边界检查和迭代器验证,这些检查在发布模式中不存在。所有这些都可能带来发布模式中不存在的性能命中率。

您还可以应用其他优化,例如在加载数据之前在DATA中保留内存。这将减少在扩展缓冲区时需要制作的副本数量。尽管性能提升可能并不显著,但它肯定会有所帮助。我建议通过探查器运行代码,查看所有瓶颈所在,并相应地进行优化。

如果你知道你在一个小的endian机器上,你可以完全跳过数据的重新打包,直接存储pixerray数据。

OffFile.Write((char *)&PixelArray, Size_Of_BMP);

它可能没有那么便携,但它肯定会加快保存到文件的速度。

(你可以有

#ifdef LITTLE_ENDIAN
struct PIXEL{
    unsigned char A, R, G, B;
};
#else
struct PIXEL{
    unsigned char B, G, R, A;
};
#endif    
PIXEL *PixelArray;

在声明中。