[求助]读取BMP图象的R,G,B值到三个二维数组,请高手看一下问题出在哪!
<P><FONT color=#f73809>[求助]读取BMP的R,G,B,值请高手看一下问题出在哪?<BR></FONT>[em01]<BR>我现在做的毕业设计是彩色图象的水印,需要把一副BMP图象的R,G,B,各个分量分别读出来然后再对各分量处理.最后再把处理后的数据写回BMP。下面的第一个程序我试了各种办法就是找不出错,请高手帮忙分析一下!<BR>程序可以在*.TXT文件中输出图象位图文件头,信息头的主要数据,但其中的调色板读出的各颜色索引值不对,还有就是读出的R,G,B,三个二维数组的数值也不对(用自己编的READ.EXE,读DAT文件到记事本中0有许多 或是把三个分量分别写到BMP文件中但显示都只是一副紫色图)但大小是对的.<BR>还想问一下就是数据处理完后怎么再把R,G,B值恢复为一副彩色图象,颜色索引值是不是还要重新确定一下?<BR>下面是从BMP读取的主要数据:<BR>bmp_img->width=256 and bmp_img->height=256 bits_per_pixel=8 bmp_type=g <BR>the bmp file is notcompressed! <BR>info_header_length = 1078 <BR>调色板的各颜色索引值:<BR>Blue =1 Green=0 Red =0 <BR>Blue =189 Green=202 Red =0 <BR>Blue =63 Green=114 Red =0 <BR>Blue =104 Green=201 Red =0 <BR>Blue =219 Green=251 Red =0 <BR>Blue =106 Green=150 Red =0<BR>Blue =57 Green=154 Red =0 <BR>Blue =64 Green=120 Red =0<BR>Blue =31 Green=84 Red =0 <BR>Blue =107 Green=199 Red =0<BR>Blue =84 Green=176 Red =0 <BR>Blue =128 Green=228 Red =0 <BR>Blue =64 Green=152 Red =0<BR>Blue =177 Green=211 Red =0<BR>Blue =128 Green=185 Red =0 <BR>Blue =203 Green=241 Red =0 <BR>Blue =52 Green=130 Red =0<BR>Blue =94 Green=202 Red =0<BR>Blue =209 Green=245 Red =0<BR>Blue =52 Green=106 Red =0 <BR>Blue =143 Green=186 Red =0<BR>Blue =49 Green=173 Red =0<BR>Blue =105 Green=201 Red =0 <BR>Blue =115 Green=154 Red =0 <BR>Blue =82 Green=177 Red =0 <BR>Blue =96 Green=138 Red =0 <BR>Blue =143 Green=212 Red =0 <BR>Blue =219 Green=239 Red =0</P><P>Blue =41 Green=107 Red =0<BR>Blue =188 Green=220 Red =0 <BR>Blue =135 Green=195 Red =0 <BR>Blue =13 Green=81 Red =0 <BR>Blue =196 Green=234 Red =0<BR>Blue =136 Green=228 Red =0 <BR>Blue =164 Green=192 Red =0 <BR>Blue =56 Green=126 Red =0<BR>Blue =72 Green=155 Red =0 <BR>Blue =21 Green=102 Red =0 <BR>Blue =104 Green=140 Red =0<BR>Blue =48 Green=151 Red =0 <BR>Blue =160 Green=236 Red =0 <BR>Blue =196 Green=245 Red =0<BR>Blue =151 Green=190 Red =0<BR>Blue =151 Green=168 Red =0 <BR>Blue =92 Green=188 Red =0 <BR>Blue =119 Green=212 Red =0<BR>Blue =197 Green=236 Red =0<BR>Blue =71 Green=135 Red =0<BR>Blue =136 Green=172 Red =0<BR>Blue =144 Green=220 Red =0<BR>Blue =136 Green=196 Red =0 <BR>Blue =21 Green=116 Red =0 <BR>Blue =60 Green=188 Red =0<BR>Blue =22 Green=92 Red =0 <BR>Blue =94 Green=164 Red =0<BR>Blue =136 Green=230 Red =0<BR>Blue =194 Green=220 Red =0<BR>Blue =105 Green=212 Red =0 <BR>Blue =107 Green=221 Red =0<BR>Blue =86 Green=188 Red =0 <BR>Blue =118 Green=199 Red =0<BR>Blue =118 Green=164 Red =0 <BR>Blue =180 Green=244 Red =0 <BR>Blue =34 Green=116 Red =0<BR>Blue =253 Green=253 Red =253<BR>Blue =164 Green=2 Red =135 <BR>Blue =0 Green=0 Red =0 <BR>Blue =0 Green=0 Red =0<BR>Blue =0 Green=0 Red =0 以下各值就全为0了,个数是对的一共读了256个索引值<BR>程序如下(在VC中运行的):</P>
<P><BR> </P>
<DIV class=htmlcode>
<P>/* This program is to read and write bmp images 只是256色位图 图片为256*256的彩色LENA图*/<BR>#include "Conio.h"<BR>#include "stdlib.h"<BR>#include "stdio.h"<BR>#include "malloc.h"<BR>#include "math.h"</P>
<P>#define SUCCESSED 0<BR>#define FAILED 1<BR>//typedef unsigned char BYTE<BR>/* ---------------------- */<BR>/* Global Variables */<BR>/* ---------------------- */</P>
<P>typedef struct BMP_img<BR>{<BR> long width;<BR> long height;<BR> char bmp_type; /* 'c'=color; 'g'=graymap; */<BR> unsigned char **mono;</P>
<P>}BMP_IMG;</P>
<P>typedef struct tagRGBQUAD {<BR> unsigned char rgbBlue;<BR> unsigned char rgbGreen;<BR> unsigned char rgbRed;<BR> unsigned char rgbReserved;<BR>} RGBQUAD;</P>
<P>long info_header_length; /* the length of bmp image information head */<BR>unsigned char *bmp_head_buffer; /* used for bmp head */<BR>RGBQUAD *bmiColor; /*调色板数组*/<BR>FILE *information; /*在.txt文件中输出BMP图象的主要数据*/ </P>
<P>/* ---------------------- */<BR>/* Global Functions */<BR>/* ---------------------- */</P>
<P>int read_bmp(FILE *infile, BMP_IMG *bmp_img);<BR>void get_bmp(BMP_IMG *img, long height, long width, char bmp_type);<BR>void write_dat(FILE *fred,FILE *fgreen,FILE *fblue,BMP_IMG *bmp_img);</P>
<P>/* ------------ */<BR>/* Main() */<BR>/* ------------ */</P>
<P>int main()<BR>{<BR> int i,j;<BR> char infilename[10],redfilename[10],greenfilename[10],bluefilename[10],inma[10];<BR> FILE *fin, *fred,*fgreen,*fblue;<BR> BMP_IMG img_in, img_out;<BR> </P>
<P>printf("input the sourse filename:\n");<BR>scanf("%s",infilename);<BR>if((fin=fopen(infilename,"rb"))==NULL)<BR>{ printf("can't open the file\n");<BR>exit(0);<BR>}<BR>printf("input the red filename(*.dat):\n");<BR>scanf("%s",redfilename);<BR>if((fred=fopen(redfilename,"wb"))==NULL)<BR>{ printf("can't open the file\n");<BR>exit(0);<BR>}<BR>printf("input the green filename(*.dat):\n");<BR>scanf("%s",greenfilename);<BR>if((fgreen=fopen(greenfilename,"wb"))==NULL)<BR>{ printf("can't open the file\n");<BR>exit(0);<BR>}<BR>printf("input the blue filename(*.dat):\n");<BR>scanf("%s",bluefilename);<BR>if((fblue=fopen(bluefilename,"wb"))==NULL)<BR>{ printf("can't open the file\n");<BR>exit(0);<BR>}<BR>printf("input the information filename(*.txt):\n");<BR>scanf("%s",inma);<BR>if((information=fopen(inma,"wb"))==NULL)<BR>{printf("can't open the file\n");<BR>exit(0);<BR>}<BR> if((read_bmp(fin, &img_in))==FAILED) {<BR> fprintf(stderr, "\n Error: BMP read failed \n");<BR> fclose(fin);<BR> exit(-1);<BR> }<BR> fclose(fin);</P>
<P> if(img_in.bmp_type=='g') {<BR> /* set up structure for output image */<BR> get_bmp(&img_out, img_in.height, img_in.width, 'g');</P>
<P> /* pixel replication */<BR> for(i=0;i<img_in.height;i++)<BR> for(j=0;j<img_in.width;j++)<BR> img_out.mono[i][j]=img_in.mono[i][j];<BR> }<BR> else {<BR> fprintf(stderr, "\n Unknown image type \n");<BR> exit(-1);<BR> }</P>
<P>write_dat(fred,fgreen,fblue,&img_out);<BR> fclose(information);<BR> return SUCCESSED;<BR> }<BR> <BR> <BR>/* ---------------- */<BR>/* read_bmp() */<BR>/* ---------------- */</P>
<P>int read_bmp(FILE *infile, BMP_IMG *bmp_img)<BR>{<BR> int i,j;<BR> long width, height;<BR> int bits_per_pixel;<BR> int compression;<BR> unsigned char *temp; /* used for read the image data */</P>
<P> /* read the bmp image head information */</P>
<P> /* read the length and width of the input image */<BR> fseek(infile, 0x12, SEEK_SET);<BR> fread(&width, sizeof(long), 1, infile);<BR> fseek(infile, 0x16, SEEK_SET);<BR> fread(&height, sizeof(long), 1, infile);</P>
<P> bmp_img->width=width;<BR> bmp_img->height=height;</P>
<P> fprintf(information, "\n bmp_img->width=%d and bmp_img->height=%d \n", bmp_img->width, bmp_img->height);</P>
<P> /* read bits/pixel and decide the type of the bmp image */<BR> fseek(infile, 0x1C, SEEK_SET);<BR> fread(&bits_per_pixel, sizeof(int), 1, infile);</P>
<P> if(bits_per_pixel==8)<BR> bmp_img->bmp_type='g';<BR> <BR> fprintf(information, "\n bits_per_pixel=%d \n", bits_per_pixel);<BR> fprintf(information, "\n bmp_type=%c \n", bmp_img->bmp_type);</P>
<P> /* decide whether the bmp file is compressed */<BR> fseek(infile, 0x1E, SEEK_SET);<BR> fread(&compression, sizeof(int), 1, infile);<BR> if(compression==0) {<BR> fprintf(information, "\n the bmp file is not compressed! \n");<BR> }</P>
<P> fseek(infile, 0x0A, SEEK_SET);<BR> fread(&info_header_length, sizeof(int), 1, infile); /* the length of bmp image information head */<BR> fprintf(information, "\n info_header_length = %d \n", info_header_length);</P>
<P> /* allocate the memory for bmp_head_buffer and read the info header of bmp file */<BR> bmp_head_buffer=(unsigned char *)malloc(sizeof(unsigned char)*info_header_length);<BR> if(bmp_head_buffer==NULL) {<BR> fprintf(stderr, "\n Allocation error for bmp_head_buffer \n");<BR> exit(-1);<BR> }<BR> fseek(infile, 0x00, SEEK_SET);<BR> fread(bmp_head_buffer, info_header_length, 1, infile);/*取从文件开始到位图数据开始之间的数据偏移量*/<BR> <BR> /* end of read the bmp head information*/</P>
<P> /*为调色板指针指向的地址分配一块内存空间*/<BR> bmiColor = (RGBQUAD *)malloc(256 * sizeof(RGBQUAD));<BR> /*从文件中读位图的调色板数据到bmiColor指向的缓冲区*/<BR> <FONT color=#ee1111> fseek(infile,0x33,SEEK_SET);/*从此处读颜色索引值不知正确不?*/</FONT><BR> fread(bmiColor, sizeof(RGBQUAD), 256, infile);<BR> /*查看调色板信息*/<BR> for(i=0;i<256;i++)<BR> {<BR> fprintf(information, " Blue =%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbBlue);<BR> fprintf(information, " Green=%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbGreen);<BR> fprintf(information, " Red =%d\n\n\n\n", (*(bmiColor+i*sizeof(RGBQUAD))).rgbRed);<BR> } </P>
<P> /* allocate the memory for mono or color array */<BR> if(bmp_img->bmp_type=='g')/*为**mono/***color分配存贮空间*/<BR> get_bmp(bmp_img, bmp_img->height, bmp_img->width, 'g');<BR> </P>
<P><BR> /* read the image data to mono or color array */<BR> if(bmp_img->bmp_type=='g') {<BR> temp=(unsigned char *)malloc(sizeof(unsigned char)*(bmp_img->width*bmp_img->height));<BR> if(temp==NULL) {<BR> fprintf(stderr, "\n Allocation error for temp in read_bmp() \n");<BR> exit(-1);<BR> }</P>
<P> fseek(infile, info_header_length, SEEK_SET);<BR> if(fread(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, infile)!=(size_t)(bmp_img->width*bmp_img->height)) {<BR> if(feof(infile)) fprintf(stderr, "\n Premature end of file %s \n", infile);<BR> else fprintf(stderr, "\n File read error %s \n", infile);<BR> return FAILED;<BR> }</P>
<P> for(i=0;i<bmp_img->height;i++)<BR> for(j=0;j<bmp_img->width;j++)<BR> bmp_img->mono[i][j]=temp[i*bmp_img->width+j];<BR> <BR> }<BR> </P>
<P> return SUCCESSED;<BR>}</P>
<P>/* --------------- */<BR>/* get_bmp() */<BR>/* --------------- */</P>
<P>void get_bmp(BMP_IMG *img, long height, long width, char bmp_type)/*为**mono/***color分配存贮空间*/<BR>{<BR> int i;</P>
<P> img->width=width;<BR> img->height=height;<BR> img->bmp_type=bmp_type;</P>
<P> /* allocate the memory for mono and color */<BR> if(img->bmp_type=='g') {<BR> img->mono=(unsigned char **)malloc(sizeof(unsigned char *)*img->height);<BR> if(img->mono==NULL) {<BR> fprintf(stderr, "\n Allocation error for mono \n");<BR> exit(-1);<BR> }<BR> for(i=0;i<img->height;i++)<BR> {<BR> img->mono[i]=(unsigned char *)malloc(sizeof(unsigned char)*img->width);<BR> if(img->mono[i]==NULL) {<BR> fprintf(stderr, "\n Allocation error for mono[%d] \n",i);<BR> exit(-1);<BR> }<BR> }<BR> }</P>
<P>}</P>
<P>/* ----------------- */<BR>/* write_dat() */<BR>/* ----------------- */<BR>void write_dat(FILE *fred,FILE *fgreen,FILE *fblue,BMP_IMG *bmp_img)<BR>{int i,j,n;<BR>int red[256][256],green[256][256],blue[256][256];<BR>for(i=255;i>=0;i--)<BR> for(j=0;j<256;j++)<BR> { n=bmp_img->mono[i][j];//找到对应的颜色索引号<BR> red[255-i][j]=bmiColor[n].rgbRed;<BR> green[255-i][j]=bmiColor[n].rgbGreen;<BR> blue[255-i][j]=bmiColor[n].rgbBlue;<BR> }</P>
<P> fwrite(red,sizeof(unsigned char),bmp_img->width*bmp_img->height,fred);<BR> fwrite(green,sizeof(unsigned char),bmp_img->width*bmp_img->height,fgreen);<BR> fwrite(blue,sizeof(unsigned char),bmp_img->width*bmp_img->height,fblue);<BR> fclose(fred);<BR> fclose(fgreen);<BR> fclose(fblue);<BR></P>}</DIV>
<P><FONT color=#f76809>急切希望你的解答![</FONT>em13]</P>
[attach]18583[/attach]<BR> 位图文件结构表<BR> 位图文件头 14 字节<BR> 位图信息头 40 字节<BR>彩色表(调色板) 4N 字节<BR>位图数据 x 字节<BR>调色板的信息应该从54字节读起!<BR>fseek(infile,54,SEEK_SET);<BR> <BR> <P>你从51开始读起,正好r就是调色板的res值,所以全部是0;</P>
<P>struct regquad<BR>{<BR> char b;<BR>char g;<BR>char r;<BR>char res;//保留<BR>}<BR></P>
<P>谢谢大家了![em19]<BR>是的你说的对调色板的位置写错了不是<FONT color=#09f709>fseek(infile,0x33,SEEK_SET);</FONT>而是第我54个字节(0x36H)我太粗心了!<BR>正确的应是 <FONT color=#f70968>fseek(infile,0x36,SEEK_SET);</FONT><FONT color=#000000> 而且void write_dat()也写错了,应是:<BR>[CODE]void write_dat(FILE *fred,FILE *fgreen,FILE *fblue,BMP_IMG *bmp_img)<BR>{int i,j,n;<BR> int red[256][256],green[256][256],blue[256][256];<BR> unsigned char *temp; /* used for write the image data */ <BR> temp=(unsigned char *)malloc(sizeof(unsigned char)*(bmp_img->width*bmp_img->height));<BR> for(i=0;i<256;i++)<BR> for(j=0;j<256;j++)<BR> { n=bmp_img->mono[i][j];//找到对应的颜色索引号<BR> red[i][j]=bmiColor[n].rgbRed;<BR> green[i][j]=bmiColor[n].rgbGreen;<BR> blue[i][j]=bmiColor[n].rgbBlue;<BR> }<BR>/* 错误<BR> fwrite(red,sizeof(unsigned char),bmp_img->width*bmp_img->height,fred);<BR> fwrite(green,sizeof(unsigned char),bmp_img->width*bmp_img->height,fgreen);<BR> fwrite(blue,sizeof(unsigned char),bmp_img->width*bmp_img->height,fblue);<BR>*/<BR> for(i=0;i<bmp_img->height;i++)<BR> for(j=0;j<bmp_img->width;j++)<BR> temp[i*bmp_img->width+j]=red[255-i][j];<BR> fwrite(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, fred);<BR> for(i=0;i<bmp_img->height;i++)<BR> for(j=0;j<bmp_img->width;j++)<BR> temp[i*bmp_img->width+j]=green[255-i][j];<BR> fwrite(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, fgreen);<BR> for(i=0;i<bmp_img->height;i++)<BR> for(j=0;j<bmp_img->width;j++)<BR> temp[i*bmp_img->width+j]=blue[255-i][j];<BR> fwrite(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, fblue);<BR> fclose(fred);<BR> fclose(fgreen);<BR> fclose(fblue);<BR>}[/CODE]<BR>最后的结果好多了把读出的R,G,B DAT文件显示后效果不错,但不明白的是调色板的数据依然有许多零,用256*4的空间存放的有效颜色数目竟是这样少不是浪费吗?难道还是错的???调色板数据如下:<BR>Blue =53 Green=5 Red =66</FONT><FONT color=#000000><BR>Blue =90 Green=80 Red =154</FONT><FONT color=#000000><BR>Blue =138 Green=160 Red =212<BR></FONT><FONT color=#000000> Blue =67 Green=38 Red =107<BR>Blue =153 Green=160 Red =210<BR>Blue =122 Green=127 Red =187 <BR>Blue =97 Green=106 Red =220<BR>Blue =171 Green=188 Red =232<BR>Blue =83 Green=79 Red =178<BR>Blue =91 Green=84 Red =222 <BR>Blue =144 Green=106 Red =176 <BR>Blue =127 Green=81 Red =124<BR>Blue =103 Green=49 Red =126<BR> Blue =118 Green=117 Red =179<BR>Blue =128 Green=107 Red =224<BR>Blue =64 Green=20 Red =83<BR>Blue =79 Green=69 Red =176<BR>Blue =121 Green=129 Red =210<BR>Blue =141 Green=144 Red =229<BR>Blue =122 Green=175 Red =228<BR>Blue =123 Green=180 Red =238<BR>Blue =100 Green=64 Red =132<BR>Blue =86 Green=32 Red =102<BR>Blue =206 Green=236 Red =247<BR>Blue =105 Green=52 Red =107<BR>Blue =127 Green=119 Red =200<BR> Blue =119 Green=144 Red =232<BR>Blue =144 Green=119 Red =178<BR>Blue =108 Green=117 Red =212<BR>Blue =187 Green=159 Red =177<BR>Blue =75 Green=59 Red =164<BR>Blue =124 Green=136 Red =209<BR> Blue =94 Green=96 Red =220<BR>Blue =88 Green=72 Red =224<BR>Blue =125 Green=120 Red =223<BR>Blue =172 Green=138 Red =204<BR>Blue =109 Green=97 Red =202<BR>Blue =161 Green=167 Red =196<BR>Blue =199 Green=167 Red =175<BR>Blue =168 Green=121 Red =178<BR> Blue =192 Green=206 Red =232<BR>Blue =106 Green=135 Red =218<BR>Blue =105 Green=87 Red =139<BR>Blue =89 Green=85 Red =212<BR>Blue =104 Green=121 Red =236<BR> Blue =119 Green=94 Red =188 <BR>Blue =178 Green=137 Red =155<BR> Blue =171 Green=136 Red =166<BR> Blue =158 Green=161 Red =196<BR>Blue =144 Green=128 Red =196<BR>Blue =143 Green=152 Red =220<BR> Blue =62 Green=34 Red =140<BR>Blue =72 Green=31 Red =92 <BR>Blue =63 Green=31 Red =116<BR>Blue =88 Green=52 Red =116<BR>Blue =196 Green=214 Red =220<BR> Blue =103 Green=82 Red =153<BR>Blue =67 Green=40 Red =116<BR>Blue =67 Green=43 Red =140<BR>Blue =146 Green=107 Red =188<BR>Blue =127 Green=105 Red =236<BR>Blue =120 Green=94 Red =164<BR> Blue =133 Green=181 Red =238<BR>Blue =128 Green=118 Red =164<BR> Blue =253 Green=253 Red =253<BR> Blue =164 Green=2 Red =135<BR>Blue =0 Green=0 Red =0 <BR>Blue =0 Green=0 Red =0<BR> Blue =0 Green=0 Red =0以下又都是0了!<BR>用另外一个程序分别把R,G,B三个分量写到BMP文件中显示,但好像不对,还有就是把三个分量恢复成原图只有一个大概<BR>轮廓,色彩不明显。是读的数据有问题还是调色板数据不对,但把R,G,B三分量的DAT文件分别显示又很清晰,看不出<BR>什么毛病,问题在哪请您指点[em13][em13][em13]<BR>此程序及相关数据在附件中请察看!</FONT></P>[attach]18764[/attach]<BR> 你读调色板数据不对,没有读完!!你在网上下一个二进制文件编辑器,打开bmp文件,看读出的数据是否正确! <P>调色板数据读完了,一共读了256组,只是后边的不对全是零。<BR><BR>多谢了![em19]我下了一个 UltraEdit 可以看到BMP里的具体存贮数据,一会儿再慢慢分析一下</P> <FONT color=#f73809>[em34][em34][em34]终于把错误全找出来了,读的数据一切正常,恢复图象和原来的一样.<BR>多亏了 "UltraEdit "帮我分析了原图象的数据.<BR><BR>读调色板时下边的代码跳过了中间的四组值,难怪错了!<BR></FONT>[CODE]/*查看调色板信息*/<BR> for(i=0;i<256;i++)<BR> {<BR> fprintf(information, " Blue =%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbBlue);<BR> fprintf(information, " Green=%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbGreen);<BR> fprintf(information, " Red =%d\n\n\n\n", (*(bmiColor+i*sizeof(RGBQUAD))).rgbRed);<BR> }<BR>正确的应是: <BR>/*查看调色板信息*/<BR> for(i=0;i<256;i++)<BR> {<BR> fprintf(information, " Blue =%d" , (*(bmiColor+i)).rgbBlue);<BR> fprintf(information, " Green=%d" , (*(bmiColor+i)).rgbGreen);<BR> fprintf(information, " Red =%d\n\n\n\n", (*(bmiColor+i)).rgbRed);<BR> } [/CODE]<BR><BR><BR>此类问题希望大家以后注意![em16]
页:
[1]
