Advertisement
Guest User

main.cpp

a guest
Mar 20th, 2015
323
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.11 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <map>
  4. #include <string>
  5. #include <png.h>
  6. #include <time.h>
  7.  
  8. #define UTF8_FULL_BLOCK   "\xE2\x96\x88"
  9. #define UTF8_DARK_SHADE   "\xE2\x96\x93"
  10. #define UTF8_MEDIUM_SHADE "\xE2\x96\x92"
  11. #define UTF8_LIGHT_SHADE  "\xE2\x96\x91"
  12. #define UTF8_NO_BLOCK     " "
  13.  
  14. struct ansi_color {
  15.     unsigned char r;
  16.     unsigned char g;
  17.     unsigned char b;
  18. };
  19.  
  20. const struct ansi_color color_table[] =
  21. {
  22.     {  0,   0,   0}, // black
  23.     {128,   0,   0}, // red
  24.     {  0, 128,   0}, // green
  25.     {128, 128,   0}, // yellow
  26.     {  0,   0, 128}, // blue
  27.     {128,   0, 128}, // magenta
  28.     {  0, 128, 128}, // cyan
  29.     {192, 192, 192}  // white                            
  30. };
  31.  
  32. const struct ansi_color bright_color_table[] =
  33. {
  34.     {128, 128, 128}, // black
  35.     {255,   0,   0}, // red
  36.     {  0, 255,   0}, // green
  37.     {255, 255,   0}, // yellow
  38.     {  0,   0, 255}, // blue
  39.     {255,   0, 255}, // magenta
  40.     {  0, 255, 255}, // cyan
  41.     {255, 255, 255}  // white                            
  42. };
  43.  
  44. int width, height;
  45. png_byte color_type;
  46. png_byte bit_depth;
  47. png_bytep *row_pointers;
  48.  
  49. void read_png_file(char *filename) {
  50.     FILE *fp = fopen(filename, "rb");
  51.  
  52.     png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  53.     if(!png) abort();
  54.  
  55.     png_infop info = png_create_info_struct(png);
  56.     if(!info) abort();
  57.  
  58.     if(setjmp(png_jmpbuf(png))) abort();
  59.  
  60.     png_init_io(png, fp);
  61.  
  62.     png_read_info(png, info);
  63.  
  64.     width      = png_get_image_width(png, info);
  65.     height     = png_get_image_height(png, info);
  66.     color_type = png_get_color_type(png, info);
  67.     bit_depth  = png_get_bit_depth(png, info);
  68.  
  69.     // Read any color_type into 8bit depth, RGBA format.
  70.     // See http://www.libpng.org/pub/png/libpng-manual.txt
  71.  
  72.     if(bit_depth == 16)
  73.     png_set_strip_16(png);
  74.  
  75.     if(color_type == PNG_COLOR_TYPE_PALETTE)
  76.     png_set_palette_to_rgb(png);
  77.  
  78.     // PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
  79.     if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
  80.     png_set_expand_gray_1_2_4_to_8(png);
  81.  
  82.     if(png_get_valid(png, info, PNG_INFO_tRNS))
  83.     png_set_tRNS_to_alpha(png);
  84.  
  85.     // These color_type don't have an alpha channel then fill it with 0xff.
  86.     if(color_type == PNG_COLOR_TYPE_RGB ||
  87.      color_type == PNG_COLOR_TYPE_GRAY ||
  88.      color_type == PNG_COLOR_TYPE_PALETTE)
  89.     png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
  90.  
  91.     if(color_type == PNG_COLOR_TYPE_GRAY ||
  92.      color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  93.     png_set_gray_to_rgb(png);
  94.  
  95.     png_read_update_info(png, info);
  96.  
  97.     row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
  98.     for(int y = 0; y < height; y++) {
  99.     row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png,info));
  100.     }
  101.  
  102.     png_read_image(png, row_pointers);
  103.  
  104.     fclose(fp);
  105. }
  106.  
  107. void ansi2rgb(bool bright, int fg,  int bg, int shade, unsigned char *r, unsigned char *g, unsigned char *b) {
  108.     double opacity;
  109.     bg %= 10;
  110.     fg %= 10;
  111.     switch (shade) {
  112.         case 0:  opacity = 1.00; break;
  113.         case 1:  opacity = 0.75; break;
  114.         case 2:  opacity = 0.50; break;
  115.         case 3:  opacity = 0.25; break;
  116.         default: opacity = 0.00; break;                
  117.     }
  118.     unsigned char r_fg, g_fg, b_fg;
  119.     unsigned char r_bg, g_bg, b_bg;
  120.    
  121.     if (bright) {
  122.         r_fg = bright_color_table[fg].r;
  123.         g_fg = bright_color_table[fg].g;
  124.         b_fg = bright_color_table[fg].b;
  125.     }
  126.     else {
  127.         r_fg = color_table[fg].r;
  128.         g_fg = color_table[fg].g;
  129.         b_fg = color_table[fg].b;
  130.     }
  131.    
  132.     r_bg = color_table[bg].r;
  133.     g_bg = color_table[bg].g;
  134.     b_bg = color_table[bg].b;    
  135.    
  136.     *r = (unsigned char)(opacity * r_fg + (1.0 - opacity) * r_bg);
  137.     *g = (unsigned char)(opacity * g_fg + (1.0 - opacity) * g_bg);
  138.     *b = (unsigned char)(opacity * b_fg + (1.0 - opacity) * b_bg);
  139. }
  140.  
  141. unsigned char dist(unsigned char x1, unsigned char x2) {
  142.      if (x1 > x2) return x1 - x2;
  143.      return x2 - x1;
  144. }
  145.  
  146. size_t color_index(unsigned char R, unsigned char G, unsigned char B, std::map<size_t, std::string> *palette) {
  147.     size_t best_index    = 0;
  148.     size_t best_distance = ~0;
  149.     size_t index;
  150.     unsigned char r,g,b;
  151.     for (std::map<size_t, std::string>::iterator it=palette->begin(); it!=palette->end(); ++it) {
  152.         index = it->first;
  153.         r = index % 256;
  154.         g = (index / 256) % 256;
  155.         b = (index / 256) / 256;
  156.         size_t rd = dist(R, r);
  157.         size_t gd = dist(G, g);
  158.         size_t bd = dist(B, b);
  159.         size_t d  = rd*rd + gd*gd + bd*bd;
  160.         if ( d < best_distance ) {
  161.             best_distance = d;
  162.             best_index = index;
  163.         }
  164.     }
  165.  
  166.     return best_index;
  167. }
  168.  
  169. int main(int argc, char** argv) {
  170.     srand (time(NULL));
  171.    
  172.     const char * shades[5];
  173.     shades[0] = UTF8_FULL_BLOCK;
  174.     shades[1] = UTF8_DARK_SHADE;
  175.     shades[2] = UTF8_MEDIUM_SHADE;
  176.     shades[3] = UTF8_LIGHT_SHADE;
  177.     shades[4] = UTF8_NO_BLOCK;
  178.  
  179.     if(argc != 2) {
  180.         printf("Usage: %s <png file>\n", argv[0]);
  181.         abort();
  182.     }
  183.    
  184.     printf("Generating color table.\n");
  185.     std::map<size_t, std::string> palette;
  186.     char buf[256];
  187.    
  188.     for (int bg=40; bg<=47; ++bg) {
  189.         for (int fg=30; fg<=37; ++fg) {
  190.             for (int shade=0; shade<5; ++shade) {
  191.                 unsigned char r,g,b;
  192.                 ansi2rgb(true, fg, bg, shade, &r, &g, &b);
  193.                 size_t index = r + 256*g + 65536*b;
  194.                 sprintf(buf, "\x1B[1;%d;%dm%s",fg, bg, shades[shade]);
  195.                 palette[index] = buf;
  196.                 //palette.insert(r + 256*g + 65536*b);
  197.                 //printf("\x1B[1;%d;%dm%s(%3d, %3d, %3d)",fg, bg, shades[shade], r, g, b);
  198.             }
  199.         }
  200.         //printf("\x1B[0m\n");
  201.     }
  202.  
  203.     for (int bg=40; bg<=47; ++bg) {
  204.         for (int fg=30; fg<=37; ++fg) {
  205.             for (int shade=0; shade<5; ++shade) {
  206.                 unsigned char r,g,b;
  207.                 ansi2rgb(false, fg, bg, shade, &r, &g, &b);
  208.                
  209.                 size_t index = r + 256*g + 65536*b;
  210.                 sprintf(buf, "\x1B[%d;%dm%s",fg, bg, shades[shade]);
  211.                 palette[index] = buf;                
  212.                
  213.                 //palette.insert(r + 256*g + 65536*b);
  214.                 //printf("\x1B[%d;%dm%s(%3d, %3d, %3d)",fg, bg, shades[shade], r, g, b);
  215.             }
  216.         }
  217.         //printf("\x1B[0m\n");
  218.     }
  219.     printf("Palette contains %lu colors.\n", palette.size());
  220.    
  221.     printf("Reading %s.\n", argv[1]);
  222.     read_png_file(argv[1]);
  223.  
  224.     std::string last_ansi;
  225.     for(int y = 0; y < height; y++) {
  226.         png_bytep row = row_pointers[y];
  227.         for(int x = 0; x < width; x++) {
  228.             png_bytep px = &(row[x * 4]);
  229.             // Do something awesome for each pixel here...
  230.             if (px[3] < 128) {
  231.                 strcpy(buf, "\x1B[0m ");
  232.                
  233.                 if (last_ansi.compare(buf) != 0) {
  234.                     last_ansi = buf;
  235.                     printf("%s", buf);
  236.                 }
  237.                 else printf(" ");
  238.             }
  239.             else {
  240.                 size_t index = color_index(px[0], px[1], px[2], &palette);
  241.                 sprintf(buf, "%s", palette[index].c_str());
  242.                
  243.                 if (last_ansi.compare(buf) != 0) {
  244.                     last_ansi = buf;
  245.                     printf("%s", buf);
  246.                 }
  247.                 else {
  248.                     std::string block;
  249.                     bool data = false;
  250.                     for (size_t i=0; last_ansi.c_str()[i] != '\0'; ++i) {
  251.                         if (last_ansi.c_str()[i] == 'm') {
  252.                             data = true;
  253.                             continue;
  254.                         }
  255.                         if (data) block.append(1, last_ansi.c_str()[i]);
  256.                     }
  257.                     printf("%s", block.c_str());
  258.                 }
  259.             }
  260.             //printf("%4d, %4d = RGBA(%3d, %3d, %3d, %3d)\n", x, y, px[0], px[1], px[2], px[3]);
  261.         }
  262.         printf("\x1B[0m\n");
  263.     }
  264.  
  265.     return 0;
  266. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement