ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/lib/print/scaler.b/
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;
}
}