home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / mpeg_play-2.1 / fs4.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-09  |  7.6 KB  |  301 lines

  1. /*
  2.  * fs4.c --
  3.  *
  4.  *      Procedures dealing with Floyd-Steinberg dithering with 4 error
  5.  *      values propagated.
  6.  *
  7.  */
  8.  
  9. /*
  10.  * Copyright (c) 1995 The Regents of the University of California.
  11.  * All rights reserved.
  12.  * 
  13.  * Permission to use, copy, modify, and distribute this software and its
  14.  * documentation for any purpose, without fee, and without written agreement is
  15.  * hereby granted, provided that the above copyright notice and the following
  16.  * two paragraphs appear in all copies of this software.
  17.  * 
  18.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  19.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  20.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  21.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22.  * 
  23.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  24.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  25.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  26.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  27.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  28.  */
  29.  
  30. /* This file contains C code to do YCrCb -> colormap space. */
  31.  
  32. #include "fs4.h"
  33. #include "video.h"
  34. #include "proto.h"
  35. #include "dither.h"
  36.  
  37. /* Structures containing precomputed error terms. */
  38.  
  39. static FS4Dither lum_index[256];
  40. static FS4Dither cr_index[256];
  41. static FS4Dither cb_index[256];
  42.  
  43.  
  44. /*
  45.  *--------------------------------------------------------------
  46.  *
  47.  * InitFS4Dither --
  48.  *
  49.  *    Initializes structures used for f-s dithering. Precomputes
  50.  *      error terms.
  51.  *
  52.  * Results:
  53.  *    None.
  54.  *
  55.  * Side effects:
  56.  *      None.
  57.  *
  58.  *--------------------------------------------------------------
  59.  */
  60.  
  61. void
  62. InitFS4Dither()
  63. {
  64.   int i;
  65.  
  66.   for (i=0; i<256; i++) {
  67.     lum_index[i].value = (i * LUM_RANGE) / 256;
  68.  
  69.     lum_index[i].e1 = (7 * (i-lum_values[lum_index[i].value])) / 16;
  70.     lum_index[i].e2 = (i-lum_values[lum_index[i].value])/16;
  71.     lum_index[i].e3 = (5 *  (i - lum_values[lum_index[i].value])) / 16;
  72.     lum_index[i].e4 = (i-lum_values[lum_index[i].value]) - lum_index[i].e1 -
  73.       lum_index[i].e2 - lum_index[i].e3;
  74.  
  75.     lum_index[i].value *= LUM_BASE;
  76.  
  77.     cr_index[i].value = (i * CR_RANGE) / 256; 
  78.  
  79.     cr_index[i].e1 = (7 * (i-cr_values[cr_index[i].value])) / 16;
  80.     cr_index[i].e2 = (i-cr_values[cr_index[i].value])/16;
  81.     cr_index[i].e3 = (5 *  (i - cr_values[cr_index[i].value])) / 16;
  82.     cr_index[i].e4 = (i-cr_values[cr_index[i].value]) - cr_index[i].e1 -
  83.       cr_index[i].e2 - cr_index[i].e3;
  84.     cr_index[i].value *= CR_BASE;
  85.  
  86.     cb_index[i].value = (i * CB_RANGE) / 256; 
  87.  
  88.     cb_index[i].e1 = (7 * (i-cb_values[cb_index[i].value])) / 16;
  89.     cb_index[i].e2 = (i-cb_values[cb_index[i].value])/16;
  90.     cb_index[i].e3 = (5 *  (i - cb_values[cb_index[i].value])) / 16;
  91.     cb_index[i].e4 = (i-cb_values[cb_index[i].value]) - cb_index[i].e1 -
  92.       cb_index[i].e2 - cb_index[i].e3;
  93.     cb_index[i].value *= CB_BASE;
  94.  
  95.   }
  96.  
  97. }
  98.  
  99.  
  100. /*
  101.  *--------------------------------------------------------------
  102.  *
  103.  * DitherImage --
  104.  *
  105.  *    Converts lum, cr, cb image planes into fixed colormap
  106.  *      space. Uses Floyd-Steinberg dithering in serpentine
  107.  *      pattern with standard 4 errors propogated.
  108.  *
  109.  * Results:
  110.  *    The display plane is replaced by 8-bit colormap space
  111.  *      image.
  112.  *
  113.  * Side effects:
  114.  *      Hopefully, none.
  115.  *
  116.  *--------------------------------------------------------------
  117.  */
  118.  
  119. void 
  120. FS4DitherImage(lum, cr, cb, disp, rows, cols)
  121.      unsigned char *lum, *cr, *cb, *disp;
  122.      int rows, cols;
  123. {
  124.   static char *cur_row_error, *next_row_error;
  125.   static int first = 1;
  126.   char  *cur_row_err_mark, *next_row_err_mark;
  127.   char *temp;
  128.   int i, j, pixsum, c_cols;
  129.   unsigned char *cur_row, *channel, *dest_row;
  130.   FS4Dither *chan_index;
  131.  
  132.   if (first) {
  133.     cur_row_error = (char *) malloc(cols+2);
  134.     next_row_error = (char *) malloc(cols+2);
  135.     first = 0;
  136.   }
  137.  
  138.   memset(cur_row_error, 0, cols+2);
  139.   memset(next_row_error, 0, cols+2);
  140.  
  141.   for(i=0; i<rows; i+=2) {
  142.      cur_row = lum + (i*cols);
  143.      dest_row = disp + (i*cols);
  144.  
  145.      cur_row_err_mark = cur_row_error + 1;
  146.      next_row_err_mark = next_row_error + 1;
  147.  
  148.      for (j=0; j<cols; j++) {
  149.  
  150.        pixsum = *cur_row + *cur_row_err_mark;
  151.        if (pixsum < 0) pixsum = 0;
  152.        else if (pixsum > 255) pixsum = 255;
  153.  
  154.        *dest_row = lum_index[pixsum].value;
  155.        *(cur_row_err_mark+1) += lum_index[pixsum].e1; 
  156.        *(next_row_err_mark+1) += lum_index[pixsum].e2;
  157.        *next_row_err_mark += lum_index[pixsum].e3; 
  158.        *(next_row_err_mark-1) += lum_index[pixsum].e4;
  159.  
  160.        cur_row++;
  161.        dest_row++;
  162.        cur_row_err_mark++;
  163.        next_row_err_mark++;
  164.      }
  165.  
  166.      temp = cur_row_error;
  167.      cur_row_error = next_row_error;
  168.      next_row_error = temp;
  169.  
  170.      memset(next_row_error, 0, cols+2); 
  171.  
  172.      cur_row += cols-1;
  173.      dest_row += cols-1;
  174.      cur_row_err_mark = cur_row_error + cols;
  175.      next_row_err_mark = next_row_error + cols;
  176.  
  177.      for (j=0; j<cols; j++) {
  178.  
  179.        pixsum = *cur_row + *cur_row_err_mark;
  180.        if (pixsum < 0) pixsum = 0;
  181.        else if (pixsum > 255) pixsum = 255;
  182.  
  183.        *dest_row = lum_index[pixsum].value;
  184.        *(cur_row_err_mark-1) += lum_index[pixsum].e1; 
  185.        *(next_row_err_mark-1) += lum_index[pixsum].e2;
  186.        *next_row_err_mark += lum_index[pixsum].e3; 
  187.        *(next_row_err_mark+1) += lum_index[pixsum].e4;
  188.  
  189.        cur_row--;
  190.        dest_row--;
  191.        cur_row_err_mark--;
  192.        next_row_err_mark--;
  193.      }
  194.  
  195.      temp = cur_row_error;
  196.      cur_row_error = next_row_error;
  197.      next_row_error = temp;
  198.  
  199.      memset(next_row_error, 0, cols+2); 
  200.    }
  201.  
  202.   memset(cur_row_error, 0, cols+2); 
  203.  
  204.   c_cols = cols >> 1;
  205.  
  206.   channel = cr;
  207.   chan_index = cr_index;
  208.  
  209.  repeat:
  210.  
  211.   for (i=0; i < rows; i+=2) {
  212.     cur_row = channel + ((i>>1)*c_cols);
  213.     dest_row = disp + (i*cols);
  214.  
  215.     cur_row_err_mark = cur_row_error+1;
  216.     next_row_err_mark = next_row_error+1;
  217.     
  218.     for (j=0; j<cols; j++) {
  219.       int p_val;
  220.  
  221.       p_val = *cur_row;
  222.  
  223.       pixsum = *cur_row_err_mark + p_val;
  224.  
  225.       if (pixsum < 0) pixsum = 0;
  226.       else if (pixsum > 255) pixsum = 255;
  227.  
  228.       *dest_row += chan_index[pixsum].value;
  229.  
  230.       *(cur_row_err_mark+1) += chan_index[pixsum].e1; 
  231.       *(next_row_err_mark+1) += chan_index[pixsum].e2;
  232.       *next_row_err_mark += chan_index[pixsum].e3; 
  233.       *(next_row_err_mark-1) += chan_index[pixsum].e4;
  234.  
  235.  
  236.       if (j&1) cur_row++;
  237.       dest_row++;
  238.       cur_row_err_mark++;
  239.       next_row_err_mark++;
  240.     }
  241.       
  242.     temp = cur_row_error;
  243.     cur_row_error = next_row_error;
  244.     next_row_error = temp;
  245.  
  246.     memset(next_row_error, 0, cols+2);
  247.  
  248.     cur_row += c_cols-1;
  249.     dest_row += cols-1;
  250.     cur_row_err_mark = cur_row_error+cols;
  251.     next_row_err_mark = next_row_error+cols;
  252.  
  253.     for (j=0; j<cols; j++) {
  254.       int p_val;
  255.  
  256.       p_val = *cur_row;
  257.  
  258.       pixsum = *cur_row_err_mark + p_val;
  259.  
  260.       if (pixsum < 0) pixsum = 0;
  261.       else if (pixsum > 255) pixsum = 255;
  262.  
  263.       *dest_row += chan_index[pixsum].value;
  264.  
  265.       *(cur_row_err_mark-1) += chan_index[pixsum].e1; 
  266.       *(next_row_err_mark-1) += chan_index[pixsum].e2;
  267.       *next_row_err_mark += chan_index[pixsum].e3; 
  268.       *(next_row_err_mark+1) += chan_index[pixsum].e4;
  269.  
  270.       if (j&1) cur_row--;
  271.       dest_row--;
  272.       cur_row_err_mark--;
  273.       next_row_err_mark--;
  274.     }
  275.  
  276.     temp = cur_row_error;
  277.     cur_row_error = next_row_error;
  278.     next_row_error = temp;
  279.  
  280.     memset(next_row_error, 0, cols+2);
  281.   }
  282.  
  283.   if (channel == cr) {
  284.     channel = cb;
  285.     chan_index = cb_index;
  286.     memset(cur_row_error, 0, cols+2);
  287.  
  288.     goto repeat;
  289.   }
  290.  
  291.   dest_row = disp;
  292.  
  293.  
  294.   for (i=0; i<rows; i++) {
  295.     for (j=0; j<cols; j++) {
  296.       *dest_row =  pixel[*dest_row];
  297.       dest_row++;
  298.     }
  299.   }
  300. }
  301.