CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C语言

跪求:24位BMP转256色后图片扭曲(付程序)

楼主hszr(随风)2006-07-22 15:47:44 在 C/C++ / C语言 提问

问题:当用的24位色图片的宽度是偶数时不扭曲,当宽度是奇数时会扭曲,找了好久都找不问题。  
  求达人帮忙。  
  #ifndef   __BMPTEST_H_  
  #define   __BMPTEST_H_  
  #include   <stdio.h>  
  typedef   unsigned   char     BYTE;  
  typedef   unsigned   short   WORD;  
  //   BMP图像各部分说明如下  
  typedef   struct  
  {  
          long   imageSize;  
          long   blank;  
          long   startPosition;  
          void   show(void)  
          {  
                  printf("BMP   Head:\n");  
                  printf("Image   Size:%d\n",imageSize);  
                  printf("Image   Data   Start   Position   :   %d\n",startPosition);  
          }  
  }BmpHead;  
         
  typedef   struct  
  {  
          long         Length;  
          long         width;  
          long         height;  
          WORD         colorPlane;  
          WORD         bitColor;  
          long         zipFormat;  
          long         realSize;  
          long         xPels;  
          long         yPels;  
          long         colorUse;  
          long         colorImportant;  
          void   show(void)  
          {  
                  printf("infoHead   Length:%d\n",Length);  
                  printf("width&height:%d*%d\n",width,height);  
                  printf("colorPlane:%d\n",colorPlane);  
                  printf("bitColor:%d\n",bitColor);  
                  printf("Compression   Format:%d\n",zipFormat);  
                  printf("Image   Real   Size:%d\n",realSize);  
                  printf("Pels(X,Y):(%d,%d)\n",xPels,yPels);  
                  printf("colorUse:%d\n",colorUse);  
                  printf("Important   Color:%d\n",colorImportant);  
          }  
  }InfoHead;  
   
  typedef   struct  
  {  
                    BYTE       rgbBlue;  
                    BYTE       rgbGreen;  
                    BYTE       rgbRed;  
                    BYTE       rgbReserved;  
                    void   show(void)  
                    {  
                          printf("Mix   Plate   B,G,R:%d   %d   %d\n",rgbBlue,rgbGreen,rgbRed);  
                    }  
  }RGBMixPlate;  
   
  #endif  
   
  /************************  
    *   change   bmp   to   .....  
    *   by   shanlimin   2005-9-25  
    *   bmpTransfer.cpp  
    *   compile:  
    *   g++   bmpTransfer.cpp    
    ************************/  
  #include   "bmp.h"  
  #include   <string.h>  
  #include   <assert.h>  
  #include   <stdlib.h>  
  char   asciichar[256]={  
          '.','.','.','.','.','.',  
          '.','.','.','.','.','.','.','.','.','.',  
          ',',',',',',',',',',',',',',',',',',',',  
          ':',':',':',':',':',':',':',':',':',':',  
          ';',';',';',';',';',';',';',';',';',';',  
          '=','=','=','=','=','=','=','=','=','=',  
          '+','+','+','+','+','+','+','+','+','+',  
          'i','i','i','i','i','i','i','i','i','i',  
          't','t','t','t','t','t','t','t','t','t',  
          'r','r','r','r','r','r','r','r','r','r',  
          '%','%','%','%','%','%','%','%','%','%',  
          's','s','s','s','s','s','s','s','s','s',  
          '*','*','*','*','*','*','*','*','*','*',  
          'h','h','h','h','h','h','h','h','h','h',  
          '#','#','#','#','#','#','#','#','#','#',  
          '&','&','&','&','&','&','&','&','&','&',  
          '$','$','$','$','$','$','$','$','$','$',  
          '@','@','@','@','@','@','@','@','@','@',  
          'V','V','V','V','V','V','V','V','V','V',  
          'Z','Z','Z','Z','Z','Z','Z','Z','Z','Z',  
          'X','X','X','X','X','X','X','X','X','X',  
          'E','E','E','E','E','E','E','E','E','E',  
          'R','R','R','R','R','R','R','R','R','R',  
          'B','B','B','B','B','B','B','B','B','B',  
          'W','W','W','W','W','W','W','W','W','W',  
          'M','M','M','M','M','M','M','M','M','M'  
  };  
  int   zoom;  
  BmpHead     headBMP;  
  InfoHead   infoHead;  
  BYTE*   pColorData;   //用于24bit  
  RGBMixPlate     mainColor[256];//调色板  
  BYTE*   Index   =   NULL;//用于256  
  int   nPad;  
  void   read_24bit_bmp_file(char   *filename);  
  void   save_256_bmp_file(char   *filename);  
  void   trans_24bit_to_256();  
  int     Transfer(WORD   *color24bit,   int   len,   BYTE   *Index,   RGBMixPlate   *mainColor);  
   
  //计算平方差的函数  
  int   PFC(int   color1,   int   color2)  
  {  
          int   x,y,z;  
          x   =   (color1   &   0xf)   -   (color2   &   0xf);  
          y   =   ((color1>>4)   &   0xf)   -   ((color2>>4)   &   0xf);  
          z   =   ((color1>>8)   &   0xf)   -   ((color2>>8)   &   0xf);  
          return   (x*x   +   y*y   +   z*z);  
  };  
   
  //直接插入排序  
  int   Sort1(int   *src,   int   *attach,   int   n)  
  {  
          int   cur,   cur1;  
          int   i,j,k=0;  
          for   (i   =   1;   i   <   n;   i++)  
          {  
                  cur           =   src[i];  
                  cur1   =   attach[i];  
                  for   (j   =   i   -   1;   j   >=   0;   j--)  
                  {  
                          if   (cur   >   src[j])  
                          {  
                                  src[j+1]         =   src[j];  
                                  attach[j+1]   =   attach[j];  
                          }  
                          else  
                                  break;  
                  }  
                  src[j+1]     =   cur;  
                  attach[j+1]   =   cur1;  
          }  
          return   0;  
  }  
  //快速排序  
  int   Sort2(int   *src,   int   *attach,   int   n)  
  {  
          if   (n   <=   12)  
                  return   Sort1(src,   attach,   n);  
          int   low   =   1,   high   =   n   -   1;  
          int   tmp;  
          while   (low   <=   high)  
          {  
                  while   (src[low]   >=   src[0])  
                  {  
                          if   (++low   >   n   -   1)  
                                  break;  
                  }  
                  while   (src[high]   <   src[0])  
                  {  
                          if   (--high   <   1)  
                                  break;  
                  }  
                  if   (low   >   high)  
                          break;  
                  {  
                          tmp                       =   src[low];  
                          src[low]             =   src[high];  
                          src[high]           =   tmp;  
                          tmp                       =   attach[low];  
                          attach[low]       =   attach[high];  
                          attach[high]     =   tmp;  
                  }  
                  low++;  
                  high--;  
          }  
          {  
                  tmp                             =   src[low   -   1];  
                  src[low   -   1]           =   src[0];  
                  src[0]                       =   tmp;  
                  tmp                             =   attach[low   -   1];  
                  attach[low   -   1]     =   attach[0];  
                  attach[0]                 =   tmp;  
          }  
          if   (low   >   1)  
                  Sort2(src,   attach,   low   -   1);  
          if   (low   <   n)  
                  Sort2(&src[low],   &attach[low],   n   -   low);  
          return   0;  
  }  
   
   
  int   main()//int   argc,char*   argv[])  
  {  
  int   argc   =   4;  
  char   *argv[5]   =   {"0",   "-2",   "2.bmp",   "256.bmp",   ""};    
          zoom=1;//用于缩小转换后的ASCII图,zoom越大图越小  
          if   (argc   <   4)  
          {  
                  printf("Usage:\n");  
                  printf("         %s   format   filename1   filename2\n",   argv[0]);  
                  printf("         format   :   choose   change   mode   like:   -2   -g   -a\n");  
                  printf("         -2   to   256   -g   to   gray   -a   to   ascii\n");  
                  printf("         filename1   :   source   24bit   BMP   filename         like:   xxx.bmp\n");  
                  printf("         filename2   :   new   256   color   BMP   filename\n");  
                  return   -1;  
          }  
          if(argc==5)  
                  zoom=atoi(argv[4]);  
          char*   filename   =   argv[2];     //"image.bmp";//  
          char*   newFile   =   argv[3];       //"256.bmp";//  
   
          if(strcmp(argv[1],"-2")==0)  
          {  
                  read_24bit_bmp_file(filename);  
                  trans_24bit_to_256();  
                  save_256_bmp_file(newFile); //写新文件  
                  delete   []Index; //释放分配的内存  
          }  
          delete   []pColorData;  
          return   0;  
  }  
   
  void   save_256_bmp_file(char   *filename)  
  {  
          /************     写一个新的256色BMP文件     *******************/  
          FILE   *p1   =   fopen(filename,"wb");  
          if   (NULL   ==   p1)  
          {  
                  printf("open   new   file   failed.\n");  
                  return   ;  
          }  
          char   hh[2]   =   {0x42,   0x4D};  
          fwrite(hh,1,2,p1);                                 //BMP文件开头两字节,   0x4d42   =   "BM"  
          fwrite(&headBMP,   1,   12,   p1);         //BMP文件头    
  //infoHead.xPels   =   96L;  
  //infoHead.yPels   =   96L;  
          fwrite(&infoHead,   1,   40,   p1);         //BMP文件头信息    
          fwrite(mainColor,   1,   sizeof(mainColor),   p1);//写调色盘信息  
          int   w   =   infoHead.width;  
          int   h   =   infoHead.height;  
          if   (nPad   !=   0)   //   调整图像长度不是4的倍数的情况  
          {//   补上填充的0  
                  char   szBuf[4]   =   {0,   0,   0,   0};  
                  for   (int   i   =   0;   i   <   h;   i++)  
                  {  
                          fwrite(Index   +   i   *   w,   1,   w,   p1);  
                          fwrite(szBuf,   1,   nPad,   p1);  
                  }  
          }  
          else  
          {  
                  fwrite(Index,   1,   w*h,   p1);  
          }  
          fclose(p1);  
  }  
  问题点数:40、回复次数:17Top

