-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDITHER.ASM
executable file
·303 lines (264 loc) · 7.2 KB
/
DITHER.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
page ,132
;-----------------------------Module-Header-----------------------------;
; Module Name: DITHER.ASM
;
; This file contains the brush dithering algorithm for brushes.
;
; Created: 17-Jan-1987
; Author: **** ***** [*****]
;
; Copyright (c) 1985-1987 Microsoft Corporation
;
; Exported Functions: none
;
; Public Functions: dither
;
; Public Data: none
;
; General Description:
;
; The dithering algorithm is called to generate the patterns
; used for brushes.
;
; Restrictions:
; The dithering algorithm assumes that the size of the brush is
; 8 x 8.
;
;-----------------------------------------------------------------------;
.xlist
include cmacros.inc
.list
sBegin Code
assumes cs,Code
page
;-----------------------------Public-Routine----------------------------;
; dither
;
; Dither(value, lpBrush)
;
; This function takes value between 0 - 255 and uses it to create
; an 8x8 pile of bits that can be used as a brush. It does this
; by reducing the input value to a number between 0 - 64 and then
; turns on that many bits in the 8x8 field. Thus the value 0 leads
; to brush of all zeros, a 255 value leads to a brush of all 1's,
; and a value of 128 leads to grey.
;
; The algorithm is equivalent to turning on bits based on an array:
;
; 0 32 8 40 2 34 10 42
; 48 16 56 24 50 18 58 26
; 12 44 4 36 14 46 6 38 This table favors devices like
; 60 28 52 20 62 30 54 22 the EGA & Hercules cards where the
; 3 35 11 43 1 33 9 41 aspect ratio is close to 1:1
; 51 19 59 27 49 17 57 25
; 15 47 7 39 13 45 5 37
; 63 31 55 23 61 29 53 21
;
;
; Where given a value between 0 - 64, turn on the bit if the array
; value is less then the desired value.
;
; When dithering for color drivers, where each plane is dither
; independently, this algorithm has a nice side effect in that
; for any value n < m, n is a proper subset of m (any bit turned
; on in n must have been turned on in m!).
;
; For the table, undesirable patterns are generated for light
; and dark grey. These will be flagged when encountered.
; The brush realization routines can then substitute the correct
; grey (we cannot do it because we do not know if the other planes of
; a color brush were the same pattern).
;
; Reference: A Survey of Techniques for the Display of Continuous
; Tone Pictures on Bilevel Displays,;
; Jarvis, Judice, & Ninke;
; COMPUTER GRAPHICS AND IMAGE PROCESSING 5, pp 13-40, (1976)
;
; Entry:
; DL = value to dither
; ES:DI --> destination
; SI = previous grey indicator
; Returns:
; ES:DI --> next destination (ES:DI + SIZE_PATTERN)
; DH = dither value (0-64)
; SI = New grey indicator (SI << 3 || grey_indicator)
; D2:D0 = 001b for dark grey
; D2:D0 = 010b for grey
; D2:D0 = 011b for light grey
; D2:D0 = 100b for black
; D2:D0 = 101b for white
; D2:D0 = 000b otherwise
; Error Returns:
; none
; Registers Destroyed:
; AX,BX,CX,DX,DS,FLAGS
; Registers Preserved:
; none
; Calls:
; none
; History:
; Sun 15-Feb-1987 18:35:01 -by- **** ***** [*****]
; Initial version
;-----------------------------------------------------------------------;
;------------------------------Pseudo-Code------------------------------;
; {
; }
;-----------------------------------------------------------------------;
public dither
dither proc near
mov ax,cs
mov ds,ax
assumes ds,Code
mov cx,3 ;Will be usefull
xor bx,bx ;Need a zero a few times
xchg ax,si ;Need SI later
shl ax,cl ;Update old grey flags
inc cx ;4 will be useful later
shr dl,1 ;Convert value 0-255 into
adc dl,bl ; value 0 - 64
shr dl,1
mov bl,dl ;base_pattern index is D6:D2
mov dh,dl ;Return mapped value to caller in DL
and bl,11111100b
lea si,cs:base_patterns[bx] ;Copy the base pattern
cld
movsw
movsw
sub si,cx ;Duplicate for second half of brush
movsw
movsw
xchg ax,si ;Restore grey flags
test dl,00000011b ;A base pattern?
jnz not_base_pattern
test dl,00001111b ;A grey to special case?
jnz is_base_pattern ; No, it is not
shr bx,cl ;D6:D4 is index into grey_flags
mov bl,cs:grey_flags[bx] ;Or in grey flag
or si,bx
is_base_pattern:
ret
not_base_pattern:
shr bx,1 ;D5:D2 will index into rows_and_masks
and bl,0FEh ;Indexing into words, must be 0
mov ax,cs:rows_and_masks[bx];AL = base row, AH = base mask
mov bl,al ;Set base row
sub bx,8 ;Adjust for di pointing past brush
mov al,ah ;Shift pattern for proper use
shr al,cl ;AH is base pattern, AL is base >> 4
and dl,11b ;Dispatch as needed
cmp dl,2 ;CL = 2
jb first_bit
je second_bit
third_bit:
or es:[di][bx][0],al ;Set third bit
second_bit:
or es:[di][bx][4],al ;Set second bit
first_bit:
or es:[di][bx][0],ah ;Set first bit
ret
dither endp
page
; The grey_flags table contains the values to OR into the
; accumulated grey flag for colors which mapped to the
; greys which must be special cased.
grey_flags label byte
db 100b ;Black (00)
db 001b ;Dark Grey (16)
db 010b ;Grey (32)
db 011b ;Light Grey (48)
db 101b ;White (64)
; The order in which the rows of the dither are accessed
; are as follows:
;
; 0,4,0,4,2,6,2,6
; 0,4,0,4,2,6,2,6
; 1,5,1,5,3,7,3,7
; 1,5,1,5,3,7,3,7
; 0,4,0,4,2,6,2,6
; 0,4,0,4,2,6,2,6
; 1,5,1,5,3,7,3,7
; 1,5,1,5,3,7,3,7
;
;
; The order in which bits are turned on is as follows:
;
; 80,08,08,80,20,02,02,20
; 20,02,02,20,80,08,08,80
; 40,04,04,40,10,01,01,10
; 10,01,01,10,40,04,04,40
; 40,04,04,40,10,01,01,10
; 10,01,01,10,40,04,04,40
; 80,08,08,80,20,02,02,20
; 20,02,02,20,80,08,08,80
;
;
; If you work in groups of four, the following observations
; can be made about how the pixels are visited:
;
; The rows are always accessed as follows:
;
; row n
; row n+4
; row n
; row n+4
;
;
; The bits are always manipulated as follows:
;
; bit n
; bit n >> 4
; bit n >> 4
; bit n
;
;
; Since base patterns are defined at intervals of four, the
; algorithm for turning on the remaining 1, 2, or 3 bits
; can be table driven.
;
;
; The following table will contain the row and the bitmask to
; use for turning on the remaining 1, 2, or 3 bits of the pattern.
; Bits D5:D2 of the mapped color are used to index into this table.
; The format is:
;
; db base row, base bit
rows_and_masks label word
db 0,80h
db 2,20h
db 0,20h
db 2,80h
db 1,40h
db 3,10h
db 1,10h
db 3,40h
db 0,40h
db 2,10h
db 0,10h
db 2,40h
db 1,80h
db 3,20h
db 1,20h
db 3,80h
base_patterns:
db 000h,000h,000h,000h
db 088h,000h,000h,000h
db 088h,000h,022h,000h
db 0AAh,000h,022h,000h
db 0AAh,000h,0AAh,000h
db 0AAh,044h,0AAh,000h
db 0AAh,044h,0AAh,011h
db 0AAh,055h,0AAh,011h
db 0AAh,055h,0AAh,055h
db 0EEh,055h,0AAh,055h
db 0EEh,055h,0BBh,055h
db 0FFh,055h,0BBh,055h
db 0FFh,055h,0FFh,055h
db 0FFh,0DDh,0FFh,055h
db 0FFh,0DDh,0FFh,077h
db 0FFh,0FFh,0FFh,077h
db 0FFh,0FFh,0FFh,0FFh
ifdef PUBDEFS
include dither.pub
endif
sEnd Code
end