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
|
implement Scaler;
include "sys.m";
sys: Sys;
include "draw.m";
include "print.m";
include "scaler.m";
DEBUG := 0;
# Scaler initialisation
init(debug: int, WidthInPixels, ScaleFactorMultiplier, ScaleFactorDivisor: int): ref RESSYNSTRUCT
{
DEBUG = debug;
ScaleFactor := real ScaleFactorMultiplier / real ScaleFactorDivisor;
ScaleBound := int ScaleFactor;
if (ScaleFactor > real ScaleBound) ScaleBound++;
ResSynStruct := ref RESSYNSTRUCT (
WidthInPixels+2, # add 2 for edges
ScaleFactorMultiplier,
ScaleFactorDivisor,
ScaleFactor,
int ((real WidthInPixels / real ScaleFactorDivisor))*ScaleFactorMultiplier + 1,
ScaleFactorMultiplier != ScaleFactorDivisor,
ScaleFactor < 2.0,
(ScaleFactorMultiplier * 256 / ScaleFactorDivisor)
- ((ScaleFactorMultiplier/ScaleFactorDivisor) * 256),
0,
0,
array[NUMBER_RASTERS] of array of int,
array[ScaleBound] of array of int,
0,
0
);
if (ResSynStruct.ScaleFactor > real ScaleBound) ScaleBound++;
for (i:=0; i<len ResSynStruct.Buffer; i++) ResSynStruct.Buffer[i] = array[WidthInPixels*NUMBER_RASTERS] of int;
for (i=0; i<len ResSynStruct.oBuffer; i++) ResSynStruct.oBuffer[i] = array[ResSynStruct.iOutputWidth] of int;
return ResSynStruct;
}
# Input a raster line to the scaler
rasterin(rs: ref RESSYNSTRUCT, inraster: array of int)
{
if (!rs.scaling) { # Just copy to output buffer
if (inraster == nil) return;
rs.oBuffer[0] = inraster;
rs.nready = 1;
rs.ndelivered = 0;
return;
}
if (rs.ReplicateOnly) { # for scaling between 1 and 2
# for (i:=0; i<len inraster; i++) rs.oBuffer[0][i] = inraster[i];
rs.oBuffer[0][:] = inraster[0:];
create_out(rs, 1);
return;
}
if (rs.RastersinBuffer == 0) { # First time through
if (inraster == nil) return;
for (i:=0; i<2; i++) {
rs.Buffer[i][0] = inraster[0];
# for (j:=1; j<rs.Width-1; j++) rs.Buffer[i][j] = inraster[j-1];
rs.Buffer[i][1:] = inraster[0:rs.Width-2];
rs.Buffer[i][rs.Width-1] = inraster[rs.Width-3];
}
rs.RastersinBuffer = 2;
return;
}
if (rs.RastersinBuffer == 2) { # Just two buffers in so far
if (inraster != nil) {
i := 2;
rs.Buffer[i][0] = inraster[0];
# for (j:=1; j<rs.Width-1; j++) rs.Buffer[i][j] = inraster[j-1];
rs.Buffer[i][1:] = inraster[0:rs.Width-2];
rs.Buffer[i][rs.Width-1] = inraster[rs.Width-3];
rs.RastersinBuffer = 3;
} else { # nil means end of image
rez_synth(rs, rs.oBuffer[0], rs.oBuffer[1]);
create_out(rs, 0);
}
return;
}
if (rs.RastersinBuffer == 3) { # All three buffers are full
(rs.Buffer[0], rs.Buffer[1], rs.Buffer[2]) = (rs.Buffer[1], rs.Buffer[2], rs.Buffer[0]);
if (inraster != nil) {
i := 2;
rs.Buffer[i][0] = inraster[0];
# for (j:=1; j<rs.Width-1; j++) rs.Buffer[i][j] = inraster[j-1];
rs.Buffer[i][1:] = inraster[0:rs.Width-2];
rs.Buffer[i][rs.Width-1] = inraster[rs.Width-3];
} else { # nil means end of image
# for (j:=0; j<len rs.Buffer[1]; j++) rs.Buffer[2][j] = rs.Buffer[1][j];
rs.Buffer[2][:] = rs.Buffer[1];
rs.RastersinBuffer = 0;
}
rez_synth(rs, rs.oBuffer[0], rs.oBuffer[1]);
create_out(rs, 0);
}
}
# Get a raster output line from the scaler
rasterout(rs: ref RESSYNSTRUCT): array of int
{
if (rs.nready-- > 0) {
return rs.oBuffer[rs.ndelivered++][:rs.iOutputWidth-1];
} else return nil;
}
# Create output raster
create_out(rs: ref RESSYNSTRUCT, simple: int)
{
factor: int;
if (simple) factor = 1;
else factor = 2;
out_width := (rs.Width-2) * rs.ScaleFactorMultiplier / rs.ScaleFactorDivisor;
number_out := rs.ScaleFactorMultiplier / rs.ScaleFactorDivisor;
if (number_out == 2 && !(rs.ScaleFactorMultiplier % rs.ScaleFactorDivisor) ) {
rs.nready = 2;
rs.ndelivered = 0;
return;
}
if (rs.ScaleFactorMultiplier % rs.ScaleFactorDivisor)
{
rs.Remainder = rs.Remainder + rs.Repeat;
if (rs.Remainder >= 256) # send extra raster
{
number_out++;
rs.Remainder = rs.Remainder - 256;
}
}
# set up pointers into the output buffer
output_raster := array[number_out] of array of int;
output_raster[:] = rs.oBuffer[0:number_out];
ScaleFactorMultiplier := rs.ScaleFactorMultiplier;
ScaleFactorDivisor := rs.ScaleFactorDivisor;
sf := factor * ScaleFactorDivisor;
# Convert the input data by starting at the bottom right hand corner and move left + up
for (i:=(number_out-1); i>=0; i--) {
y_index := i*sf/ScaleFactorMultiplier;
orast_i := output_raster[i];
orast_y := output_raster[y_index];
for (lx := out_width-1; lx>=0; --lx) {
x_index := lx*sf/ScaleFactorMultiplier;
orast_i[lx] = orast_y[x_index];
}
}
rs.nready = number_out;
rs.ndelivered = 0;
return;
}
# Synthesise raster line
rez_synth(rs: ref RESSYNSTRUCT, output_raster0, output_raster1: array of int)
{
i := 1;
Buffer := rs.Buffer[i];
h_offset := 0;
for (j:=1; j<rs.Width-1; j++) {
rgb := Buffer[j];
output_raster0[h_offset] = rgb;
output_raster1[h_offset++] = rgb;
output_raster0[h_offset] = rgb;
output_raster1[h_offset++] = rgb;
}
}
|