1 楼hszr(随风)回复于 2006-07-22 15:48:38 得分 0

续上面的程序:  
   
  void   trans_24bit_to_256()  
  {  
          long   nData   =   headBMP.imageSize-headBMP.startPosition;//infoHead.realSize;  
          /************     24bit到256色的颜色数据转换     *****************/  
          nPad   =   infoHead.width   %   4;  
          int   w   =   infoHead.width;  
          int   h   =   infoHead.height;  
          if   (nPad   !=   0) //去掉数据区中填充的0  
          {  
                  nPad   =   4   -   nPad;  
                  BYTE*   pNewData   =   new   BYTE[w   *   h   *   3];  
                  for   (int   i   =   0;   i   <   h;   i++)  
                  {  
                          memcpy(pNewData   +   i   *   w   *   3,   pColorData   +   i   *   (w   *   3   +   nPad),   w   *   3);  
                  }  
                  delete   []pColorData;  
                  pColorData   =   pNewData;  
          }  
          long   nNewData   =   w   *   h;  
          Index   =   new   BYTE[nNewData];  
           
          memset(mainColor,   0,   sizeof(mainColor)); //调色板  
          WORD*   shortColor   =   new   WORD[nNewData];  
          int   iRed,   iGreen,   iBlue;  
          for   (int   i   =   0;   i   <   nNewData;   i++) //取RGB颜色的高4位  
          {  
                  iRed       =   pColorData[i*3]>>4;  
                  iGreen       =   pColorData[i*3+1]>>4;  
                  iBlue       =   pColorData[i*3+2]>>4;  
                  shortColor[i]   =   (iRed<<8)   +   (iGreen<<4)   +   iBlue;  
          }  
          //调用转换函数  
          Transfer(shortColor,   nNewData,   Index,   mainColor);  
          //256色位图的调色盘数据(保存在mainColor)和图像数据区的数据(保存在Index中)  
          delete   []shortColor;  
          //修改一下前面读出的BmpHead和InfoHead的结构信息  
          headBMP.imageSize   =   14   +   40   +   4*256   +   nData/3;     //1189;//  
          //   4*256是调色盘的长度,nData/3是图像数据区长度  
          headBMP.startPosition   +=   4*256;           //新文件加上了调色盘部分  
          infoHead.bitColor   =   8;                             //颜色位数改为8  
          infoHead.realSize   =   nData/3;     //1189;//             //图像数据区长度  
  }  
   
  void   read_24bit_bmp_file(char   *filename)  
  {  
          FILE*   p;  
          p   =   fopen(filename,"rb");  
          if   (p   ==   NULL)  
          {  
                  printf("!!!file   %s   open   failed.\n",   filename);  
          }  
          printf("file   %s   open   success.\n",filename);  
          /**********       read   BMP   head   ********************/  
          fseek(p,2,SEEK_CUR);  
          fread(&headBMP,1,12,p);  
          headBMP.show();  
          fread(&infoHead,1,40,p);  
          infoHead.show();  
          if   (infoHead.bitColor   !=   24)  
          {  
                  fclose(p);  
                  printf("This   is   not   a   24bit   BMP   file.\n");  
                  return;  
          }  
          long   nData   =   headBMP.imageSize-headBMP.startPosition;//infoHead.realSize;  
          /***********     read   Image   Date     **************/  
          pColorData   =   new   BYTE[nData];  
          fread(pColorData,1,nData,p);  
          /***********     read   file   over   ***************/  
          int   leftData   =   0;  
          char   ch   =   0;  
          while   (!feof(p))  
          {  
                  fread(&ch,1,1,p);  
                  leftData++;  
          }  
          if   (leftData)  
                  printf("%d   bytes   not   read   in   file.\n",   leftData);  
          printf("read   file   over.\n");  
          if(!fclose(p))  
          {  
                  printf("file   close.\n");  
          }  
          //   24位BMP文件信息都读出来了,可以查看打印信息  
  }  
   
  //将24bit的象素颜色数据转换为256色图的图像数据(即索引值)  
  int   Transfer(WORD   *color24bit,   int   len,   BYTE   *Index,   RGBMixPlate   *mainColor)  
  {  
          int   usedTimes[4096]   =   {0};  
          int   miniColor[4096];  
          int   i;  
          for   (i   =   0;   i   <   4096;   i++)  
                  miniColor[i]   =   i;  
          i   =   0;  
          for   (i   =   0;   i   <   len;   i++)  
          {  
                  assert(color24bit[i]   <   4096);  
                  usedTimes[color24bit[i]]++;  
          }  
   
          int   numberOfColors   =   0;  
          for   (i   =   0;   i   <   4096;   i++)  
          {  
                  if   (usedTimes[i]   >   0)  
                          numberOfColors++;  
          }  
   
          //对usedTimes进行排序,排序过程中minColor数组(保存了颜色值)也作与useTimes  
          //数组相似的交换  
          Sort2(usedTimes,   miniColor,   4096);  
   
          //usedTimes数组中是各颜色使用频率,从高到低排列,显然第numberOfColor个之后的都为0  
          //miniColor数组中是相应的颜色数据</font>  
          //将前256个颜色数据保存到256色位图的调色盘中  
          for(i   =   0;   i   <   256;   i++)  
          {  
                  mainColor[i].rgbBlue   =   (BYTE)((miniColor[i]>>8)<<4);  
                  mainColor[i].rgbGreen         =   (BYTE)(((miniColor[i]>>4)   &   0xf)<<4);  
                  mainColor[i].rgbRed             =   (BYTE)((miniColor[i]   &   0xf)<<4);  
                  mainColor[i].rgbReserved   =   0;  
          }  
   
          int   *colorIndex   =   usedTimes;//用原来的useTimes数组来保存索引值  
          memset(colorIndex,   0,   sizeof(int)   *   4096);  
   
          if   (numberOfColors   <=   256)  
          {  
                  for   (i   =   0;   i   <   numberOfColors;   i++)  
                          colorIndex[miniColor[i]]   =   i;  
          }  
          else//为第256之后的颜色在前256种颜色中找一个最接近的  
          {  
                  for   (i   =   0;   i   <   256;   i++)  
                          colorIndex[miniColor[i]]   =   i;  
   
                  int   index,   tmp,   tmp1;  
                  for   (i   =   256;   i   <   numberOfColors;   i++)  
                  {  
                          tmp             =   PFC(miniColor[0],   miniColor[i]);  
                          index   =   0;  
                          for   (int   j   =   1;   j   <   256;   j++)  
                          {  
                                  tmp1   =   PFC(miniColor[j],   miniColor[i]);  
                                  if   (tmp   >   tmp1)  
                                  {  
                                          tmp   =   tmp1;  
                                          index   =   j;  
                                  }  
                          }  
                          colorIndex[miniColor[i]]   =   index;  
                  }  
          }  
          //记录各点颜色数据的索引值,即256色位图的颜色数据  
          for   (i   =   0;   i   <   len;   i++)  
          {  
                  assert(colorIndex[color24bit[i]]   <   256);  
                  Index[i]   =   colorIndex[color24bit[i]];  
          }  
   
          return   1;  
  }  
  各位可以把上面的程序复制到机器上运行Top

