我把位图保存到硬盘上,但是用系统自带的画图打开发现图像错位了,效果是这样的
    这是一只猫,但是用PS或者图片查看器打开显示的结果就正常,谁知道这是什么缘故?

解决方案 »

  1.   

    下面是代码,width和height是图像的宽度和高度,tempData是个保存图像数据的动态数组,大小是width*height*4,         CFile greyFile;
    greyFile.Open("d:\\greyFile.bmp",CFile::modeCreate|CFile::modeWrite);
    BITMAPFILEHEADER bfHeader;
    BITMAPINFOHEADER biHeader;
    memset(&bfHeader,0,sizeof(BITMAPFILEHEADER));
    memset(&biHeader,0,sizeof(BITMAPINFOHEADER));
    bfHeader.bfType=0x4d42;
    bfHeader.bfSize=54+width*height;
    bfHeader.bfOffBits=54;
    biHeader.biBitCount=8;
    biHeader.biCompression=BI_RGB;
    biHeader.biHeight=height;
    biHeader.biPlanes=1;
    biHeader.biSize=sizeof(BITMAPINFOHEADER);
    biHeader.biWidth=width; greyFile.Write(&bfHeader,sizeof(BITMAPFILEHEADER));
    greyFile.Write(&biHeader,sizeof(BITMAPINFOHEADER));
    for(int j=width*height;j>0;j--)
    {
    greyFile.Write(tempData+j*4+2,1);
    }
    greyFile.Close();另外还有一个问题,图像的方向变了,猫脸应该是向左的,保存之后就向右了我靠,QQ空间图片还不能引用
      

  2.   

    biHeader.biBitCount=8;
    8位的图片怎么会有width*height*4这么大的数据
      

  3.   


    原图是32 位的bmp图像?
      

  4.   

    楼主代码的目的是想将一副彩色图像的红色分量单独保存为1位灰度图。
    代码里N多错误。1、bfHeader.bfSize=54+width*height;   //大小计算错误
    这个成员反映的是BMP文件的大小  
    计算公示为:位图文件头大小+位图信息头大小+颜色表大小(位深小于8位才有该项)+位图数据大小
    前两项之和对于大部分BMP格式都是(40+14)=54字节,唯独对于16位图像有所区别:X1R5G5B5格式的16位图像他们之后也是54,而 R5G6B5 、    R6G5B5   、 R5G5B6     、X4R4G4B4  、   A1R5G5B5  、  A4R4G4B4格式的话他们的和为(56+14)=70;
    实际上这项可以不填写,直接为0,系统也认。2、你的调色板数据没有写,这你自己也说了。3、8位图像数据本身占用的字节数并不是总是 width*height;这个已经不晓得讲过好多遍了。新手总是不注意四字节对齐这个铁规矩。4、如果发现图像倒立了,可以直接把biHeader.biHeight改为biHeader.biHeight=-height,当然也可以直接改变数据的顺序。
      

  5.   

    楼主代码的目的是想将一副彩色图像的红色分量单独保存为1位灰度图。
    代码里N多错误。1、bfHeader.bfSize=54+width*height; //大小计算错误
    这个成员反映的是BMP文件的大小   
    计算公示为:位图文件头大小+位图信息头大小+颜色表大小(位深小于8位才有该项)+位图数据大小
    前两项之和对于大部分BMP格式都是(40+14)=54字节,唯独对于16位图像有所区别:X1R5G5B5格式的16位图像他们之后也是54,而 R5G6B5 、 R6G5B5 、 R5G5B6 、X4R4G4B4 、 A1R5G5B5 、 A4R4G4B4格式的话他们的和为(56+14)=70;
    实际上这项可以不填写,直接为0,系统也认。2、你的调色板数据没有写,这你自己也说了。3、8位图像数据本身占用的字节数并不是总是 width*height;这个已经不晓得讲过好多遍了。新手总是不注意四字节对齐这个铁规矩。4、如果发现图像倒立了,可以直接把biHeader.biHeight改为biHeader.biHeight=-height,当然也可以直接改变数据的顺序。
      

  6.   

          9楼上课的老师,我这幅图像宽度是240的,能对4字节齐吗,我是不是少加了一个sizeof(RGBQUAD) ?
             还有一个问题,我保存的结果是左右颠倒的,这应该怎么办,为什么用不同软件打开的结果不一样,画图程序正常,photoshop和图片查看器错位,不同软件读取文件的方式不一样吗?
     
            顺便问一下,如果我想全面学习数字图像处理,应该从哪里开始,需要什么基础,我说的是傅里叶变换,小波变换这种数学分析手段
      

  7.   

    慢慢来吧.先把DIB格式熟悉下.在看看数字图像处理的基础.什么几何变换.正交变换,图像增强等等.我也在学数字图像处理.微积分是不能少的.矩阵运算等等都是基础.感觉学好了挺难的.楼主加油
      

  8.   

         多谢,确实很难,什么酉变换,haar变换,wavelet分析,开始一点看不懂,不过我导师也说了,一般本科生没这个本事,何况我又不是学信号处理的。但是我觉得这个东西很神奇,以前二外上日语,我挺感兴趣就自学了,现在也有点小成,所以有信心,兴趣很关键……  呃,  共勉吧
           现在不错位了,原来是我吧数据偏移量写错了,没加调色板的256字节,但是猫脸的方向还是不对
      

  9.   

    看不到图,如果是上下颠倒了,那10楼的方法就可以
    要是左右颠倒了for(int j=width*height;j>0;j--)
    {
    greyFile.Write(tempData+j*4+2,1);
    }这里是倒着写的.顺着写就OK了.原始数据的第一个字节对应你的第一个字节.Windows显示的时候会自动从下到上扫描的.这里不用翻转
      

  10.   

           还有一个问题,我想用GetBitmapBits()方法把设备环境里widt*height的灰度图像数据复制到数组里,这个方法总是把图像当成真彩色复制,数组的大小就得是width*height*4,很多空间浪费了,还得跳跃着访问数组,不知道可不可以用一个width*height的数组保存设备中的256色灰度图?
      

  11.   

    GetBitmapBits   是DDB函数,他的获取的数据和屏幕色深始终一致,你无法控制。 
    所以你得用DIB函数。