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

  1. /****************************************************************
  2.  * fpplc.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. #include <stdio.h>
  17. #include "fpfli.h"
  18.  
  19. static int change[FLI_MAX_X];
  20. static int val[FLI_MAX_X];
  21. static int work[FLI_MAX_X];
  22.  
  23. int
  24. make_lc_line
  25. (
  26. unsigned char *preprevious_line,
  27. unsigned char *previous_line,
  28. unsigned char *current_line,
  29. unsigned char *lc_line,
  30. int start_flag
  31. );
  32.  
  33. static int improve_lc_line();
  34. static int test_lc_skip();
  35. static int test_lc_packets();
  36.  
  37. static int new_pixels;
  38. static int merge_count;
  39.  
  40. /****************************************************************
  41.  * make_lc_chunk
  42.  ****************************************************************/
  43.  
  44. int
  45. make_lc_chunk
  46. (
  47. unsigned char *preprevious,            /* pre previous image */
  48. unsigned char *previous,            /* previous image */
  49. unsigned char *current                /* current image */
  50. )
  51. {
  52.   int skip_count, start_flag, last_mod;
  53.   unsigned char *lc_line;
  54.   int chunk_count, line_count;
  55.   int j, line_size, help;
  56.   float change_factor;
  57.  
  58.   new_pixels=0;
  59.   chunk_count=10;        /* 4 bytes for total size of chunk (header)*/
  60.                 /* 2 bytes for chunk type (header)*/
  61.                 /* 2 bytes for number of skipped lines */
  62.                 /* 2 bytes for number of modified lines */
  63.  
  64.   skip_count=-1;
  65.   last_mod=-1;
  66.   start_flag=0;
  67.  
  68.   for (j=0; j < fli_height; j++)
  69.     {
  70.       lc_line = &pixel_chunk_buffer[chunk_count];
  71.       line_size = make_lc_line(preprevious, previous, current, 
  72.                    lc_line, start_flag);
  73.  
  74.       preprevious += fli_width;
  75.       previous += fli_width;
  76.       current += fli_width;
  77.  
  78.       if (line_size > 0)            /* yes, we got a new line */
  79.     {
  80.       chunk_count += line_size;
  81.       if (skip_count == -1)
  82.         skip_count = j;
  83.       start_flag=1;
  84.     }
  85.       if (line_size > 1)
  86.     last_mod = j;
  87.     }
  88.  
  89.   if (last_mod == -1)        /* no lines no chunk */
  90.     return(0);
  91.  
  92.   line_count=last_mod - skip_count + 1;
  93.  
  94.   if ((chunk_count % 2) == 1)
  95.     add_bytes(pixel_chunk_buffer, &chunk_count, 0x0000, IOM_UBYTE);
  96.  
  97.   help=0;
  98.   add_bytes(pixel_chunk_buffer, &help, chunk_count, IOM_LONG);
  99.   add_bytes(pixel_chunk_buffer, &help, FLI_LC, IOM_UWORD);
  100.   add_bytes(pixel_chunk_buffer, &help, skip_count, IOM_UWORD);
  101.   add_bytes(pixel_chunk_buffer, &help, line_count, IOM_UWORD);
  102.  
  103.   change_factor=100.0*((float)new_pixels)/(fli_width*fli_height);
  104.  
  105.   fprintf(stdout," LC chunk: %d bytes    new pixels: %.2f %%\n",
  106.       chunk_count,change_factor);
  107.  
  108.   return(chunk_count);
  109. }
  110.  
  111. /****************************************************************
  112.  * make_lc_line
  113.  ****************************************************************/
  114.  
  115. int
  116. make_lc_line
  117. (
  118. unsigned char *preprevious_line,
  119. unsigned char *previous_line,
  120. unsigned char *current_line,
  121. unsigned char *lc_line,
  122. int start_flag
  123. )
  124. {
  125.   int skip_count, size_count, packets;
  126.   int i, m, ipos, help, ch_flag;
  127.  
  128.   ch_flag = 0;
  129.   for (i=0; i < fli_width; i++)
  130.     {
  131.       val[i]=current_line[i];
  132.       if ((previous_line[i] != current_line[i]) ||
  133.       ((double_buffer == 1) && (preprevious_line[i] != current_line[i])))
  134.     {
  135.       change[i]=1;            /* yes, update */
  136.       ch_flag=1;
  137.     }
  138.       else
  139.     {
  140.       change[i]=0;            /* no update */
  141.     }
  142.     }
  143.  
  144.   if (ch_flag == 0)
  145.     {
  146.       if (start_flag == 0)
  147.     return(0);
  148.       *lc_line = 0;
  149.       return(1);
  150.     }
  151.  
  152.   if (change[fli_width-1] != 0)
  153.     {
  154.       work[fli_width-1]=1;
  155.       new_pixels++;
  156.     }
  157.   else
  158.     {
  159.       work[fli_width-1]=0;
  160.     }
  161.  
  162.   for (i=(fli_width-2); i >= 0; i--)
  163.     {
  164.       if (change[i] != 0)
  165.     {
  166.       new_pixels++;
  167.       if (val[i] == val[i+1])
  168.         {
  169.           if (work[i+1] < 0)
  170.         {
  171.           work[i]=work[i+1]-1;
  172.           if (work[i] < -127) work[i]=-1;
  173.         }
  174.           else if (work[i+1] == 0)
  175.         {
  176.           work[i]=1;
  177.         }
  178.           else
  179.         {
  180.           work[i+1]=-1;
  181.           work[i]=-2;
  182.         }
  183.         }
  184.       else                /* count nonequal bytes */
  185.         {
  186.           if (work[i+1] > 0)
  187.         {
  188.           work[i]=work[i+1]+1;
  189.           if (work[i] > 127) work[i]=1;
  190.         }
  191.           else
  192.         {
  193.           work[i]=1;
  194.         }
  195.         }
  196.     }
  197.       else
  198.     {
  199.       work[i]=0;
  200.     }
  201.     }
  202.  
  203.   test_lc_skip();
  204.   merge_count = 1;
  205.   while (merge_count > 0)
  206.     {
  207.       merge_count=0;
  208.       improve_lc_line();
  209.     }
  210.   test_lc_packets();
  211.  
  212.   packets=0;
  213.   skip_count=0;
  214.   i=0;
  215.   ipos=1;
  216.  
  217.   while (i < fli_width)                /* assemble output */
  218.     {
  219.       if (work[i] != 0)                /* add data packet */
  220.     {
  221.       packets++;
  222.       size_count=work[i];
  223.       add_bytes(lc_line, &ipos, skip_count, IOM_UBYTE);
  224.       add_bytes(lc_line, &ipos, size_count, IOM_SBYTE);
  225.       if (size_count < 0)
  226.         {
  227.           m=i;
  228.           add_bytes(lc_line, &ipos, val[i], IOM_UBYTE);
  229.           i -= size_count;
  230.         }
  231.       else
  232.         {
  233.           for (m=0; m < size_count; m++)
  234.         {
  235.           add_bytes(lc_line, &ipos, val[i++], IOM_UBYTE);
  236.         }
  237.         }
  238.       skip_count=0;
  239.     }
  240.       else
  241.     {
  242.       skip_count++;
  243.       i++;
  244.     }
  245.     }
  246.  
  247.   /* printf("(%d %d) ",packets,ipos); */
  248.  
  249.   help=0;
  250.   add_bytes(lc_line, &help, packets, IOM_UBYTE);
  251.  
  252.   return(ipos);                /* return number of bytes */
  253. }
  254.  
  255. /****************************************************************
  256.  * get_packet_start
  257.  ****************************************************************/
  258.  
  259. static int get_packet_start(int i)
  260. {
  261.   int j,igo;
  262.  
  263.   igo=0;
  264.  
  265.   if (work[i] > 0)
  266.     {
  267.       for (j=i; j > 0; j--)
  268.     {
  269.       if (work[j-1] != work[j]+1)
  270.         {
  271.           igo=j;
  272.           break;
  273.         }
  274.     }
  275.     }
  276.   else
  277.     {
  278.       for (j=i; j > 0; j--)
  279.     {
  280.       if (work[j-1] != work[j]-1)
  281.         {
  282.           igo=j;
  283.           break;
  284.         }
  285.     }
  286.     }
  287.  
  288.   return(igo);
  289. }
  290.  
  291.  
  292. /****************************************************************
  293.  * merge_packets
  294.  ****************************************************************/
  295.  
  296. static int merge_packets(int igo1, int igo2, int m)
  297. {
  298.   int j, len;
  299.  
  300.   len = igo2-igo1+1;
  301.   if (len > 127) return(0);
  302.  
  303.   merge_count++;
  304.  
  305.   if (m == 1)
  306.     for (j=igo2; j >= igo1; j--) work[j] = m++;
  307.   else if (m == -1)
  308.     for (j=igo2; j >= igo1; j--) work[j] = m--;
  309.  
  310.   return(m);
  311. }
  312.  
  313. /****************************************************************
  314.  * improve_lc_line
  315.  ****************************************************************/
  316.  
  317. static int improve_lc_line()
  318. {
  319.   int i,igo1,igo2;
  320.  
  321.   for (i=0; i < fli_width-1; i++)                  /* | +1 | -2 | */
  322.     {                                              /* | +1 | -3 | */
  323.  
  324.       if ((work[i] == 1) && ((work[i+1] == -2) || (work[i+1] == -3)))
  325.     {
  326.       igo1 = get_packet_start(i);
  327.       igo2 = i-work[i+1];
  328.       merge_packets(igo1,igo2,1);
  329.     }
  330.     }
  331.  
  332.   for (i=0; i < fli_width-2; i++)                  /* | XX | -2 | -1 | +N | */
  333.     {
  334.       if ((work[i] == -2) && (work[i+2] > 0) && 
  335.       ((i == 0) || (work[i-1] != -3)))
  336.     {
  337.       igo1 = i;
  338.       igo2 = i+1+work[i+2];
  339.       merge_packets(igo1,igo2,1);
  340.     }
  341.     }
  342.  
  343.   for (i=0; i < fli_width-3; i++)           /* | XX | -3 | -2 | -1 | +N | */
  344.     {
  345.       if ((work[i] == -3) && (work[i+3] > 0) &&
  346.       ((i == 0) || (work[i-1] != -4)))
  347.     {
  348.       igo1 = i;
  349.       igo2 = i+2+work[i+3];
  350.       merge_packets(igo1,igo2,1);
  351.     }
  352.     }
  353.  
  354.   for (i=0; i < fli_width-2; i++)                  /* | XX | -2 | -1 | -2 | */
  355.     {
  356.       if ((work[i] == -2) && (work[i+2] == -2) && 
  357.       ((i == 0) || work[i-1] != -3))
  358.     {
  359.       igo1 = i;
  360.       igo2 = i+3;
  361.       merge_packets(igo1,igo2,1);
  362.     }
  363.     }
  364.  
  365.   for (i=0; i < fli_width-2; i++)                  /* | +1 |  0 | +N | */
  366.     {
  367.       if ((work[i] == 1) && (work[i+1] == 0) && (work[i+2] > 0))
  368.     {
  369.       igo1 = get_packet_start(i);
  370.       igo2 = i+1+work[i+2];
  371.       merge_packets(igo1,igo2,1);
  372.     }
  373.     }
  374.  
  375.   for (i=0; i < fli_width-2; i++)                  /* | -1 |  0 | -N | */
  376.     {
  377.       if ((work[i] == -1) && (work[i+1] == 0) && (work[i+2] < 0) &&
  378.       (val[i] == val[i+1]) && (val[i] == val[i+2]))
  379.     {
  380.       igo1 = get_packet_start(i);
  381.       igo2 = i+1-work[i+2];
  382.       merge_packets(igo1,igo2,-1);
  383.     }
  384.     }
  385.  
  386.   for (i=0; i < fli_width-3; i++)             /* | XX | -2 | -1 | 0 | +N | */
  387.     {
  388.       if ((work[i] == -2) && (work[i+2] == 0) && (work[i+3] > 0) &&
  389.       ((i == 0) || (work[i-1] != -3)))
  390.     {
  391.       igo1=i;
  392.       igo2 = i+2+work[i+2];
  393.       merge_packets(igo1,igo2,1);
  394.     }
  395.     }
  396.  
  397.   for (i=0; i < fli_width-2; i++)                  /* | +1 |  0 | -2 | */
  398.     {
  399.       if ((work[i] == 1) && (work[i+1] == 0) && (work[i+2] == -2))
  400.     {
  401.       igo1 = get_packet_start(i);
  402.       igo2 = i+3;
  403.       merge_packets(igo1,igo2,1);
  404.     }
  405.     }
  406.  
  407.   for (i=0; i < fli_width-3; i++)                  /* | +1 |  0 |  0 | +N | */
  408.     {
  409.       if ((work[i] == 1) && (work[i+1] == 0) &&
  410.       (work[i+2] == 0) && (work[i+3] > 0))
  411.     {
  412.       igo1 = get_packet_start(i);
  413.       igo2 = i+2+work[i+2];
  414.       merge_packets(igo1,igo2,1);
  415.     }
  416.     }
  417.  
  418.   for (i=0; i < fli_width-3; i++)                  /* | -1 |  0 |  0 | -N | */
  419.     {
  420.       if ((work[i] == -1) && (work[i+1] == 0) &&
  421.       (work[i+2] == 0) && (work[i+3] < 0) &&
  422.       (val[i] == val[i+1]) && (val[i] == val[i+2]) &&
  423.       (val[i] == val[i+3]))
  424.     {
  425.       igo1 = get_packet_start(i);
  426.       igo2 = i+2-work[i+2];
  427.       merge_packets(igo1,igo2,-1);
  428.     }
  429.     }
  430.  
  431.   for (i=0; i < fli_width-1; i++)                  /* | +1 | +N | */
  432.     {
  433.       if ((work[i] == 1) && (work[i+1] > 0))
  434.     {
  435.       igo1 = get_packet_start(i);
  436.       igo2 = i+work[i+1];
  437.       merge_packets(igo1,igo2,1);
  438.     }
  439.     }
  440.  
  441.   return(1);
  442. }
  443.  
  444. /****************************************************************
  445.  * test_lc_skip
  446.  ****************************************************************/
  447.  
  448. static int test_lc_skip()
  449. {
  450.   int i, iend, ic;
  451.  
  452.   iend=-1;
  453.   for (i=fli_width-1; i >= 0; i--)
  454.     if (work[i] != 0)
  455.       {
  456.     iend=i;
  457.     break;
  458.       }
  459.  
  460.   ic=0;
  461.   for (i=0; i <= iend; i++)
  462.     {
  463.       if (work[i] == 0)
  464.     {
  465.       ic++;
  466.       if (ic >= 256)
  467.         {
  468.           work[i]=1;
  469.           ic=0;
  470.         }
  471.     }
  472.       else
  473.     ic=0;
  474.     }
  475.  
  476.   return(iend);
  477. }
  478.  
  479. /****************************************************************
  480.  * test_lc_packets
  481.  ****************************************************************/
  482.  
  483. static int test_lc_packets()
  484. {
  485.   int packets,i, igo1,igo2, istart,iend;
  486.  
  487.   packets=0;
  488.   for (i = 0; i < fli_width; i++)
  489.     if ((work[i] == 1) || (work[i] == -1)) packets++;
  490.   if (packets < 256) return(packets);
  491.  
  492.   istart=0;
  493.   iend=0;
  494.   for (i=0; i < fli_width; i++)
  495.     if (work[i] != 0)
  496.       {
  497.     istart=i;
  498.     break;
  499.       }
  500.  
  501.   for (i=fli_width-1; i >= 0; i--)
  502.     if (work[i] != 0)
  503.       {
  504.     iend=i;
  505.     break;
  506.       }
  507.  
  508.   igo1=istart;
  509.   while (igo1 <= iend)
  510.     {
  511.       igo2=i+125;
  512.       if (igo2 > iend) igo2=iend;
  513.       merge_packets(igo1,igo2,1);
  514.       igo1=igo2+1;
  515.     }
  516.  
  517.   return(-1);
  518. }
  519.