2 楼hszr(随风)回复于 2006-07-22 15:51:29 得分 0

我找了好几天了,都没发现问题。  
   
  各位达人帮帮我Top

3 楼jixingzhong(瞌睡虫·星辰)回复于 2006-07-22 17:26:58 得分 20

用的24位色图片的宽度是偶数时不扭曲,当宽度是奇数时会扭曲  
  =============================  
  从这里看,  
  楼主在处理的时候,  
  在边界上存在问题,  
  可能是   处理或者是   写新文件的时候,  
  对于   奇数宽度   图像,  
  边界点被忽略了一个,  
  或者是其他原因,造成了扭曲   ...  
   
  楼主主要检查一下你的   转换部分、   新文件生成部分,  
  代码不少,  
  看起来有点麻烦啊   ...Top

4 楼vosine()回复于 2006-07-22 18:47:57 得分 0

lz,   bmp有个对齐的问题!  
  不对奇的要补齐的!Top

5 楼hszr(随风)回复于 2006-07-22 20:42:30 得分 0

我知道读去BMP宽度要是4的倍数,也在程序里做了处理。  
   
  不对奇的要补齐的!===》   就是补上是4的倍数嘛Top

6 楼ccwcc()回复于 2006-07-23 10:43:11 得分 0

很可能是Zoom的时候出了问题。  
  建议把各个功能抽取出来,单独测试。Top

