Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2009 Daniel Silverstone <dsilvers@netsurf-browser.org>
  3.  *
  4.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  5.  *
  6.  * NetSurf is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; version 2 of the License.
  9.  *
  10.  * NetSurf is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. #include <stdbool.h>
  20. #include <errno.h>
  21. #include <stdio.h>
  22. #include <png.h>
  23. #include <stdlib.h>
  24.  
  25. #if PNG_LIBPNG_VER < 10209
  26. #define png_set_expand_gray_1_2_4_to_8(png) png_set_gray_1_2_4_to_8(png)
  27. #endif
  28.  
  29. static png_structp png;
  30. static png_infop info;
  31. static int interlace;
  32. static size_t rowbytes;
  33. static int raw_width, raw_height;
  34. static int rowstride;
  35. static unsigned char *bitmap_data;
  36. static bool is_cursor = true;
  37. static int raw_hot_x, raw_hot_y;
  38.  
  39. #define WIDTH (is_cursor?raw_width-1:raw_width)
  40. #define HEIGHT (is_cursor?raw_height-1:raw_height)
  41.  
  42. #define HOT_X (is_cursor?raw_hot_x-1:0)
  43. #define HOT_Y (is_cursor?raw_hot_y-1:0)
  44.  
  45. #define REAL(v) (is_cursor?v+1:v)
  46.  
  47. #define PPIX_AT(x,y) ((bitmap_data + (rowstride * y)) + (x * 4))
  48.  
  49. #define R_OFF 2
  50. #define G_OFF 1
  51. #define B_OFF 0
  52. #define A_OFF 3
  53.  
  54. #define R_AT(x,y) *(PPIX_AT(x,y) + R_OFF)
  55. #define G_AT(x,y) *(PPIX_AT(x,y) + G_OFF)
  56. #define B_AT(x,y) *(PPIX_AT(x,y) + B_OFF)
  57. #define A_AT(x,y) *(PPIX_AT(x,y) + A_OFF)
  58.  
  59. static void info_callback(png_structp png, png_infop info);
  60. static void row_callback(png_structp png, png_bytep new_row,
  61.                          png_uint_32 row_num, int pass);
  62. static void end_callback(png_structp png, png_infop info);
  63.  
  64.  
  65.  
  66. static void
  67. usage(void)
  68. {
  69.         fprintf(stderr, "usage: fb_convert_image input.png output.inc varname\n");
  70. }
  71.  
  72. static void info_callback(png_structp png, png_infop info);
  73. static void row_callback(png_structp png, png_bytep new_row,
  74.                          png_uint_32 row_num, int pass);
  75. static void end_callback(png_structp png, png_infop info);
  76.  
  77.  
  78. static void
  79. detect_hotspot(void)
  80. {
  81.         int i;
  82.         int greenpixels = 0;
  83.        
  84.         for (i = 0; i < raw_width; ++i) {
  85.                 if (A_AT(i, 0) == 255) {
  86.                         if (G_AT(i, 0) == 255) {
  87.                                 greenpixels++;
  88.                                 raw_hot_x = i;
  89.                         }
  90.                         if ((B_AT(i, 0) != 0) || (R_AT(i, 0) != 0)) {
  91.                                 is_cursor = false;
  92.                                 return;
  93.                         }
  94.                 } else if (A_AT(i, 0) != 0) {
  95.                         is_cursor = false;
  96.                         return;
  97.                 }
  98.         }
  99.         if (greenpixels != 1) {
  100.                 is_cursor = false;
  101.                 return;
  102.         }
  103.  
  104.         for (i = 0; i < raw_height; ++i) {
  105.                 if (A_AT(0, i) == 255) {
  106.                         if (G_AT(0, i) == 255) {
  107.                                 greenpixels++;
  108.                                 raw_hot_y = i;
  109.                         }
  110.                         if ((B_AT(0, i) != 0) || (R_AT(0, i) != 0)) {
  111.                                 is_cursor = false;
  112.                                 return;
  113.                         }
  114.                 } else if (A_AT(0, i) != 0) {
  115.                         is_cursor = false;
  116.                         return;
  117.                 }
  118.         }
  119.         if (greenpixels != 2) {
  120.                 is_cursor = false;
  121.                 return;
  122.         }
  123.         printf("          Pointer detected. Adjusted hotspot at %d, %d (0-based)\n",
  124.                raw_hot_x - 1, raw_hot_y - 1);
  125. }
  126.  
  127. int
  128. main(int argc, char **argv)
  129. {
  130.         FILE *f;
  131.         unsigned char buffer[1024];
  132.         int br;
  133.         int x, y, c;
  134.        
  135.         if (argc != 4) {
  136.                 usage();
  137.                 return 1;
  138.         }
  139.        
  140.         printf(" CONVERT: %s (%s)\n", argv[1], argv[3]);
  141.        
  142.         png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  143.         info = png_create_info_struct(png);
  144.        
  145.         png_set_progressive_read_fn(png, NULL, info_callback, row_callback, end_callback);
  146.        
  147.         f = fopen(argv[1], "rb");
  148.         if (f == NULL) {
  149.                 printf("          Unable to open %s\n", argv[1]);
  150.                 return 1;
  151.         }
  152.        
  153.         do {
  154.                 br = fread(buffer, 1, 1024, f);
  155.                 if (br > 0) {
  156.                         png_process_data(png, info, buffer, br);
  157.                 }
  158.         } while (br > 0);
  159.        
  160.         if (br < 0) {
  161.                 printf("Error reading input: %s\n", strerror(errno));
  162.                 return 1;
  163.         }
  164.        
  165.         fclose(f);
  166.        
  167.         detect_hotspot();
  168.        
  169.         f = fopen(argv[2], "w");
  170.         if (f == NULL) {
  171.                 printf("          Unable to open %s\n", argv[2]);
  172.                 return 2;
  173.         }
  174.        
  175.         fprintf(f, "/* This file is auto-generated from %s\n", argv[1]);
  176.         fprintf(f, " *\n * Do not edit this file directly.\n */\n\n");
  177.         fprintf(f, "#include <sys/types.h>\n\n");
  178.         fprintf(f, "#include <stdint.h>\n\n");
  179.         fprintf(f, "#include <stdbool.h>\n\n");
  180.         fprintf(f, "#include <libnsfb.h>\n\n");
  181.         fprintf(f, "#include \"desktop/plot_style.h\"\n");
  182.         fprintf(f, "#include \"framebuffer/gui.h\"\n");
  183.         fprintf(f, "#include \"framebuffer/fbtk.h\"\n\n");
  184.        
  185.         fprintf(f, "static uint8_t %s_pixdata[] = {\n", argv[3]);
  186.         for (y = 0; y < HEIGHT; ++y) {
  187.                 unsigned char *rowptr = bitmap_data + (rowstride * y);
  188.                 if (is_cursor) {
  189.                         /* If it's a cursor, skip one row and one column */
  190.                         rowptr += rowstride + 4;
  191.                 }
  192.                 fprintf(f, "\t");
  193.                 for (x = 0; x < WIDTH; ++x) {
  194.                         for (c = 0; c < 4; ++c) {
  195.                                 unsigned char b = *rowptr++;
  196.                                 fprintf(f, "0x%02x, ", b);
  197.                         }
  198.                 }
  199.                 fprintf(f, "\n");
  200.         }
  201.         fprintf(f, "};\n\n");
  202.        
  203.         fprintf(f, "struct fbtk_bitmap %s = {\n", argv[3]);
  204.         fprintf(f, "\t.width\t\t= %d,\n", WIDTH);
  205.         fprintf(f, "\t.height\t\t= %d,\n", HEIGHT);
  206.         fprintf(f, "\t.hot_x\t\t= %d,\n", HOT_X);
  207.         fprintf(f, "\t.hot_y\t\t= %d,\n", HOT_Y);
  208.         fprintf(f, "\t.pixdata\t= %s_pixdata,\n", argv[3]);
  209.        
  210.         fprintf(f, "};\n\n");
  211.         fclose(f);
  212.        
  213.         return 0;
  214. }
  215.  
  216. static void
  217. info_callback(png_structp png, png_infop info)
  218. {
  219.         int bit_depth, color_type, interlace, intent;
  220.         double gamma;
  221.         unsigned long width, height;
  222.        
  223.         /* Read the PNG details */
  224.         png_get_IHDR(png, info, &width, &height, &bit_depth,
  225.                         &color_type, &interlace, 0, 0);
  226.        
  227.         /* Set up our transformations */
  228.         if (color_type == PNG_COLOR_TYPE_PALETTE)
  229.                 png_set_palette_to_rgb(png);
  230.         if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
  231.                 png_set_expand_gray_1_2_4_to_8(png);
  232.         if (png_get_valid(png, info, PNG_INFO_tRNS))
  233.                 png_set_tRNS_to_alpha(png);
  234.         if (bit_depth == 16)
  235.                 png_set_strip_16(png);
  236.         if (color_type == PNG_COLOR_TYPE_GRAY ||
  237.                         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  238.                 png_set_gray_to_rgb(png);
  239.         if (!(color_type & PNG_COLOR_MASK_ALPHA))
  240.                 png_set_filler(png, 0xff, PNG_FILLER_AFTER);
  241.         /* gamma correction - we use 2.2 as our screen gamma
  242.          * this appears to be correct (at least in respect to !Browse)
  243.          * see http://www.w3.org/Graphics/PNG/all_seven.html for a test case
  244.          */
  245.         if (png_get_sRGB(png, info, &intent))
  246.                 png_set_gamma(png, 2.2, 0.45455);
  247.         else {
  248.                 if (png_get_gAMA(png, info, &gamma))
  249.                         png_set_gamma(png, 2.2, gamma);
  250.                 else
  251.                         png_set_gamma(png, 2.2, 0.45455);
  252.         }
  253.  
  254.  
  255.         png_read_update_info(png, info);
  256.  
  257.         rowbytes = png_get_rowbytes(png, info);
  258.         interlace = (interlace == PNG_INTERLACE_ADAM7);
  259.         raw_width = width;
  260.         raw_height = height;
  261.        
  262.         rowstride = raw_width * 4;
  263.         bitmap_data = malloc(rowstride * raw_height);
  264. }
  265.  
  266. static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0};
  267. static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0};
  268. static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1};
  269. static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2};
  270.  
  271. static void
  272. row_callback(png_structp png, png_bytep new_row,
  273.              png_uint_32 row_num, int pass)
  274. {
  275.         unsigned long i, j;
  276.         unsigned int start, step;
  277.         unsigned char *row = bitmap_data + (rowstride * row_num);
  278.                
  279.         if (new_row == 0)
  280.                 return;
  281.        
  282.         if (interlace) {
  283.                 start = interlace_start[pass];
  284.                 step = interlace_step[pass];
  285.                 row_num = interlace_row_start[pass] +
  286.                         interlace_row_step[pass] * row_num;
  287.  
  288.                 /* Copy the data to our current row taking interlacing
  289.                  * into consideration */
  290.                 row = bitmap_data + (rowstride * row_num);
  291.                 for (j = 0, i = start; i < rowbytes; i += step) {
  292.                         row[i++] = new_row[j++];
  293.                         row[i++] = new_row[j++];
  294.                         row[i++] = new_row[j++];
  295.                         row[i++] = new_row[j++];
  296.                 }
  297.         } else {
  298.                 memcpy(row, new_row, rowbytes);
  299.         }
  300. }
  301.  
  302. static void
  303. end_callback(png_structp png, png_infop info)
  304. {
  305. }
  306.  
  307.  
  308.  
  309. /*
  310.  * Local Variables:
  311.  * c-basic-offset:8
  312.  * End:
  313.  */
  314.  
  315.