Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* Copyright (C) 2021- Rustem Gimadutdinov (rgimad), GPLv2 */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stddef.h>
  6. #include <kos32sys.h>
  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. }
  314.