7 楼hszr(随风)回复于 2006-07-23 13:31:05 得分 0

怎么就没有建设性的建议了???Top

8 楼martmy(白金汉公爵)回复于 2006-07-23 17:35:08 得分 0

你看是不是字节对齐的问题。分配空间时四字节对其Top

9 楼martmy(白金汉公爵)回复于 2006-07-23 17:37:19 得分 0

((pic_width   +   31)   >>   3)   &   ~3Top

10 楼hszr(随风)回复于 2006-07-23 19:52:45 得分 0

martmy(白金汉公爵)    
    ((pic_width   +   31)   >>   3)   &   ~3         =======>   这是图片的大小  
   
  字节对齐了  
       
     
  Top

11 楼hmily0917(卖造钱机)回复于 2006-07-23 22:19:51 得分 0

http://www.pris.edu.cn/imgprocess/theory/subject.htm  
  楼主   我不太清楚   但是知道一个网站   你看有没有!?Top

12 楼hmily0917(卖造钱机)回复于 2006-07-23 22:21:59 得分 20

我们定义了一个宏#define   WIDTHBYTES(i)   ((i+31)/32*4),上面曾经提到过,每一行的字节数必须是4的整倍数,只要调用WIDTHBYTES(bi.biWidth*bi.biBitCount)就能完成这一换算.举一个例子,对于2色图,如果图象宽是31,则每一行需要31位存储,合3个字节加7位,因为字节数必须是4的整倍数,所以应该是4,而此时的biWidth=31,biBitCount=1,WIDTHBYTES(31*1)=4,和我们设想的一样。再举一个256色的例子,如果图象宽是31,则每一行需要31个字节存储,因为字节数必须是4的整倍数,所以应该是32,而此时的biWidth=31,biBitCount=8,WIDTHBYTES(31*8)=32,和我们设想的一样。你可以多举几个例子来验证一下Top

13 楼hszr(随风)回复于 2006-07-24 11:42:28 得分 0

各位大虾先看了我的代码再发言吧,上面说的我的都做了,  
  就是TMD不知道在哪里出错了Top

14 楼hhyytt(鹦鹉螺)回复于 2006-07-24 16:27:52 得分 0

我改好了,楼主。Top

15 楼hszr(随风)回复于 2006-07-24 16:38:17 得分 0

真的,是哪里出的问题?  
  Top

16 楼hszr(随风)回复于 2006-07-24 16:41:56 得分 0

能把你的程序发我吗?  
   
  邮箱:   hszr99@126.com  
  MSN:   hszr@hotmail.com  
  QQ:   420649191  
   
  谢谢Top

17 楼hszr(随风)回复于 2006-07-24 18:32:01 得分 0

求人不如求己,还是自己解决了Top

相关问题

关键词

得分解答快速导航

  • 帖主:hszr
  • jixingzhong
  • hmily0917

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo