unity_support.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /**
  2. * @file lv_test_assert.c
  3. *
  4. * Copyright 2002-2010 Guillaume Cottenceau.
  5. *
  6. * This software may be freely redistributed under the terms
  7. * of the X11 license.
  8. *
  9. */
  10. /*********************
  11. * INCLUDES
  12. *********************/
  13. #if LV_BUILD_TEST
  14. #include "../lvgl.h"
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdarg.h>
  20. #include "unity.h"
  21. #define PNG_DEBUG 3
  22. #include <png.h>
  23. /*********************
  24. * DEFINES
  25. *********************/
  26. //#define REF_IMGS_PATH "lvgl/tests/lv_test_ref_imgs/"
  27. #define REF_IMGS_PATH "ref_imgs/"
  28. #define ERR_FILE_NOT_FOUND -1
  29. #define ERR_PNG -2
  30. /**********************
  31. * TYPEDEFS
  32. **********************/
  33. typedef struct {
  34. int width, height;
  35. png_byte color_type;
  36. png_byte bit_depth;
  37. png_structp png_ptr;
  38. png_infop info_ptr;
  39. int number_of_passes;
  40. png_bytep * row_pointers;
  41. } png_img_t;
  42. /**********************
  43. * STATIC PROTOTYPES
  44. **********************/
  45. static int read_png_file(png_img_t * p, const char * file_name);
  46. static int write_png_file(void * raw_img, uint32_t width, uint32_t height, char * file_name);
  47. static void png_release(png_img_t * p);
  48. /**********************
  49. * STATIC VARIABLES
  50. **********************/
  51. /**********************
  52. * MACROS
  53. **********************/
  54. /**********************
  55. * GLOBAL FUNCTIONS
  56. **********************/
  57. bool lv_test_assert_img_eq(const char * fn_ref)
  58. {
  59. char fn_ref_full[512];
  60. sprintf(fn_ref_full, "%s%s", REF_IMGS_PATH, fn_ref);
  61. uint8_t * screen_buf;
  62. lv_obj_invalidate(lv_scr_act());
  63. lv_refr_now(NULL);
  64. extern lv_color32_t test_fb[];
  65. screen_buf = (uint8_t *)test_fb;
  66. png_img_t p;
  67. int res = read_png_file(&p, fn_ref_full);
  68. if(res == ERR_FILE_NOT_FOUND) {
  69. TEST_PRINTF("%s%s", fn_ref_full, " was not found, creating is now from the rendered screen");
  70. fflush(stderr);
  71. write_png_file(screen_buf, 800, 480, fn_ref_full);
  72. return true;
  73. }
  74. else if(res == ERR_PNG) {
  75. return false;
  76. }
  77. uint8_t * ptr_act = NULL;
  78. const png_byte * ptr_ref = NULL;
  79. bool err = false;
  80. int x, y, i_buf = 0;
  81. for(y = 0; y < p.height; y++) {
  82. png_byte * row = p.row_pointers[y];
  83. for(x = 0; x < p.width; x++) {
  84. ptr_ref = &(row[x * 3]);
  85. ptr_act = &(screen_buf[i_buf * 4]);
  86. uint32_t ref_px = 0;
  87. uint32_t act_px = 0;
  88. memcpy(&ref_px, ptr_ref, 3);
  89. memcpy(&act_px, ptr_act, 3);
  90. //printf("0xFF%06x, ", act_px);
  91. uint8_t act_swap[3] = {ptr_act[2], ptr_act[1], ptr_act[0]};
  92. if(memcmp(act_swap, ptr_ref, 3) != 0) {
  93. err = true;
  94. break;
  95. }
  96. i_buf++;
  97. }
  98. if(err) break;
  99. }
  100. if(err) {
  101. char fn_ref_no_ext[64];
  102. strcpy(fn_ref_no_ext, fn_ref);
  103. fn_ref_no_ext[strlen(fn_ref_no_ext) - 4] = '\0';
  104. char fn_err_full[512];
  105. sprintf(fn_err_full, "%s%s_err.png", REF_IMGS_PATH, fn_ref_no_ext);
  106. write_png_file(screen_buf, 800, 480, fn_err_full);
  107. }
  108. png_release(&p);
  109. return !err;
  110. }
  111. /**********************
  112. * STATIC FUNCTIONS
  113. **********************/
  114. static int read_png_file(png_img_t * p, const char * file_name)
  115. {
  116. char header[8]; // 8 is the maximum size that can be checked
  117. /*open file and test for it being a png*/
  118. FILE * fp = fopen(file_name, "rb");
  119. if(!fp) {
  120. TEST_PRINTF("[read_png_file %s] could not be opened for reading", file_name);
  121. return ERR_FILE_NOT_FOUND;
  122. }
  123. size_t rcnt = fread(header, 1, 8, fp);
  124. if(rcnt != 8 || png_sig_cmp((png_const_bytep)header, 0, 8)) {
  125. TEST_PRINTF("[read_png_file %s] not recognized as a PNG file", file_name);
  126. return ERR_PNG;
  127. }
  128. /*initialize stuff*/
  129. p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  130. if(!p->png_ptr) {
  131. TEST_PRINTF("[read_png_file %s] png_create_read_struct failed", file_name);
  132. return ERR_PNG;
  133. }
  134. p->info_ptr = png_create_info_struct(p->png_ptr);
  135. if(!p->info_ptr) {
  136. TEST_PRINTF("[read_png_file %s] png_create_info_struct failed", file_name);
  137. return ERR_PNG;
  138. }
  139. if(setjmp(png_jmpbuf(p->png_ptr))) {
  140. TEST_PRINTF("[read_png_file %s] Error during init_io", file_name);
  141. return ERR_PNG;
  142. }
  143. png_init_io(p->png_ptr, fp);
  144. png_set_sig_bytes(p->png_ptr, 8);
  145. png_read_info(p->png_ptr, p->info_ptr);
  146. p->width = png_get_image_width(p->png_ptr, p->info_ptr);
  147. p->height = png_get_image_height(p->png_ptr, p->info_ptr);
  148. p->color_type = png_get_color_type(p->png_ptr, p->info_ptr);
  149. p->bit_depth = png_get_bit_depth(p->png_ptr, p->info_ptr);
  150. p->number_of_passes = png_set_interlace_handling(p->png_ptr);
  151. png_read_update_info(p->png_ptr, p->info_ptr);
  152. /*read file*/
  153. if(setjmp(png_jmpbuf(p->png_ptr))) {
  154. TEST_PRINTF("[read_png_file %s] Error during read_image", file_name);
  155. return ERR_PNG;
  156. }
  157. p->row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * p->height);
  158. int y;
  159. for(y = 0; y < p->height; y++)
  160. p->row_pointers[y] = (png_byte *) malloc(png_get_rowbytes(p->png_ptr, p->info_ptr));
  161. png_read_image(p->png_ptr, p->row_pointers);
  162. fclose(fp);
  163. return 0;
  164. }
  165. static int write_png_file(void * raw_img, uint32_t width, uint32_t height, char * file_name)
  166. {
  167. png_structp png_ptr;
  168. png_infop info_ptr;
  169. /* create file */
  170. FILE * fp = fopen(file_name, "wb");
  171. if(!fp) {
  172. printf("###### %s\n", file_name);
  173. fflush(stdout);
  174. TEST_PRINTF("[write_png_file %s] could not be opened for writing", file_name);
  175. TEST_PRINTF("%s", file_name);
  176. return -1;
  177. }
  178. /* initialize stuff */
  179. png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  180. if(!png_ptr) {
  181. TEST_PRINTF("[write_png_file %s] png_create_write_struct failed", file_name);
  182. return -1;
  183. }
  184. info_ptr = png_create_info_struct(png_ptr);
  185. if(!info_ptr) {
  186. TEST_PRINTF("[write_png_file %s] png_create_info_struct failed", file_name);
  187. return -1;
  188. }
  189. if(setjmp(png_jmpbuf(png_ptr))) {
  190. TEST_PRINTF("[write_png_file %s] Error during init_io", file_name);
  191. return -1;
  192. }
  193. png_init_io(png_ptr, fp);
  194. /* write header */
  195. if(setjmp(png_jmpbuf(png_ptr))) {
  196. TEST_PRINTF("[write_png_file %s] Error during writing header", file_name);
  197. return -1;
  198. }
  199. png_set_IHDR(png_ptr, info_ptr, width, height,
  200. 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
  201. PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  202. png_write_info(png_ptr, info_ptr);
  203. /* write bytes */
  204. if(setjmp(png_jmpbuf(png_ptr))) {
  205. TEST_PRINTF("[write_png_file %s] Error during writing bytes", file_name);
  206. return -1;
  207. }
  208. uint8_t * raw_img8 = (uint8_t *)raw_img;
  209. png_bytep * row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * height);
  210. for(uint32_t y = 0; y < height; y++) {
  211. row_pointers[y] = malloc(3 * width);
  212. uint8_t * line = raw_img8 + y * width * 4;
  213. for(uint32_t x = 0; x < width; x++) {
  214. row_pointers[y][x * 3 + 0] = line[x * 4 + 2];
  215. row_pointers[y][x * 3 + 1] = line[x * 4 + 1];
  216. row_pointers[y][x * 3 + 2] = line[x * 4 + 0];
  217. }
  218. }
  219. png_write_image(png_ptr, row_pointers);
  220. /* end write */
  221. if(setjmp(png_jmpbuf(png_ptr))) {
  222. TEST_PRINTF("[write_png_file %s] Error during end of write", file_name);
  223. return -1;
  224. }
  225. png_write_end(png_ptr, NULL);
  226. /* cleanup heap allocation */
  227. for(uint32_t y = 0; y < height; y++) free(row_pointers[y]);
  228. free(row_pointers);
  229. png_destroy_write_struct(&png_ptr, &info_ptr);
  230. fclose(fp);
  231. return 0;
  232. }
  233. static void png_release(png_img_t * p)
  234. {
  235. int y;
  236. for(y = 0; y < p->height; y++) free(p->row_pointers[y]);
  237. free(p->row_pointers);
  238. png_destroy_read_struct(&p->png_ptr, &p->info_ptr, NULL);
  239. }
  240. #endif