Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;:读取位图错误 我尝试用C++读取一个 .bmp < /Cord>文件,并将灰度值(平均值超过RGB值)归入Ubuntu 14.04中的一个向量。不知何故,向量的值最终是完全错误的。你能想象为什么吗 std::vector<double> readBMP(const char* filename, int* width, int* height){ std::vector<double> bmp; FILE* f = fopen(filename, "rb"); if(f == NULL){ std::cerr << "file not found!" << std::endl; std::vector<double> empty; width = NULL; height = NULL; return empty; } unsigned char info[54]; fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header // extract image height and width from header *width = *(int*)&info[18]; *height = *(int*)&info[22]; int data_offset = *(int*)(&info[0x0A]); fseek(f, (long int)(data_offset - 54), SEEK_CUR); int row_padded = (*width*3 + 3) & (~3); unsigned char* data = new unsigned char[row_padded]; unsigned char tmp; for(int i = 0; i < *height; i++) { fread(data, sizeof(unsigned char), row_padded, f); for(int j = 0; j < *width*3; j += 3) { // Convert (B, G, R) to (R, G, B) tmp = data[j]; data[j] = data[j+2]; data[j+2] = tmp; bmp.push_back(((double)data[j]+(double)data[j+1]+(double)data[j+2])/(3*255)); std::cout << "R: "<< (int)data[j] << " G: " << (int)data[j+1]<< " B: " << (int)data[j+2]<< std::endl; } } return bmp; }_C++_Colors_Bitmap - Fatal编程技术网

C++;:读取位图错误 我尝试用C++读取一个 .bmp < /Cord>文件,并将灰度值(平均值超过RGB值)归入Ubuntu 14.04中的一个向量。不知何故,向量的值最终是完全错误的。你能想象为什么吗 std::vector<double> readBMP(const char* filename, int* width, int* height){ std::vector<double> bmp; FILE* f = fopen(filename, "rb"); if(f == NULL){ std::cerr << "file not found!" << std::endl; std::vector<double> empty; width = NULL; height = NULL; return empty; } unsigned char info[54]; fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header // extract image height and width from header *width = *(int*)&info[18]; *height = *(int*)&info[22]; int data_offset = *(int*)(&info[0x0A]); fseek(f, (long int)(data_offset - 54), SEEK_CUR); int row_padded = (*width*3 + 3) & (~3); unsigned char* data = new unsigned char[row_padded]; unsigned char tmp; for(int i = 0; i < *height; i++) { fread(data, sizeof(unsigned char), row_padded, f); for(int j = 0; j < *width*3; j += 3) { // Convert (B, G, R) to (R, G, B) tmp = data[j]; data[j] = data[j+2]; data[j+2] = tmp; bmp.push_back(((double)data[j]+(double)data[j+1]+(double)data[j+2])/(3*255)); std::cout << "R: "<< (int)data[j] << " G: " << (int)data[j+1]<< " B: " << (int)data[j+2]<< std::endl; } } return bmp; }

C++;:读取位图错误 我尝试用C++读取一个 .bmp < /Cord>文件,并将灰度值(平均值超过RGB值)归入Ubuntu 14.04中的一个向量。不知何故,向量的值最终是完全错误的。你能想象为什么吗 std::vector<double> readBMP(const char* filename, int* width, int* height){ std::vector<double> bmp; FILE* f = fopen(filename, "rb"); if(f == NULL){ std::cerr << "file not found!" << std::endl; std::vector<double> empty; width = NULL; height = NULL; return empty; } unsigned char info[54]; fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header // extract image height and width from header *width = *(int*)&info[18]; *height = *(int*)&info[22]; int data_offset = *(int*)(&info[0x0A]); fseek(f, (long int)(data_offset - 54), SEEK_CUR); int row_padded = (*width*3 + 3) & (~3); unsigned char* data = new unsigned char[row_padded]; unsigned char tmp; for(int i = 0; i < *height; i++) { fread(data, sizeof(unsigned char), row_padded, f); for(int j = 0; j < *width*3; j += 3) { // Convert (B, G, R) to (R, G, B) tmp = data[j]; data[j] = data[j+2]; data[j+2] = tmp; bmp.push_back(((double)data[j]+(double)data[j+1]+(double)data[j+2])/(3*255)); std::cout << "R: "<< (int)data[j] << " G: " << (int)data[j+1]<< " B: " << (int)data[j+2]<< std::endl; } } return bmp; },c++,colors,bitmap,C++,Colors,Bitmap,预期输出应为(相反): 但事实是: R: 255 G: 255 B: 255 R: 255 G: 255 B: 255 R: 255 G: 255 B: 255 R: 128 G: 128 B: 255 R: 128 G: 255 B: 128 R: 255 G: 128 B: 128 R: 0 G: 0 B: 255 R: 0 G: 255 B: 0 R: 255 G: 0 B: 0 注意: 该代码是此问题答案的修改版本: 根据其编码方式,您的BMP头可能不是标准的,其大小将大于54字节。如

预期输出应为(相反):

但事实是:

R: 255 G: 255 B: 255
R: 255 G: 255 B: 255
R: 255 G: 255 B: 255
R: 128 G: 128 B: 255
R: 128 G: 255 B: 128
R: 255 G: 128 B: 128
R: 0 G: 0 B: 255
R: 0 G: 255 B: 0
R: 255 G: 0 B: 0
注意: 该代码是此问题答案的修改版本:

根据其编码方式,您的BMP头可能不是标准的,其大小将大于54字节。如果是这种情况,则需要使用
fseek
将光标移动到数据块的开头

int data_offset = *(int*)(&info[0x0A]); 

if (data_offset > 54) {
    fseek(f, (long int)(data_offset - 54), SEEK_CUR);
} 
正如Brandon所指出的,您的图片按照格式规范的规定被颠倒编码(因为您指定在Ubuntu上):

像素阵列是一个32位DWORD块,逐像素描述图像。通常情况下,像素按照正常图像光栅扫描顺序“颠倒”存储,从左下角开始,从左到右,然后从图像的底部到顶部逐行存储。[5]除非使用BITMAPCOREHEADER,否则未压缩的Windows位图也可以从上到下存储,当图像高度值为负值时


来源:

停止对偏移量进行硬编码。像素的偏移量实际上位于
info[10]+(info[11]bpp=0;
bmp->width=0;
bmp->height=0;
bmp->pixels.clear();
无符号字符信息[54]={0};
fread(info,sizeof(unsigned char),54,f);
bmp->width=info[18]+(info[19]height=info[22]+(info[23]像素。调整大小((((((bmp->width*bmp->height)+31)和~31)/8)*bmp->height);//位图中像素的大小。
fseek(f,info[10]+(info[11]像素[0],sizeof(无符号字符),bmp->pixels.size(),f);//读取像素。
fclose(f);
//对像素执行任何操作..翻转它们..将BGR交换为RGB,等等。。
返回true;
}
返回false;
}

最后,您的黑色像素低于白色像素,因为位图是颠倒存储的。您必须自己翻转它或自下而上阅读。

最后,我正确地理解了我的代码,以防有人偶然发现这个问题:我的错误是,图像在ABGR中,我假设是BGR

#include <cstdio>
#include <iostream>
#include <vector>

std::vector<double> readBMP(const char* filename, int* width, int* height){
    std::vector<double> bmp;
    FILE* f = fopen(filename, "rb");

    if(f == NULL){
        std::cerr << "file not found!" << std::endl;
        std::vector<double> empty;
        width = NULL;
        height = NULL;
        return empty;
    }

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header

    // extract image height and width from header
    *width = *(int*)&info[18];
    *height = *(int*)&info[22];

    int data_offset = *(int*)(&info[0x0A]);
    if(data_offset > 0)
        fseek(f, (long int)(data_offset - 53), SEEK_CUR);

    std::cout << "  Name: " << filename << std::endl;
    std::cout << " Width: " << *width << std::endl;
    std::cout << "Height: " << *height << std::endl;
    std::cout << "Offset: " << data_offset << std::endl;

    int row_padded = (*width*4 + 4) & (~4);
    unsigned char* data = new unsigned char[row_padded];
    //unsigned char tmp;

    for(int i = 0; i < *height; i++){
        fread(data, sizeof(unsigned char), row_padded, f);
        for(int j = 0; j < row_padded; j += 4)
        {
            // Convert (B, G, R) to (R, G, B)
            //tmp = data[j];
            //data[j] = data[j+2];
            //data[j+2] = tmp;
            bmp.push_back(((double)data[j+2]+(double)data[j+1]+(double)data[j+2])/(3*255));

            //std::cout << "R: "<< (int)data[j+1] << " G: " << (int)data[j+2]<< " B: " << (int)data[j+3]<< std::endl;
        }
    }
    free(data);

    //reverse order of the vector
    std::vector<double>bmp_final;
    std::cout << bmp.size() << std::endl;
    for(int i=*height-1; i>=0; --i){
        for(int j=0; j<*width; ++j){
            bmp_final.push_back(bmp.at(*width*i+j));
        }
    }

    return bmp_final;
}
#包括
#包括
#包括
std::vector readBMP(常量字符*文件名,整数*宽度,整数*高度){
std::载体bmp;
FILE*f=fopen(文件名为“rb”);
如果(f==NULL){

std::cerr大小值是否与宽度*高度匹配?(标题中的地址0x22)。还要确保没有要考虑的偏移量(0x0A)除了54字节的头。我检查宽度和高度,它被正确读取。你指的是什么样的偏移量?有时头不是标准的,大于54字节。如果是这种情况,你需要使用
fseek
,以便将光标移动到数据块的开头。接下来的问题是,你在使用什么操作系统?I updated这个问题,我在使用Ubuntu14.04。我怎么看呢?头不是标准的?
int data\u offset=*(int*)(&info[0x0A]);fseek(f,(long int)(data\u offset-54),SEEK\u CUR);
因为info[11]是char类型的,因此包含8位,不会移位8位(谢谢,这解决了2x2的问题,但现在我用3x3尝试了,它再次读取了错误的值。虽然前3个像素是正确的,但后来出现了错误
int data_offset = *(int*)(&info[0x0A]); 

if (data_offset > 54) {
    fseek(f, (long int)(data_offset - 54), SEEK_CUR);
} 
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <vector>

typedef struct bitmap
{
    unsigned short bpp;
    unsigned int width, height;
    std::vector<unsigned char> pixels;
} bitmap;

bool LoadBmp(const char *filepath, bitmap *bmp)
{
    FILE *f = fopen(filepath, "rb");

    if (f)
    {
        bmp->bpp = 0;
        bmp->width = 0;
        bmp->height = 0;
        bmp->pixels.clear();

        unsigned char info[54] = {0};
        fread(info, sizeof(unsigned char), 54, f);

        bmp->width = info[18] + (info[19] << 8); //Width
        bmp->height = info[22] + (info[23] << 8); //Height


        bmp->pixels.resize(((((bmp->width * bmp->height) + 31) & ~31) / 8) * bmp->height); //Size of the pixels in the bitmap.

        fseek(f, info[10] + (info[11] << 8), SEEK_SET); //Seek to Pixel Offset.

        fread(&bmp->pixels[0], sizeof(unsigned char), bmp->pixels.size(), f); //Read the pixels.
        fclose(f);

        //Do whatever with pixels.. Flip them.. Swap BGR to RGB, etc..
        return true;
    }

    return false;
}
#include <cstdio>
#include <iostream>
#include <vector>

std::vector<double> readBMP(const char* filename, int* width, int* height){
    std::vector<double> bmp;
    FILE* f = fopen(filename, "rb");

    if(f == NULL){
        std::cerr << "file not found!" << std::endl;
        std::vector<double> empty;
        width = NULL;
        height = NULL;
        return empty;
    }

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header

    // extract image height and width from header
    *width = *(int*)&info[18];
    *height = *(int*)&info[22];

    int data_offset = *(int*)(&info[0x0A]);
    if(data_offset > 0)
        fseek(f, (long int)(data_offset - 53), SEEK_CUR);

    std::cout << "  Name: " << filename << std::endl;
    std::cout << " Width: " << *width << std::endl;
    std::cout << "Height: " << *height << std::endl;
    std::cout << "Offset: " << data_offset << std::endl;

    int row_padded = (*width*4 + 4) & (~4);
    unsigned char* data = new unsigned char[row_padded];
    //unsigned char tmp;

    for(int i = 0; i < *height; i++){
        fread(data, sizeof(unsigned char), row_padded, f);
        for(int j = 0; j < row_padded; j += 4)
        {
            // Convert (B, G, R) to (R, G, B)
            //tmp = data[j];
            //data[j] = data[j+2];
            //data[j+2] = tmp;
            bmp.push_back(((double)data[j+2]+(double)data[j+1]+(double)data[j+2])/(3*255));

            //std::cout << "R: "<< (int)data[j+1] << " G: " << (int)data[j+2]<< " B: " << (int)data[j+3]<< std::endl;
        }
    }
    free(data);

    //reverse order of the vector
    std::vector<double>bmp_final;
    std::cout << bmp.size() << std::endl;
    for(int i=*height-1; i>=0; --i){
        for(int j=0; j<*width; ++j){
            bmp_final.push_back(bmp.at(*width*i+j));
        }
    }

    return bmp_final;
}