2198|0

7

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

TI DSP TMS320C66x学习笔记之TI官方读BMP程序(一) [复制链接]

一直想认真写一下关于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:\ti\mcsdk_2_01_02_06\demos\image_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. #ifndef BMP_UTILS_H
  2. #define BMP_UTILS_H
  3. #include <stdint.h>
  4. #include <xdc/runtime/Memory.h>
  5. #include <xdc/runtime/Error.h>
  6. /****************************************************************************/
  7. /* 位图文件头结构体 */
  8. /****************************************************************************/
  9. #ifdef _HOST_BUILD
  10. #pragma pack(1)
  11. #endif
  12. typedef struct bmpfile_signature {
  13. uint8_t signature[2]; /* Signature - 'BM' */
  14. } bmpfile_signature_t;
  15. typedef struct bmpfile_header {
  16. uint32_t file_size; /* BMP图像文件的大小 */
  17. uint16_t reserved1;
  18. uint16_t reserved2;
  19. uint32_t bitmap_offset; /* BMP图像数据的偏移地址 */
  20. } bmpfile_header_t;
  21. typedef struct bmpfile_dib_header {
  22. uint32_t header_size; /* 本结构的大小 */
  23. int32_t image_width; /* 位图的宽度 */
  24. int32_t image_height; /* 位图的高度 */
  25. uint16_t number_of_planes; /* Number of planes */
  26. uint16_t bits_per_pixel; /* 每个像素的位数 */
  27. uint32_t compression_type;/* 压缩类型 */
  28. uint32_t image_size; /* 表示位图数据区域的大小以字节为单位 */
  29. int32_t horizontal_resolution; /* 水平分辨率,单位像素/m */
  30. int32_t vertical_resolution; /* 垂直分辨率,单位像素/m */
  31. uint32_t number_of_colors; /* BMP图像使用的颜色,0表示使用全部颜色,对于256色位图来说,此值为100h=256 */
  32. uint32_t important_color_count; /* Important color count */
  33. } bmpfile_dib_header_t;
  34. typedef struct bmp_header {
  35. bmpfile_signature_t signature;
  36. bmpfile_header_t file;
  37. bmpfile_dib_header_t dib;
  38. } bmp_header_t;
  39. /****************************************************************************/
  40. /* 位图RGB调色板入口结构体 */
  41. /****************************************************************************/
  42. typedef struct {
  43. uint8_t red;
  44. uint8_t green;
  45. uint8_t blue;
  46. uint8_t reserved;
  47. } bmp_color_table_t;
  48. typedef enum {
  49. BMP_RGB = 0,
  50. BMP_RLE8,
  51. BMP_RLE4,
  52. BMP_BITFIELDS,
  53. BMP_JPEG,
  54. BMP_PNG
  55. } bmp_compression_method_e;
  56. /* 原始图像数据,需要解码
  57. */
  58. typedef struct raw_image_data {
  59. uint8_t * data;
  60. uint32_t length;
  61. } raw_image_data_t;
复制代码

