xref: /inferno-os/appl/lib/print/scaler.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Scaler;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsythinclude "print.m";
7*37da2899SCharles.Forsythinclude "scaler.m";
8*37da2899SCharles.Forsyth
9*37da2899SCharles.ForsythDEBUG := 0;
10*37da2899SCharles.Forsyth
11*37da2899SCharles.Forsyth# Scaler initialisation
12*37da2899SCharles.Forsyth
13*37da2899SCharles.Forsythinit(debug: int, WidthInPixels, ScaleFactorMultiplier, ScaleFactorDivisor: int): ref RESSYNSTRUCT
14*37da2899SCharles.Forsyth{
15*37da2899SCharles.Forsyth	DEBUG = debug;
16*37da2899SCharles.Forsyth	ScaleFactor := real ScaleFactorMultiplier / real ScaleFactorDivisor;
17*37da2899SCharles.Forsyth	ScaleBound := int ScaleFactor;
18*37da2899SCharles.Forsyth	if  (ScaleFactor > real ScaleBound) ScaleBound++;
19*37da2899SCharles.Forsyth	ResSynStruct := ref RESSYNSTRUCT (
20*37da2899SCharles.Forsyth					WidthInPixels+2,	# add 2 for edges
21*37da2899SCharles.Forsyth					ScaleFactorMultiplier,
22*37da2899SCharles.Forsyth					ScaleFactorDivisor,
23*37da2899SCharles.Forsyth					ScaleFactor,
24*37da2899SCharles.Forsyth					int ((real WidthInPixels / real ScaleFactorDivisor))*ScaleFactorMultiplier + 1,
25*37da2899SCharles.Forsyth					ScaleFactorMultiplier != ScaleFactorDivisor,
26*37da2899SCharles.Forsyth					ScaleFactor < 2.0,
27*37da2899SCharles.Forsyth					(ScaleFactorMultiplier * 256 / ScaleFactorDivisor)
28*37da2899SCharles.Forsyth										  -  ((ScaleFactorMultiplier/ScaleFactorDivisor) * 256),
29*37da2899SCharles.Forsyth					0,
30*37da2899SCharles.Forsyth					0,
31*37da2899SCharles.Forsyth					array[NUMBER_RASTERS] of array of int,
32*37da2899SCharles.Forsyth					array[ScaleBound] of array of int,
33*37da2899SCharles.Forsyth					0,
34*37da2899SCharles.Forsyth					0
35*37da2899SCharles.Forsyth				);
36*37da2899SCharles.Forsyth	if (ResSynStruct.ScaleFactor > real ScaleBound) ScaleBound++;
37*37da2899SCharles.Forsyth	for (i:=0; i<len ResSynStruct.Buffer; i++) ResSynStruct.Buffer[i] = array[WidthInPixels*NUMBER_RASTERS] of int;
38*37da2899SCharles.Forsyth	for (i=0; i<len ResSynStruct.oBuffer; i++) ResSynStruct.oBuffer[i] = array[ResSynStruct.iOutputWidth] of int;
39*37da2899SCharles.Forsyth	return ResSynStruct;
40*37da2899SCharles.Forsyth}
41*37da2899SCharles.Forsyth
42*37da2899SCharles.Forsyth
43*37da2899SCharles.Forsyth# Input a raster line to the scaler
44*37da2899SCharles.Forsyth
45*37da2899SCharles.Forsythrasterin(rs: ref RESSYNSTRUCT, inraster: array of int)
46*37da2899SCharles.Forsyth{
47*37da2899SCharles.Forsyth	if (!rs.scaling) {		# Just copy to output buffer
48*37da2899SCharles.Forsyth		if (inraster == nil) return;
49*37da2899SCharles.Forsyth		rs.oBuffer[0] = inraster;
50*37da2899SCharles.Forsyth		rs.nready = 1;
51*37da2899SCharles.Forsyth		rs.ndelivered = 0;
52*37da2899SCharles.Forsyth		return;
53*37da2899SCharles.Forsyth	}
54*37da2899SCharles.Forsyth
55*37da2899SCharles.Forsyth	if (rs.ReplicateOnly) {	# for scaling between 1 and 2
56*37da2899SCharles.Forsyth#		for (i:=0; i<len inraster; i++) rs.oBuffer[0][i] = inraster[i];
57*37da2899SCharles.Forsyth		rs.oBuffer[0][:] = inraster[0:];
58*37da2899SCharles.Forsyth		create_out(rs, 1);
59*37da2899SCharles.Forsyth		return;
60*37da2899SCharles.Forsyth	}
61*37da2899SCharles.Forsyth
62*37da2899SCharles.Forsyth	if (rs.RastersinBuffer == 0) {	# First time through
63*37da2899SCharles.Forsyth		if (inraster == nil) return;
64*37da2899SCharles.Forsyth		for (i:=0; i<2; i++) {
65*37da2899SCharles.Forsyth			rs.Buffer[i][0] = inraster[0];
66*37da2899SCharles.Forsyth#			for (j:=1; j<rs.Width-1; j++) rs.Buffer[i][j] = inraster[j-1];
67*37da2899SCharles.Forsyth			rs.Buffer[i][1:] = inraster[0:rs.Width-2];
68*37da2899SCharles.Forsyth			rs.Buffer[i][rs.Width-1] = inraster[rs.Width-3];
69*37da2899SCharles.Forsyth		}
70*37da2899SCharles.Forsyth		rs.RastersinBuffer = 2;
71*37da2899SCharles.Forsyth		return;
72*37da2899SCharles.Forsyth	}
73*37da2899SCharles.Forsyth
74*37da2899SCharles.Forsyth	if (rs.RastersinBuffer == 2) {	# Just two buffers in so far
75*37da2899SCharles.Forsyth		if (inraster != nil) {
76*37da2899SCharles.Forsyth			i := 2;
77*37da2899SCharles.Forsyth			rs.Buffer[i][0] = inraster[0];
78*37da2899SCharles.Forsyth#			for (j:=1; j<rs.Width-1; j++) rs.Buffer[i][j] = inraster[j-1];
79*37da2899SCharles.Forsyth			rs.Buffer[i][1:] = inraster[0:rs.Width-2];
80*37da2899SCharles.Forsyth			rs.Buffer[i][rs.Width-1] = inraster[rs.Width-3];
81*37da2899SCharles.Forsyth			rs.RastersinBuffer = 3;
82*37da2899SCharles.Forsyth		} else {	# nil means end of image
83*37da2899SCharles.Forsyth			rez_synth(rs, rs.oBuffer[0], rs.oBuffer[1]);
84*37da2899SCharles.Forsyth			create_out(rs, 0);
85*37da2899SCharles.Forsyth		}
86*37da2899SCharles.Forsyth		return;
87*37da2899SCharles.Forsyth	}
88*37da2899SCharles.Forsyth	if (rs.RastersinBuffer == 3) {	# All three buffers are full
89*37da2899SCharles.Forsyth		(rs.Buffer[0], rs.Buffer[1], rs.Buffer[2]) = (rs.Buffer[1], rs.Buffer[2], rs.Buffer[0]);
90*37da2899SCharles.Forsyth		if (inraster != nil) {
91*37da2899SCharles.Forsyth			i := 2;
92*37da2899SCharles.Forsyth			rs.Buffer[i][0] = inraster[0];
93*37da2899SCharles.Forsyth#			for (j:=1; j<rs.Width-1; j++) rs.Buffer[i][j] = inraster[j-1];
94*37da2899SCharles.Forsyth			rs.Buffer[i][1:] = inraster[0:rs.Width-2];
95*37da2899SCharles.Forsyth			rs.Buffer[i][rs.Width-1] = inraster[rs.Width-3];
96*37da2899SCharles.Forsyth		} else {	# nil means end of image
97*37da2899SCharles.Forsyth#			for (j:=0; j<len rs.Buffer[1]; j++) rs.Buffer[2][j] = rs.Buffer[1][j];
98*37da2899SCharles.Forsyth			rs.Buffer[2][:] = rs.Buffer[1];
99*37da2899SCharles.Forsyth			rs.RastersinBuffer = 0;
100*37da2899SCharles.Forsyth
101*37da2899SCharles.Forsyth		}
102*37da2899SCharles.Forsyth		rez_synth(rs, rs.oBuffer[0], rs.oBuffer[1]);
103*37da2899SCharles.Forsyth		create_out(rs, 0);
104*37da2899SCharles.Forsyth	}
105*37da2899SCharles.Forsyth
106*37da2899SCharles.Forsyth}
107*37da2899SCharles.Forsyth
108*37da2899SCharles.Forsyth
109*37da2899SCharles.Forsyth# Get a raster output line from the scaler
110*37da2899SCharles.Forsyth
111*37da2899SCharles.Forsythrasterout(rs: ref RESSYNSTRUCT): array of int
112*37da2899SCharles.Forsyth{
113*37da2899SCharles.Forsyth	if (rs.nready-- > 0) {
114*37da2899SCharles.Forsyth		return rs.oBuffer[rs.ndelivered++][:rs.iOutputWidth-1];
115*37da2899SCharles.Forsyth	} else return nil;
116*37da2899SCharles.Forsyth}
117*37da2899SCharles.Forsyth
118*37da2899SCharles.Forsyth
119*37da2899SCharles.Forsyth
120*37da2899SCharles.Forsyth# Create output raster
121*37da2899SCharles.Forsyth
122*37da2899SCharles.Forsythcreate_out(rs: ref RESSYNSTRUCT, simple: int)
123*37da2899SCharles.Forsyth{
124*37da2899SCharles.Forsyth	factor: int;
125*37da2899SCharles.Forsyth	if (simple) factor = 1;
126*37da2899SCharles.Forsyth	else factor = 2;
127*37da2899SCharles.Forsyth
128*37da2899SCharles.Forsyth	out_width := (rs.Width-2) * rs.ScaleFactorMultiplier / rs.ScaleFactorDivisor;
129*37da2899SCharles.Forsyth	number_out := rs.ScaleFactorMultiplier / rs.ScaleFactorDivisor;
130*37da2899SCharles.Forsyth	if (number_out == 2 && !(rs.ScaleFactorMultiplier % rs.ScaleFactorDivisor) ) {
131*37da2899SCharles.Forsyth		rs.nready = 2;
132*37da2899SCharles.Forsyth		rs.ndelivered = 0;
133*37da2899SCharles.Forsyth		return;
134*37da2899SCharles.Forsyth	}
135*37da2899SCharles.Forsyth
136*37da2899SCharles.Forsyth	if (rs.ScaleFactorMultiplier % rs.ScaleFactorDivisor)
137*37da2899SCharles.Forsyth	{
138*37da2899SCharles.Forsyth		rs.Remainder = rs.Remainder + rs.Repeat;
139*37da2899SCharles.Forsyth
140*37da2899SCharles.Forsyth		if (rs.Remainder >= 256)	# send extra raster
141*37da2899SCharles.Forsyth		{
142*37da2899SCharles.Forsyth			number_out++;
143*37da2899SCharles.Forsyth			rs.Remainder = rs.Remainder - 256;
144*37da2899SCharles.Forsyth		}
145*37da2899SCharles.Forsyth	}
146*37da2899SCharles.Forsyth	# set up pointers into the output buffer
147*37da2899SCharles.Forsyth	output_raster := array[number_out] of array of int;
148*37da2899SCharles.Forsyth	output_raster[:] = rs.oBuffer[0:number_out];
149*37da2899SCharles.Forsyth
150*37da2899SCharles.Forsyth	ScaleFactorMultiplier := rs.ScaleFactorMultiplier;
151*37da2899SCharles.Forsyth	ScaleFactorDivisor := rs.ScaleFactorDivisor;
152*37da2899SCharles.Forsyth	sf := factor * ScaleFactorDivisor;
153*37da2899SCharles.Forsyth
154*37da2899SCharles.Forsyth	# Convert the input data by starting at the bottom right hand corner and move left + up
155*37da2899SCharles.Forsyth	for (i:=(number_out-1); i>=0; i--) {
156*37da2899SCharles.Forsyth		y_index := i*sf/ScaleFactorMultiplier;
157*37da2899SCharles.Forsyth		orast_i := output_raster[i];
158*37da2899SCharles.Forsyth		orast_y := output_raster[y_index];
159*37da2899SCharles.Forsyth		for (lx := out_width-1; lx>=0; --lx) {
160*37da2899SCharles.Forsyth			x_index := lx*sf/ScaleFactorMultiplier;
161*37da2899SCharles.Forsyth			orast_i[lx] = orast_y[x_index];
162*37da2899SCharles.Forsyth		}
163*37da2899SCharles.Forsyth	}
164*37da2899SCharles.Forsyth
165*37da2899SCharles.Forsyth	rs.nready = number_out;
166*37da2899SCharles.Forsyth	rs.ndelivered = 0;
167*37da2899SCharles.Forsyth	return;
168*37da2899SCharles.Forsyth}
169*37da2899SCharles.Forsyth
170*37da2899SCharles.Forsyth
171*37da2899SCharles.Forsyth# Synthesise raster line
172*37da2899SCharles.Forsyth
173*37da2899SCharles.Forsythrez_synth(rs: ref RESSYNSTRUCT, output_raster0, output_raster1: array of int)
174*37da2899SCharles.Forsyth{
175*37da2899SCharles.Forsyth
176*37da2899SCharles.Forsyth	i := 1;
177*37da2899SCharles.Forsyth	Buffer := rs.Buffer[i];
178*37da2899SCharles.Forsyth	h_offset := 0;
179*37da2899SCharles.Forsyth	for (j:=1; j<rs.Width-1; j++) {
180*37da2899SCharles.Forsyth		rgb := Buffer[j];
181*37da2899SCharles.Forsyth		output_raster0[h_offset] = rgb;
182*37da2899SCharles.Forsyth		output_raster1[h_offset++] = rgb;
183*37da2899SCharles.Forsyth		output_raster0[h_offset] = rgb;
184*37da2899SCharles.Forsyth		output_raster1[h_offset++] = rgb;
185*37da2899SCharles.Forsyth	}
186*37da2899SCharles.Forsyth}
187