标题:[求助]读取BMP图象的R,G,B值到三个二维数组,请高手看一下问题出在哪!
只看楼主
feixiang569
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2007-3-30
 问题点数:0 回复次数:6 
[求助]读取BMP图象的R,G,B值到三个二维数组,请高手看一下问题出在哪!

[求助]读取BMP的R,G,B,值请高手看一下问题出在哪?

我现在做的毕业设计是彩色图象的水印,需要把一副BMP图象的R,G,B,各个分量分别读出来然后再对各分量处理.最后再把处理后的数据写回BMP。下面的第一个程序我试了各种办法就是找不出错,请高手帮忙分析一下!
程序可以在*.TXT文件中输出图象位图文件头,信息头的主要数据,但其中的调色板读出的各颜色索引值不对,还有就是读出的R,G,B,三个二维数组的数值也不对(用自己编的READ.EXE,读DAT文件到记事本中0有许多 或是把三个分量分别写到BMP文件中但显示都只是一副紫色图)但大小是对的.
还想问一下就是数据处理完后怎么再把R,G,B值恢复为一副彩色图象,颜色索引值是不是还要重新确定一下?
下面是从BMP读取的主要数据:
bmp_img->width=256 and bmp_img->height=256 bits_per_pixel=8 bmp_type=g
the bmp file is notcompressed!
info_header_length = 1078
调色板的各颜色索引值:
Blue =1 Green=0 Red =0
Blue =189 Green=202 Red =0
Blue =63 Green=114 Red =0
Blue =104 Green=201 Red =0
Blue =219 Green=251 Red =0
Blue =106 Green=150 Red =0
Blue =57 Green=154 Red =0
Blue =64 Green=120 Red =0
Blue =31 Green=84 Red =0
Blue =107 Green=199 Red =0
Blue =84 Green=176 Red =0
Blue =128 Green=228 Red =0
Blue =64 Green=152 Red =0
Blue =177 Green=211 Red =0
Blue =128 Green=185 Red =0
Blue =203 Green=241 Red =0
Blue =52 Green=130 Red =0
Blue =94 Green=202 Red =0
Blue =209 Green=245 Red =0
Blue =52 Green=106 Red =0
Blue =143 Green=186 Red =0
Blue =49 Green=173 Red =0
Blue =105 Green=201 Red =0
Blue =115 Green=154 Red =0
Blue =82 Green=177 Red =0
Blue =96 Green=138 Red =0
Blue =143 Green=212 Red =0
Blue =219 Green=239 Red =0

Blue =41 Green=107 Red =0
Blue =188 Green=220 Red =0
Blue =135 Green=195 Red =0
Blue =13 Green=81 Red =0
Blue =196 Green=234 Red =0
Blue =136 Green=228 Red =0
Blue =164 Green=192 Red =0
Blue =56 Green=126 Red =0
Blue =72 Green=155 Red =0
Blue =21 Green=102 Red =0
Blue =104 Green=140 Red =0
Blue =48 Green=151 Red =0
Blue =160 Green=236 Red =0
Blue =196 Green=245 Red =0
Blue =151 Green=190 Red =0
Blue =151 Green=168 Red =0
Blue =92 Green=188 Red =0
Blue =119 Green=212 Red =0
Blue =197 Green=236 Red =0
Blue =71 Green=135 Red =0
Blue =136 Green=172 Red =0
Blue =144 Green=220 Red =0
Blue =136 Green=196 Red =0
Blue =21 Green=116 Red =0
Blue =60 Green=188 Red =0
Blue =22 Green=92 Red =0
Blue =94 Green=164 Red =0
Blue =136 Green=230 Red =0
Blue =194 Green=220 Red =0
Blue =105 Green=212 Red =0
Blue =107 Green=221 Red =0
Blue =86 Green=188 Red =0
Blue =118 Green=199 Red =0
Blue =118 Green=164 Red =0
Blue =180 Green=244 Red =0
Blue =34 Green=116 Red =0
Blue =253 Green=253 Red =253
Blue =164 Green=2 Red =135
Blue =0 Green=0 Red =0
Blue =0 Green=0 Red =0
Blue =0 Green=0 Red =0 以下各值就全为0了,个数是对的一共读了256个索引值
程序如下(在VC中运行的):


