1

大家好:)

几天前,我终于设法创建了一个功能性 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;
};

};

4

2 回答 2

0

If you know you are on a little-endian machine, you can completely skip the re-packing of the data, and just store the pixelarray data directly.

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

It may not be quite as portable, but it will certainly speed up the saving to file.

(And you could have a

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

PIXEL *PixelArray;

in the declaration.

于 2013-08-03T18:53:42.120 回答
0

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

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

于 2013-08-03T19:23:43.863 回答