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

  1. /****************************************************************
  2.  * fppdelta.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_delta_line
  25. (
  26. unsigned char *preprevious_line,
  27. unsigned char *previous_line,
  28. unsigned char *current_line,
  29. unsigned char *delta_line,
  30. int line_skip_count
  31. );
  32.  
  33. static int improve_delta_line();
  34. static int test_delta_skip();
  35.  
  36. static int new_pixels;
  37. static int merge_count;
  38.  
  39. /****************************************************************
  40.  * make_delta_chunk
  41.  ****************************************************************/
  42.  
  43. int
  44. make_delta_chunk
  45. (
  46. unsigned char *preprevious,            /* pre previous image */
  47. unsigned char *previous,            /* previous image */
  48. unsigned char *current                /* current image */
  49. )
  50. {
  51.     int skip_count;
  52.     unsigned char *delta_line;
  53.     int chunk_count, line_count;
  54.     int j, line_size, help;
  55.     float change_factor;
  56.  
  57.     new_pixels=0;
  58.     chunk_count=8;        /* 4 bytes for total size of chunk (header)*/
  59.                 /* 2 bytes for chunk type (header)*/
  60.                 /* 2 bytes for number of compressed lines */
  61.  
  62.     skip_count=0;
  63.     line_count=0;
  64.  
  65.     for (j=0; j < fli_height; j++)
  66.     {
  67.     delta_line = &pixel_chunk_buffer[chunk_count];
  68.  
  69.     /* printf(" Line: %d   chunk_count: %d   skip: %d\n",
  70.                     j,chunk_count,skip_count); */
  71.  
  72.     line_size = make_delta_line(preprevious, previous, current, 
  73.             delta_line, skip_count);
  74.  
  75.     preprevious += fli_width;
  76.     previous += fli_width;
  77.     current += fli_width;
  78.  
  79.     /* printf(" Line: %d  size: %d\n",j,line_size); */
  80.  
  81.     if (line_size > 0)            /* yes, we got a new line */
  82.     {
  83.         chunk_count += line_size;
  84.         skip_count=0;
  85.         line_count++;
  86.     }
  87.     else
  88.     {
  89.         skip_count--;
  90.     }
  91.     }
  92.  
  93.     if (line_count == 0)        /* no lines no chunk */
  94.     return(0);
  95.  
  96.     if ((chunk_count % 2) == 1)
  97.     add_bytes(pixel_chunk_buffer, &chunk_count, 0x0000, IOM_UBYTE);
  98.  
  99.     help=0;
  100.     add_bytes(pixel_chunk_buffer, &help, chunk_count, IOM_LONG);
  101.     add_bytes(pixel_chunk_buffer, &help, FLI_DELTA, IOM_UWORD);
  102.     add_bytes(pixel_chunk_buffer, &help, line_count, IOM_UWORD);
  103.  
  104.     change_factor=100.0*((float)new_pixels)/(fli_width*fli_height);
  105.  
  106.     fprintf(stdout," Delta chunk: %d bytes    new pixels: %.2f %%\n",
  107.         chunk_count,change_factor);
  108.  
  109.     return(chunk_count);
  110. }
  111.  
  112. /****************************************************************
  113.  * make_delta_line
  114.  ****************************************************************/
  115.  
  116. int
  117. make_delta_line
  118. (
  119. unsigned char *preprevious_line,
  120. unsigned char *previous_line,
  121. unsigned char *current_line,
  122. unsigned char *delta_line,
  123. int line_skip_count
  124. )
  125. {
  126.   int skip_count, size_count, packets;
  127.   int i, m, ipos, help, ch_flag;
  128.  
  129.   ch_flag=0;
  130.   for (i=0; i < fli_width; i++)
  131.     {
  132.       val[i]=current_line[i];
  133.       if ((previous_line[i] != current_line[i]) ||
  134.       ((double_buffer == 1) && (preprevious_line[i] != current_line[i])))
  135.     {
  136.       change[i]=1;            /* yes, update */
  137.       ch_flag=1;
  138.     }
  139.       else
  140.     {
  141.       change[i]=0;            /* no update */
  142.     }
  143.     }
  144.  
  145.   if (ch_flag == 0) return(0);
  146.  
  147.   if ((change[fli_width-2] != 0) || (change[fli_width-1] != 0))
  148.     {
  149.       work[fli_width-2]=1;
  150.       new_pixels += 2;
  151.     }
  152.   else
  153.     {
  154.       work[fli_width-2]=0;
  155.     }
  156.   work[fli_width-1]=0;
  157.  
  158.   for (i=(fli_width-4); i >= 0; i -= 2)
  159.     {
  160.       if ((change[i] != 0) || (change[i+1] != 0))
  161.     {
  162.       new_pixels += 2;
  163.       if ((val[i] == val[i+2]) && (val[i+1] == val[i+3]))
  164.         {
  165.           if (work[i+2] < 0)
  166.         {
  167.           work[i]=work[i+2]-1;
  168.           if (work[i] < -127) work[i]=-1;
  169.         }
  170.           else if (work[i+2] == 0)
  171.         {
  172.           work[i]=1;
  173.         }
  174.           else
  175.         {
  176.           work[i+2]=-1;
  177.           work[i]=-2;
  178.         }
  179.         }
  180.       else                /* count nonequal words */
  181.         {
  182.           if (work[i+2] > 0)
  183.         {
  184.           work[i]=work[i+2]+1;
  185.           if (work[i] > 127) work[i]=1;
  186.         }
  187.           else
  188.         {
  189.           work[i]=1;
  190.         }
  191.         }
  192.     }
  193.       else
  194.     {
  195.       work[i]=0;
  196.     }
  197.       work[i+1]=0;
  198.     }
  199.  
  200.   test_delta_skip();
  201.   merge_count = 1;
  202.   while (merge_count > 0)
  203.     {
  204.       merge_count=0;
  205.       improve_delta_line();
  206.     }
  207.  
  208.   packets=0;
  209.   skip_count=0;
  210.   i=0;
  211.   if (line_skip_count != 0)
  212.     ipos=4;
  213.   else
  214.     ipos=2;
  215.  
  216.   while (i < fli_width)                /* assemble output */
  217.     {
  218.       if (work[i] != 0)                /* add data packet */
  219.     {
  220.       packets++;
  221.       size_count=work[i];
  222.       add_bytes(delta_line, &ipos, skip_count, IOM_UBYTE);
  223.       add_bytes(delta_line, &ipos, size_count, IOM_SBYTE);
  224.       if (size_count < 0)
  225.         {
  226.           m=i;
  227.           add_bytes(delta_line, &ipos, val[i], IOM_UBYTE);
  228.           add_bytes(delta_line, &ipos, val[i+1], IOM_UBYTE);
  229.           i -= 2*size_count;
  230.         }
  231.       else
  232.         {
  233.           for (m=0; m < size_count; m++)
  234.         {
  235.           add_bytes(delta_line, &ipos, val[i++], IOM_UBYTE);
  236.           add_bytes(delta_line, &ipos, val[i++], IOM_UBYTE);
  237.         }
  238.         }
  239.       skip_count=0;
  240.     }
  241.       else
  242.     {
  243.       skip_count++;
  244.       i++;
  245.     }
  246.     }
  247.  
  248.   help=0;
  249.   if (line_skip_count != 0)
  250.     {
  251.       add_bytes(delta_line, &help, line_skip_count, IOM_SWORD);
  252.       add_bytes(delta_line, &help, packets, IOM_SWORD);
  253.     }
  254.   else
  255.     {
  256.       add_bytes(delta_line, &help, packets, IOM_SWORD);
  257.     }
  258.  
  259.   return(ipos);                /* return number of bytes */
  260. }
  261.  
  262. /****************************************************************
  263.  * get_packet_start
  264.  ****************************************************************/
  265.  
  266. static int get_packet_start(int i)
  267. {
  268.   int j,igo;
  269.  
  270.   igo=0;
  271.  
  272.   if (work[i] > 0)
  273.     {
  274.       for (j=i; j > 1; j -= 2)
  275.     {
  276.       if (work[j-2] != work[j]+1)
  277.         {
  278.           igo=j;
  279.           break;
  280.         }
  281.     }
  282.     }
  283.   else
  284.     {
  285.       for (j=i; j > 1; j -= 2)
  286.     {
  287.       if (work[j-2] != work[j]-1)
  288.         {
  289.           igo=j;
  290.           break;
  291.         }
  292.     }
  293.     }
  294.  
  295.   return(igo);
  296. }
  297.  
  298.  
  299. /****************************************************************
  300.  * merge_packets
  301.  ****************************************************************/
  302.  
  303. static int merge_packets(int igo1, int igo2, int m)
  304. {
  305.   int j, len;
  306.  
  307.   len = (igo2-igo1)/2+1;
  308.   if (len > 127) return(0);
  309.  
  310.   merge_count++;
  311.   if (m == 1)
  312.     for (j=igo2; j >= igo1; j -= 2) work[j] = m++;
  313.   else if (m == -1)
  314.     for (j=igo2; j >= igo1; j -= 2) work[j] = m--;
  315.  
  316.   return(m);
  317. }
  318.  
  319. /****************************************************************
  320.  * improve_delta_line
  321.  ****************************************************************/
  322.  
  323. static int improve_delta_line()
  324. {
  325.   int i,igo1,igo2;
  326.  
  327.   for (i=0; i < fli_width-5; i += 2)                  /* | -1 |  0 | -N | */
  328.     {
  329.       if ((work[i] == -1) && (work[i+2] == 0) && (work[i+4] < 0) &&
  330.       (val[i] == val[i+2]) && (val[i] == val[i+4]) &&
  331.       (val[i+1] == val[i+3]) && (val[i+1] == val[i+5]))
  332.     {
  333.       igo1 = get_packet_start(i);
  334.       igo2 = i+2-2*work[i+4];
  335.       merge_packets(igo1,igo2,-1);
  336.     }
  337.     }
  338.  
  339.   for (i=0; i < fli_width-8; i += 2)       /* | +1 | -3 | -2 | -1 | +N |*/
  340.     {
  341.       if ((work[i] == 1) && (work[i+2] == -3) && (work[i+8] > 0))
  342.     {
  343.       igo1 = get_packet_start(i);
  344.       igo2 = i+6+2*work[i+8];
  345.       merge_packets(igo1,igo2,1);
  346.     }
  347.     }
  348.  
  349.   for (i=0; i < fli_width-2; i += 2)                  /* | +1 | -2 | */
  350.     {
  351.       if ((work[i] == 1) && (work[i+2] == -2))
  352.     {
  353.       igo1 = get_packet_start(i);
  354.       igo2 = i+4;
  355.       merge_packets(igo1,igo2,1);
  356.     }
  357.     }
  358.  
  359.   for (i=0; i < fli_width-4; i += 2)               /* | XX | -2 | -1 | +N | */
  360.     {
  361.       if ((work[i] == -2) && (work[i+4] > 0) && 
  362.       ((i == 0) || work[i-2] != -3))
  363.     {
  364.       igo1 = i;
  365.       igo2 = i+2+2*work[i+4];
  366.       merge_packets(igo1,igo2,1);
  367.     }
  368.     }
  369.  
  370.   for (i=0; i < fli_width-4; i += 2)                  /* | +1 |  0 | +N | */
  371.     {
  372.       if ((work[i] == 1) && (work[i+2] == 0) && (work[i+4] > 0))
  373.     {
  374.       igo1 = get_packet_start(i);
  375.       igo2 = i+2+2*work[i+4];
  376.       merge_packets(igo1,igo2,1);
  377.     }
  378.     }
  379.  
  380.   for (i=0; i < fli_width-4; i += 2)                  /* | +1 | +N | */
  381.     {
  382.       if ((work[i] == 1) && (work[i+2] > 0))
  383.     {
  384.       igo1 = get_packet_start(i);
  385.       igo2 = i+2*work[i+2];
  386.       merge_packets(igo1,igo2,1);
  387.     }
  388.     }
  389.  
  390.   return(1);
  391. }
  392.  
  393. /****************************************************************
  394.  * test_delta_skip
  395.  ****************************************************************/
  396.  
  397. static int test_delta_skip()
  398. {
  399.   int i, iend, ic;
  400.  
  401.   iend=-1;
  402.   for (i=fli_width-1; i >= 0; i--)
  403.     if (work[i] != 0)
  404.       {
  405.     iend=i;
  406.     break;
  407.       }
  408.  
  409.   ic=0;
  410.   for (i=0; i <= iend; i += 2)
  411.     {
  412.       if (work[i] == 0)
  413.     {
  414.       ic += 2;
  415.       if (ic >= 256)
  416.         {
  417.           work[i]=1;
  418.           ic=0;
  419.         }
  420.     }
  421.       else
  422.     ic=0;
  423.     }
  424.  
  425.   return(iend);
  426. }
  427.  
  428.