现有bmp文件,拟遍历像素数据,将其中红色改为绿色。
若位图为8位,程序可正常执行;
若位图为24位,为何不能?
感激您的帮助!困惑了一下午了。代码如下:
for (long j=0;j<bi.biHeight;j++)    
for(long i=0;i<bi.biWidth;i++)
{
switch(bi.biBitCount) {
case 8:      //若为8位bmp,则将绿色0x01替换为红色0x03。
if (gFilechar[i+(bi.biHeight-j-1)*LineBytes]==0x01)
gFilechar[i+(bi.biHeight-j-1)*LineBytes]=0x03;
break; case 24:     //若为24位,则将绿色0x00DC00替换为红色0xDC0000
if (gFilechar[i+(bi.biHeight-j-1)*LineBytes] == (unsigned char) 0x00DC00)
gFilechar[i+(bi.biHeight-j-1)*LineBytes] = (unsigned char) 0xDC0000);

break; }
}

解决方案 »

  1.   

    别的没仔细看,最后两句
    gFilechar[i+(bi.biHeight-j-1)*LineBytes] == (unsigned char) 0x00DC00
    gFilechar[i+(bi.biHeight-j-1)*LineBytes] = (unsigned char) 0xDC0000unsigned char是单字节长,上面的两个强转后都是0
      

  2.   

    long matchcolor=0;
    for(char k=2;k>=0;k--){
    matchcolor += gFilechar[i*3+(bi.biHeight-j-1)*LineBytes+k]<<(k*8)
    }
    if (matchcolor == 0x00DC00){
    gFilechar[i+(bi.biHeight-j-1)*LineBytes] = 0xDC
    gFilechar[i+(bi.biHeight-j-1)*LineBytes+1] = 0;
    gFilechar[i+(bi.biHeight-j-1)*LineBytes+2] = 0;
    }24位,一个像素用三个字节保存像素值。
    for(long i=0;i<bi.biWidth;i++)只能遍历图像三分之一行
      

  3.   

    修改一处
    matchcolor += gFilechar[i*3+(bi.biHeight-j-1)*LineBytes+2-k]<<(k*8)
      

  4.   

    1 调试显示,条件 (matchcolor == 0x00DC00)始终没有满足,可能是得到matchcolor时出现了问题。
    2 调试时,matchcolor值为 -394752 -394758 -393216,请问如何查看十进制值为多少?比如0xDC0032;
    3 感谢jasonshark(没暑假了...),unsigned char是单字节长,强转后是0;改为char应该可以吧。
    4 感谢starshx(数星星)。答复语句中:for(char k=2;k>=0;k--){,我想当然地认为char 为笔误,应改为int。对吧?期待大家的帮助!
      

  5.   

    char 也不行,char也是单个字节具体处理的算法代码我不是很懂,我猜测你是不是这个意思:
    if (*(u_short *)gFilechar[i+(bi.biHeight-j-1)*LineBytes] == 0xDC00)
    *(u_short *)gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = 0xDC00;试下吧,瞎猜的~
      

  6.   

    错了...
    if (*(u_short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes] == 0xDC00)
    *(u_short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = 0xDC00;
      

  7.   

    谢谢jasonshark(没暑假了...) ,调试不能通过。error C2065: 'u_short' : undeclared identifier
      

  8.   

    哦,那就用unsigned short, 顺便多加个判断
    if (*(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes] == (unsigned char) 0xDC00 || gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] == 0x00)*(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = (unsigned char) 0xDC00;
      

  9.   

    谢谢jasonshark(没暑假了...)。调试通过,但结果图形中基本全黑。
    按照starshx(数星星)的思路,我设置:
    for(long i=0;i<bi.biWidth*3;i++)
    并进行判断:
    if ((gFilechar[3*i+(bi.biHeight-j-1)*LineBytes]==0x00)&&(gFilechar[3*i+1+(bi.biHeight-j-1)*LineBytes]==0x00)&&(gFilechar[3*i+2+(bi.biHeight-j-1)*LineBytes]==0xDC))
    {
    gFilechar[3*i+(bi.biHeight-j-1)*LineBytes] = 0x00;
    gFilechar[3*i+1+(bi.biHeight-j-1)*LineBytes] = 0xDC;
    gFilechar[3*i+2+(bi.biHeight-j-1)*LineBytes] = 0x00;
    }
    为何始终不能满足条件呢?
      

  10.   

    修正一下:
    for(long i=0;i<bi.biWidth*3;i++)
    改为:
    for(long i=0;i<bi.biWidth;i++)
      

  11.   

    调试显示(gFilechar[3*i+2+(bi.biHeight-j-1)*LineBytes]==0xDC)满足条件是不可能的。
    但)&&(gFilechar[3*i+2+(bi.biHeight-j-1)*LineBytes]==0x00))可以。按照jasonshark(没暑假了...)的提示,改为:
    (*(unsigned short *)&gFilechar[3*i+2+(bi.biHeight-j-1)*LineBytes]==0xDC)
    也始终不能满足条件。
      

  12.   

    -_-b汗我自己一个...改对一个地方又写错另一个地方...if (*(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes] == (unsigned short) 0xDC00 || gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] == 0x00)
    *(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = (unsigned short) 0xDC00;你的意思大概就是把RGB的0x00DC00改成0xDC0000, 对吧?
      

  13.   

    感谢jasonshark(没暑假了...)的支持,您对指针的理解非常透彻,佩服佩服!不过,您提供代码的执行结果仍不理想。问题基本上解决,代码略为:for(long i=0;i<3*bi.biWidth;i+=3)if (*(unsigned short *)&gFilechar[i+2+(bi.biHeight-j-1)*LineBytes]==0xDC)
    {
    gFilechar[i+1+(bi.biHeight-j-1)*LineBytes] = 0xDC;
    gFilechar[i+2+(bi.biHeight-j-1)*LineBytes] = 0x00;
    }
    但不知为何,if ((*(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes]==0x00)&&(*(unsigned short *)&gFilechar[i+1+(bi.biHeight-j-1)*LineBytes]==0x00)&&(*(unsigned short *)&gFilechar[i+2+(bi.biHeight-j-1)*LineBytes]==0xDC))条件始终不能满足。三个条件分开,都可以。为何(()&&()&&())之后就不能满足呢?期盼指正!
      

  14.   

    :( 怎么你又把比较的大小改了...short/unsigned short是2字节, char/unsigned char是单字节..既然这样,那干脆把比较元素统一到字节上, 还不用强转这么麻烦了
    if (gFilechar[i+(bi.biHeight-j-1)*LineBytes] = 0x00 ||
    gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = 0xDC ||
    gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] = 0x00)
    {
    *(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = (unsigned short) 0xDC00;
    }
      

  15.   

    if (gFilechar[i+(bi.biHeight-j-1)*LineBytes] == 0x00 ||
    gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] == 0xDC ||
    gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] == 0x00)
    {
    gFilechar[i+(bi.biHeight-j-1)*LineBytes = 0x00;
                      gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = 0x00;
                      gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] = 0xDC
              }
      

  16.   

    if (gFilechar[i+(bi.biHeight-j-1)*LineBytes] == 0x00 &&
    gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] == 0xDC &&
    gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] == 0x00)
    {
    gFilechar[i+(bi.biHeight-j-1)*LineBytes = 0x00;
                      gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = 0x00;
                      gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] = 0xDC
              }
      

  17.   

    按照逻辑,我赞同lfchen(一条晚起的虫)的建议,之间用&&连接。 
    关于是否需要数据转换的调试结果如下:
    1 if (*(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes]==0x00)与
      if (gFilechar[i+(bi.biHeight-j-1)*LineBytes]==0x00):二者等同;
    2 if (*(unsigned short *)&gFilechar[i+2+(bi.biHeight-j-1)*LineBytes]==0xDC)与 
      if (gFilechar[i+2+(bi.biHeight-j-1)*LineBytes]==0xDC)不同。前者有满足条件的数据,而后者没有。3 这是否意味着必须添加*(unsigned short *)&进行字符转换呢?关于颜色匹配的调试结果如下:
    4 按照上述条件判断时,其中有颜色8C6400。判断是否(==0x64)(==0x00)皆有满足条件像素,但(==0x8C)始终没有满足条件的像素。
    这就很奇怪,8C6400千真万确地存在,为何始终不能满足条件(==0x8C)呢?
      

  18.   

    :( 这两天写代码有点晕,经常写错... 那个确实应该是&&以前我强转成unsigned short * 是为了偷懒,现在为了程序的易读性,就全部按照单字节(unsigned char)来做比较,所以按照lfchen(一条晚起的虫)的写法就是最清晰的了另:
    if (*(unsigned short *)&gFilechar[i+(bi.biHeight-j-1)*LineBytes]==0x00)与
    if (gFilechar[i+(bi.biHeight-j-1)*LineBytes]==0x00)是完全不同的判断,前者判断的是两个字节长的0, 后者判断的是单个字节长的0.
      

  19.   

    颜色是按照 G/B/R 的顺序存储的
      

  20.   

    case 24:     //若为24位,则将绿色0x00DC00替换为红色0xDC0000
    if( gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] == (unsigned char)0xDC )
    {
       gFilechar[i+(bi.biHeight-j-1)*LineBytes + 1] = 0;
       gFilechar[i+(bi.biHeight-j-1)*LineBytes + 2] = 0xDC;
    }break;
    还有一个问题就是你的gFilechar的下标运算是否正确?// 另:楼上的应该是B/G/R顺序。
      

  21.   

    感谢各位陪同我调试这么久。1 调试时,请问如何查看gFilechar[i+(bi.biHeight-j-1)*LineBytes] 十六进制值为多少?比如0xDC0000;问题很多:
    1 if (*(unsigned short *)&gFilechar[i+2+(bi.biHeight-j-1)*LineBytes]==0xDC)与 if (gFilechar[i+2+(bi.biHeight-j-1)*LineBytes]==0xDC): 前者运行结果正确,后者不正确:按照jasonshark(没暑假了...) 的建议,*(unsigned short *)&是判断两个字节长度,可是不转换,结果不对;2 很奇怪,8C6400千真万确地存在,为何始终不能满足条件(==0x8C)呢?
    甚至出现了相同的程序代码,可以识别出图片A中的颜色,却不能识别出图片B中的相同颜色。3 gFilechar的下标和颜色存储顺序(B/G/R)我检查过多次。不会有问题。4 百思不得其解,程序肯定有问题。希望高人告诉我问题1的答案,接着调试。
      

  22.   

    写错了、
    1 调试时,请问如何查看gFilechar[i+(bi.biHeight-j-1)*LineBytes] 十六进制值为多少?比如0xDC;
      

  23.   

    可以TRACE出来或者你用几个变量来赋值 unsigned char = gFilechar[i+(bi.biHeight-j-1)*LineBytes]; 这样
    用#ifdef _DEBUG/ #endif 括起来,只在调试时用
      

  24.   

    感谢诸位,尤其是jasonshark(没暑假了...)。感激之情如滔滔江水,连绵不绝……正确代码如下,也就是在之前添加(unsigned char)转化一下:
    if (((unsigned char)gFilechar[3*i+(bi.biHeight-j-1)*LineBytes ] == 0x8C)&&((unsigned char)gFilechar[3*i+(bi.biHeight-j-1)*LineBytes +1] == 0x64)&&((unsigned char)gFilechar[3*i+(bi.biHeight-j-1)*LineBytes +2] == 0x00))
    {
    gFilechar[3*i+(bi.biHeight-j-1)*LineBytes] = 0xBB;
    gFilechar[3*i+(bi.biHeight-j-1)*LineBytes + 1] = 0xAA;
    gFilechar[3*i+(bi.biHeight-j-1)*LineBytes + 2] = 0xDC;
    }
    转化为十六进制的调试代码如下:unsigned char c_i = gFilechar[3*i+(bi.biHeight-j-1)*LineBytes] ;
    unsigned char c_i1 = gFilechar[3*i+(bi.biHeight-j-1)*LineBytes+1] ;
    unsigned char c_i2 = gFilechar[3*i+(bi.biHeight-j-1)*LineBytes+2] ;
    char   s[99];   
    sprintf(s,"c=%x%x%x",c_i,c_i1,c_i2);  感谢一切!结贴喽。