home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / msdos / utils / fbm2fl03.lha / fboctree.c < prev    next >
C/C++ Source or Header  |  1993-10-19  |  17KB  |  736 lines

  1. /****************************************************************
  2.  * fboctree.c:
  3.  ****************************************************************/
  4.  
  5. /******
  6.   Copyright (C) 1993 by Klaus Ehrenfried. 
  7.  
  8.   Permission to use, copy, modify, and distribute this software
  9.   is hereby granted, provided that the above copyright notice appears 
  10.   in all copies and that the software is available to all free of charge. 
  11.   The author disclaims all warranties with regard to this software, 
  12.   including all implied warranties of merchant-ability and fitness. 
  13.   The code is simply distributed as it is.
  14.   *******/
  15.  
  16. /*******
  17.   This program is an implementation of the Octree algorithm described 
  18.   by Michael Gervautz and Werner Purgathofer (Technical University 
  19.   Vienna, Austria) in the article "A Simple Method for Color Quantization:
  20.   Octree Quantization" published in Graphic Gems edited by Andrew Glassner
  21.   pp. 287 ff.
  22.   *******/
  23.  
  24. #include <stdio.h>
  25. #include <math.h>
  26. #include <string.h>
  27.  
  28. #include "fbm.h"
  29. #include <stdlib.h>
  30.  
  31. #define PRNAM "fboctree"
  32. #define BIGVAL 0x10000000
  33.  
  34. typedef unsigned char UBYTE;
  35. typedef unsigned long ULONG;
  36.  
  37. typedef struct node *OCTREE;
  38.  
  39. struct node
  40. {
  41.     UBYTE leaf;
  42.     UBYTE level;
  43.     UBYTE color;
  44.     UBYTE sub_count;
  45.     ULONG pixels_low;
  46.     ULONG pixels_high;
  47.     ULONG red_sum_low;
  48.     ULONG red_sum_high;
  49.     ULONG green_sum_low;
  50.     ULONG green_sum_high;
  51.     ULONG blue_sum_low;
  52.     ULONG blue_sum_high;
  53.     OCTREE next_reduceable;
  54.     OCTREE sub[8];
  55.     OCTREE nlist;
  56.     int index;
  57. };
  58.  
  59. void search_colors(OCTREE tree);
  60. void clr_quantize(FBM *input, FBM *output, int colors);
  61. void add_to_octree(FBM *image);
  62.  
  63. int write_bitmap (FBM *image,FILE *wfile, int type);
  64. int read_bitmap (FBM *image, char *fname);
  65. int alloc_fbm (FBM *image);
  66. void search_tree(OCTREE tree);
  67. int out_tree(char *treefile);
  68. int input_tree(char *treefile, int add_flag);
  69. int check_kennung(FILE *fp);
  70. void print_usage();
  71.  
  72. #define MAXDEPTH 7
  73.  
  74. #define RED 0
  75. #define GREEN 1
  76. #define BLUE 2
  77.  
  78. #define MAXCOLORS 256
  79.  
  80. #define TRUE        1
  81. #define FALSE        0
  82.  
  83. static UBYTE palette[MAXCOLORS][3];
  84.  
  85. static int octree_size;
  86. static int reduce_level;
  87. static int leaf_level;
  88. static int max_colors;
  89.  
  90. static OCTREE basetree;
  91. static OCTREE reduce_list[MAXDEPTH + 1];
  92. static int tree_count;
  93. static OCTREE tlist;
  94. static UBYTE b_field[]={128,64,32,16,8,4,2,1};
  95.  
  96. static double color_factor;
  97. static int color_count;
  98.  
  99. #define MAX_KENN 20
  100. static char Kennung[]="#OCTREE_v0.2a";
  101.  
  102. /****************************************************************
  103.  * main
  104.  ****************************************************************/
  105.  
  106. void main (int argc, char *argv[])
  107. { FBM input, output;    /* Images */
  108.   int color_depth;
  109.   int outtype;
  110.   int add_flag, single_flag;
  111.   int i;
  112.   char *tfname, *ppa;
  113.  
  114.   /* Clear pointers */
  115.   input.bm = input.cm = (UBYTE *) NULL;
  116.   output.bm = output.cm = (UBYTE *) NULL;
  117.  
  118.   color_depth=8;
  119.   max_colors=MAXCOLORS;
  120.   outtype = DEF_8BIT;
  121.   add_flag=0;
  122.   single_flag=0;
  123.   tfname=NULL;
  124.  
  125.   for (i=1; i < argc; i++)
  126.     {
  127.       ppa=argv[i];    
  128.       if (ppa[0] == '-')
  129.     {
  130.       switch (ppa[1])
  131.         {
  132.         case 'A':    outtype = FMT_ATK; break;
  133.         case 'B':    outtype = FMT_FACE; break;
  134.         case 'F':    outtype = FMT_FBM; break;
  135.         case 'G':    outtype = FMT_GIF; break;
  136.         case 'I':    outtype = FMT_IFF; break;
  137.         case 'L':    outtype = FMT_LEAF; break;
  138.         case 'M':    outtype = FMT_MCP; break;
  139.         case 'P':    outtype = FMT_PBM; break;
  140.         case 'R':    outtype = FMT_RLE; break;
  141.         case 'S':    outtype = FMT_SUN; break;
  142.         case 'T':    outtype = FMT_TIFF; break;
  143.         case 'X':    outtype = FMT_X11; break;
  144.         case 'Z':    outtype = FMT_PCX; break;
  145.         case 'a':   add_flag = 1; break;
  146.         case 'c':    max_colors = atoi(&ppa[2]); break;
  147.         case 'd':    color_depth = atoi(&ppa[2]); break;
  148.         case 's':   single_flag = 1; break;
  149.         default:
  150.           fprintf(stderr,"Unknown option: %s\n",ppa);
  151.           exit(1);
  152.         }
  153.     }
  154.     }
  155.  
  156.   for (i=1; i < argc; i++)
  157.     {
  158.       ppa=argv[i];    
  159.       if (ppa[0] != '-')
  160.     {
  161.       if (tfname == NULL)
  162.         {
  163.           tfname=argv[i];
  164.         }
  165.       else
  166.         {
  167.           print_usage();
  168.           exit(1);
  169.         }
  170.     }
  171.     }
  172.  
  173.   /* Check arguments */
  174.  
  175.   if ((tfname == NULL && single_flag == 0) || 
  176.       (add_flag == 1 && single_flag == 1))
  177.     {
  178.       print_usage();
  179.       exit (1);
  180.     }
  181.  
  182.   if (color_depth > 8 || color_depth < 2)
  183.     { 
  184.       fprintf (stderr, "%s can only handle 2..8 color depth\n",PRNAM);
  185.       exit (1);
  186.     }
  187.  
  188.   if (max_colors > 256 || max_colors < 9)
  189.   {
  190.     fprintf (stderr, "%s can only handle 9..256 colors\n",PRNAM);
  191.     exit (1);
  192.   }
  193.  
  194.   for (i=0; i <= MAXDEPTH; i++)
  195.     reduce_list[i]=NULL;
  196.  
  197.   basetree=NULL;
  198.   reduce_level = MAXDEPTH;
  199.   leaf_level = reduce_level + 1;
  200.   octree_size=0;
  201.  
  202.   if (tfname != NULL)
  203.     if (input_tree(tfname, add_flag) != 0) exit(1);
  204.  
  205.   if (! read_bitmap (&input, (char *) NULL))
  206.   { exit (1); }
  207.  
  208.   if (input.hdr.planes != 3 || input.hdr.bits != 8)
  209.   { fprintf (stderr, "fboctree can only handle 24bit RGB inputs\n");
  210.     exit (1);
  211.   }
  212.  
  213.   if (add_flag == 1 || single_flag == 1)
  214.     {
  215.       fprintf (stderr,"Scanning \"%s\" [%dx%d]\n",
  216.            input.hdr.title, input.hdr.cols, input.hdr.rows);
  217.       add_to_octree(&input);
  218.     }
  219.  
  220.   if (add_flag == 1)
  221.     {
  222.       tree_count = 0;
  223.       tlist=NULL;
  224.       search_tree(basetree);
  225.       fprintf(stderr,"Octree nodes : %d\n",tree_count);
  226.  
  227.       out_tree(tfname);
  228.       exit(0);
  229.     }
  230.  
  231.   fprintf (stderr,
  232.     "Quantizing \"%s\" [%dx%d] with %d colors (%d bits/clr)\n",
  233.     input.hdr.title, input.hdr.cols, input.hdr.rows, max_colors,
  234.     color_depth);
  235.  
  236.   for (i = 0; i < MAXCOLORS; i++)          /* init palette */
  237.     palette[i][0] = palette[i][1] = palette[i][2] = 0;
  238.  
  239.   /* color 0 is always black !! */
  240.  
  241.   color_count = 1;
  242.   color_factor = (double) ((1 << color_depth) - 1) / 0xFF;
  243.   search_colors(basetree);
  244.  
  245.   /* Now build header for output bit map */
  246.   output.hdr = input.hdr;
  247.   output.hdr.planes = 1;
  248.   output.hdr.clrlen = 3 * MAXCOLORS;
  249.   
  250.   /* Allocate space for output */
  251.   alloc_fbm (&output);
  252.  
  253.   clr_quantize (&input, &output, MAXCOLORS);
  254.   
  255.   /* Write out the result */
  256.   if (write_bitmap (&output, stdout, outtype))
  257.   { exit (0); }
  258.  
  259.   exit (1);
  260. }
  261.  
  262. /************************************************************************
  263.  * print_usage                                                          *
  264.  ************************************************************************/
  265.  
  266. void print_usage()
  267. {
  268.   fprintf(stderr,"Usage:\n");
  269.   fprintf(stderr,
  270.       "  %s -s [-c<numcolors>] [-d<bits>] [-<type>] < rgb > mapped\n",
  271.       PRNAM);
  272.   fprintf(stderr,"  %s -a [-c<numcolors>] octree < rgb\n",PRNAM);
  273.   fprintf(stderr,"  %s [-d<bits>] [-<type>] octree < rgb > mapped\n",PRNAM);
  274. }
  275.  
  276. /************************************************************************
  277.  * search_colors                                                        *
  278.  ************************************************************************/
  279.  
  280. void search_colors(OCTREE tree)
  281. {
  282.   int j;
  283.   double dhelp0, dhelp1;
  284.  
  285.   if (tree == NULL) return;
  286.   if (tree->leaf || tree->level == leaf_level)
  287.     {
  288.       dhelp0=(double) tree->pixels_high * (double) BIGVAL
  289.     +(double) tree->pixels_low;
  290.       dhelp0=color_factor / dhelp0;
  291.  
  292.       dhelp1=
  293.     (double) tree->red_sum_high * (double) BIGVAL
  294.       +(double) tree->red_sum_low;
  295.       palette[color_count][RED]   = (char) (dhelp0 * dhelp1 + 0.5);
  296.  
  297.       dhelp1=
  298.     (double) tree->green_sum_high * (double) BIGVAL
  299.       +(double) tree->green_sum_low;
  300.       palette[color_count][GREEN] = (char) (dhelp0 * dhelp1 + 0.5);
  301.  
  302.       dhelp1=
  303.     (double) tree->blue_sum_high * (double) BIGVAL
  304.       +(double) tree->blue_sum_low;
  305.       palette[color_count][BLUE]  = (char) (dhelp0 * dhelp1 + 0.5);
  306.  
  307.       tree->color = color_count;
  308.       tree->leaf = TRUE;
  309.       color_count++;
  310.     }
  311.   else
  312.     {
  313.       for (j = 0; j < 8; j++)
  314.     search_colors(tree->sub[j]);
  315.     }
  316. }
  317.  
  318. /************************************************************************
  319.  * add_to_octree                                                        *
  320.  ************************************************************************/
  321.  
  322. void add_to_octree(FBM *image)
  323. {
  324.   UBYTE b_red, b_green, b_blue, branch, btest;
  325.   UBYTE *p_red, *p_green, *p_blue;
  326.   OCTREE tree, *p_tree;
  327.   int i, ihelp, depth;
  328.  
  329.   p_red = image->bm;
  330.   p_green = &p_red[image->hdr.plnlen];
  331.   p_blue = &p_green[image->hdr.plnlen];
  332.  
  333.   for (i=0; i < image->hdr.plnlen; i++)
  334.     {
  335.       b_red = *(p_red++);
  336.       b_green = *(p_green++);
  337.       b_blue = *(p_blue++);
  338.  
  339.       p_tree = &basetree;
  340.       depth = 0;
  341.  
  342.       while (p_tree != NULL)
  343.     {
  344.       if (*p_tree == NULL)            /* init new node */
  345.         {
  346.           tree = (OCTREE) calloc(1, sizeof(struct node));
  347.           if (tree == NULL)
  348.         {
  349.           printf("Out of memory");
  350.           exit(1);
  351.         }
  352.           tree->level = depth;
  353.           tree->leaf = (depth >= leaf_level);
  354.           if (tree->leaf) octree_size++;
  355.           *p_tree = tree;
  356.         }
  357.       else
  358.         tree = *p_tree;
  359.  
  360.       tree->pixels_low++;
  361.       tree->red_sum_low += b_red;
  362.       tree->green_sum_low += b_green;
  363.       tree->blue_sum_low += b_blue;
  364.  
  365.       if (tree->leaf == FALSE && depth < leaf_level)
  366.         {
  367.           btest=b_field[depth];
  368.           branch=((b_red & btest) == 0) ? (UBYTE) 0 : (UBYTE) 4;
  369.           if ((b_green & btest) != 0) branch += (UBYTE) 2;
  370.           if ((b_blue & btest) != 0) branch += (UBYTE) 1;
  371.  
  372.           if (tree->sub[branch] == NULL)
  373.         {
  374.           tree->sub_count++;
  375.           if (tree->sub_count == 2)   /* add to reduce_list */
  376.             {
  377.               tree->next_reduceable = reduce_list[depth];
  378.               reduce_list[depth] = tree;
  379.             }
  380.         }
  381.           p_tree=&(tree->sub[branch]);
  382.           depth++;
  383.         }
  384.       else
  385.         p_tree = NULL;
  386.     }
  387.  
  388.       if (octree_size >= max_colors)     /* reduce octree */
  389.     {
  390.       ihelp = reduce_level;
  391.       while (reduce_list[ihelp] == NULL) ihelp--;
  392.       tree = reduce_list[ihelp];
  393.       reduce_list[ihelp] = reduce_list[ihelp]->next_reduceable;
  394.       tree->leaf = 1;
  395.       octree_size = octree_size - tree->sub_count + 1;
  396.       depth = tree->level;
  397.       if (depth < reduce_level)
  398.         {
  399.           reduce_level = depth;
  400.           leaf_level = reduce_level + 1;
  401.         }
  402.     }
  403.     }
  404. }
  405.  
  406. /************************************************************************
  407.  * clr_quantize                                                         *
  408.  ************************************************************************/
  409.  
  410. void clr_quantize(FBM *input, FBM *output, int colors)
  411. {
  412.   UBYTE b_red, b_green, b_blue, branch, btest;
  413.   UBYTE *p_red, *p_green, *p_blue, *p_output;
  414.   OCTREE tree;
  415.   int i;
  416.  
  417.   p_red = input->bm;
  418.   p_green = &p_red[input->hdr.plnlen];
  419.   p_blue = &p_green[input->hdr.plnlen];
  420.   p_output = output->bm;
  421.  
  422.   for (i=0; i < input->hdr.plnlen; i++)
  423.     {
  424.       b_red = *(p_red++);
  425.       b_green = *(p_green++);
  426.       b_blue = *(p_blue++);
  427.  
  428.       tree=basetree;
  429.  
  430.       while (tree->leaf == 0)
  431.     {
  432.       btest=b_field[tree->level];
  433.       branch=((b_red & btest) == 0) ? (UBYTE) 0 : (UBYTE) 4;
  434.       if ((b_green & btest) != 0) branch += (UBYTE) 2;
  435.       if ((b_blue & btest) != 0) branch += (UBYTE) 1;
  436.       tree=tree->sub[branch];
  437.     }
  438.  
  439.       *(p_output++) = tree->color;
  440.     }
  441.  
  442.   p_red = output->cm;
  443.   p_green = &p_red[colors];
  444.   p_blue = &p_green[colors];
  445.  
  446.   for (i=0; i < colors; i++)
  447.     {
  448.       *(p_red++) = palette[i][RED];
  449.       *(p_green++) = palette[i][GREEN];
  450.       *(p_blue++) = palette[i][BLUE];
  451.     }
  452. }
  453.  
  454. /************************************************************************
  455.  * search tree                                                          *
  456.  ************************************************************************/
  457.  
  458. void search_tree(OCTREE tree)
  459. {
  460.   OCTREE subtree;
  461.   int i;
  462.  
  463.   tree->index=tree_count++;
  464.   tree->nlist=tlist;
  465.   tlist=tree;
  466.  
  467.   while (tree->pixels_low >= BIGVAL)
  468.     {
  469.       tree->pixels_low -= BIGVAL;
  470.       tree->pixels_high++;
  471.     }
  472.  
  473.   while (tree->red_sum_low >= BIGVAL)
  474.     {
  475.       tree->red_sum_low -= BIGVAL;
  476.       tree->red_sum_high++;
  477.     }
  478.  
  479.   while (tree->green_sum_low >= BIGVAL)
  480.     {
  481.       tree->green_sum_low -= BIGVAL;
  482.       tree->green_sum_high++;
  483.     }
  484.  
  485.   while (tree->blue_sum_low >= BIGVAL)
  486.     {
  487.       tree->blue_sum_low -= BIGVAL;
  488.       tree->blue_sum_high++;
  489.     }
  490.  
  491.   if (tree->leaf == FALSE && tree->level < leaf_level)
  492.     {
  493.       for (i=0; i < 8; i++)
  494.     {
  495.       subtree=tree->sub[i];
  496.       if (subtree != NULL)
  497.         search_tree(subtree);
  498.     }
  499.     }
  500. }
  501.  
  502.  
  503. /************************************************************************
  504.  * out_tree                                                             *
  505.  ************************************************************************/
  506.  
  507. int out_tree(char *tfname)
  508. {
  509.   FILE *fopen(), *output;
  510.   OCTREE twork, thelp;
  511.   int iwas,isub,i;
  512.  
  513.   fprintf(stderr,"Write octree file `%s'\n",tfname);
  514.  
  515.   if ((output = fopen(tfname, "w")) == NULL)
  516.     {
  517.       fprintf(stderr,"Error opening octree-file `%s'\n",tfname);
  518.       return(1);
  519.     }
  520.  
  521.   fprintf(output,"%s\n",Kennung);
  522.   fprintf(output,"%d %d\n",tree_count,max_colors);
  523.   fprintf(output,"%d %d %d\n",octree_size,reduce_level,leaf_level);
  524.  
  525.   for (i=0; i <= MAXDEPTH; i++)
  526.     {
  527.       thelp=reduce_list[i];
  528.       iwas=(thelp == NULL) ? 0 : (thelp->index+1);
  529.       fprintf(output," %X",iwas);
  530.     }
  531.  
  532.   fprintf(output,"\n");
  533.  
  534.   twork=tlist;
  535.   while (twork != NULL)
  536.     {
  537.       if (twork->leaf == FALSE)
  538.     isub=twork->sub_count;
  539.       else
  540.     isub=0;
  541.  
  542.       fprintf(output,"%d %d %d %X %X %X %X %X %X %X %X",
  543.           (int) twork->leaf,
  544.           (int) twork->level,
  545.           isub,
  546.           twork->pixels_low,
  547.           twork->pixels_high,
  548.           twork->red_sum_low,
  549.           twork->red_sum_high,
  550.           twork->green_sum_low,
  551.           twork->green_sum_high,
  552.           twork->blue_sum_low,
  553.           twork->blue_sum_high);
  554.  
  555.       if (isub != 0)
  556.     {
  557.       for (i=0; i< 8; i++)
  558.         {
  559.           thelp=twork->sub[i];
  560.           iwas=(thelp == NULL) ? 0 : (thelp->index+1);
  561.           fprintf(output," %X",iwas);
  562.         }
  563.     }
  564.  
  565.       thelp=twork->next_reduceable;
  566.       iwas=(thelp == NULL) ? 0 : (thelp->index+1);
  567.  
  568.       fprintf(output," %X\n",iwas);
  569.  
  570.       twork=twork->nlist;
  571.     }
  572.  
  573.   fclose(output);
  574.   return(0);
  575. }
  576.  
  577. /************************************************************************
  578.  * input_tree                                                             *
  579.  ************************************************************************/
  580.  
  581. int input_tree(char *tfname, int add_flag)
  582. {
  583.   FILE *fopen(), *input;
  584.   OCTREE twork;
  585.   int n,i,iwas,il;
  586.  
  587.   if ((input = fopen(tfname, "r")) == NULL)
  588.     {
  589.       if (add_flag == 1)
  590.     {
  591.       fprintf(stderr,"New octree file `%s'\n",tfname);
  592.       return(0);
  593.     }
  594.       else
  595.     {
  596.       fprintf(stderr,"Can't open octree file `%s'\n",tfname);
  597.       return(1);
  598.     }
  599.     }
  600.  
  601.   fprintf(stderr,"Read octree file `%s'\n",tfname);
  602.   fflush(stderr);
  603.  
  604.   il=1;
  605.   if (check_kennung(input) != 1) goto Rfail;
  606.  
  607.   il=2;
  608.   if (fscanf(input,"%d",&tree_count) != 1) goto Rfail;
  609.   if (fscanf(input,"%d",&max_colors) != 1) goto Rfail;
  610.  
  611.   il=3;
  612.   if (fscanf(input,"%d",&octree_size) != 1) goto Rfail;
  613.   if (fscanf(input,"%d",&reduce_level) != 1) goto Rfail;
  614.   if (fscanf(input,"%d",&leaf_level) != 1) goto Rfail;
  615.  
  616.   tlist=(OCTREE) calloc(tree_count, sizeof(struct node));
  617.   if (tlist == NULL)
  618.     {
  619.       fprintf(stderr,"Out of memory\n");
  620.       fclose(input);
  621.       return(1);
  622.     }
  623.  
  624.   il=4;
  625.   for (i=0; i <= MAXDEPTH; i++)
  626.     {
  627.       if (fscanf(input,"%X",&iwas) != 1) goto Rfail;
  628.       if (iwas > tree_count)
  629.     {
  630.       fprintf(stderr,"Bad octree file (a): %d %d\n",i,iwas);
  631.       goto Rfail;
  632.     }
  633.       if (iwas > 0)
  634.     reduce_list[i]=&tlist[iwas-1];
  635.       else
  636.     reduce_list[i]=NULL;
  637.     }
  638.  
  639.   for (n=tree_count-1; n >= 0; n--)
  640.     {
  641.       il++;
  642.       twork=&tlist[n];
  643.       twork->index = 0;
  644.       if (fscanf(input,"%d",&iwas) != 1) goto Rfail; twork->leaf = iwas;
  645.       if (fscanf(input,"%d",&iwas) != 1) goto Rfail; twork->level = iwas;
  646.       if (fscanf(input,"%d",&iwas) != 1) goto Rfail; twork->sub_count = iwas;
  647.  
  648.       if (fscanf(input,"%lX %lX %lX %lX %lX %lX %lX %lX",
  649.          &(twork->pixels_low),
  650.          &(twork->pixels_high),
  651.          &(twork->red_sum_low),
  652.          &(twork->red_sum_high),
  653.          &(twork->green_sum_low),
  654.          &(twork->green_sum_high),
  655.          &(twork->blue_sum_low),
  656.          &(twork->blue_sum_high)) != 8) goto Rfail;
  657.       
  658.       if (twork->sub_count != 0)
  659.     {
  660.       for (i=0; i< 8; i++)
  661.         {
  662.           if (fscanf(input,"%X",&iwas) != 1) goto Rfail;
  663.           if (iwas > tree_count)
  664.         {
  665.           fprintf(stderr,"Bad octree file (b): %d %d\n",n,iwas);
  666.           goto Rfail;
  667.         }
  668.           if (iwas > 0)
  669.         twork->sub[i] = &tlist[iwas-1];
  670.           else
  671.         twork->sub[i] = NULL;
  672.         }
  673.     }
  674.       else
  675.     {
  676.       for (i=0; i< 8; i++)
  677.         twork->sub[i] = NULL;
  678.     }
  679.  
  680.       if (fscanf(input,"%X",&iwas) != 1) goto Rfail;
  681.       if (iwas > tree_count)
  682.     {
  683.       fprintf(stderr,"Bad octree file (c): %d %d\n",n,iwas);
  684.       goto Rfail;
  685.     }
  686.       if (iwas > 0)
  687.     twork->next_reduceable = &tlist[iwas-1];
  688.       else
  689.     twork->next_reduceable = NULL;
  690.     }
  691.  
  692.   fclose(input);
  693.  
  694.   basetree=tlist;
  695.   return(0);
  696.  
  697. Rfail:
  698.  
  699.   fprintf(stderr,"Error in line %d of file `%s'\n",il,tfname);
  700.   fclose(input);
  701.   return(1);
  702. }
  703.  
  704. /****************************************************************
  705.  * check_kennung
  706.  ****************************************************************/
  707.  
  708. int check_kennung(FILE *fp)
  709. {
  710.   int c, i;
  711.   char KennTest[MAX_KENN];
  712.  
  713.   i=0;
  714.   while (1)
  715.     {
  716.       c=getc(fp);
  717.       if (i < MAX_KENN) KennTest[i]=c;
  718.       if ((c == '\n') || (c == EOF))
  719.     {
  720.       if (i < MAX_KENN)
  721.         KennTest[i]='\0';
  722.       else
  723.         KennTest[MAX_KENN-1]='\0';
  724.       break;
  725.     }
  726.       i++;
  727.     }
  728.  
  729.   if (strcmp(Kennung,KennTest) != 0)
  730.     {
  731.       fprintf(stderr,"Wrong file format\n");
  732.       return(0);
  733.     }
  734.   return(1);
  735. }
  736.