Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 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
}