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