/* This program is to read and write bmp images 只是256色位图 图片为256*256的彩色LENA图*/
#include "Conio.h"
#include "stdlib.h"
#include "stdio.h"
#include "malloc.h"
#include "math.h"

#define SUCCESSED 0
#define FAILED 1
//typedef unsigned char BYTE
/* ---------------------- */
/* Global Variables */
/* ---------------------- */

typedef struct BMP_img
{
long width;
long height;
char bmp_type; /* 'c'=color; 'g'=graymap; */
unsigned char **mono;

}BMP_IMG;

typedef struct tagRGBQUAD {
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD;

long info_header_length; /* the length of bmp image information head */
unsigned char *bmp_head_buffer; /* used for bmp head */
RGBQUAD *bmiColor; /*调色板数组*/
FILE *information; /*在.txt文件中输出BMP图象的主要数据*/

/* ---------------------- */
/* Global Functions */
/* ---------------------- */

int read_bmp(FILE *infile, BMP_IMG *bmp_img);
void get_bmp(BMP_IMG *img, long height, long width, char bmp_type);
void write_dat(FILE *fred,FILE *fgreen,FILE *fblue,BMP_IMG *bmp_img);

/* ------------ */
/* Main() */
/* ------------ */

int main()
{
int i,j;
char infilename[10],redfilename[10],greenfilename[10],bluefilename[10],inma[10];
FILE *fin, *fred,*fgreen,*fblue;
BMP_IMG img_in, img_out;

printf("input the sourse filename:\n");
scanf("%s",infilename);
if((fin=fopen(infilename,"rb"))==NULL)
{ printf("can't open the file\n");
exit(0);
}
printf("input the red filename(*.dat):\n");
scanf("%s",redfilename);
if((fred=fopen(redfilename,"wb"))==NULL)
{ printf("can't open the file\n");
exit(0);
}
printf("input the green filename(*.dat):\n");
scanf("%s",greenfilename);
if((fgreen=fopen(greenfilename,"wb"))==NULL)
{ printf("can't open the file\n");
exit(0);
}
printf("input the blue filename(*.dat):\n");
scanf("%s",bluefilename);
if((fblue=fopen(bluefilename,"wb"))==NULL)
{ printf("can't open the file\n");
exit(0);
}
printf("input the information filename(*.txt):\n");
scanf("%s",inma);
if((information=fopen(inma,"wb"))==NULL)
{printf("can't open the file\n");
exit(0);
}
if((read_bmp(fin, &img_in))==FAILED) {
fprintf(stderr, "\n Error: BMP read failed \n");
fclose(fin);
exit(-1);
}
fclose(fin);

if(img_in.bmp_type=='g') {
/* set up structure for output image */
get_bmp(&img_out, img_in.height, img_in.width, 'g');

/* pixel replication */
for(i=0;i<img_in.height;i++)
for(j=0;j<img_in.width;j++)
img_out.mono[i][j]=img_in.mono[i][j];
}
else {
fprintf(stderr, "\n Unknown image type \n");
exit(-1);
}

write_dat(fred,fgreen,fblue,&img_out);
fclose(information);
return SUCCESSED;
}


/* ---------------- */
/* read_bmp() */
/* ---------------- */

int read_bmp(FILE *infile, BMP_IMG *bmp_img)
{
int i,j;
long width, height;
int bits_per_pixel;
int compression;
unsigned char *temp; /* used for read the image data */

/* read the bmp image head information */

/* read the length and width of the input image */
fseek(infile, 0x12, SEEK_SET);
fread(&width, sizeof(long), 1, infile);
fseek(infile, 0x16, SEEK_SET);
fread(&height, sizeof(long), 1, infile);

bmp_img->width=width;
bmp_img->height=height;

fprintf(information, "\n bmp_img->width=%d and bmp_img->height=%d \n", bmp_img->width, bmp_img->height);

/* read bits/pixel and decide the type of the bmp image */
fseek(infile, 0x1C, SEEK_SET);
fread(&bits_per_pixel, sizeof(int), 1, infile);

if(bits_per_pixel==8)
bmp_img->bmp_type='g';

fprintf(information, "\n bits_per_pixel=%d \n", bits_per_pixel);
fprintf(information, "\n bmp_type=%c \n", bmp_img->bmp_type);

/* decide whether the bmp file is compressed */
fseek(infile, 0x1E, SEEK_SET);
fread(&compression, sizeof(int), 1, infile);
if(compression==0) {
fprintf(information, "\n the bmp file is not compressed! \n");
}

fseek(infile, 0x0A, SEEK_SET);
fread(&info_header_length, sizeof(int), 1, infile); /* the length of bmp image information head */
fprintf(information, "\n info_header_length = %d \n", info_header_length);

/* allocate the memory for bmp_head_buffer and read the info header of bmp file */
bmp_head_buffer=(unsigned char *)malloc(sizeof(unsigned char)*info_header_length);
if(bmp_head_buffer==NULL) {
fprintf(stderr, "\n Allocation error for bmp_head_buffer \n");
exit(-1);
}
fseek(infile, 0x00, SEEK_SET);
fread(bmp_head_buffer, info_header_length, 1, infile);/*取从文件开始到位图数据开始之间的数据偏移量*/

/* end of read the bmp head information*/

/*为调色板指针指向的地址分配一块内存空间*/
bmiColor = (RGBQUAD *)malloc(256 * sizeof(RGBQUAD));
/*从文件中读位图的调色板数据到bmiColor指向的缓冲区*/
fseek(infile,0x33,SEEK_SET);/*从此处读颜色索引值不知正确不?*/
fread(bmiColor, sizeof(RGBQUAD), 256, infile);
/*查看调色板信息*/
for(i=0;i<256;i++)
{
fprintf(information, " Blue =%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbBlue);
fprintf(information, " Green=%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbGreen);
fprintf(information, " Red =%d\n\n\n\n", (*(bmiColor+i*sizeof(RGBQUAD))).rgbRed);
}

/* allocate the memory for mono or color array */
if(bmp_img->bmp_type=='g')/*为**mono/***color分配存贮空间*/
get_bmp(bmp_img, bmp_img->height, bmp_img->width, 'g');


/* read the image data to mono or color array */
if(bmp_img->bmp_type=='g') {
temp=(unsigned char *)malloc(sizeof(unsigned char)*(bmp_img->width*bmp_img->height));
if(temp==NULL) {
fprintf(stderr, "\n Allocation error for temp in read_bmp() \n");
exit(-1);
}

fseek(infile, info_header_length, SEEK_SET);
if(fread(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, infile)!=(size_t)(bmp_img->width*bmp_img->height)) {
if(feof(infile)) fprintf(stderr, "\n Premature end of file %s \n", infile);
else fprintf(stderr, "\n File read error %s \n", infile);
return FAILED;
}

for(i=0;i<bmp_img->height;i++)
for(j=0;j<bmp_img->width;j++)
bmp_img->mono[i][j]=temp[i*bmp_img->width+j];

}

return SUCCESSED;
}

/* --------------- */
/* get_bmp() */
/* --------------- */

void get_bmp(BMP_IMG *img, long height, long width, char bmp_type)/*为**mono/***color分配存贮空间*/
{
int i;

img->width=width;
img->height=height;
img->bmp_type=bmp_type;

/* allocate the memory for mono and color */
if(img->bmp_type=='g') {
img->mono=(unsigned char **)malloc(sizeof(unsigned char *)*img->height);
if(img->mono==NULL) {
fprintf(stderr, "\n Allocation error for mono \n");
exit(-1);
}
for(i=0;i<img->height;i++)
{
img->mono[i]=(unsigned char *)malloc(sizeof(unsigned char)*img->width);
if(img->mono[i]==NULL) {
fprintf(stderr, "\n Allocation error for mono[%d] \n",i);
exit(-1);
}
}
}

}

/* ----------------- */
/* write_dat() */
/* ----------------- */
void write_dat(FILE *fred,FILE *fgreen,FILE *fblue,BMP_IMG *bmp_img)
{int i,j,n;
int red[256][256],green[256][256],blue[256][256];
for(i=255;i>=0;i--)
for(j=0;j<256;j++)
{ n=bmp_img->mono[i][j];//找到对应的颜色索引号
red[255-i][j]=bmiColor[n].rgbRed;
green[255-i][j]=bmiColor[n].rgbGreen;
blue[255-i][j]=bmiColor[n].rgbBlue;
}

fwrite(red,sizeof(unsigned char),bmp_img->width*bmp_img->height,fred);
fwrite(green,sizeof(unsigned char),bmp_img->width*bmp_img->height,fgreen);
fwrite(blue,sizeof(unsigned char),bmp_img->width*bmp_img->height,fblue);
fclose(fred);
fclose(fgreen);
fclose(fblue);

}

急切希望你的解答![em13]


搜索更多相关主题的帖子: BMP图象 B值 分量 水印 
2007-04-01 09:41
lyood
Rank: 1
等 级:新手上路
帖 子:22
专家分:0
注 册:2006-6-15
得分:0 
位图文件结构表
位图文件头 14 字节
位图信息头 40 字节
彩色表(调色板) 4N 字节
位图数据 x 字节
调色板的信息应该从54字节读起!
fseek(infile,54,SEEK_SET);


2007-04-04 15:37
lyood
Rank: 1
等 级:新手上路
帖 子:22
专家分:0
注 册:2006-6-15
得分:0 

你从51开始读起,正好r就是调色板的res值,所以全部是0;

struct regquad
{
char b;
char g;
char r;
char res;//保留
}


2007-04-04 15:44
feixiang569
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2007-3-30
得分:0 

谢谢大家了!
是的你说的对调色板的位置写错了不是fseek(infile,0x33,SEEK_SET);而是第我54个字节(0x36H)我太粗心了!
正确的应是 fseek(infile,0x36,SEEK_SET); 而且void write_dat()也写错了,应是:
[CODE]void write_dat(FILE *fred,FILE *fgreen,FILE *fblue,BMP_IMG *bmp_img)
{int i,j,n;
int red[256][256],green[256][256],blue[256][256];
unsigned char *temp; /* used for write the image data */
temp=(unsigned char *)malloc(sizeof(unsigned char)*(bmp_img->width*bmp_img->height));
for(i=0;i<256;i++)
for(j=0;j<256;j++)
{ n=bmp_img->mono[i][j];//找到对应的颜色索引号
red[i][j]=bmiColor[n].rgbRed;
green[i][j]=bmiColor[n].rgbGreen;
blue[i][j]=bmiColor[n].rgbBlue;
}
/* 错误
fwrite(red,sizeof(unsigned char),bmp_img->width*bmp_img->height,fred);
fwrite(green,sizeof(unsigned char),bmp_img->width*bmp_img->height,fgreen);
fwrite(blue,sizeof(unsigned char),bmp_img->width*bmp_img->height,fblue);
*/
for(i=0;i<bmp_img->height;i++)
for(j=0;j<bmp_img->width;j++)
temp[i*bmp_img->width+j]=red[255-i][j];
fwrite(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, fred);
for(i=0;i<bmp_img->height;i++)
for(j=0;j<bmp_img->width;j++)
temp[i*bmp_img->width+j]=green[255-i][j];
fwrite(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, fgreen);
for(i=0;i<bmp_img->height;i++)
for(j=0;j<bmp_img->width;j++)
temp[i*bmp_img->width+j]=blue[255-i][j];
fwrite(temp, sizeof(unsigned char), bmp_img->width*bmp_img->height, fblue);
fclose(fred);
fclose(fgreen);
fclose(fblue);
}[/CODE]
最后的结果好多了把读出的R,G,B DAT文件显示后效果不错,但不明白的是调色板的数据依然有许多零,用256*4的空间存放的有效颜色数目竟是这样少不是浪费吗?难道还是错的???调色板数据如下:
Blue =53 Green=5 Red =66

Blue =90 Green=80 Red =154

Blue =138 Green=160 Red =212
Blue =67 Green=38 Red =107
Blue =153 Green=160 Red =210
Blue =122 Green=127 Red =187
Blue =97 Green=106 Red =220
Blue =171 Green=188 Red =232
Blue =83 Green=79 Red =178
Blue =91 Green=84 Red =222
Blue =144 Green=106 Red =176
Blue =127 Green=81 Red =124
Blue =103 Green=49 Red =126
Blue =118 Green=117 Red =179
Blue =128 Green=107 Red =224
Blue =64 Green=20 Red =83
Blue =79 Green=69 Red =176
Blue =121 Green=129 Red =210
Blue =141 Green=144 Red =229
Blue =122 Green=175 Red =228
Blue =123 Green=180 Red =238
Blue =100 Green=64 Red =132
Blue =86 Green=32 Red =102
Blue =206 Green=236 Red =247
Blue =105 Green=52 Red =107
Blue =127 Green=119 Red =200
Blue =119 Green=144 Red =232
Blue =144 Green=119 Red =178
Blue =108 Green=117 Red =212
Blue =187 Green=159 Red =177
Blue =75 Green=59 Red =164
Blue =124 Green=136 Red =209
Blue =94 Green=96 Red =220
Blue =88 Green=72 Red =224
Blue =125 Green=120 Red =223
Blue =172 Green=138 Red =204
Blue =109 Green=97 Red =202
Blue =161 Green=167 Red =196
Blue =199 Green=167 Red =175
Blue =168 Green=121 Red =178
Blue =192 Green=206 Red =232
Blue =106 Green=135 Red =218
Blue =105 Green=87 Red =139
Blue =89 Green=85 Red =212
Blue =104 Green=121 Red =236
Blue =119 Green=94 Red =188
Blue =178 Green=137 Red =155
Blue =171 Green=136 Red =166
Blue =158 Green=161 Red =196
Blue =144 Green=128 Red =196
Blue =143 Green=152 Red =220
Blue =62 Green=34 Red =140
Blue =72 Green=31 Red =92
Blue =63 Green=31 Red =116
Blue =88 Green=52 Red =116
Blue =196 Green=214 Red =220
Blue =103 Green=82 Red =153
Blue =67 Green=40 Red =116
Blue =67 Green=43 Red =140
Blue =146 Green=107 Red =188
Blue =127 Green=105 Red =236
Blue =120 Green=94 Red =164
Blue =133 Green=181 Red =238
Blue =128 Green=118 Red =164
Blue =253 Green=253 Red =253
Blue =164 Green=2 Red =135
Blue =0 Green=0 Red =0
Blue =0 Green=0 Red =0
Blue =0 Green=0 Red =0以下又都是0了!
用另外一个程序分别把R,G,B三个分量写到BMP文件中显示,但好像不对,还有就是把三个分量恢复成原图只有一个大概
轮廓,色彩不明显。是读的数据有问题还是调色板数据不对,但把R,G,B三分量的DAT文件分别显示又很清晰,看不出
什么毛病,问题在哪请您指点
此程序及相关数据在附件中请察看!

lCUB1gCq.rar (112.34 KB) [求助]读取BMP图象的R,G,B值到三个二维数组,请高手看一下问题出在哪!




jZ9jrdUb.rar (495.93 KB) [求助]读取BMP图象的R,G,B值到三个二维数组,请高手看一下问题出在哪!

2007-04-05 14:02
lyood
Rank: 1
等 级:新手上路
帖 子:22
专家分:0
注 册:2006-6-15
得分:0 
你读调色板数据不对,没有读完!!你在网上下一个二进制文件编辑器,打开bmp文件,看读出的数据是否正确!

2007-04-05 14:59
feixiang569
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2007-3-30
得分:0 

调色板数据读完了,一共读了256组,只是后边的不对全是零。

多谢了!我下了一个 UltraEdit 可以看到BMP里的具体存贮数据,一会儿再慢慢分析一下

2007-04-07 14:46
feixiang569
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2007-3-30
得分:0 
终于把错误全找出来了,读的数据一切正常,恢复图象和原来的一样.
多亏了 "UltraEdit "帮我分析了原图象的数据.

读调色板时下边的代码跳过了中间的四组值,难怪错了!
[CODE]/*查看调色板信息*/
for(i=0;i<256;i++)
{
fprintf(information, " Blue =%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbBlue);
fprintf(information, " Green=%d" , (*(bmiColor+i*sizeof(RGBQUAD))).rgbGreen);
fprintf(information, " Red =%d\n\n\n\n", (*(bmiColor+i*sizeof(RGBQUAD))).rgbRed);
}
正确的应是:
/*查看调色板信息*/
for(i=0;i<256;i++)
{
fprintf(information, " Blue =%d" , (*(bmiColor+i)).rgbBlue);
fprintf(information, " Green=%d" , (*(bmiColor+i)).rgbGreen);
fprintf(information, " Red =%d\n\n\n\n", (*(bmiColor+i)).rgbRed);
} [/CODE]


此类问题希望大家以后注意!
2007-04-08 19:01



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-128472-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.108315 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved