Blame |
Last modification |
View Log
| RSS feed
/*
* fs4.c --
*
* Procedures dealing with Floyd-Steinberg dithering with 4 error
* values propagated.
*
*/
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/* This file contains C code to do YCrCb -> colormap space. */
#include "fs4.h"
#include "video.h"
#include "proto.h"
#include "dither.h"
/* Structures containing precomputed error terms. */
static FS4Dither lum_index
[256];
static FS4Dither cr_index
[256];
static FS4Dither cb_index
[256];
/*
*--------------------------------------------------------------
*
* InitFS4Dither --
*
* Initializes structures used for f-s dithering. Precomputes
* error terms.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
InitFS4Dither
()
{
int i
;
for (i
=0; i
<256; i
++) {
lum_index
[i
].
value = (i
* LUM_RANGE
) / 256;
lum_index
[i
].
e1 = (7 * (i
-lum_values
[lum_index
[i
].
value])) / 16;
lum_index
[i
].
e2 = (i
-lum_values
[lum_index
[i
].
value])/16;
lum_index
[i
].
e3 = (5 * (i
- lum_values
[lum_index
[i
].
value])) / 16;
lum_index
[i
].
e4 = (i
-lum_values
[lum_index
[i
].
value]) - lum_index
[i
].
e1 -
lum_index
[i
].
e2 - lum_index
[i
].
e3;
lum_index
[i
].
value *= LUM_BASE
;
cr_index
[i
].
value = (i
* CR_RANGE
) / 256;
cr_index
[i
].
e1 = (7 * (i
-cr_values
[cr_index
[i
].
value])) / 16;
cr_index
[i
].
e2 = (i
-cr_values
[cr_index
[i
].
value])/16;
cr_index
[i
].
e3 = (5 * (i
- cr_values
[cr_index
[i
].
value])) / 16;
cr_index
[i
].
e4 = (i
-cr_values
[cr_index
[i
].
value]) - cr_index
[i
].
e1 -
cr_index
[i
].
e2 - cr_index
[i
].
e3;
cr_index
[i
].
value *= CR_BASE
;
cb_index
[i
].
value = (i
* CB_RANGE
) / 256;
cb_index
[i
].
e1 = (7 * (i
-cb_values
[cb_index
[i
].
value])) / 16;
cb_index
[i
].
e2 = (i
-cb_values
[cb_index
[i
].
value])/16;
cb_index
[i
].
e3 = (5 * (i
- cb_values
[cb_index
[i
].
value])) / 16;
cb_index
[i
].
e4 = (i
-cb_values
[cb_index
[i
].
value]) - cb_index
[i
].
e1 -
cb_index
[i
].
e2 - cb_index
[i
].
e3;
cb_index
[i
].
value *= CB_BASE
;
}
}
/*
*--------------------------------------------------------------
*
* DitherImage --
*
* Converts lum, cr, cb image planes into fixed colormap
* space. Uses Floyd-Steinberg dithering in serpentine
* pattern with standard 4 errors propogated.
*
* Results:
* The display plane is replaced by 8-bit colormap space
* image.
*
* Side effects:
* Hopefully, none.
*
*--------------------------------------------------------------
*/
void
FS4DitherImage
(lum
, cr
, cb
, disp
, rows
, cols
)
unsigned char *lum
, *cr
, *cb
, *disp
;
int rows
, cols
;
{
static char *cur_row_error
, *next_row_error
;
static int first
= 1;
char *cur_row_err_mark
, *next_row_err_mark
;
char *temp
;
int i
, j
, pixsum
, c_cols
;
unsigned char *cur_row
, *channel
, *dest_row
;
FS4Dither
*chan_index
;
if (first
) {
cur_row_error
= (char *) malloc(cols
+2);
next_row_error
= (char *) malloc(cols
+2);
first
= 0;
}
memset(cur_row_error
, 0, cols
+2);
memset(next_row_error
, 0, cols
+2);
for(i
=0; i
<rows
; i
+=2) {
cur_row
= lum
+ (i
*cols
);
dest_row
= disp
+ (i
*cols
);
cur_row_err_mark
= cur_row_error
+ 1;
next_row_err_mark
= next_row_error
+ 1;
for (j
=0; j
<cols
; j
++) {
pixsum
= *cur_row
+ *cur_row_err_mark
;
if (pixsum
< 0) pixsum
= 0;
else if (pixsum
> 255) pixsum
= 255;
*dest_row
= lum_index
[pixsum
].
value;
*(cur_row_err_mark
+1) += lum_index
[pixsum
].
e1;
*(next_row_err_mark
+1) += lum_index
[pixsum
].
e2;
*next_row_err_mark
+= lum_index
[pixsum
].
e3;
*(next_row_err_mark
-1) += lum_index
[pixsum
].
e4;
cur_row
++;
dest_row
++;
cur_row_err_mark
++;
next_row_err_mark
++;
}
temp
= cur_row_error
;
cur_row_error
= next_row_error
;
next_row_error
= temp
;
memset(next_row_error
, 0, cols
+2);
cur_row
+= cols
-1;
dest_row
+= cols
-1;
cur_row_err_mark
= cur_row_error
+ cols
;
next_row_err_mark
= next_row_error
+ cols
;
for (j
=0; j
<cols
; j
++) {
pixsum
= *cur_row
+ *cur_row_err_mark
;
if (pixsum
< 0) pixsum
= 0;
else if (pixsum
> 255) pixsum
= 255;
*dest_row
= lum_index
[pixsum
].
value;
*(cur_row_err_mark
-1) += lum_index
[pixsum
].
e1;
*(next_row_err_mark
-1) += lum_index
[pixsum
].
e2;
*next_row_err_mark
+= lum_index
[pixsum
].
e3;
*(next_row_err_mark
+1) += lum_index
[pixsum
].
e4;
cur_row
--;
dest_row
--;
cur_row_err_mark
--;
next_row_err_mark
--;
}
temp
= cur_row_error
;
cur_row_error
= next_row_error
;
next_row_error
= temp
;
memset(next_row_error
, 0, cols
+2);
}
memset(cur_row_error
, 0, cols
+2);
c_cols
= cols
>> 1;
channel
= cr
;
chan_index
= cr_index
;
repeat
:
for (i
=0; i
< rows
; i
+=2) {
cur_row
= channel
+ ((i
>>1)*c_cols
);
dest_row
= disp
+ (i
*cols
);
cur_row_err_mark
= cur_row_error
+1;
next_row_err_mark
= next_row_error
+1;
for (j
=0; j
<cols
; j
++) {
int p_val
;
p_val
= *cur_row
;
pixsum
= *cur_row_err_mark
+ p_val
;
if (pixsum
< 0) pixsum
= 0;
else if (pixsum
> 255) pixsum
= 255;
*dest_row
+= chan_index
[pixsum
].
value;
*(cur_row_err_mark
+1) += chan_index
[pixsum
].
e1;
*(next_row_err_mark
+1) += chan_index
[pixsum
].
e2;
*next_row_err_mark
+= chan_index
[pixsum
].
e3;
*(next_row_err_mark
-1) += chan_index
[pixsum
].
e4;
if (j
&1) cur_row
++;
dest_row
++;
cur_row_err_mark
++;
next_row_err_mark
++;
}
temp
= cur_row_error
;
cur_row_error
= next_row_error
;
next_row_error
= temp
;
memset(next_row_error
, 0, cols
+2);
cur_row
+= c_cols
-1;
dest_row
+= cols
-1;
cur_row_err_mark
= cur_row_error
+cols
;
next_row_err_mark
= next_row_error
+cols
;
for (j
=0; j
<cols
; j
++) {
int p_val
;
p_val
= *cur_row
;
pixsum
= *cur_row_err_mark
+ p_val
;
if (pixsum
< 0) pixsum
= 0;
else if (pixsum
> 255) pixsum
= 255;
*dest_row
+= chan_index
[pixsum
].
value;
*(cur_row_err_mark
-1) += chan_index
[pixsum
].
e1;
*(next_row_err_mark
-1) += chan_index
[pixsum
].
e2;
*next_row_err_mark
+= chan_index
[pixsum
].
e3;
*(next_row_err_mark
+1) += chan_index
[pixsum
].
e4;
if (j
&1) cur_row
--;
dest_row
--;
cur_row_err_mark
--;
next_row_err_mark
--;
}
temp
= cur_row_error
;
cur_row_error
= next_row_error
;
next_row_error
= temp
;
memset(next_row_error
, 0, cols
+2);
}
if (channel
== cr
) {
channel
= cb
;
chan_index
= cb_index
;
memset(cur_row_error
, 0, cols
+2);
goto repeat
;
}
dest_row
= disp
;
for (i
=0; i
<rows
; i
++) {
for (j
=0; j
<cols
; j
++) {
*dest_row
= pixel
[*dest_row
];
dest_row
++;
}
}
}