The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/scripts/pnmtologo.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 
    2 /*
    3  *  Convert a logo in ASCII PNM format to C source suitable for inclusion in
    4  *  the Linux kernel
    5  *
    6  *  (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
    7  *
    8  *  --------------------------------------------------------------------------
    9  *
   10  *  This file is subject to the terms and conditions of the GNU General Public
   11  *  License. See the file COPYING in the main directory of the Linux
   12  *  distribution for more details.
   13  */
   14 
   15 #include <ctype.h>
   16 #include <errno.h>
   17 #include <stdarg.h>
   18 #include <stdio.h>
   19 #include <stdlib.h>
   20 #include <string.h>
   21 #include <unistd.h>
   22 
   23 
   24 static const char *programname;
   25 static const char *filename;
   26 static const char *logoname = "linux_logo";
   27 static const char *outputname;
   28 static FILE *out;
   29 
   30 
   31 #define LINUX_LOGO_MONO         1       /* monochrome black/white */
   32 #define LINUX_LOGO_VGA16        2       /* 16 colors VGA text palette */
   33 #define LINUX_LOGO_CLUT224      3       /* 224 colors */
   34 #define LINUX_LOGO_GRAY256      4       /* 256 levels grayscale */
   35 
   36 static const char *logo_types[LINUX_LOGO_GRAY256+1] = {
   37     [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
   38     [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
   39     [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
   40     [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256"
   41 };
   42 
   43 #define MAX_LINUX_LOGO_COLORS   224
   44 
   45 struct color {
   46     unsigned char red;
   47     unsigned char green;
   48     unsigned char blue;
   49 };
   50 
   51 static const struct color clut_vga16[16] = {
   52     { 0x00, 0x00, 0x00 },
   53     { 0x00, 0x00, 0xaa },
   54     { 0x00, 0xaa, 0x00 },
   55     { 0x00, 0xaa, 0xaa },
   56     { 0xaa, 0x00, 0x00 },
   57     { 0xaa, 0x00, 0xaa },
   58     { 0xaa, 0x55, 0x00 },
   59     { 0xaa, 0xaa, 0xaa },
   60     { 0x55, 0x55, 0x55 },
   61     { 0x55, 0x55, 0xff },
   62     { 0x55, 0xff, 0x55 },
   63     { 0x55, 0xff, 0xff },
   64     { 0xff, 0x55, 0x55 },
   65     { 0xff, 0x55, 0xff },
   66     { 0xff, 0xff, 0x55 },
   67     { 0xff, 0xff, 0xff },
   68 };
   69 
   70 
   71 static int logo_type = LINUX_LOGO_CLUT224;
   72 static unsigned int logo_width;
   73 static unsigned int logo_height;
   74 static struct color **logo_data;
   75 static struct color logo_clut[MAX_LINUX_LOGO_COLORS];
   76 static unsigned int logo_clutsize;
   77 static int is_plain_pbm = 0;
   78 
   79 static void die(const char *fmt, ...)
   80     __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2)));
   81 static void usage(void) __attribute ((noreturn));
   82 
   83 
   84 static unsigned int get_number(FILE *fp)
   85 {
   86     int c, val;
   87 
   88     /* Skip leading whitespace */
   89     do {
   90         c = fgetc(fp);
   91         if (c == EOF)
   92             die("%s: end of file\n", filename);
   93         if (c == '#') {
   94             /* Ignore comments 'till end of line */
   95             do {
   96                 c = fgetc(fp);
   97                 if (c == EOF)
   98                     die("%s: end of file\n", filename);
   99             } while (c != '\n');
  100         }
  101     } while (isspace(c));
  102 
  103     /* Parse decimal number */
  104     val = 0;
  105     while (isdigit(c)) {
  106         val = 10*val+c-'';
  107         /* some PBM are 'broken'; GiMP for example exports a PBM without space
  108          * between the digits. This is Ok cause we know a PBM can only have a '1'
  109          * or a '' for the digit. */
  110         if (is_plain_pbm)
  111                 break;
  112         c = fgetc(fp);
  113         if (c == EOF)
  114             die("%s: end of file\n", filename);
  115     }
  116     return val;
  117 }
  118 
  119 static unsigned int get_number255(FILE *fp, unsigned int maxval)
  120 {
  121     unsigned int val = get_number(fp);
  122     return (255*val+maxval/2)/maxval;
  123 }
  124 
  125 static void read_image(void)
  126 {
  127     FILE *fp;
  128     unsigned int i, j;
  129     int magic;
  130     unsigned int maxval;
  131 
  132     /* open image file */
  133     fp = fopen(filename, "r");
  134     if (!fp)
  135         die("Cannot open file %s: %s\n", filename, strerror(errno));
  136 
  137     /* check file type and read file header */
  138     magic = fgetc(fp);
  139     if (magic != 'P')
  140         die("%s is not a PNM file\n", filename);
  141     magic = fgetc(fp);
  142     switch (magic) {
  143         case '1':
  144         case '2':
  145         case '3':
  146             /* Plain PBM/PGM/PPM */
  147             break;
  148 
  149         case '4':
  150         case '5':
  151         case '6':
  152             /* Binary PBM/PGM/PPM */
  153             die("%s: Binary PNM is not supported\n"
  154                 "Use pnmnoraw(1) to convert it to ASCII PNM\n", filename);
  155 
  156         default:
  157             die("%s is not a PNM file\n", filename);
  158     }
  159     logo_width = get_number(fp);
  160     logo_height = get_number(fp);
  161 
  162     /* allocate image data */
  163     logo_data = (struct color **)malloc(logo_height*sizeof(struct color *));
  164     if (!logo_data)
  165         die("%s\n", strerror(errno));
  166     for (i = 0; i < logo_height; i++) {
  167         logo_data[i] = malloc(logo_width*sizeof(struct color));
  168         if (!logo_data[i])
  169             die("%s\n", strerror(errno));
  170     }
  171 
  172     /* read image data */
  173     switch (magic) {
  174         case '1':
  175             /* Plain PBM */
  176             is_plain_pbm = 1;
  177             for (i = 0; i < logo_height; i++)
  178                 for (j = 0; j < logo_width; j++)
  179                     logo_data[i][j].red = logo_data[i][j].green =
  180                         logo_data[i][j].blue = 255*(1-get_number(fp));
  181             break;
  182 
  183         case '2':
  184             /* Plain PGM */
  185             maxval = get_number(fp);
  186             for (i = 0; i < logo_height; i++)
  187                 for (j = 0; j < logo_width; j++)
  188                     logo_data[i][j].red = logo_data[i][j].green =
  189                         logo_data[i][j].blue = get_number255(fp, maxval);
  190             break;
  191 
  192         case '3':
  193             /* Plain PPM */
  194             maxval = get_number(fp);
  195             for (i = 0; i < logo_height; i++)
  196                 for (j = 0; j < logo_width; j++) {
  197                     logo_data[i][j].red = get_number255(fp, maxval);
  198                     logo_data[i][j].green = get_number255(fp, maxval);
  199                     logo_data[i][j].blue = get_number255(fp, maxval);
  200                 }
  201             break;
  202     }
  203 
  204     /* close file */
  205     fclose(fp);
  206 }
  207 
  208 static inline int is_black(struct color c)
  209 {
  210     return c.red == 0 && c.green == 0 && c.blue == 0;
  211 }
  212 
  213 static inline int is_white(struct color c)
  214 {
  215     return c.red == 255 && c.green == 255 && c.blue == 255;
  216 }
  217 
  218 static inline int is_gray(struct color c)
  219 {
  220     return c.red == c.green && c.red == c.blue;
  221 }
  222 
  223 static inline int is_equal(struct color c1, struct color c2)
  224 {
  225     return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
  226 }
  227 
  228 static void write_header(void)
  229 {
  230     /* open logo file */
  231     if (outputname) {
  232         out = fopen(outputname, "w");
  233         if (!out)
  234             die("Cannot create file %s: %s\n", outputname, strerror(errno));
  235     } else {
  236         out = stdout;
  237     }
  238 
  239     fputs("/*\n", out);
  240     fputs(" *  DO NOT EDIT THIS FILE!\n", out);
  241     fputs(" *\n", out);
  242     fprintf(out, " *  It was automatically generated from %s\n", filename);
  243     fputs(" *\n", out);
  244     fprintf(out, " *  Linux logo %s\n", logoname);
  245     fputs(" */\n\n", out);
  246     fputs("#include <linux/linux_logo.h>\n\n", out);
  247     fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
  248             logoname);
  249 }
  250 
  251 static void write_footer(void)
  252 {
  253     fputs("\n};\n\n", out);
  254     fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
  255     fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
  256     fprintf(out, "\t.width\t\t= %d,\n", logo_width);
  257     fprintf(out, "\t.height\t\t= %d,\n", logo_height);
  258     if (logo_type == LINUX_LOGO_CLUT224) {
  259         fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize);
  260         fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname);
  261     }
  262     fprintf(out, "\t.data\t\t= %s_data\n", logoname);
  263     fputs("};\n\n", out);
  264 
  265     /* close logo file */
  266     if (outputname)
  267         fclose(out);
  268 }
  269 
  270 static int write_hex_cnt;
  271 
  272 static void write_hex(unsigned char byte)
  273 {
  274     if (write_hex_cnt % 12)
  275         fprintf(out, ", 0x%02x", byte);
  276     else if (write_hex_cnt)
  277         fprintf(out, ",\n\t0x%02x", byte);
  278     else
  279         fprintf(out, "\t0x%02x", byte);
  280     write_hex_cnt++;
  281 }
  282 
  283 static void write_logo_mono(void)
  284 {
  285     unsigned int i, j;
  286     unsigned char val, bit;
  287 
  288     /* validate image */
  289     for (i = 0; i < logo_height; i++)
  290         for (j = 0; j < logo_width; j++)
  291             if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j]))
  292                 die("Image must be monochrome\n");
  293 
  294     /* write file header */
  295     write_header();
  296 
  297     /* write logo data */
  298     for (i = 0; i < logo_height; i++) {
  299         for (j = 0; j < logo_width;) {
  300             for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1)
  301                 if (logo_data[i][j].red)
  302                     val |= bit;
  303             write_hex(val);
  304         }
  305     }
  306 
  307     /* write logo structure and file footer */
  308     write_footer();
  309 }
  310 
  311 static void write_logo_vga16(void)
  312 {
  313     unsigned int i, j, k;
  314     unsigned char val;
  315 
  316     /* validate image */
  317     for (i = 0; i < logo_height; i++)
  318         for (j = 0; j < logo_width; j++) {
  319             for (k = 0; k < 16; k++)
  320                 if (is_equal(logo_data[i][j], clut_vga16[k]))
  321                     break;
  322             if (k == 16)
  323                 die("Image must use the 16 console colors only\n"
  324                     "Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
  325                     "of colors\n");
  326         }
  327 
  328     /* write file header */
  329     write_header();
  330 
  331     /* write logo data */
  332     for (i = 0; i < logo_height; i++)
  333         for (j = 0; j < logo_width; j++) {
  334             for (k = 0; k < 16; k++)
  335                 if (is_equal(logo_data[i][j], clut_vga16[k]))
  336                     break;
  337             val = k<<4;
  338             if (++j < logo_width) {
  339                 for (k = 0; k < 16; k++)
  340                     if (is_equal(logo_data[i][j], clut_vga16[k]))
  341                         break;
  342                 val |= k;
  343             }
  344             write_hex(val);
  345         }
  346 
  347     /* write logo structure and file footer */
  348     write_footer();
  349 }
  350 
  351 static void write_logo_clut224(void)
  352 {
  353     unsigned int i, j, k;
  354 
  355     /* validate image */
  356     for (i = 0; i < logo_height; i++)
  357         for (j = 0; j < logo_width; j++) {
  358             for (k = 0; k < logo_clutsize; k++)
  359                 if (is_equal(logo_data[i][j], logo_clut[k]))
  360                     break;
  361             if (k == logo_clutsize) {
  362                 if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
  363                     die("Image has more than %d colors\n"
  364                         "Use ppmquant(1) to reduce the number of colors\n",
  365                         MAX_LINUX_LOGO_COLORS);
  366                 logo_clut[logo_clutsize++] = logo_data[i][j];
  367             }
  368         }
  369 
  370     /* write file header */
  371     write_header();
  372 
  373     /* write logo data */
  374     for (i = 0; i < logo_height; i++)
  375         for (j = 0; j < logo_width; j++) {
  376             for (k = 0; k < logo_clutsize; k++)
  377                 if (is_equal(logo_data[i][j], logo_clut[k]))
  378                     break;
  379             write_hex(k+32);
  380         }
  381     fputs("\n};\n\n", out);
  382 
  383     /* write logo clut */
  384     fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
  385             logoname);
  386     write_hex_cnt = 0;
  387     for (i = 0; i < logo_clutsize; i++) {
  388         write_hex(logo_clut[i].red);
  389         write_hex(logo_clut[i].green);
  390         write_hex(logo_clut[i].blue);
  391     }
  392 
  393     /* write logo structure and file footer */
  394     write_footer();
  395 }
  396 
  397 static void write_logo_gray256(void)
  398 {
  399     unsigned int i, j;
  400 
  401     /* validate image */
  402     for (i = 0; i < logo_height; i++)
  403         for (j = 0; j < logo_width; j++)
  404             if (!is_gray(logo_data[i][j]))
  405                 die("Image must be grayscale\n");
  406 
  407     /* write file header */
  408     write_header();
  409 
  410     /* write logo data */
  411     for (i = 0; i < logo_height; i++)
  412         for (j = 0; j < logo_width; j++)
  413             write_hex(logo_data[i][j].red);
  414 
  415     /* write logo structure and file footer */
  416     write_footer();
  417 }
  418 
  419 static void die(const char *fmt, ...)
  420 {
  421     va_list ap;
  422 
  423     va_start(ap, fmt);
  424     vfprintf(stderr, fmt, ap);
  425     va_end(ap);
  426 
  427     exit(1);
  428 }
  429 
  430 static void usage(void)
  431 {
  432     die("\n"
  433         "Usage: %s [options] <filename>\n"
  434         "\n"
  435         "Valid options:\n"
  436         "    -h          : display this usage information\n"
  437         "    -n <name>   : specify logo name (default: linux_logo)\n"
  438         "    -o <output> : output to file <output> instead of stdout\n"
  439         "    -t <type>   : specify logo type, one of\n"
  440         "                      mono    : monochrome black/white\n"
  441         "                      vga16   : 16 colors VGA text palette\n"
  442         "                      clut224 : 224 colors (default)\n"
  443         "                      gray256 : 256 levels grayscale\n"
  444         "\n", programname);
  445 }
  446 
  447 int main(int argc, char *argv[])
  448 {
  449     int opt;
  450 
  451     programname = argv[0];
  452 
  453     opterr = 0;
  454     while (1) {
  455         opt = getopt(argc, argv, "hn:o:t:");
  456         if (opt == -1)
  457             break;
  458 
  459         switch (opt) {
  460             case 'h':
  461                 usage();
  462                 break;
  463 
  464             case 'n':
  465                 logoname = optarg;
  466                 break;
  467 
  468             case 'o':
  469                 outputname = optarg;
  470                 break;
  471 
  472             case 't':
  473                 if (!strcmp(optarg, "mono"))
  474                     logo_type = LINUX_LOGO_MONO;
  475                 else if (!strcmp(optarg, "vga16"))
  476                     logo_type = LINUX_LOGO_VGA16;
  477                 else if (!strcmp(optarg, "clut224"))
  478                     logo_type = LINUX_LOGO_CLUT224;
  479                 else if (!strcmp(optarg, "gray256"))
  480                     logo_type = LINUX_LOGO_GRAY256;
  481                 else
  482                     usage();
  483                 break;
  484 
  485             default:
  486                 usage();
  487                 break;
  488         }
  489     }
  490     if (optind != argc-1)
  491         usage();
  492 
  493     filename = argv[optind];
  494 
  495     read_image();
  496     switch (logo_type) {
  497         case LINUX_LOGO_MONO:
  498             write_logo_mono();
  499             break;
  500 
  501         case LINUX_LOGO_VGA16:
  502             write_logo_vga16();
  503             break;
  504 
  505         case LINUX_LOGO_CLUT224:
  506             write_logo_clut224();
  507             break;
  508 
  509         case LINUX_LOGO_GRAY256:
  510             write_logo_gray256();
  511             break;
  512     }
  513     exit(0);
  514 }
  515 

Cache object: 41b2d3206496a85d61728ea71421255f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.