DIRECTORY AIS USING [CloseFile, CloseWindow, CreateFile, DeleteFile, FRef, GetWindowParams, OpenFile, OpenWindow, Raster, RasterPart, ReadRaster, ReadSample, WRef, WriteSample], ConvertUnsafe USING [AppendRope], DitherAIS, Rope USING [ROPE]; DitherAISImpl: PROGRAM IMPORTS AIS, ConvertUnsafe EXPORTS DitherAIS = BEGIN OPEN DitherAIS; Squash: PUBLIC PROCEDURE [redFn, greenFn, blueFn, rgbFn:Rope.ROPE, map:UserMapProc] = { redString: LONG STRING _ [30]; greenString: LONG STRING _ [30]; blueString: LONG STRING _ [30]; rgbString: LONG STRING _ [30]; redFD, greenFD, blueFD, rgbFD:AIS.FRef; temp, this, next:PixelBuf; -- 'this' holds current line's data, 'next - the one below r:AIS.RasterPart; redW, blueW, greenW, rgbW:AIS.WRef; scan, top, bottom, left, right:CARDINAL; ConvertUnsafe.AppendRope[redString, redFn]; ConvertUnsafe.AppendRope[greenString, greenFn]; ConvertUnsafe.AppendRope[blueString, blueFn]; redFD _ AIS.OpenFile[redString]; redW _ AIS.OpenWindow[redFD]; greenFD _ AIS.OpenFile[greenString]; greenW _ AIS.OpenWindow[greenFD]; blueFD _ AIS.OpenFile[blueString]; blueW _ AIS.OpenWindow[blueFD]; AIS.ReadRaster[redFD, @r]; ConvertUnsafe.AppendRope[rgbString, rgbFn]; [] _ AIS.DeleteFile[rgbString]; rgbFD _ AIS.CreateFile[name:rgbString, raster:@r, overwrite:TRUE]; rgbW _ AIS.OpenWindow[rgbFD]; [top, bottom, left, right] _ AIS.GetWindowParams[redW]; this _ NEW[PixelBufRec[right+2]]; -- make it a bit bigger to catch error propogation next _ NEW[PixelBufRec[right+2]]; ReadRGB[redW, greenW, blueW, left, right, 1, next]; FOR scan IN [top..bottom] DO temp _ this; this _ next; next _ temp; IF scan < bottom THEN ReadRGB[redW, greenW, blueW, left, right, scan+1, next]; SquashScan[this, next, left,right, map]; Writergb[rgbW, left, right, scan, this]; ENDLOOP; AIS.CloseWindow[redW]; AIS.CloseWindow[blueW]; AIS.CloseWindow[greenW]; AIS.CloseWindow[rgbW]; AIS.CloseFile[redFD]; AIS.CloseFile[blueFD]; AIS.CloseFile[greenFD]; AIS.CloseFile[rgbFD]; }; Stretch: PUBLIC PROCEDURE [redFn, greenFn, blueFn, rgbFn:Rope.ROPE, unMap:UserUnmapProc] = { redString: LONG STRING _ [30]; greenString: LONG STRING _ [30]; blueString: LONG STRING _ [30]; rgbString: LONG STRING _ [30]; redFD, greenFD, blueFD, rgbFD:AIS.FRef; raster:AIS.RasterPart; redW, blueW, greenW, rgbW:AIS.WRef; scan, pixel, top, bottom, left, right:CARDINAL; r,g,b:CARDINAL; ConvertUnsafe.AppendRope[redString, redFn]; ConvertUnsafe.AppendRope[greenString, greenFn]; ConvertUnsafe.AppendRope[blueString, blueFn]; ConvertUnsafe.AppendRope[rgbString, rgbFn]; rgbFD _ AIS.OpenFile[name:rgbString]; rgbW _ AIS.OpenWindow[rgbFD]; AIS.ReadRaster[rgbFD, @raster]; [] _ AIS.DeleteFile[redString]; redFD _ AIS.CreateFile[name:redString, raster:@raster, overwrite:TRUE]; redW _ AIS.OpenWindow[redFD]; [] _ AIS.DeleteFile[greenString]; greenFD _ AIS.CreateFile[name:greenString, raster:@raster, overwrite:TRUE]; greenW _ AIS.OpenWindow[greenFD]; [] _ AIS.DeleteFile[blueString]; blueFD _ AIS.CreateFile[name:blueString, raster:@raster, overwrite:TRUE]; blueW _ AIS.OpenWindow[blueFD]; [top, bottom, left, right] _ AIS.GetWindowParams[rgbW]; FOR scan IN [top..bottom] DO FOR pixel IN [left..right] DO [r,g,b] _ unMap[AIS.ReadSample[rgbW, scan, pixel]]; AIS.WriteSample[redW, r, scan, pixel]; AIS.WriteSample[greenW, g, scan, pixel]; AIS.WriteSample[blueW, b, scan, pixel]; ENDLOOP; ENDLOOP; AIS.CloseWindow[redW]; AIS.CloseWindow[blueW]; AIS.CloseWindow[greenW]; AIS.CloseWindow[rgbW]; AIS.CloseFile[redFD]; AIS.CloseFile[blueFD]; AIS.CloseFile[greenFD]; AIS.CloseFile[rgbFD]; }; SquashScan: PUBLIC PROCEDURE [this, next:PixelBuf, left,right:CARDINAL, map:UserMapProc] = { redError, greenError, blueError: INTEGER; FOR pixel:CARDINAL IN [left..right] DO [this.data[pixel].rgb, redError, greenError, blueError] _ map[this.data[pixel].red, this.data[pixel].green, this.data[pixel].blue]; this.data[pixel+1].red _ this.data[pixel+1].red + redError*3/8; this.data[pixel+1].green _ this.data[pixel+1].green + greenError*3/8; this.data[pixel+1].blue _ this.data[pixel+1].blue + blueError*3/8; next.data[pixel].red _ next.data[pixel].red + redError*3/8; next.data[pixel].green _ next.data[pixel].green + greenError*3/8; next.data[pixel].blue _ next.data[pixel].blue + blueError*3/8; next.data[pixel+1].red _ next.data[pixel+1].red + redError/4; next.data[pixel+1].green _ next.data[pixel+1].green + greenError/4; next.data[pixel+1].blue _ next.data[pixel+1].blue + blueError/4; ENDLOOP }; ReadRGB: PROCEDURE [r,g,b:AIS.WRef, left, right, scan:CARDINAL, buf:PixelBuf] = { FOR i:CARDINAL IN [left..right] DO buf.data[i].red _ AIS.ReadSample[r, scan, i]; buf.data[i].green _ AIS.ReadSample[g, scan, i]; buf.data[i].blue _ AIS.ReadSample[b, scan, i]; ENDLOOP; }; Writergb: PROCEDURE [rgb:AIS.WRef, left, right, scan:CARDINAL, buf:PixelBuf] = { FOR i:CARDINAL IN [left..right] DO AIS.WriteSample[rgb, buf.data[i].rgb, scan, i]; ENDLOOP; }; END. ΆDitherAISImple.mesa Mik Lamming September 29, 1982 2:44 pm Transforms the three AIS files red,green and blue into the single AIS file: rgb using the user supplied map procedure and applying Floyd-Steinberg error distribution. Open the input files and get hold of the raster info. for use in generating the rgb ouput file Create the output file Create two working buffers for scan lines initialise the 'next' buffer with the first scan line advance the scan line buffers to the next line Takes a dithered file rgbFn and cretates three separations using the unMap procedure Open the input file and get hold of the raster info. for use in generating the ouput files Processes the pixel buffer 'this' using the user supplied map procedure 'map' to fill in the rgb field in each pixel of 'this' and modifies the contents of the buffer 'next' using Floyd-Steinberg error distribution use Floyd-Steinberg to distribute error to right and next line ΚD– "Mesa" style˜Jšœ™Jšœ&™&J™šΟk ˜ Jšœœž˜ͺJšœœ˜!Jšœ ˜ Jšœœ˜—J˜šΟn œœ˜Jšœœ˜Jšœ ˜Jšœ ˜˜Jšžœ#œ˜W™¦Jšœ œœ˜Jšœ œœ˜ Jšœ œœ˜Jšœ œœ˜Jšœœ˜'JšœΟc:˜UJšœœ ˜Jšœœ˜#Jšœœ˜(J˜J™^Jšœ+˜+Jšœ/˜/Jšœ-˜-Jšœ ˜ Jšœ˜Jšœ$˜$Jšœ!˜!Jšœ"˜"Jšœ˜J˜J™Jšœ˜Jšœ+˜+Jšœ˜Jšœ;œ˜BJšœ˜J˜J™)Jšœ7˜7Jšœ"Ÿ2˜TJšœ!˜!J˜J™5Jšœ3˜3šœ˜J™.Jšœ(˜(šœœ˜Jšœ8˜8—Jšœ(˜(Jšœ(˜(Jš˜—Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜J˜—Jšžœœ#œ˜\J™T™Jšœ œœ˜Jšœ œœ˜ Jšœ œœ˜Jšœ œœ˜Jšœœ˜'Jšœœ ˜Jšœœ˜#Jšœ&œ˜/Jšœœ˜J˜J™ZJšœ+˜+Jšœ/˜/Jšœ-˜-Jšœ+˜+J˜Jšœ%˜%Jšœ˜Jšœ˜J˜J˜Jšœ˜Jšœ@œ˜GJšœ˜Jšœ!˜!JšœDœ˜KJšœ"˜"Jšœ ˜ JšœBœ˜IJšœ ˜ Jšœ7˜7J˜šœ˜šœœ˜Jšœœ!˜4Jšœ#˜&Jšœ%˜(Jšœ$˜'Jš˜—Jš˜—Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—J˜—procšž œœ" œœ˜\KšœΦ™ΦKšœ!œ˜)šœœœ˜&šœ7˜7JšœK˜K—J˜J™>Jšœ?˜?JšœE˜EJšœB˜BJšœ;˜;JšœA˜AJšœ>˜>Jšœ=˜=JšœC˜CJšœ@˜@Jš˜—J˜—š œžœ œœœ˜Ršœœœ˜"Jšœœ˜-Jšœœ˜/Jšœœ˜.Jšœ˜—J˜—š žœ œžœžœœ˜Pšœœœ˜"Jšœ,˜/Jšœ˜—J˜—J˜Jšœ˜——…—<6