Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * hybrid.c --
3
 *
4
 *      Procedures dealing with hybrid dithers.
5
 *
6
 */
7
 
8
/*
9
 * Copyright (c) 1995 The Regents of the University of California.
10
 * All rights reserved.
11
 *
12
 * Permission to use, copy, modify, and distribute this software and its
13
 * documentation for any purpose, without fee, and without written agreement is
14
 * hereby granted, provided that the above copyright notice and the following
15
 * two paragraphs appear in all copies of this software.
16
 *
17
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
18
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
19
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
20
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
 *
22
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
23
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
25
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
26
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
27
 */
28
 
29
/* This file contains C code to implement an ordered dither. */
30
 
31
#include "video.h"
32
#include "proto.h"
33
#include "dither.h"
34
 
35
#define DITH_SIZE 16
36
 
37
 
38
/* Structures used to implement hybrid ordered dither/floyd-steinberg
39
   dither algorithm.
40
*/
41
 
42
static unsigned char *l_darrays[DITH_SIZE];
43
static unsigned char cr_fsarray[256][4];
44
static unsigned char cb_fsarray[256][4];
45
 
46
 
47
/*
48
 *--------------------------------------------------------------
49
 *
50
 *  InitHybridDither--
51
 *
52
 *      Structures intialized for hybrid dithering. Ordered dither
53
 *      patterns set for luminance channel, f-s errors precomputed
54
 *      for chrominance channels.
55
 *
56
 * Results:
57
 *      None.
58
 *
59
 * Side effects:
60
 *      None.
61
 *
62
 *--------------------------------------------------------------
63
 */
64
 
65
void
66
InitHybridDither()
67
{
68
  int i, j, k, err_range, threshval;
69
  unsigned char *lmark;
70
 
71
  for (i=0; i<DITH_SIZE; i++) {
72
    lmark = l_darrays[i] = (unsigned char *) malloc(256);
73
 
74
    for (j=0; j<lum_values[0]; j++) {
75
      *lmark++ = 0;
76
    }
77
 
78
    for (j=0; j<(LUM_RANGE-1); j++) {
79
      err_range = lum_values[j+1] - lum_values[j];
80
      threshval = ((i * err_range) / DITH_SIZE)+lum_values[j];
81
 
82
      for (k=lum_values[j]; k<lum_values[j+1]; k++) {
83
        if (k > threshval) *lmark++ = ((j+1) * (CR_RANGE * CB_RANGE));
84
        else *lmark++ = (j * (CR_RANGE * CB_RANGE));
85
      }
86
    }
87
 
88
    for (j=lum_values[LUM_RANGE-1]; j<256; j++) {
89
      *lmark++ = (LUM_RANGE-1)*(CR_RANGE * CB_RANGE);
90
    }
91
 
92
  }
93
  {
94
    int cr1, cr2, cr3, cr4, err1, err2;
95
    int cb1, cb2, cb3, cb4, val, nval;
96
 
97
    for (i=0; i<256; i++) {
98
 
99
      val = i;
100
 
101
      cr1 = (val * CR_RANGE) / 256;
102
      err1 = (val - cr_values[cr1])/2;
103
      err2 = (val - cr_values[cr1]) - err1;
104
 
105
      nval = val+err1;
106
      if (nval > 255) nval = 255;
107
      else if (nval < 0) nval = 0;
108
      cr2 = (nval * CR_RANGE) / 256;
109
      err1 = (nval - cr_values[cr2])/2;
110
 
111
      nval = val+err2;
112
      if (nval > 255) nval = 255;
113
      else if (nval < 0) nval = 0;
114
      cr3 = (nval * CR_RANGE) / 256;
115
      err2 = (nval - cr_values[cr3])/2;
116
 
117
      nval = val+err1+err2;
118
      if (nval > 255) nval = 255;
119
      else if (nval < 0) nval = 0;
120
      cr4 = (nval * CR_RANGE) / 256;
121
 
122
      cr_fsarray[i][0] = cr1*CB_RANGE;
123
      cr_fsarray[i][1] = cr2*CB_RANGE;
124
      cr_fsarray[i][2] = cr3*CB_RANGE;
125
      cr_fsarray[i][3] = cr4*CB_RANGE;
126
    }
127
 
128
    for (i=0; i<256; i++) {
129
 
130
      val = i;
131
 
132
      cb1 = (val * CB_RANGE) / 256;
133
      err1 = (val - cb_values[cb1])/2;
134
      err2 = (val - cb_values[cb1]) - err1;
135
 
136
      nval = val+err1;
137
      if (nval > 255) nval = 255;
138
      else if (nval < 0) nval = 0;
139
      cb2 = (nval * CB_RANGE) / 256;
140
      err1 = (nval - cb_values[cb2])/2;
141
 
142
      nval = val+err2;
143
      if (nval > 255) nval = 255;
144
      else if (nval < 0) nval = 0;
145
      cb3 = (nval * CB_RANGE) / 256;
146
      err2 = (nval - cb_values[cb3])/2;
147
 
148
      nval = val+err1+err2;
149
      if (nval > 255) nval = 255;
150
      else if (nval < 0) nval = 0;
151
      cb4 = (nval * CB_RANGE) / 256;
152
 
153
      cb_fsarray[i][0] = cb1;
154
      cb_fsarray[i][1] = cb2;
155
      cb_fsarray[i][2] = cb3;
156
      cb_fsarray[i][3] = cb4;
157
    }
158
  }
159
}
160
 
