Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8585 | rgimad | 1 | /* Copyright (C) 2021- Rustem Gimadutdinov (rgimad), GPLv2 */ |
2 | #include |
||
3 | #include |
||
4 | #include |
||
5 | #include |
||
6 | #include |
||
7 | |||
8 | #include "kolibri_gui.h" |
||
9 | #include "kolibri_opendialog.h" |
||
10 | #include "kolibri_libimg.h" |
||
11 | |||
12 | #include "quirc.h" |
||
13 | |||
14 | /* ------------------------------------------------------- */ |
||
15 | |||
16 | #define X_W(X, W) ((X<<16)+W) |
||
17 | #define Y_H X_W |
||
18 | |||
19 | #define WINDOW_WIDTH 650 |
||
20 | #define WINDOW_HEIGHT 320 |
||
21 | |||
22 | #define WINDOW_ROW1_Y 34 |
||
23 | #define WINDOW_COL2_X 280 |
||
24 | |||
25 | #define TEDIT1_MAXCHAR 2048 |
||
26 | #define TEDIT1_W 340 |
||
27 | #define TEDIT1_H 150 |
||
28 | |||
29 | #define IMG1_DISPLAY_W 256 |
||
30 | #define IMG1_DISPLAY_H 256 |
||
31 | |||
32 | const char WINDOW_TITLE[] = "QR Tool 0.2b"; |
||
33 | |||
34 | kolibri_system_colors sys_color_table; |
||
35 | const color_t DRAWTEXT_FLAG_DEFAULT = 0x90000000; |
||
36 | |||
37 | enum MYCOLORS { |
||
38 | COL_GREEN = 0x067D06, |
||
39 | COL_BLUE = 0x0000FF, |
||
40 | COL_RED = 0xFF0000, |
||
41 | COL_BLACK = 0x000000, |
||
42 | COL_WHITE = 0xFFFFFF, |
||
43 | COL_GREY = 0x919191 |
||
44 | }; |
||
45 | |||
46 | enum MYBUTTONS { |
||
47 | MYBTN_QUIT = 1, |
||
48 | MYBTN_OPEN = 10/*, |
||
49 | MYBTN_CLEAR = 20*/ |
||
50 | // |
||
51 | }; |
||
52 | |||
53 | editor *tedit1; |
||
54 | void *tedit1_lock; |
||
55 | |||
56 | open_dialog *op_dialog1; |
||
57 | |||
58 | Image *img1 = NULL; |
||
59 | Image *img1_grayscale = NULL; |
||
60 | char *img1_path; |
||
61 | |||
62 | char cur_dir_path[256]; |
||
63 | |||
64 | |||
65 | char* load_img(char* fname, uint32_t* read_sz) { |
||
66 | FILE *f = fopen(fname, "rb"); |
||
67 | if (!f) { |
||
68 | printf("Can't open file: %s\n", fname); |
||
69 | exit(0); |
||
70 | } |
||
71 | if (fseek(f, 0, SEEK_END)) { |
||
72 | printf("Can't SEEK_END file: %s\n", fname); |
||
73 | exit(0); |
||
74 | } |
||
75 | int filesize = ftell(f); |
||
76 | rewind(f); |
||
77 | char* fdata = malloc(filesize); |
||
78 | if(!fdata) { |
||
79 | printf("No memory for file %s\n", fname); |
||
80 | exit(0); |
||
81 | } |
||
82 | *read_sz = fread(fdata, 1, filesize, f); |
||
83 | if (ferror(f)) { |
||
84 | printf("Error reading file %s\n", fname); |
||
85 | exit(0); |
||
86 | } |
||
87 | fclose(f); |
||
88 | return fdata; |
||
89 | } |
||
90 | |||
91 | /* mode: 0 - ASCII, 1 - SCAN*/ |
||
92 | void set_os_keyb_mode(int mode) { __asm__ __volatile__("int $0x40"::"a"(66), "b"(1), "c"(mode)); } |
||
93 | |||
94 | void redraw_window() { |
||
95 | pos_t win_pos = get_mouse_pos(0); |
||
96 | begin_draw(); |
||
97 | sys_create_window(win_pos.x, win_pos.y, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, sys_color_table.color_work_area, 0x14); |
||
98 | |||
99 | //draw_text_sys("", /*x*/, /*y*/, 0, DRAWTEXT_FLAG_DEFAULT | sys_color_table.work_text); |
||
100 | |||
101 | define_button(X_W(WINDOW_COL2_X,100), Y_H(WINDOW_ROW1_Y,30), MYBTN_OPEN, sys_color_table.color_work_button); |
||
102 | draw_text_sys("Open image", WINDOW_COL2_X + 12, WINDOW_ROW1_Y + 7, 0, DRAWTEXT_FLAG_DEFAULT | sys_color_table.color_work_button_text); |
||
103 | |||
104 | //define_button(X_W(WINDOW_COL2_X + 120,100), Y_H(WINDOW_ROW1_Y,30), MYBTN_CLEAR, sys_color_table.color_work_button); |
||
105 | |||
106 | draw_text_sys("Recognition results below.", WINDOW_COL2_X, WINDOW_ROW1_Y + 40, 0, DRAWTEXT_FLAG_DEFAULT | sys_color_table.color_work_text); |
||
107 | draw_text_sys("Selection & Ctrl+C available.", WINDOW_COL2_X, WINDOW_ROW1_Y + 60, 0, DRAWTEXT_FLAG_DEFAULT | sys_color_table.color_work_text); |
||
108 | |||
109 | ted_draw(tedit1); |
||
110 | |||
111 | if (img1 != NULL) { |
||
112 | //printf("drawing...\n"); |
||
113 | img_draw(img1, 10, WINDOW_ROW1_Y, IMG1_DISPLAY_W, IMG1_DISPLAY_H , 0, 0); |
||
114 | } else { |
||
115 | draw_bar(10, WINDOW_ROW1_Y, IMG1_DISPLAY_W, IMG1_DISPLAY_H, COL_GREY); |
||
116 | } |
||
117 | |||
118 | end_draw(); |
||
119 | } |
||
120 | |||
121 | void tedit1_print(const char *text, int text_len, int do_newline) { |
||
122 | if (text_len == -1) { text_len = strlen(text); } |
||
123 | ted_text_add(tedit1, (char *)text, text_len, 1); |
||
124 | if (do_newline != 0 ) { ted_text_add(tedit1, "\r", 1, 1); } |
||
125 | } |
||
126 | |||
127 | void create_components() { |
||
128 | tedit1 = kolibri_new_editor(X_W(WINDOW_COL2_X, TEDIT1_W), Y_H(WINDOW_ROW1_Y + IMG1_DISPLAY_H - TEDIT1_H - 16, TEDIT1_H), 0/*0x11*/, TEDIT1_MAXCHAR, &tedit1_lock); // 0x11 font 8x16 sized x2, 0 - default (8x16) |
||
129 | tedit1_lock = tedit1; |
||
130 | tedit1->mode_invis = 0; /* dont show invisible characters */ |
||
131 | |||
132 | op_dialog1 = kolibri_new_open_dialog(OPEN, 10, 10, 420, 320); |
||
133 | op_dialog1->dir_default_path = cur_dir_path; |
||
134 | op_dialog1->draw_window = redraw_window; |
||
135 | OpenDialog_init(op_dialog1); |
||
136 | } |
||
137 | |||
138 | void recognize_qr() { |
||
139 | puts("Starting QUIRC...\n"); |
||
140 | struct quirc *qr; |
||
141 | |||
142 | qr = quirc_new(); |
||
143 | if (!qr) { |
||
144 | puts("Failed to allocate memory"); |
||
145 | exit(-1); |
||
146 | } |
||
147 | |||
148 | if (quirc_resize(qr, img1_grayscale->Width, img1_grayscale->Height) < 0) { |
||
149 | puts("Failed to allocate video memory"); |
||
150 | exit(-1); |
||
151 | } |
||
152 | |||
153 | void *gsbuf = img1_grayscale->Data; |
||
154 | uint32_t gsbuf_size = img1_grayscale->Width*img1_grayscale->Height; |
||
155 | |||
156 | uint8_t *buffer; |
||
157 | int w, h; |
||
158 | puts("quirc_begin()...\n"); |
||
159 | buffer = quirc_begin(qr, &w, &h); |
||
160 | //printf("buffer = %x qr = %x\n", buffer, qr); |
||
161 | //printf("w = %d h = %d\n", w, h); |
||
162 | memcpy(buffer, gsbuf, gsbuf_size); |
||
163 | puts("quirc_end()...\n"); |
||
164 | quirc_end(qr); |
||
165 | |||
166 | ted_clear(tedit1, 1); /* cleaning output text area */ |
||
167 | |||
168 | int num_codes, i; |
||
169 | puts("quirc_count()...\n"); |
||
170 | num_codes = quirc_count(qr); |
||
171 | printf(" NUM_CODES = %d\n", num_codes); |
||
172 | if (num_codes == 0) { |
||
173 | tedit1_print("DECODE FAILED: NO CODES FOUND", -1, 1); |
||
174 | } |
||
175 | for (i = 0; i < num_codes; i++) { |
||
176 | struct quirc_code code; |
||
177 | struct quirc_data data; |
||
178 | quirc_decode_error_t err; |
||
179 | |||
180 | quirc_extract(qr, i, &code); |
||
181 | |||
182 | // decoding stage |
||
183 | err = quirc_decode(&code, &data); |
||
184 | if (err) { |
||
185 | //printf(" DECODE FAILED: %s\n", quirc_strerror(err)); |
||
186 | tedit1_print("DECODE FAILED: ", -1, 0); |
||
187 | tedit1_print(quirc_strerror(err), -1, 1); |
||
188 | } else { |
||
189 | //printf("\n RECOGNIZED DATA: %s\n", data.payload); |
||
190 | tedit1_print("RECOGNIZED: ", -1, 0); |
||
191 | tedit1_print(data.payload, data.payload_len, 1); |
||
192 | } |
||
193 | } |
||
194 | |||
195 | puts("\nquirc_destroy()...\n"); |
||
196 | quirc_destroy(qr); |
||
197 | } |
||
198 | |||
199 | void on_btn_open() { |
||
200 | //ted_text_add(tedit1, "Hello world!\r", strlen("Hello world!\r"), 1); |
||
201 | op_dialog1->mode = OPEN; |
||
202 | OpenDialog_start(op_dialog1); |
||
203 | if (op_dialog1->status != 2 && op_dialog1->status != 0) {// fail or cancel |
||
204 | img1_path = op_dialog1->openfile_path; |
||
205 | //ted_text_add(tedit1, img1_path, strlen(img1_path), 1); |
||
206 | //ted_text_add(tedit1, "\r", 1, 1); // newline |
||
207 | } else { |
||
208 | return; |
||
209 | } |
||
210 | Image *oldimg; |
||
211 | if (img1 != NULL) { img_destroy(img1); } |
||
212 | if (img1_grayscale != NULL) { img_destroy(img1_grayscale); } |
||
213 | uint32_t file_size; |
||
214 | void *file_data = load_img(img1_path, &file_size); // Get RAW data and size |
||
215 | img1 = img_decode(file_data, file_size, 0); // Decode RAW data to Image data |
||
216 | img1_grayscale = img_decode(file_data, file_size, 0); // Decode RAW data to Image data |
||
217 | free(file_data); // |
||
218 | printf("original: image->Width = %d, Image->Height = %d,\n original image type = %d\n\n", img1->Width, img1->Height, img1->Type); |
||
219 | if (img1->Type != IMAGE_BPP24) { |
||
220 | oldimg = img1; // |
||
221 | img1 = img_convert(img1, NULL, IMAGE_BPP24, 0, 0); // Convert image to RGB 24 |
||
222 | img_destroy(oldimg); // |
||
223 | if (!img1) { |
||
224 | printf("Сonvert img1 to BPP24 error!: \n"); |
||
225 | exit(-1); |
||
226 | } |
||
227 | } |
||
228 | if (img1_grayscale->Type != IMAGE_BPP24) { |
||
229 | oldimg = img1_grayscale; // |
||
230 | img1_grayscale = img_convert(img1_grayscale, NULL, IMAGE_BPP24, 0, 0); // Convert image to RGB |
||
231 | img_destroy(oldimg); // |
||
232 | if (!img1_grayscale) { |
||
233 | printf("Сonvert img1_grayscale to BPP24 error!: \n"); |
||
234 | exit(-1); |
||
235 | } |
||
236 | } |
||
237 | if (img1_grayscale->Type != IMAGE_BPP8g) { |
||
238 | oldimg = img1_grayscale; // |
||
239 | img1_grayscale = img_convert(img1_grayscale, NULL, IMAGE_BPP8g, 0, 0); // Convert image to grayscale |
||
240 | img_destroy(oldimg); // |
||
241 | if (!img1_grayscale) { |
||
242 | printf("Сonvert img1_grayscale to BPP8g error!: \n"); |
||
243 | exit(-1); |
||
244 | } |
||
245 | } |
||
246 | oldimg = img1; // |
||
247 | img1 = img_scale(img1, 0, 0, img1->Width, img1->Height, NULL, LIBIMG_SCALE_STRETCH , LIBIMG_INTER_BILINEAR, IMG1_DISPLAY_W, IMG1_DISPLAY_H); |
||
248 | img_destroy(oldimg); // |
||
249 | |||
250 | recognize_qr(); |
||
251 | } |
||
252 | |||
253 | int main(int argc, char *argv[]) { |
||
254 | int gui_event; /* variable for storing event */ |
||
255 | uint32_t pressed_button = 0; /* code of button pressed in window */ |
||
256 | unsigned int keyval; /* for saving pressed key */ |
||
257 | oskey_t key; |
||
258 | |||
259 | ((void)argc); |
||
260 | strcpy(cur_dir_path, argv[0] + 2); char *pc = strrchr(cur_dir_path, '/'); if (pc) { *pc = '\0'; } |
||
261 | printf("cur_dir_path = %s\n", cur_dir_path); |
||
262 | |||
263 | kolibri_boxlib_init(); |
||
264 | kolibri_proclib_init(); // opensave && color dialogs |
||
265 | kolibri_libimg_init(); |
||
266 | |||
267 | set_wanted_events_mask(0xC0000027); |
||
268 | set_os_keyb_mode(1); // scan code mode needed for editor |
||
269 | |||
270 | kolibri_get_system_colors(&sys_color_table); // Get system colors theme |
||
271 | |||
272 | create_components(); |
||
273 | |||
274 | do { |
||
275 | gui_event = get_os_event(); |
||
276 | switch(gui_event) { |
||
277 | case KOLIBRI_EVENT_NONE: |
||
278 | break; |
||
279 | case KOLIBRI_EVENT_REDRAW: |
||
280 | redraw_window(); |
||
281 | break; |
||
282 | case KOLIBRI_EVENT_MOUSE: |
||
283 | ted_mouse(tedit1); |
||
284 | break; |
||
285 | case KOLIBRI_EVENT_KEY: |
||
286 | key = get_key(); |
||
287 | if (tedit1_lock == tedit1) { editor_key(tedit1, key); } |
||
288 | break; |
||
289 | case KOLIBRI_EVENT_BUTTON: |
||
290 | pressed_button = get_os_button(); |
||
291 | switch (pressed_button) |
||
292 | { |
||
293 | case MYBTN_OPEN: |
||
294 | { |
||
295 | on_btn_open(); |
||
296 | redraw_window(); |
||
297 | break; |
||
298 | } |
||
299 | |||
300 | /*case MYBTN_CLEAR: |
||
301 | ted_clear(tedit1, 1); |
||
302 | redraw_window(); |
||
303 | break; */ |
||
304 | |||
305 | case MYBTN_QUIT: |
||
306 | exit(0); |
||
307 | break; |
||
308 | } |
||
309 | } |
||
310 | } while (1); |
||
311 | |||
312 | exit(0); |
||
313 | }>>16)+W) |