tomwalters@0
|
1 /*
|
tomwalters@0
|
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
|
tomwalters@0
|
3 ===========================================================================
|
tomwalters@0
|
4
|
tomwalters@0
|
5 Permission to use, copy, modify, and distribute this software without fee
|
tomwalters@0
|
6 is hereby granted for research purposes, provided that this copyright
|
tomwalters@0
|
7 notice appears in all copies and in all supporting documentation, and that
|
tomwalters@0
|
8 the software is not redistributed for any fee (except for a nominal shipping
|
tomwalters@0
|
9 charge). Anyone wanting to incorporate all or part of this software in a
|
tomwalters@0
|
10 commercial product must obtain a license from the Medical Research Council.
|
tomwalters@0
|
11
|
tomwalters@0
|
12 The MRC makes no representations about the suitability of this
|
tomwalters@0
|
13 software for any purpose. It is provided "as is" without express or implied
|
tomwalters@0
|
14 warranty.
|
tomwalters@0
|
15
|
tomwalters@0
|
16 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
tomwalters@0
|
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
|
tomwalters@0
|
18 A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
|
tomwalters@0
|
19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
tomwalters@0
|
20 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
tomwalters@0
|
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
tomwalters@0
|
22 */
|
tomwalters@0
|
23
|
tomwalters@0
|
24 /*
|
tomwalters@0
|
25 grey.c
|
tomwalters@0
|
26 ======
|
tomwalters@0
|
27
|
tomwalters@0
|
28 Greyscale routines for mapping arrays of shorts into
|
tomwalters@0
|
29 columns of pixel values (dithered if necessary).
|
tomwalters@0
|
30
|
tomwalters@0
|
31
|
tomwalters@0
|
32 Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit.
|
tomwalters@0
|
33
|
tomwalters@0
|
34
|
tomwalters@0
|
35 Author : John Holdsworth
|
tomwalters@0
|
36 Written : 11th May, 1989.
|
tomwalters@0
|
37
|
tomwalters@0
|
38 Edited :
|
tomwalters@0
|
39
|
tomwalters@0
|
40 */
|
tomwalters@0
|
41 #if defined( NeXT )
|
tomwalters@0
|
42 #include <stdlib.h>
|
tomwalters@0
|
43 #else
|
tomwalters@0
|
44 #include <malloc.h>
|
tomwalters@0
|
45 #endif
|
tomwalters@0
|
46 #include "grey.h"
|
tomwalters@0
|
47
|
tomwalters@0
|
48
|
tomwalters@0
|
49 #ifndef lint
|
tomwalters@0
|
50 static char *sccs_id = "@(#)grey.c 1.9 J. Holdsworth (MRC-APU) 11/8/90" ;
|
tomwalters@0
|
51 #endif
|
tomwalters@0
|
52
|
tomwalters@0
|
53 /* standard recursive dither patterns for grey scales */
|
tomwalters@0
|
54
|
tomwalters@0
|
55 static int dither(n,x,y)
|
tomwalters@0
|
56 int n,x,y;
|
tomwalters@0
|
57 {
|
tomwalters@0
|
58 static int seed[2][2] = {{ 0, 2 } , { 3, 1 }};
|
tomwalters@0
|
59
|
tomwalters@0
|
60 if( n==2 )
|
tomwalters@0
|
61 return ( seed[y][x] ) ;
|
tomwalters@0
|
62 else
|
tomwalters@0
|
63 return ( dither(n/2,x%(n/2),y%(n/2))*4 + seed[y%n/(n/2)][x%n/(n/2)] );
|
tomwalters@0
|
64
|
tomwalters@0
|
65 }
|
tomwalters@0
|
66
|
tomwalters@0
|
67 int *DitherLine( size, line, length, min, max )
|
tomwalters@0
|
68 int size, line, length, min, max ;
|
tomwalters@0
|
69 {
|
tomwalters@0
|
70 int i, *dither_line = (int *) malloc( (unsigned) length * sizeof ( *dither_line ) ) ;
|
tomwalters@0
|
71
|
tomwalters@0
|
72 if( dither_line != (int *) 0 ) {
|
tomwalters@0
|
73 for( i=0; i < size && i < length ; i++ )
|
tomwalters@0
|
74 dither_line[ i ] = min + (double) dither( size, i, line ) * ( max - min ) / ( size * size ) + 0.5 ;
|
tomwalters@0
|
75
|
tomwalters@0
|
76 /* repeat for rest of line */
|
tomwalters@0
|
77
|
tomwalters@0
|
78 for( ; i < length ; i++ )
|
tomwalters@0
|
79 dither_line[ i ] = dither_line[ i%size ] ;
|
tomwalters@0
|
80 }
|
tomwalters@0
|
81
|
tomwalters@0
|
82 return ( dither_line ) ;
|
tomwalters@0
|
83 }
|
tomwalters@0
|
84
|
tomwalters@0
|
85 int **Dithers( size, length, min, max )
|
tomwalters@0
|
86 int size, length, min, max ;
|
tomwalters@0
|
87 {
|
tomwalters@0
|
88 int i, **diths = (int **) malloc( (unsigned) size * sizeof ( *diths ) ) ;
|
tomwalters@0
|
89
|
tomwalters@0
|
90 if( diths != (int **) 0 )
|
tomwalters@0
|
91 for( i=0 ; i<size ; i++ )
|
tomwalters@0
|
92 diths[i] = DitherLine( size, i, length, min, max ) ;
|
tomwalters@0
|
93
|
tomwalters@0
|
94 return ( diths ) ;
|
tomwalters@0
|
95 }
|
tomwalters@0
|
96
|
tomwalters@0
|
97 void FreeDithers( diths, size )
|
tomwalters@0
|
98 int **diths, size ;
|
tomwalters@0
|
99 {
|
tomwalters@0
|
100 int i ;
|
tomwalters@0
|
101
|
tomwalters@0
|
102 for( i=0 ; i<size ; i++ )
|
tomwalters@0
|
103 free( (char *) diths[i] ) ;
|
tomwalters@0
|
104
|
tomwalters@0
|
105 free( (char *) diths ) ;
|
tomwalters@0
|
106
|
tomwalters@0
|
107 return ;
|
tomwalters@0
|
108 }
|
tomwalters@0
|
109
|
tomwalters@0
|
110 /*
|
tomwalters@0
|
111
|
tomwalters@0
|
112 makeLookup prepares 64k byte lookup table for mapping shorts to pixel values.
|
tomwalters@0
|
113 setmap is a routine to be called to locate the window system's color map
|
tomwalters@0
|
114 and set it up returning the number of pixels availiable and allocating an
|
tomwalters@0
|
115 array containing these values in order of increasing blackness.
|
tomwalters@0
|
116
|
tomwalters@0
|
117 */
|
tomwalters@0
|
118
|
tomwalters@0
|
119 #define GREY_DITHER_SIZE 8
|
tomwalters@0
|
120
|
tomwalters@0
|
121 #define PIXEL_TABLE_SIZE ((1l<<16)-1)
|
tomwalters@0
|
122
|
tomwalters@0
|
123 struct _lookup *makeLookup( getgreyscale, black, white, height )
|
tomwalters@0
|
124 char *(*getgreyscale)() ;
|
tomwalters@0
|
125 int black, white ;
|
tomwalters@0
|
126 int height ;
|
tomwalters@0
|
127 {
|
tomwalters@0
|
128 register char *tableptr, *end, pixval ;
|
tomwalters@0
|
129 char *greyscale ;
|
tomwalters@0
|
130 struct _lookup *lookup ;
|
tomwalters@0
|
131 int npixels, pix, min, diff ;
|
tomwalters@0
|
132
|
tomwalters@0
|
133 if( ( lookup = (struct _lookup *) malloc( (unsigned) sizeof (*lookup) ) ) != 0 &&
|
tomwalters@0
|
134 ( lookup->pixeltable = malloc( (unsigned) PIXEL_TABLE_SIZE ) ) != 0 &&
|
tomwalters@0
|
135 ( lookup->output = malloc( (unsigned) height + 1 ) ) != 0 ) {
|
tomwalters@0
|
136
|
tomwalters@0
|
137 /* output null terminated for potential printing out */
|
tomwalters@0
|
138
|
tomwalters@0
|
139 lookup->output[height] = '\000' ;
|
tomwalters@0
|
140
|
tomwalters@0
|
141 /* get black to white greyscale */
|
tomwalters@0
|
142
|
tomwalters@0
|
143 greyscale = getgreyscale( &npixels ) ;
|
tomwalters@0
|
144
|
tomwalters@0
|
145
|
tomwalters@0
|
146 if( black < white ) {
|
tomwalters@0
|
147 min = black ;
|
tomwalters@0
|
148 diff = white - black ;
|
tomwalters@0
|
149 }
|
tomwalters@0
|
150 else {
|
tomwalters@0
|
151 min = white ;
|
tomwalters@0
|
152 diff = black - white ;
|
tomwalters@0
|
153 }
|
tomwalters@0
|
154
|
tomwalters@0
|
155 lookup->dithers = Dithers( GREY_DITHER_SIZE, height, min, min + diff / ( npixels - 1 ) ) ;
|
tomwalters@0
|
156
|
tomwalters@0
|
157 tableptr = lookup->pixeltable ;
|
tomwalters@0
|
158
|
tomwalters@0
|
159 for( pix=0 ; pix<npixels ; pix++ ) {
|
tomwalters@0
|
160
|
tomwalters@0
|
161 if( black < white )
|
tomwalters@0
|
162 pixval = greyscale[ pix] ;
|
tomwalters@0
|
163 else
|
tomwalters@0
|
164 pixval = greyscale[npixels-1-pix] ;
|
tomwalters@0
|
165
|
tomwalters@0
|
166 if( pix < npixels-1 )
|
tomwalters@0
|
167 end = lookup->pixeltable + diff * pix / ( npixels - 1 ) + 1 ;
|
tomwalters@0
|
168 else
|
tomwalters@0
|
169 end = lookup->pixeltable + PIXEL_TABLE_SIZE ;
|
tomwalters@0
|
170
|
tomwalters@0
|
171 while( tableptr < end )
|
tomwalters@0
|
172 *tableptr++ = pixval ;
|
tomwalters@0
|
173 }
|
tomwalters@0
|
174
|
tomwalters@0
|
175 return ( lookup ) ;
|
tomwalters@0
|
176 }
|
tomwalters@0
|
177
|
tomwalters@0
|
178 return ( 0 ) ;
|
tomwalters@0
|
179 }
|
tomwalters@0
|
180
|
tomwalters@0
|
181 /*
|
tomwalters@0
|
182 doLookup just performs the lookup of pixel values to convert an
|
tomwalters@0
|
183 array of short values into the corresponding pixels for output.
|
tomwalters@0
|
184 when few pixel values are availiable dithering is used to make the
|
tomwalters@0
|
185 most of them.
|
tomwalters@0
|
186
|
tomwalters@0
|
187 */
|
tomwalters@0
|
188
|
tomwalters@0
|
189 char *lookup( col, lookup, input, match, height )
|
tomwalters@0
|
190 int col ;
|
tomwalters@0
|
191 struct _lookup *lookup ;
|
tomwalters@0
|
192 short *input ;
|
tomwalters@0
|
193 int *match, height ;
|
tomwalters@0
|
194 {
|
tomwalters@0
|
195 register int diff ;
|
tomwalters@0
|
196 register int *mptr = match ;
|
tomwalters@0
|
197 register int *mend = match + height ;
|
tomwalters@0
|
198 register char *dptr = lookup->output ;
|
tomwalters@0
|
199 register char *lookuptable = lookup->pixeltable ;
|
tomwalters@0
|
200 register int *ditherptr = lookup->dithers[ col%GREY_DITHER_SIZE ] ;
|
tomwalters@0
|
201
|
tomwalters@0
|
202 while( mptr < mend ) {
|
tomwalters@0
|
203
|
tomwalters@0
|
204 diff = input[ *mptr++ ] - *ditherptr++ ;
|
tomwalters@0
|
205
|
tomwalters@0
|
206 if( diff > 0 )
|
tomwalters@0
|
207 *dptr++ = lookuptable[ diff ] ;
|
tomwalters@0
|
208 else
|
tomwalters@0
|
209 *dptr++ = lookuptable[ 0 ] ;
|
tomwalters@0
|
210 }
|
tomwalters@0
|
211
|
tomwalters@0
|
212 return ( lookup->output ) ;
|
tomwalters@0
|
213 }
|
tomwalters@0
|
214
|
tomwalters@0
|
215 void freeLookup( lookup )
|
tomwalters@0
|
216 struct _lookup *lookup ;
|
tomwalters@0
|
217 {
|
tomwalters@0
|
218 if( lookup != 0 ) {
|
tomwalters@0
|
219
|
tomwalters@0
|
220 free( lookup->pixeltable ) ;
|
tomwalters@0
|
221
|
tomwalters@0
|
222 free( lookup->output ) ;
|
tomwalters@0
|
223
|
tomwalters@0
|
224 FreeDithers( lookup->dithers, GREY_DITHER_SIZE ) ;
|
tomwalters@0
|
225
|
tomwalters@0
|
226 free( (char *) lookup ) ;
|
tomwalters@0
|
227 }
|
tomwalters@0
|
228 }
|
tomwalters@0
|
229
|
tomwalters@0
|
230 /* for compattability */
|
tomwalters@0
|
231
|
tomwalters@0
|
232 void doLookup( col, lookup, input, match, height, data )
|
tomwalters@0
|
233 int col ;
|
tomwalters@0
|
234 struct _lookup *lookup ;
|
tomwalters@0
|
235 short *input ;
|
tomwalters@0
|
236 int *match, height ;
|
tomwalters@0
|
237 char *data ;
|
tomwalters@0
|
238 {
|
tomwalters@0
|
239 register int diff ;
|
tomwalters@0
|
240 register int *mptr = match ;
|
tomwalters@0
|
241 register int *mend = match + height ;
|
tomwalters@0
|
242 register char *dptr = data ;
|
tomwalters@0
|
243 register char *lookuptable = lookup->pixeltable ;
|
tomwalters@0
|
244 register int *ditherptr = lookup->dithers[ col%GREY_DITHER_SIZE ] ;
|
tomwalters@0
|
245
|
tomwalters@0
|
246 while( mptr < mend ) {
|
tomwalters@0
|
247
|
tomwalters@0
|
248 diff = input[ *mptr++ ] - *ditherptr++ ;
|
tomwalters@0
|
249
|
tomwalters@0
|
250 if( diff > 0 )
|
tomwalters@0
|
251 *dptr++ = lookuptable[ diff ] ;
|
tomwalters@0
|
252 else
|
tomwalters@0
|
253 *dptr++ = lookuptable[ 0 ] ;
|
tomwalters@0
|
254 }
|
tomwalters@0
|
255
|
tomwalters@0
|
256 return ;
|
tomwalters@0
|
257 }
|
tomwalters@0
|
258
|