161
/*
162
 *--------------------------------------------------------------
163
 *
164
 * HybridDitherImage --
165
 *
166
 *      Dithers an image using an ordered dither.
167
 *      Assumptions made:
168
 *        1) The color space is allocated y:cr:cb = 8:4:4
169
 *        2) The spatial resolution of y:cr:cb is 4:1:1
170
 *      The luminance channel is dithered based on the standard
171
 *      ordered dither pattern for a 4x4 area. The Chrominance
172
 *      channels are dithered based on precomputed f-s errors.
173
 *      Two errors are propogated per pixel. Errors are NOT propogated
174
 *      beyond a 2x2 pixel area.
175
 *
176
 * Results:
177
 *      None.
178
 *
179
 * Side effects:
180
 *      None.
181
 *
182
 *--------------------------------------------------------------
183
 */
184
void
185
HybridDitherImage (lum, cr, cb, out, h, w)
186
    unsigned char *lum;
187
    unsigned char *cr;
188
    unsigned char *cb;
189
    unsigned char *out;
190
    int w, h;
191
{
192
  unsigned char *l, *r, *b, *o1, *o2;
193
  unsigned char *l2;
194
  int i, j;
195
 
196
  l = lum;
197
  l2 = lum+w;
198
  r = cr;
199
  b = cb;
200
  o1 = out;
201
  o2 = out+w;
202
 
203
  for (i=0; i<h; i+=4) {
204
 
205
    for (j=0; j<w; j+=4) {
206
 
207
      *o1++ = pixel[(l_darrays[0][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
208
      *o1++ = pixel[(l_darrays[8][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
209
      *o2++ = pixel[(l_darrays[12][*l2++] | cr_fsarray[*r][2] | cb_fsarray[*b][2])];
210
      *o2++ = pixel[(l_darrays[4][*l2++] | cr_fsarray[*r++][3] | cb_fsarray[*b++][3])];
211
 
212
      *o1++ = pixel[(l_darrays[2][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
213
      *o1++ = pixel[(l_darrays[10][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
214
      *o2++ = pixel[(l_darrays[14][*l2++] | cr_fsarray[*r][2] | cb_fsarray[*b][2])];
215
      *o2++ = pixel[(l_darrays[6][*l2++] | cr_fsarray[*r++][3] | cb_fsarray[*b++][3])];
216
    }
217
 
218
    l += w; l2 += w;
219
    o1 += w; o2 += w;
220
 
221
    for (j=0; j<w; j+=4) {
222
 
223
      *o1++ = pixel[(l_darrays[3][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
224
      *o1++ = pixel[(l_darrays[11][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
225
      *o2++ = pixel[(l_darrays[15][*l2++] | cr_fsarray[*r][3] | cb_fsarray[*b][3])];
226
      *o2++ = pixel[(l_darrays[7][*l2++] | cr_fsarray[*r++][2] | cb_fsarray[*b++][2])];
227
 
228
      *o1++ = pixel[(l_darrays[1][*l++] | cr_fsarray[*r][1] | cb_fsarray[*b][1])];
229
      *o1++ = pixel[(l_darrays[9][*l++] | cr_fsarray[*r][0] | cb_fsarray[*b][0])];
230
      *o2++ = pixel[(l_darrays[13][*l2++] | cr_fsarray[*r][3] | cb_fsarray[*b][3])];
231
      *o2++ = pixel[(l_darrays[5][*l2++] | cr_fsarray[*r++][2] | cb_fsarray[*b++][2])];
232
    }
233
 
234
    l += w; l2 += w;
235
    o1 += w; o2 += w;
236
  }
237
}
238
 
239
 
240