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