一直想认真写一下关于DSP的学习笔记,但是由于时间和惰性,徘徊许久,都没能提笔,趁着系统学习TMS320C6657的机会,在此开博,用于对自己学习的总结,也希望能跟大家分享学习心得,相互交流共同进步。
博客暂时是以自己学习过程为次序,将觉得有必要拿出来分享的经验贴出来,才疏学浅,有错误,请大家不吝赐教。
TI可以说是很厚道的一家芯片公司,大量的代码和文档给大家学习深入带来了很大方便,但也正因为资料繁多,新手往往不知从何下手。现在提供几个在线学习的网站,大部分问题都可以在这几个网站得到解决。
首先推荐TI wiki几乎所有的文档都可以通过这里一一找到,网址:http://processors.wiki.ti.com/;
其次是德州仪器在线支持社区,可以在上面提问和搜索你遇到的问题,一般提问在1-2个工作日会有TI的支持工程师解答,在此提一下,这里有很多TI支持发出来的源代码可以用于学习,网址:http://www.deyisupport.com/;
最后是TI的英文帮助社区--TI E2E Community,英文比较好的朋友,在此提问会得到更专业的回答,网址:http://e2e.ti.com/。
好了,现在进入今天的主题,TI官方提供的源代码---读BMP图像。
可以从多核开发套件的图像处理demo文件夹C:timcsdk_2_01_02_06demosimage_processing中导入工程,读BMP图像主要是两个文件mcip_bmp_utils.c和mcip_bmp_utils.h,我的代码也是“拿来主义”,大部分与TI源代码相同,只修改部分,以适用自己的需求,期间对代码进行了详细注释,大家可以参考下,理清思路。
分析程序首先从mcip_bmp_utils.h开始,贴出BMP图像文件头定义,可以参考本博客---图像处理与模式识别分类中----BMP文件结构,即可了解。它对文件头结构体做了很好的划分,分别后续操作。觉得做得最科学的是它设计了一个原始图像数据的结构体raw_image_data_t,这个做法开始我还不太理解,后来发现,有了它可以将文件的获取和文件解码松耦合,使得原始数据可以从通过任何形式进行获取,例如,TCP、摄像头、文件系统中的原始数据,提高了读BMP图像程序模块的通用性,不仅仅限于在CCS进行软仿,而且可以脱离PC机通过TCP、摄像头之类的方式获取原始图像数据,然后进行BMP图像解码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85#ifndef BMP_UTILS_H #define BMP_UTILS_H #include <stdint.h> #include <xdc/runtime/Memory.h> #include <xdc/runtime/Error.h> /****************************************************************************/ /* 位图文件头结构体 */ /****************************************************************************/ #ifdef _HOST_BUILD #pragma pack(1) #endif typedef struct bmpfile_signature { uint8_t signature[2]; /* Signature - 'BM' */ } bmpfile_signature_t; typedef struct bmpfile_header { uint32_t file_size; /* BMP图像文件的大小 */ uint16_t reserved1; uint16_t reserved2; uint32_t bitmap_offset; /* BMP图像数据的偏移地址 */ } bmpfile_header_t; typedef struct bmpfile_dib_header { uint32_t header_size; /* 本结构的大小 */ int32_t image_width; /* 位图的宽度 */ int32_t image_height; /* 位图的高度 */ uint16_t number_of_planes; /* Number of planes */ uint16_t bits_per_pixel; /* 每个像素的位数 */ uint32_t compression_type;/* 压缩类型 */ uint32_t image_size; /* 表示位图数据区域的大小以字节为单位 */ int32_t horizontal_resolution; /* 水平分辨率,单位像素/m */ int32_t vertical_resolution; /* 垂直分辨率,单位像素/m */ uint32_t number_of_colors; /* BMP图像使用的颜色,0表示使用全部颜色,对于256色位图来说,此值为100h=256 */ uint32_t important_color_count; /* Important color count */ } bmpfile_dib_header_t; typedef struct bmp_header { bmpfile_signature_t signature; bmpfile_header_t file; bmpfile_dib_header_t dib; } bmp_header_t; /****************************************************************************/ /* 位图RGB调色板入口结构体 */ /****************************************************************************/ typedef struct { uint8_t red; uint8_t green; uint8_t blue; uint8_t reserved; } bmp_color_table_t; typedef enum { BMP_RGB = 0, BMP_RLE8, BMP_RLE4, BMP_BITFIELDS, BMP_JPEG, BMP_PNG } bmp_compression_method_e; /* 原始图像数据,需要解码 */ typedef struct raw_image_data { uint8_t * data; uint32_t length; } raw_image_data_t;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81/*****************************************************************************/ /** * Created on: 2015-11-9 * Author: HeWu * 这个函数用于从文件系统中读取文件的元素数据, * 参数说明:const char *_fname文件名 * const char *_mode读写模式 * 返回类型:raw_image_data_t(整个原始文件的字节数据,以及字节长度) * */ /*****************************************************************************/ extern raw_image_data_t get_raw_image_data_from_file(const char *_fname, const char *_mode); /*****************************************************************************/ /** * Created on: 2015-11-9 * Author: HeWu * 这个函数用于从raw data转换到bmp结构体, * 参数说明:raw_image_data_t * p_input_image图像原始字节数据 * unsigned char * p_output_pixel_array图像的像素信息,用于后续处理 * 返回:raw_image_data_t结构体 * */ /*****************************************************************************/ extern int raw_data_cvt_bmp_pixels(raw_image_data_t * p_input_image,unsigned char * p_output_pixel_array); /*****************************************************************************/ /* * * 函数功能:这个函数BMP文件中读取文件头信息。 * 说明:函数对文件做了一些初步的检查。 * 如果读取文件成功返回0; * 如果读取文件失败或检查失败,返回负数。 */ /*****************************************************************************/ extern int bmp_read_header (raw_image_data_t * image, bmp_header_t * hdr); /*****************************************************************************/ /* * * 函数说明:读取调色板。这个函数用的比较少,调色板是单色、16色和256色图像文件特有。 * */ /*****************************************************************************/ extern int bmp_read_colormap (raw_image_data_t * image, bmp_header_t * hdr, bmp_color_table_t * color_table); /*****************************************************************************/ /* * * 函数功能:读取图像(像素值),需要计算像素占用字节数。 * 参数说明:raw_image_data_t * image,待解码数据 * bmp_header_t * hdr, 文件头 * uint8_t * pixel_array_rgb,用于返回的像素值指针,后续图像算法就是对它进行了 */ extern int bmp_read_image (raw_image_data_t * image, bmp_header_t * hdr, uint8_t * pixel_array_rgb); /*****************************************************************************/ /* * * 函数功能:通过BMP图像,创建并将像素值保存为灰度图像。 * 参数说明:raw_image_data_t * image,保存结果 * uint8_t * pixel_array,像素值指针 */ /*****************************************************************************/ extern int bmp_write_gray_bmpfile (raw_image_data_t * image, uint8_t * pixel_array, uint32_t width, uint32_t height); /*****************************************************************************/ /* * 函数功能:获取灰度BMP图的文件大小 */ /*****************************************************************************/ extern uint32_t bmp_get_gray_bmpfile_size (uint32_t width, uint32_t height); #endif /*BMP_UTILS_H*/
1extern raw_image_data_t get_raw_image_data_from_file(const char *_fname, const char *_mode);
1extern int raw_data_cvt_bmp_pixels(raw_image_data_t * p_input_image,unsigned char * p_output_pixel_array);
下面是mcip_bmp_utils.c函数的实现文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324/* ======================================================================== */ /* TEXAS INSTRUMENTS, INC. */ /* */ /* ======================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "mcip_bmp_utils.h" /*#define BMP_UTILS_DEBUG*/ /* BMP灰度图像默认文件头*/ static bmp_header_t default_grayscale_bmp_header = { { {'B', 'M'} /*signature*/ }, { 263222, /*file_size*/ 0, 0, /*reserved1, reserved2*/ 1078 /*bitmap_offset*/ }, { 40, /*header_size*/ 512, /*width*/ 512, /*height*/ 1, /*nplanes*/ 8, /*bitspp*/ 0, /*compress_type*/ 262144, /*bmp_bytesz*/ 0, /*hres*/ 0, /*vres*/ 256, /*ncolors*/ 0 /*nimpcolors*/ } }; /*****************************************************************************/ /** * Created on: 2015-11-9 * Author: HeWu * 这个函数用于从文件系统中读取文件的元素数据, * 返回类型包括整个文件的字节数据,以及字节长度 * */ /*****************************************************************************/ raw_image_data_t get_raw_image_data_from_file(const char *_fname, const char *_mode) { Error_Block eb; Error_init(&eb); FILE * fpr = 0; raw_image_data_t raw_image = {0, 0}; uint32_t read_length = 0; int ret_val = 0; fpr = fopen(_fname, _mode); if(!fpr) { printf("Unable to open image file %sn", _fname); } fseek(fpr, 0, SEEK_END); raw_image.length = ftell(fpr); fseek(fpr, 0, SEEK_SET); /** * 之所以用这个Memory_alloc(),而不用malloc(), * 是为了放置内存碎片化,还是用TI提供的函数咯 * */ raw_image.data = (uint8_t*)Memory_alloc(NULL,raw_image.length,0,&eb); if(!raw_image.data) { printf("Unable allocate buffer for raw image file read (%s)n", _fname); } //fread()返回的是已读取的字节数,ret_val用于指针移动和检查 do { ret_val = fread(raw_image.data + read_length, 1, raw_image.length - read_length, fpr); if (!ret_val) { printf("Unable read the raw image file %sn", _fname); } read_length += ret_val; } while (read_length < raw_image.length); return raw_image;//返回原始图像数据 } /*****************************************************************************/ /** * Created on: 2015-11-9 * Author: HeWu * 这个函数用于从raw data转换到bmp结构体, * 返回类型包括像素数据指针 * */ /*****************************************************************************/ extern int raw_data_cvt_bmp_pixels(raw_image_data_t * p_input_image,unsigned char * p_output_pixel_array) { Error_Block eb; Error_init(&eb); bmp_color_table_t * p_color_table = 0; bmp_header_t bmp_header; uint8_t * pixel_array_rgb = 0; int color_table_size,pixel_array_rgb_size; int pixel_size, row_width; int i, j, ret_val = 0; if ((p_input_image == 0) || (p_input_image->length == 0) || (p_input_image->data == 0)) { printf("Invalid BMP image datan"); ret_val = -1; return ret_val; } if (bmp_read_header(p_input_image, &bmp_header) < 0) { printf("Error in reading headern"); ret_val = -1; return ret_val; } pixel_size = bmp_header.dib.bits_per_pixel / 8;//一个像素的字节数 row_width = bmp_header.dib.image_width * pixel_size;//一行的字节数 /*读调色板,现在很多bmp图像都没有调色板,可以忽略这一部分*/ if (bmp_header.dib.number_of_colors) { /* Color table present */ color_table_size = sizeof(bmp_color_table_t) * bmp_header.dib.number_of_colors; p_color_table = (bmp_color_table_t *)Memory_alloc(NULL,color_table_size,0,&eb); if(!p_color_table) { printf("Can't allocate memory for color tablen"); ret_val = -1; return ret_val; } if (bmp_read_colormap(p_input_image, &bmp_header, p_color_table) < 0) { printf("Error in reading color mapn"); ret_val = -1; return ret_val; } } /* 读像素数据 ,直接由第二个参数传入指针,不用在此分配内存*/ if (bmp_read_image (p_input_image, &bmp_header, p_output_pixel_array) < 0) { printf("Error in reading pixel imagen"); ret_val = -1; return ret_val; } } /****************************************************************************/ /* 读BMP信息头 */ /****************************************************************************/ int bmp_read_header (raw_image_data_t * image, bmp_header_t * hdr) { /*如果文件头结构体大于原始图像数据大小,则是无效图像*/ if (image->length < sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t) + sizeof(bmpfile_dib_header_t)) { printf ("Insufficient Image Buffer Length %dn", image->length); return -1; } /*将原始图像数据解码到三个BMP文件头结构体*/ memcpy(&(hdr->signature), image->data, sizeof(bmpfile_signature_t)); memcpy(&(hdr->file), image->data + sizeof(bmpfile_signature_t), sizeof(bmpfile_header_t)); memcpy(&(hdr->dib), image->data + sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t), sizeof(bmpfile_dib_header_t)); /*做一些检查,自己看英文咯*/ if((hdr->signature.signature[0] != 'B') || (hdr->signature.signature[1] != 'M')) { printf("Incorrect MAGIC number 0x%x 0x%xn", hdr->signature.signature[0], hdr->signature.signature[1]); return -1; } if((hdr->dib.bits_per_pixel != 8) && (hdr->dib.bits_per_pixel != 24)) { printf("Only 8 or 24 bits per pixel supported, the image bpp is %dn", hdr->dib.bits_per_pixel); return -1; } if(hdr->dib.compression_type != BMP_RGB) { printf("Need a RGB type image, the image type is %dn", hdr->dib.compression_type); return -1; } return 0; } /****************************************************************************/ /* 读BMP调色板 */ /****************************************************************************/ int bmp_read_colormap (raw_image_data_t * image, bmp_header_t * hdr, bmp_color_table_t * color_table) { int index; if(hdr->dib.number_of_colors == 0) { printf("Color table can't be read, ncolors = %dn", hdr->dib.number_of_colors); return -1; } index = sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t) + hdr->dib.header_size; memcpy(color_table, image->data + index, sizeof(bmp_color_table_t) * hdr->dib.number_of_colors); #if BMP_UTILS_DEBUG { int i; printf("Color Table:nindex:tbluetgreentredn"); for (i = 0; i < hdr->dib.number_of_colors; i++){ printf("%d:t0x%02xt0x%02xt0x%02xn", i, color_table[i].blue, color_table[i].green, color_table[i].red); } } #endif return 0; } /****************************************************************************/ /* <span style="font-family: Arial, Helvetica, sans-serif;">读取图像(像素值)</span><span style="font-family: Arial, Helvetica, sans-serif;"> */</span> /****************************************************************************/ int bmp_read_image (raw_image_data_t * image, bmp_header_t * hdr, uint8_t * pixel_array_rgb) { int i; int index; int pixel_size = hdr->dib.bits_per_pixel / 8;//一个像素字节数 int row_width = hdr->dib.image_width * pixel_size;//一行字节数 int row_width_with_pad = ((row_width) + 3) & (~3);//这里不懂?一下跳四个字节?应该是对齐? for(i = 0; i < hdr->dib.image_height; i++) { /*index从原始图像数据最后一行开始,与bmp结构有关,自己查*/ index = hdr->file.bitmap_offset + (row_width_with_pad * (hdr->dib.image_height - i - 1)); /*读取row_width个字节,将原始图像数据最后一行当做真实图像pixel_array_rgb像素值的第一行*/ memcpy(pixel_array_rgb + (i * row_width), image->data + index, row_width); } return 0; } /****************************************************************************/ /* 存储灰度图像到文件中 */ /****************************************************************************/ int bmp_write_gray_bmpfile (raw_image_data_t * image, uint8_t * pixel_array, uint32_t width, uint32_t height) { int i; int index = 0; int row_width_with_pad = (width + 3) & (~3); int pad_size = row_width_with_pad - width; bmp_color_table_t * color_table = 0; uint8_t * pad_array = 0; bmp_header_t hdr = default_grayscale_bmp_header; int ret_val = 0; if(pad_size) { pad_array = calloc(pad_size, 1); } hdr.dib.image_height = height; hdr.dib.image_width = width; hdr.dib.image_size = (row_width_with_pad * hdr.dib.image_height); color_table = calloc(sizeof(bmp_color_table_t), hdr.dib.number_of_colors); for(i = 0; i < hdr.dib.number_of_colors; i++) { color_table[i].blue = i; color_table[i].green = i; color_table[i].red = i; } hdr.file.file_size = sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t) + hdr.dib.header_size + (sizeof(bmp_color_table_t) * hdr.dib.number_of_colors) + (row_width_with_pad * hdr.dib.image_height); hdr.file.bitmap_offset = sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t) + hdr.dib.header_size + (sizeof(bmp_color_table_t) * hdr.dib.number_of_colors); if (image->length < hdr.file.file_size) { printf("Insufficient image array size %d (expected %d)", image->length, hdr.file.file_size); ret_val = -1; goto close_n_exit; } memcpy(image->data, &hdr.signature, sizeof(bmpfile_signature_t)); index = sizeof(bmpfile_signature_t); memcpy(image->data + index, &hdr.file, sizeof(bmpfile_header_t)); index += sizeof(bmpfile_header_t); memcpy(image->data + index, &hdr.dib, sizeof(bmpfile_dib_header_t)); index += sizeof(bmpfile_dib_header_t); memcpy(image->data + index, color_table, sizeof(bmp_color_table_t) * hdr.dib.number_of_colors); index += sizeof(bmp_color_table_t) * hdr.dib.number_of_colors; for(i = hdr.dib.image_height - 1; i >= 0; i--) { memcpy(image->data + index, pixel_array + (hdr.dib.image_width * i), hdr.dib.image_width); index += hdr.dib.image_width; if (pad_size) { memcpy(image->data + index, pad_array, pad_size); index += pad_size; } } ret_val = 0; close_n_exit: if(color_table) free(color_table); if(pad_array) free(pad_array); return ret_val; } /****************************************************************************/ /* 获取灰度图像文件的文件大小 */ /****************************************************************************/ uint32_t bmp_get_gray_bmpfile_size (uint32_t width, uint32_t height) { int row_width_with_pad = (width + 3) & (~3); /*默认bmp文件头,修改一些信息,返回真实图像文件大小*/ bmp_header_t hdr = default_grayscale_bmp_header; return(sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t) + hdr.dib.header_size + (sizeof(bmp_color_table_t) * hdr.dib.number_of_colors) + (row_width_with_pad * height)); }
需要源代码的朋友,可以留言。谢谢支持。
最后
以上就是踏实大侠最近收集整理的关于TI DSP TMS320C66x学习笔记之TI官方读BMP程序(一)的全部内容,更多相关TI内容请搜索靠谱客的其他文章。
发表评论 取消回复