接下来是函数外部声明

  1. /*****************************************************************************/
  2. /**
  3. * Created on: 2015-11-9
  4. * Author: HeWu
  5. * 这个函数用于从文件系统中读取文件的元素数据,
  6. * 参数说明:const char *_fname文件名
  7. * const char *_mode读写模式
  8. * 返回类型:raw_image_data_t(整个原始文件的字节数据,以及字节长度)
  9. * */
  10. /*****************************************************************************/
  11. extern raw_image_data_t get_raw_image_data_from_file(const char *_fname, const char *_mode);
  12. /*****************************************************************************/
  13. /**
  14. * Created on: 2015-11-9
  15. * Author: HeWu
  16. * 这个函数用于从raw data转换到bmp结构体,
  17. * 参数说明:raw_image_data_t * p_input_image图像原始字节数据
  18. * unsigned char * p_output_pixel_array图像的像素信息,用于后续处理
  19. * 返回:raw_image_data_t结构体
  20. * */
  21. /*****************************************************************************/
  22. extern int raw_data_cvt_bmp_pixels(raw_image_data_t * p_input_image,unsigned char * p_output_pixel_array);
  23. /*****************************************************************************/
  24. /* *
  25. * 函数功能:这个函数BMP文件中读取文件头信息。
  26. * 说明:函数对文件做了一些初步的检查。
  27. * 如果读取文件成功返回0;
  28. * 如果读取文件失败或检查失败,返回负数。
  29. */
  30. /*****************************************************************************/
  31. extern int bmp_read_header (raw_image_data_t * image, bmp_header_t * hdr);
  32. /*****************************************************************************/
  33. /* *
  34. * 函数说明:读取调色板。这个函数用的比较少,调色板是单色、16色和256色图像文件特有。
  35. *
  36. */
  37. /*****************************************************************************/
  38. extern int bmp_read_colormap (raw_image_data_t * image, bmp_header_t * hdr,
  39. bmp_color_table_t * color_table);
  40. /*****************************************************************************/
  41. /* *
  42. * 函数功能:读取图像(像素值),需要计算像素占用字节数。
  43. * 参数说明:raw_image_data_t * image,待解码数据
  44. * bmp_header_t * hdr, 文件头
  45. * uint8_t * pixel_array_rgb,用于返回的像素值指针,后续图像算法就是对它进行了
  46. */
  47. extern int bmp_read_image (raw_image_data_t * image, bmp_header_t * hdr, uint8_t * pixel_array_rgb);
  48. /*****************************************************************************/
  49. /* *
  50. * 函数功能:通过BMP图像,创建并将像素值保存为灰度图像。
  51. * 参数说明:raw_image_data_t * image,保存结果
  52. * uint8_t * pixel_array,像素值指针
  53. */
  54. /*****************************************************************************/
  55. extern int bmp_write_gray_bmpfile (raw_image_data_t * image, uint8_t * pixel_array,
  56. uint32_t width, uint32_t height);
  57. /*****************************************************************************/
  58. /*
  59. * 函数功能:获取灰度BMP图的文件大小
  60. */
  61. /*****************************************************************************/
  62. extern uint32_t bmp_get_gray_bmpfile_size (uint32_t width, uint32_t height);
  63. #endif /*BMP_UTILS_H*/
复制代码

对一下两个函数稍作解释,

  1. extern raw_image_data_t get_raw_image_data_from_file(const char *_fname, const char *_mode);
复制代码
  1. extern int raw_data_cvt_bmp_pixels(raw_image_data_t * p_input_image,unsigned char * p_output_pixel_array);
复制代码

这两个函数本身不应该放在这个读bmp模块中,这是直接写来,第一个是从文件系统中获取原始图像数据(也可以从其他途径获取),第二个是将原始图像解码成像素数组(读取BMP图像的完整先bmp_read_header()函数和后bmp_read_image()函数)。

