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