下面是mcip_bmp_utils.c函数的实现文件。

  1. /* ======================================================================== */
  2. /* TEXAS INSTRUMENTS, INC. */
  3. /* */
  4. /* ======================================================================== */
  5. #include
  6. #include
  7. #include
  8. #include "mcip_bmp_utils.h"
  9. /*#define BMP_UTILS_DEBUG*/
  10. /* BMP灰度图像默认文件头*/
  11. static bmp_header_t default_grayscale_bmp_header = {
  12. {
  13. {'B', 'M'} /*signature*/
  14. },
  15. {
  16. 263222, /*file_size*/
  17. 0, 0, /*reserved1, reserved2*/
  18. 1078 /*bitmap_offset*/
  19. },
  20. {
  21. 40, /*header_size*/
  22. 512, /*width*/
  23. 512, /*height*/
  24. 1, /*nplanes*/
  25. 8, /*bitspp*/
  26. 0, /*compress_type*/
  27. 262144, /*bmp_bytesz*/
  28. 0, /*hres*/
  29. 0, /*vres*/
  30. 256, /*ncolors*/
  31. 0 /*nimpcolors*/
  32. }
  33. };
  34. /*****************************************************************************/
  35. /**
  36. * Created on: 2015-11-9
  37. * Author: HeWu
  38. * 这个函数用于从文件系统中读取文件的元素数据,
  39. * 返回类型包括整个文件的字节数据,以及字节长度
  40. * */
  41. /*****************************************************************************/
  42. raw_image_data_t get_raw_image_data_from_file(const char *_fname, const char *_mode)
  43. {
  44. Error_Block eb;
  45. Error_init(&eb);
  46. FILE * fpr = 0;
  47. raw_image_data_t raw_image = {0, 0};
  48. uint32_t read_length = 0;
  49. int ret_val = 0;
  50. fpr = fopen(_fname, _mode);
  51. if(!fpr) {
  52. printf("Unable to open image file %s\n", _fname);
  53. }
  54. fseek(fpr, 0, SEEK_END);
  55. raw_image.length = ftell(fpr);
  56. fseek(fpr, 0, SEEK_SET);
  57. /**
  58. * 之所以用这个Memory_alloc(),而不用malloc(),
  59. * 是为了放置内存碎片化,还是用TI提供的函数咯
  60. * */
  61. raw_image.data = (uint8_t*)Memory_alloc(NULL,raw_image.length,0,&eb);
  62. if(!raw_image.data) {
  63. printf("Unable allocate buffer for raw image file read (%s)\n", _fname);
  64. }
  65. //fread()返回的是已读取的字节数,ret_val用于指针移动和检查
  66. do {
  67. ret_val = fread(raw_image.data + read_length, 1, raw_image.length - read_length, fpr);
  68. if (!ret_val) {
  69. printf("Unable read the raw image file %s\n", _fname);
  70. }
  71. read_length += ret_val;
  72. } while (read_length < raw_image.length);
  73. return raw_image;//返回原始图像数据
  74. }
  75. /*****************************************************************************/
  76. /**
  77. * Created on: 2015-11-9
  78. * Author: HeWu
  79. * 这个函数用于从raw data转换到bmp结构体,
  80. * 返回类型包括像素数据指针
  81. * */
  82. /*****************************************************************************/
  83. extern int raw_data_cvt_bmp_pixels(raw_image_data_t * p_input_image,unsigned char * p_output_pixel_array)
  84. {
  85. Error_Block eb;
  86. Error_init(&eb);
  87. bmp_color_table_t * p_color_table = 0;
  88. bmp_header_t bmp_header;
  89. uint8_t * pixel_array_rgb = 0;
  90. int color_table_size,pixel_array_rgb_size;
  91. int pixel_size, row_width;
  92. int i, j, ret_val = 0;
  93. if ((p_input_image == 0) || (p_input_image->length == 0) || (p_input_image->data == 0)) {
  94. printf("Invalid BMP image data\n");
  95. ret_val = -1;
  96. return ret_val;
  97. }
  98. if (bmp_read_header(p_input_image, &bmp_header) < 0) {
  99. printf("Error in reading header\n");
  100. ret_val = -1;
  101. return ret_val;
  102. }
  103. pixel_size = bmp_header.dib.bits_per_pixel / 8;//一个像素的字节数
  104. row_width = bmp_header.dib.image_width * pixel_size;//一行的字节数
  105. /*读调色板,现在很多bmp图像都没有调色板,可以忽略这一部分*/
  106. if (bmp_header.dib.number_of_colors) {
  107. /* Color table present */
  108. color_table_size = sizeof(bmp_color_table_t) * bmp_header.dib.number_of_colors;
  109. p_color_table = (bmp_color_table_t *)Memory_alloc(NULL,color_table_size,0,&eb);
  110. if(!p_color_table) {
  111. printf("Can't allocate memory for color table\n");
  112. ret_val = -1;
  113. return ret_val;
  114. }
  115. if (bmp_read_colormap(p_input_image, &bmp_header, p_color_table) < 0) {
  116. printf("Error in reading color map\n");
  117. ret_val = -1;
  118. return ret_val;
  119. }
  120. }
  121. /* 读像素数据 ,直接由第二个参数传入指针,不用在此分配内存*/
  122. if (bmp_read_image (p_input_image, &bmp_header, p_output_pixel_array) < 0) {
  123. printf("Error in reading pixel image\n");
  124. ret_val = -1;
  125. return ret_val;
  126. }
  127. }
  128. /****************************************************************************/
  129. /* 读BMP信息头 */
  130. /****************************************************************************/
  131. int bmp_read_header (raw_image_data_t * image, bmp_header_t * hdr)
  132. {
  133. /*如果文件头结构体大于原始图像数据大小,则是无效图像*/
  134. if (image->length <
  135. sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t) + sizeof(bmpfile_dib_header_t)) {
  136. printf ("Insufficient Image Buffer Length %d\n", image->length);
  137. return -1;
  138. }
  139. /*将原始图像数据解码到三个BMP文件头结构体*/
  140. memcpy(&(hdr->signature), image->data, sizeof(bmpfile_signature_t));
  141. memcpy(&(hdr->file), image->data + sizeof(bmpfile_signature_t),
  142. sizeof(bmpfile_header_t));
  143. memcpy(&(hdr->dib), image->data + sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t),
  144. sizeof(bmpfile_dib_header_t));
  145. /*做一些检查,自己看英文咯*/
  146. if((hdr->signature.signature[0] != 'B') || (hdr->signature.signature[1] != 'M')) {
  147. printf("Incorrect MAGIC number 0x%x 0x%x\n", hdr->signature.signature[0], hdr->signature.signature[1]);
  148. return -1;
  149. }
  150. if((hdr->dib.bits_per_pixel != 8) && (hdr->dib.bits_per_pixel != 24)) {
  151. printf("Only 8 or 24 bits per pixel supported, the image bpp is %d\n", hdr->dib.bits_per_pixel);
  152. return -1;
  153. }
  154. if(hdr->dib.compression_type != BMP_RGB) {
  155. printf("Need a RGB type image, the image type is %d\n", hdr->dib.compression_type);
  156. return -1;
  157. }
  158. return 0;
  159. }
  160. /****************************************************************************/
  161. /* 读BMP调色板 */
  162. /****************************************************************************/
  163. int bmp_read_colormap (raw_image_data_t * image, bmp_header_t * hdr,
  164. bmp_color_table_t * color_table)
  165. {
  166. int index;
  167. if(hdr->dib.number_of_colors == 0) {
  168. printf("Color table can't be read, ncolors = %d\n", hdr->dib.number_of_colors);
  169. return -1;
  170. }
  171. index = sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t) + hdr->dib.header_size;
  172. memcpy(color_table, image->data + index, sizeof(bmp_color_table_t) * hdr->dib.number_of_colors);
  173. #if BMP_UTILS_DEBUG
  174. {
  175. int i;
  176. printf("Color Table:\nindex:\tblue\tgreen\tred\n");
  177. for (i = 0; i < hdr->dib.number_of_colors; i++){
  178. printf("%d:\t0x%02x\t0x%02x\t0x%02x\n",
  179. i, color_table[i].blue, color_table[i].green, color_table[i].red);
  180. }
  181. }
  182. #endif
  183. return 0;
  184. }
  185. /****************************************************************************/
  186. /* 读取图像(像素值) */
  187. /****************************************************************************/
  188. int bmp_read_image (raw_image_data_t * image, bmp_header_t * hdr, uint8_t * pixel_array_rgb)
  189. {
  190. int i;
  191. int index;
  192. int pixel_size = hdr->dib.bits_per_pixel / 8;//一个像素字节数
  193. int row_width = hdr->dib.image_width * pixel_size;//一行字节数
  194. int row_width_with_pad = ((row_width) + 3) & (~3);//这里不懂?一下跳四个字节?应该是对齐?
  195. for(i = 0; i < hdr->dib.image_height; i++) {
  196. /*index从原始图像数据最后一行开始,与bmp结构有关,自己查*/
  197. index = hdr->file.bitmap_offset + (row_width_with_pad * (hdr->dib.image_height - i - 1));
  198. /*读取row_width个字节,将原始图像数据最后一行当做真实图像pixel_array_rgb像素值的第一行*/
  199. memcpy(pixel_array_rgb + (i * row_width), image->data + index, row_width);
  200. }
  201. return 0;
  202. }
  203. /****************************************************************************/
  204. /* 存储灰度图像到文件中 */
  205. /****************************************************************************/
  206. int bmp_write_gray_bmpfile (raw_image_data_t * image, uint8_t * pixel_array,
  207. uint32_t width, uint32_t height)
  208. {
  209. int i;
  210. int index = 0;
  211. int row_width_with_pad = (width + 3) & (~3);
  212. int pad_size = row_width_with_pad - width;
  213. bmp_color_table_t * color_table = 0;
  214. uint8_t * pad_array = 0;
  215. bmp_header_t hdr = default_grayscale_bmp_header;
  216. int ret_val = 0;
  217. if(pad_size) {
  218. pad_array = calloc(pad_size, 1);
  219. }
  220. hdr.dib.image_height = height;
  221. hdr.dib.image_width = width;
  222. hdr.dib.image_size = (row_width_with_pad * hdr.dib.image_height);
  223. color_table = calloc(sizeof(bmp_color_table_t), hdr.dib.number_of_colors);
  224. for(i = 0; i < hdr.dib.number_of_colors; i++) {
  225. color_table[i].blue = i;
  226. color_table[i].green = i;
  227. color_table[i].red = i;
  228. }
  229. hdr.file.file_size =
  230. sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t)
  231. + hdr.dib.header_size
  232. + (sizeof(bmp_color_table_t) * hdr.dib.number_of_colors)
  233. + (row_width_with_pad * hdr.dib.image_height);
  234. hdr.file.bitmap_offset =
  235. sizeof(bmpfile_signature_t)
  236. + sizeof(bmpfile_header_t) + hdr.dib.header_size
  237. + (sizeof(bmp_color_table_t) * hdr.dib.number_of_colors);
  238. if (image->length < hdr.file.file_size) {
  239. printf("Insufficient image array size %d (expected %d)",
  240. image->length, hdr.file.file_size);
  241. ret_val = -1;
  242. goto close_n_exit;
  243. }
  244. memcpy(image->data, &hdr.signature, sizeof(bmpfile_signature_t));
  245. index = sizeof(bmpfile_signature_t);
  246. memcpy(image->data + index, &hdr.file, sizeof(bmpfile_header_t));
  247. index += sizeof(bmpfile_header_t);
  248. memcpy(image->data + index, &hdr.dib, sizeof(bmpfile_dib_header_t));
  249. index += sizeof(bmpfile_dib_header_t);
  250. memcpy(image->data + index, color_table, sizeof(bmp_color_table_t) * hdr.dib.number_of_colors);
  251. index += sizeof(bmp_color_table_t) * hdr.dib.number_of_colors;
  252. for(i = hdr.dib.image_height - 1; i >= 0; i--) {
  253. memcpy(image->data + index, pixel_array + (hdr.dib.image_width * i), hdr.dib.image_width);
  254. index += hdr.dib.image_width;
  255. if (pad_size) {
  256. memcpy(image->data + index, pad_array, pad_size);
  257. index += pad_size;
  258. }
  259. }
  260. ret_val = 0;
  261. close_n_exit:
  262. if(color_table) free(color_table);
  263. if(pad_array) free(pad_array);
  264. return ret_val;
  265. }
  266. /****************************************************************************/
  267. /* 获取灰度图像文件的文件大小 */
  268. /****************************************************************************/
  269. uint32_t bmp_get_gray_bmpfile_size (uint32_t width, uint32_t height)
  270. {
  271. int row_width_with_pad = (width + 3) & (~3);
  272. /*默认bmp文件头,修改一些信息,返回真实图像文件大小*/
  273. bmp_header_t hdr = default_grayscale_bmp_header;
  274. return(sizeof(bmpfile_signature_t) + sizeof(bmpfile_header_t)
  275. + hdr.dib.header_size
  276. + (sizeof(bmp_color_table_t) * hdr.dib.number_of_colors)
  277. + (row_width_with_pad * height));
  278. }
复制代码
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表