unit UMPixel16u;

{Contributed by Edward J. Huff <huff@mcclb0.med.nyu.edu> }
{Copyright is hereby waived:  UMPixel16u.p is in the public domain.}

interface

	uses
		QuickDraw, Palettes, PrintTraps, Globals, Utilities, UMacroDef, SANE;

	procedure UMPixel16uInit;
	procedure UMPixel16uFinal;
	procedure UMPixel16uAdd;
	procedure UMPixel16uLookup (var uma: UserMacroArgs);
	procedure UMPixel16uRun (var uma: UserMacroArgs);

implementation

	type
		u16r = packed record
				u: 0..65535;
			end;
		u16p = ^u16r;
		s32p = ^LongInt;

{record for "view" windows}
{A handle to this record is kept in UserData field of UserInfoRec}
		view16uHandle = ^view16uPtr;
		view16uPtr = ^view16uRec;
		view16uRec = record
				inPic: infoPtr;
				maskPic: infoPtr;
				nlines, PixelsPerLine: integer;
				BytesPerRow: integer;
				PicBaseHandle: handle;
				osPort: cGrafPtr;         {Offscreen Port}
				Active: Boolean;
				wrect: Rect; {onscreen destination rect for copybits}

			end;


{;/* add16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipA, skipB, skipOut; }
{;    unsigned short *baseA, *baseB, *baseOut; }
{;] Pixel16uPair; }
{; }
{;pascal add16u( }
{;    register Pixel16uPair *arg }
{;) [ }
{;    register unsigned short *a, *b, *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipA, skipB, skipOut; }
{;    register unsigned long acc; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            acc = *a++ + *b++; }
{;            if (acc <= 65535) }
{;                *out++ = acc; }
{;            else }
{;                *out++ = 65535; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type Pixel16uPair = record ' }
{ DC.B 'wpix, height, skipA, skipB, skipOut: longint;' }
{ DC.B 'baseA, baseB, baseOut: ptr;' }
{ DC.B 'end;' }
{ DC.B 'procedure add16u (var arg: Pixel16uPair); inline',0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D6/A2-A4,-(A7) }
{ MOVEM.L 4(A1),D3-D6/A2-A4 }
{L1: MOVE.L (A1),D1 }
{L2: MOVE.W (A3)+,D0 }
{ ADD.W (A2)+,D0 }
{ BCS.S L3 }
{ MOVE.W D0,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L2 }
{ BRA.S L4 }
{L3: MOVE.W #$FFFF,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L2 }
{L4: ADDA.L D4,A2 }
{ ADDA.L D5,A3 }
{ ADDA.L D6,A4 }
{ SUBQ.L #$1,D3 }
{ BHI.S L1 }
{ MOVEM.L (A7)+,D3-D6/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		Pixel16uPair = record
				wpix, height, skipA, skipB, skipOut: longint;
				baseA, baseB, baseOut: ptr;
			end;
	procedure add16u (var arg: Pixel16uPair);
	inline
		$225F, $48E7, $1E38, $4CE9, $1C78, $0004, $2211, $301B,{}
		$D05A, $6508, $38C0, $5381, $62F4, $6008, $38FC, $FFFF,{}
		$5381, $62EA, $D5C4, $D7C5, $D9C6, $5383, $62DE, $4CDF,{}
		$1C78;
{;/* sub16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipA, skipB, skipOut; }
{;    unsigned short *baseA, *baseB, *baseOut; }
{;] Pixel16uPair; }
{; }
{;pascal sub16u( }
{;    register Pixel16uPair *arg }
{;) [ }
{;    register unsigned short *a, *b, *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipA, skipB, skipOut; }
{;    register unsigned long acc; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            acc = ((unsigned long)*a++) - *b++; }
{;            if (acc <= 65535) }
{;                *out++ = acc; }
{;            else }
{;                *out++ = 0; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type Pixel16uPair = record ' }
{ DC.B 'wpix, height, skipA, skipB, skipOut: longint;' }
{ DC.B 'baseA, baseB, baseOut: ptr;' }
{ DC.B 'end;' }
{ DC.B 'procedure sub16u (var arg: Pixel16uPair); inline',0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D6/A2-A4,-(A7) }
{ MOVEM.L 4(A1),D3-D6/A2-A4 }
{ MOVEQ.L #0,D2 }
{L1: MOVE.L (A1),D1 }
{L2: MOVE.W (A2)+,D0 }
{ SUB.W (A3)+,D0 }
{ BCS.S L3 }
{ MOVE.W D0,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L2 }
{ BRA.S L4 }
{L3: MOVE.W D2,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L2 }
{L4: ADDA.L D4,A2 }
{ ADDA.L D5,A3 }
{ ADDA.L D6,A4 }
{ SUBQ.L #$1,D3 }
{ BHI.S L1 }
{ MOVEM.L (A7)+,D3-D6/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	procedure sub16u (var arg: Pixel16uPair);
	inline
		$225F, $48E7, $1E38, $4CE9, $1C78, $0004, $7400, $2211,{}
		$301A, $905B, $6508, $38C0, $5381, $62F4, $6006, $38C2,{}
		$5381, $62EC, $D5C4, $D7C5, $D9C6, $5383, $62E0, $4CDF,{}
		$1C78;
{;/* mpy16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipA, skipB, skipOut; }
{;    unsigned short *baseA, *baseB, *baseOut; }
{;] Pixel16uPair; }
{; }
{;pascal mpy16u( }
{;    register Pixel16uPair *arg }
{;) [ }
{;    register unsigned short *a, *b, *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipA, skipB, skipOut; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            *out++ = *a++ * *b++; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D6/A2-A4,-(A7) }
{ MOVEM.L 4(A1),D3-D6/A2-A4 }
{L1: MOVE.L (A1),D1 }
{L2: MOVE.W (A3)+,D0 }
{ MULU.W (A2)+,D0 }
{ MOVE.W D0,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L2 }
{ ADDA.L D4,A2 }
{ ADDA.L D5,A3 }
{ ADDA.L D6,A4 }
{ SUBQ.L #$1,D3 }
{ BHI.S L1 }
{ MOVEM.L (A7)+,D3-D6/A2-A4 }
	procedure mpy16u (var arg: Pixel16uPair);
	inline
		$225F, $48E7, $1E38, $4CE9, $1C78, $0004, $2211, $301B,{}
		$C0DA, $38C0, $5381, $62F6, $D5C4, $D7C5, $D9C6, $5383,{}
		$62EA, $4CDF, $1C78;
{;/* div16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipA, skipB, skipOut; }
{;    unsigned short *baseA, *baseB, *baseOut; }
{;] Pixel16uPair; }
{; }
{;pascal div16u( }
{;    register Pixel16uPair *arg }
{;) [ }
{;    register unsigned short *a, *b, *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipA, skipB, skipOut; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            *out++ = *a++ / *b++; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D6/A2-A4,-(A7) }
{ MOVEM.L 4(A1),D3-D6/A2-A4 }
{L1: MOVE.L (A1),D1 }
{L2: MOVEQ #$00,D0 }
{ MOVE.W (A2)+,D0 }
{ DIVU.W (A3)+,D0 }
{ MOVE.W D0,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L2 }
{ ADDA.L D4,A2 }
{ ADDA.L D5,A3 }
{ ADDA.L D6,A4 }
{ SUBQ.L #$1,D3 }
{ BHI.S L1 }
{ MOVEM.L (A7)+,D3-D6/A2-A4 }
	procedure div16u (var arg: Pixel16uPair);
	inline
		$225F, $48E7, $1E38, $4CE9, $1C78, $0004, $2211, $7000,{}
		$301A, $80DB, $38C0, $5381, $62F4, $D5C4, $D7C5, $D9C6,{}
		$5383, $62E8, $4CDF, $1C78;
{;/* ratio16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipA, skipB, skipOut, scale; }
{;    unsigned short *baseA, *baseB, *baseOut; }
{;    long zeroDivide; }
{;] ratio16uArg; }
{; }
{;pascal ratio16u( }
{;    register ratio16uArg *arg }
{;) [ }
{;    register unsigned short *a, *b, *out; }
{;    register unsigned long cols, scale, denom; }
{;    register unsigned long skipA, skipB, skipOut; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    scale = arg->scale; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            denom = *b++; }
{;            if (denom == 0) [ }
{;                a++; }
{;                denom = arg->zeroDivide; }
{;            ] else [ }
{;                denom = (scale * *a++ + (denom >> 2)) / denom; }
{;                if (denom > 65535) [ }
{;                    denom = -1; }
{;                ] }
{;            ] }
{;            *out++ = denom; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--arg->height > 0); }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type ratio16uArg = record',13 }
{ DC.B ' wpix, height, skipA, skipB, skipOut, scale: longint;',13 }
{ DC.B ' baseA, baseB, baseOut: ptr; ',13 }
{ DC.B ' zeroDivide: longint;',13 }
{ DC.B ' end;',13 }
{ DC.B ' procedure ratio16u (var arg: ratio16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7/A2-A3,-(A7) }
{ MOVEM.L 8(A0),D2-D5/A1-A3 }
{L0028 MOVE.L (A0),D6 }
{L002A MOVEQ #$00,D7 }
{ MOVE.W (A2)+,D7 }
{ TST.L D7 }
{ BNE.S L003A }
{ ADDQ.W #$2,A1 }
{ MOVE.L $0024(A0),D7 }
{ BRA.S L005A }
{L003A MOVEQ #$00,D0 }
{ MOVE.W (A1)+,D0 }
{ TST.L D0 }
{ MULU.L D5,D0 }
{ MOVE.L D7,D1 }
{ LSR.L #$2,D1 }
{ ADD.L D0,D1 }
{ DIVU.L D7,D1 }
{ MOVE.L D1,D7 }
{ CMPI.L #$0000FFFF,D7 }
{ BLS.S L005A }
{ MOVEQ #-1,D7 }
{L005A MOVE.W D7,(A3)+ }
{ SUBQ.L #$1,D6 }
{ BHI.S L002A }
{ ADDA.L D2,A1 }
{ ADDA.L D3,A2 }
{ ADDA.L D4,A3 }
{ SUBQ.L #$1,$0004(A0) }
{ BGT.S L0028 }
{ MOVEM.L (A7)+,D3-D7/A2-A3 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		ratio16uArg = record
				wpix, height, skipA, skipB, skipOut, scale: longint;
				baseA, baseB, baseOut: ptr;
				zeroDivide: longint;
			end;
	procedure ratio16u (var arg: ratio16uArg);
	inline
		$205F, $48E7, $1F30, $4CE8, $0E3C, $0008, $2C10, $7E00,{}
		$3E1A, $4A87, $6608, $5449, $2E28, $0024, $6020, $7000,{}
		$3019, $4A80, $4C05, $0000, $2207, $E489, $D280, $4C47,{}
		$1001, $2E01, $0C87, $0000, $FFFF, $6302, $7EFF, $36C7,{}
		$5386, $62CA, $D3C2, $D5C3, $D7C4, $53A8, $0004, $6EBC,{}
		$4CDF, $0CF8;
{;/* lrg16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipA, skipB, skipOut; }
{;    unsigned short *baseA, *baseB, *baseOut; }
{;] Pixel16uPair; }
{; }
{;pascal lrg16u( }
{;    register Pixel16uPair *arg }
{;) [ }
{;    register unsigned short *a, *b, *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipA, skipB, skipOut; }
{;    register unsigned long av,bv; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            av = *a++; }
{;            bv = *b++; }
{;            if (av > bv) }
{;                bv = av; }
{;            *out++ = bv; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVEM.L 4(A1),D1-D4/A2-A4 }
{ MOVEQ #$00,D6 }
{ MOVEQ #$00,D7 }
{L1: MOVE.L (A1),D5 }
{L2: MOVE.W (A2)+,D6 }
{ MOVE.W (A3)+,D7 }
{ CMP.L D6,D7 }
{ BCC.S L3 }
{ MOVE.L D6,D7 }
{L3: MOVE.W D7,(A4)+ }
{ SUBQ.L #$1,D5 }
{ BHI.S L2 }
{ ADDA.L D2,A2 }
{ ADDA.L D3,A3 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,D1 }
{ BHI.S L1 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
	procedure lrg16u (var arg: Pixel16uPair);
	inline
		$225F, $48E7, $1F38, $4CE9, $1C1E, $0004, $7C00, $7E00,{}
		$2A11, $3C1A, $3E1B, $BE86, $6402, $2E06, $38C7, $5385,{}
		$62F0, $D5C2, $D7C3, $D9C4, $5381, $62E4, $4CDF, $1CF8;
{;/* sml16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipA, skipB, skipOut; }
{;    unsigned short *baseA, *baseB, *baseOut; }
{;] Pixel16uPair; }
{; }
{;pascal sml16u( }
{;    register Pixel16uPair *arg }
{;) [ }
{;    register unsigned short *a, *b, *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipA, skipB, skipOut; }
{;    register unsigned long av,bv; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            av = *a++; }
{;            bv = *b++; }
{;            if (av > bv) }
{;                bv = av; }
{;            *out++ = bv; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVEM.L 4(A1),D1-D4/A2-A4 }
{ MOVEQ #$00,D6 }
{ MOVEQ #$00,D7 }
{L1: MOVE.L (A1),D5 }
{L2: MOVE.W (A2)+,D6 }
{ MOVE.W (A3)+,D7 }
{ CMP.L D6,D7 }
{ BLS.S L3 }
{ MOVE.L D6,D7 }
{L3: MOVE.W D7,(A4)+ }
{ SUBQ.L #$1,D5 }
{ BHI.S L2 }
{ ADDA.L D2,A2 }
{ ADDA.L D3,A3 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,D1 }
{ BHI.S L1 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
	procedure sml16u (var arg: Pixel16uPair);
	inline
		$225F, $48E7, $1F38, $4CE9, $1C1E, $0004, $7C00, $7E00,{}
		$2A11, $3C1A, $3E1B, $BE86, $6302, $2E06, $38C7, $5385,{}
		$62F0, $D5C2, $D7C3, $D9C4, $5381, $62E4, $4CDF, $1CF8;

{;/* Cnvrt16uTo8.c */ }
{; }
{;typedef struct [ }
{;    unsigned long wpix, height, skipIn, skipOut; }
{;    unsigned short *baseIn; }
{;    unsigned char *baseLUT, *baseOut; }
{;] Cnvrt16uTo8Arg; }
{; }
{;pascal Cnvrt16uTo8( }
{;    register Cnvrt16uTo8Arg *arg }
{;) [ }
{;    register unsigned short *in; }
{;    register unsigned char *LUT; }
{;    register unsigned char *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    in = arg->baseIn; }
{;    LUT = arg->baseLUT; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            *out++ = LUT[*in++]; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{; }
{;] }
{; }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3/D4/A2-A4,-(A7) }
{ MOVEM.L (A1),D1-D4/A2-A4 }
{ MOVEQ #$00,D0 }
{ MOVEA.L D1,A1 }
{L2: MOVE.L A1,D1 }
{L1: MOVE.W (A2)+,D0 }
{ MOVE.B $00(A3,D0.L),(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L1 }
{ ADDA.L D3,A2 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,D2 }
{ BHI.S L2 }
{ MOVEM.L (A7)+,D3/D4/A2-A4 }
	type
		Cnvrt16uTo8Arg = record
				wpix, height, skipIn, skipOut: longint;
				baseIn, baseLUT, baseOut: ptr;
			end;
	procedure Cnvrt16uTo8 (var arg: Cnvrt16uTo8Arg);
	inline
		$225F, $48E7, $1838, $4CD1, $1C1E, $7000, $2241, $2209,{}
		$301A, $18F3, $0800, $5381, $62F6, $D5C3, $D9C4, $5382,{}
		$62EC, $4CDF, $1C18;
{;/* Cnvrt8To16u.c */ }
{; }
{;typedef struct [ }
{;    unsigned long wpix, height, skipIn, skipOut; }
{;    unsigned char *baseIn; }
{;    unsigned short *baseLUT, *baseOut; }
{;] Cnvrt8To16uArg; }
{; }
{;pascal Cnvrt8To16u( }
{;    register Cnvrt8To16uArg *arg }
{;) [ }
{;    register unsigned char *in; }
{;    register unsigned short *LUT; }
{;    register unsigned short *out; }
{;    register unsigned long lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    in = arg->baseIn; }
{;    LUT = arg->baseLUT; }
{;    out = arg->baseOut; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            *out++ = LUT[*in++]; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3/D4/A2-A4,-(A7) }
{ MOVEM.L (A1),D1-D4/A2-A4 }
{ MOVEQ #$00,D0 }
{ MOVEA.L D1,A1 }
{L1: MOVE.L A1,D1 }
{L2: MOVE.B (A2)+,D0 }
{ MOVE.W $00(A3,D0.L*2),(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L2 }
{ ADDA.L D3,A2 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,D2 }
{ BHI.S L1 }
{ MOVEM.L (A7)+,D3/D4/A2-A4 }
	type
		Cnvrt8To16uArg = record
				wpix, height, skipIn, skipOut: longint;
				baseIn, baseLUT, baseOut: ptr;
			end;
	procedure Cnvrt8To16u (var arg: Cnvrt8To16uArg);
	inline
		$225F, $48E7, $1838, $4CD1, $1C1E, $7000, $2241, $2209,{}
		$101A, $38F3, $0A00, $5381, $62F6, $D5C3, $D9C4, $5382,{}
		$62EC, $4CDF, $1C18;

{;/* Convolve16u.c */ }
{; }
{;/* }
{; }
{;Kernel Array:  array of structs, each with value and two offsets. }
{; }
{;The kernel is preprocessed by the caller and passed in as a array }
{;of structs which contain the kernel value and byte offsets to the }
{;input pixel and the mask pixel which correspond to the value.  Only }
{;nonzero kernel entries are placed in the array.  The end of the array }
{;is signaled by a zero value.  The offsets encode knowledge about the }
{;bytes per row and bytes per pixel of the two images. }
{; }
{; }
{;Input Data Image:  16 bit unsigned. }
{; }
{; }
{;Mask Image:  8 bit unsigned. }
{; }
{;Zero means use input data from this point. }
{; }
{;The base address passed in by the caller is not the smallest }
{;address which will be referred to.  The base address is the }
{;address of the pixel which corresponds to the top left pixel }
{;of the input image.  This will be added to the sometimes negative }
{;offsets specified in the kernel array, and it is the responsibility }
{;of the caller to guarantee that the result will always fall within }
{;the mask image. }
{; }
{;The mask image has two purposes.  First, it is used to specify that }
{;certain pixels within the input image should not be used for calculating }
{;the convolution.  Convolution is a weighted average of pixels, and masked }
{;pixels are left out by setting their weight to zero. }
{; }
{;Second, the identical rule is used to deal with the edges of the image: }
{;when the kernel calls for a pixel outside the image, the mask image }
{;(which is larger) must specify that that pixel is masked out, so that }
{;the weight will be zero.  It is the responsibility of the caller to }
{;ensure that the mask image correctly specifys that pixels outside the }
{;input image are masked.  Otherwise, the algorithm will read the memory }
{;locations outside of the input image.  In a worst case with a very }
{;large kernel and an input image near the end of physical memory, this }
{;might cause an access violation and crash. }
{; }
{; }
{;Flag Image:  8 bit unsigned. }
{; }
{;Zero means calculate output at this point, dimensions }
{;must be idendical to the input image (allowing for different pixel size). }
{;Zero values will be replaced by the number of input pixels which }
{;contributed to the output, or left unchanged if there were no unmasked }
{;input pixels available.  If more than 255 pixels contributed, the }
{;value will be 255. }
{; }
{;The main purpose of this image is to permit substitution of }
{;a larger kernel for those output points where all of the }
{;input points were masked out. }
{; }
{;Output Data Image:  16 bit unsigned, same size as input. }
{; }
{;Algorithm: }
{; }
{;loop over each row of input, mask, flag, output }
{;    (where mask starts at pixel (hx,hy)) }
{;    loop over each pixel of current row of input, mask, flag, output }
{;        if *flag is zero }
{;            clear n,d,f }
{;            loop over each kernel record k }
{;                if mask[k->maskOffset] is zero }
{;                    v = k->value }
{;                    add v to d }
{;                    add input[k->inOffset] * v to n }
{;                    add 1 to f }
{;                end }
{;            end }
{;            if f is not zero }
{;                *flag = smaller of f or 255 }
{;                if d is not zero }
{;                    *output = n / d }
{;                else }
{;                    *output = n }
{;            end }
{;        end }
{;    end }
{;end }
{; }
{;*/ }
{; }
{;typedef struct [ }
{;    long value; /* last entry has value == 0 */ }
{;    long maskOffset; }
{;    long inOffset; }
{;] KernelValue; }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipMask, skipFlag, skipOut; }
{;    KernelValue *baseK; }
{;    unsigned short *baseIn; }
{;    unsigned char *baseMask; }
{;    unsigned char *baseFlag; }
{;    unsigned short *baseOut; }
{;] conv16uarg; }
{; }
{;Convolve16u( }
{;    register conv16uarg *a }
{;) [ }
{;    register KernelValue *k; }
{;    register unsigned short *in; }
{;    register unsigned char *mask; }
{;    register unsigned char *flag; }
{;    register unsigned short *out; }
{;    register long cols; }
{;    register long n, d, f, v; }
{; }
{;    in = a->baseIn; }
{;    mask = a->baseMask; /* already points to pixel hx,hy */ }
{;    flag = a->baseFlag; }
{;    out = a->baseOut; }
{; }
{;    do [ }
{;        cols = a->wpix; }
{;        do [ }
{;            if ( *flag == 0) [ }
{;                n = d = f = 0; }
{;                k = a->baseK; }
{;                v = k->value; }
{;                do [ }
{;                    if (mask[k->maskOffset] == 0) [ }
{;                        n += in[k->inOffset>>1] * v; }
{;                        d += v; }
{;                        f++; }
{;                    ] }
{;                    k++; }
{;                ] while ((v = k->value) != 0); }
{;                if (f != 0) [ }
{;                    if (( *flag = f) == 0) *flag = 255; }
{;                    if (d != 0) [ }
{;                        *out = n / d; }
{;                    ] else [ }
{;                        *out = n; }
{;                    ] }
{;                ] }
{;            ] }
{;            in++; }
{;            mask++; }
{;            flag++; }
{;            out++; }
{;        ] while (--cols > 0); }
{;        (char * )in += a->skipIn; }
{;        (char * )mask += a->skipMask; }
{;        (char * )flag += a->skipFlag; }
{;        (char * )out += a->skipOut; }
{;    ] while (--a->height > 0); }
{; }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type KernelValue = record value, maskOffset, inOffset: LongInt;' }
{ DC.B 'end;KernelValuePtr = ^KernelValue;' }
{ DC.B 'Convolve16uArg = record wpix, height, skipIn, skipMask, skipFlag,' }
{ DC.B ' skipOut: LongInt;baseK: KernelValuePtr;baseIn, baseMask, baseFlag,' }
{ DC.B ' baseOut: Ptr;end; procedure Convolve16u(var arg: Convolve16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVE.L (A7)+,A0 }
{ MOVEM.L D3-D7/A2-A5,-(A7) }
{ MOVEA.L $001C(A0),A2 ;in = a->baseIn }
{ MOVEA.L $0020(A0),A3 ;mask = a->baseMask }
{ MOVEA.L $0024(A0),A1 ;flag = a->baseFlag }
{ MOVE.L $0028(A0),A5 ;out = a->baseOut }
{L1: MOVE.L (A0),D3 ;do [ cols = a->wpix }
{L2: MOVE.B (A1),D0 ;do [ if ( *flag == 0) [ }
{ BNE.S L7 }
{ MOVEQ #$00,D6 ;n = d = f = 0 }
{ MOVE.L D6,D5 }
{ MOVE.L D5,D4 }
{ MOVEA.L $0018(A0),A4 ;k = a->baseK }
{ MOVE.L (A4),D7 ;v = k->value }
{L3: MOVE.L $0004(A4),D0 ;do [ if (mask[k->maskOffset] == 0) [ }
{ MOVE.B $00(A3,D0.L),D1 }
{ BNE.S L4 }
{ MOVE.L $0008(A4),D0 ;n += in[k->inOffset>>1] * v }
{ MOVEQ #$00,D1 }
{ MOVE.W $00(A2,D0.L),D1 }
{ TST.L D1 }
{ MULS.L D7,D1 }
{ ADD.L D1,D4 }
{ ADD.L D7,D5 ;d += v }
{ ADDQ.L #$1,D6 ;f++ }
{L4: LEA $000C(A4),A4 ;] k++ }
{ MOVE.L (A4),D7 ;] while ((v = k->value) != 0) }
{ BNE.S L3 }
{ TST.L D6 ;if (f != 0) [ }
{ BEQ.S L7 }
{ MOVE.B D6,(A1) ;if (( *flag = f) == 0) *flag = 255 }
{ BNE.S L5 }
{ MOVE.B #$FF,(A1) }
{L5: TST.L D5 ;if (d != 0) }
{ BEQ.S L6 }
{ DIVS.L D5,D4 ;*out = n / d }
{L6: MOVE.W D4,(A5) ;else *out = n }
{L7: ADDQ.W #$2,A2 ;] ] in++ }
{ ADDQ.W #$1,A3 ;mask++ }
{ ADDQ.W #$1,A1 ;flag++ }
{ ADDQ.W #$2,A5 ;out++ }
{ SUBQ.L #$1,D3 ;] while (--cols > 0) }
{ BGT.S L2 }
{ ADDA.L $0008(A0),A2 ;(char * )in += a->skipIn }
{ ADDA.L $000C(A0),A3 ;(char * )mask += a->skipMask }
{ ADDA.L $0010(A0),A1 ;(char * )flag += a->skipFlag }
{ ADDA.L $0014(A0),A5 ;(char * )out += a->skipOut }
{ SUBQ.L #$1,$0004(A0) ;] while (--a->height > 0); }
{ BGT.S L1 }
{ MOVEM.L (A7)+,D3-D7/A2-A5 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		KernelValue = record
				value, maskOffset, inOffset: LongInt;
			end;
		KernelValuePtr = ^KernelValue;
		Convolve16uArg = record
				wpix, height, skipIn, skipMask, skipFlag, skipOut: LongInt;
				baseK: KernelValuePtr;
				baseIn, baseMask, baseFlag, baseOut: Ptr;
			end;
	procedure Convolve16u (var arg: Convolve16uArg);
	inline
		$205F, $48E7, $1F3C, $2468, $001C, $2668, $0020, $2268,{}
		$0024, $2A68, $0028, $2610, $1011, $664A, $7C00, $2A06,{}
		$2805, $2868, $0018, $2E14, $202C, $0004, $1233, $0800,{}
		$6616, $202C, $0008, $7200, $3232, $0800, $4A81, $4C07,{}
		$1801, $D881, $DA87, $5286, $49EC, $000C, $2E14, $66D8,{}
		$4A86, $6712, $1286, $6604, $12BC, $00FF, $4A85, $6704,{}
		$4C45, $4804, $3A84, $544A, $524B, $5249, $544D, $5383,{}
		$6EA6, $D5E8, $0008, $D7E8, $000C, $D3E8, $0010, $DBE8,{}
		$0014, $53A8, $0004, $6E8E, $4CDF, $3CF8;

{; find the 5th largest of 9 unsigned shorts }
{; in the case of equal values, consider either one smaller }
{  }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'function median9x16u(var vals: array[1..9] of integer): integer; inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVE.L (A7)+,A0 }
{ MOVEM.L D3-D7,-(A7) }
{ movem.w (a0)+,d0-d7 }
{ cmp.w d1,d0 }
{ blo.s @1 }
{ exg d1,d0 }
{@1 ;d0 <= d1 }
{ cmp.w d3,d2 }
{ blo.s @2 }
{ exg d3,d2 }
{@2 ;d2 <= d3 }
{ cmp.w d3,d1 }
{ blo.s @3 }
{ exg d2,d0 }
{ exg d3,d1 }
{@3 ;d0 <= d1, d1 <= d3, d2 <= d3 }
{ cmp.w d5,d4 }
{ blo.s @4 }
{ exg d5,d4 }
{@4 ;d4 <= d5 }
{ cmp.w d7,d6 }
{ blo.s @5 }
{ exg d7,d6 }
{@5 ;d6 <= d7 }
{ cmp.w d7,d5 }
{ blo.s @6 }
{ exg d6,d4 }
{ exg d7,d5 }
{@6 ;d4 <= d5, d5 <= d7, d6 <= d7 }
{ cmp.w d5,d1 }
{ blo.s @7 }
{ exg d7,d3 }
{ exg d6,d2 }
{ exg d5,d1 }
{ exg d4,d0 }
{@7 ;d0 <= d1, d1 <= d5, d4 <= d5, d5 <= d7, d6 <= d7 }
{ ; (also, d1 <= d3, d2 <= d3) }
{ ; hence, d0, d1, d4, d5, and d6 are all <= d7 }
{ ; hence d7 cannot be the median. }
{ move.w (a0),d7 ;pick up the 9th value into d7 }
{ cmp.w d7,d6 }
{ blo.s @8 }
{ exg d7,d6 }
{@8 ;d6 <= d7 }
{ cmp.w d7,d5 }
{ blo.s @9 }
{ exg d6,d4 }
{ exg d7,d5 }
{@9 ;d4 <= d5, d5 <= d7, d6 <= d7 }
{ cmp.w d5,d1 }
{ blo.s @10 }
{ exg d7,d3 }
{ exg d6,d2 }
{ exg d5,d1 }
{ exg d4,d0 }
{@10 ;d0 <= d1, d1 <= d5, d4 <= d5, d5 <= d7, d6 <= d7 }
{ ; (also, d1 <= d3, d2 <= d3) }
{ ; hence, d0, d1, d4, d5, and d6 are all <= d7 }
{ ; hence 5 values are smaller than d7 }
{ ; hence d7 cannot be the median. }
{ ; also, d0 <= all of d1, d3, d5, d7, old d7 }
{ ; hence 5 values are larger than d0 }
{ ; hence d0 cannot be the median. }
{ ; possible medians are d1, d2, d3, d4, d5, d6 }
{ cmp.w d6,d1 }
{ blo.s medof5 }
{ ; d6 <= d1 }
{ ; hence d6 <= all of d1, d3, d5, d7, old d7 }
{ ; possible medians are d1, d2, d3, d4, d5 }
{ ; d1 <= d3, d2 <= d3, d1 <= d5, d4 <= d5 }
{ cmp.w d2,d1 }
{ blo.s @11 }
{ ; d2 <= all of d1, d3, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; leaving d1, d3, d4 }
{ cmp.w d4,d1 }
{ blo.s @10a }
{ ; d4 <= d1, the median is d1. }
{ ; d4 <= all of d1, d3, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ move.w d1,d0 }
{ bra.s done }
{ }
{@10a ; d1 < d4 }
{ ; d1 <= all of d3, d4, d5, d7, old d7 }
{ ; leaving d3, d4 }
{ cmp.w d4,d3 }
{ blo.s @10b }
{ ; d4 <= d3, the median is d4. }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ move.w d4,d0 }
{ bra.s done }
{ }
{@10b ; d3 < d4, the median is d3. }
{ ; d0, d1, d2, d3, d6 all <= d4 }
{ move.w d3,d0 }
{ bra.s done }
{ }
{@11 ;d1 < d2 }
{ ; d1 <= all of d2, d3, d5, d7, old d7 }
{ ; leaving d2, d3, d4, d5 }
{ ; d2 <= d3, d4 <= d5 }
{ cmp.w d4,d2 }
{ blo.s @12 }
{ ; d4 <= all of d2, d3, d5, d7, old d7 }
{ ; leaving d2, d3, d5 }
{ cmp.w d5,d2 }
{ blo.s @11a }
{ ; d5 <= d2 }
{ ; d0, d1, d4, d5, d6 all <= d2 }
{ ; d0, d1, d2, d4, d5, d6 all <= d3 }
{ ; median is d5 }
{ move.w d5,d0 }
{ bra.s done }
{  }
{@11a ; d2 < d5 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ ; median is d2 }
{ move.w d2,d0 }
{ bra.s done }
{ }
{@12 ; d2 < d4 }
{ ; d2 <= all of d3, d4, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; leaving d3, d4 }
{ cmp.w d4,d3 }
{ blo.s @12a }
{ ; d4 <= d3 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ ; median is d4 }
{ move.w d4,d0 }
{ bra.s done }
{@12a ; d3 < d4 }
{ ; d0, d1, d2, d3, d6 all <= d4 }
{ ; median is d3 }
{ move.w d3,d0 }
{ bra.s done }
{ }
{medof5 ;d1 < d6 }
{ ; d1 <= all of d3, d5, d6, d7, old d7 }
{ ; leaving d2, d3, d4, d5, d6 }
{ ; and the median is the third largest of these }
{ ; d2 <= d3, d4 <= d5 }
{ cmp.w d5,d3 }
{ blo.s @1 }
{ exg d4,d2 }
{ exg d5,d3 }
{@1 ;d2 <= d3, d3 <= d5, d4 <= d5 }
{ cmp.w d6,d4 }
{ blo.s @cmp36 }
{ ; d6 <= d4 }
{ cmp.w d4,d3 }
{ blo.s @cmp36a }
{ ; d4 <= d3 }
{ cmp.w d4,d2 }
{ blo.s @med4 }
{ ; d4 <= d2 }
{ move.w d2,d0 }
{ bra.s done }
{@med4 move.w d4,d0 }
{ bra.s done }
{@cmp36a ;d3 < d4 }
{ cmp.w d6,d3 }
{ blo.s @med6 }
{ ; d6 <= d3 }
{ move.w d3,d0 }
{ bra.s done }
{@med6 move.w d6,d0 }
{ bra.s done }
{@cmp36 ;d4 < d6 }
{ cmp.w d6,d3 }
{ blo.s @cmp34 }
{ ; d6 <= d3 }
{ cmp.w d6,d2 }
{ blo.s @med6 }
{ move.w d2,d0 }
{ bra.s done }
{@cmp34 ;d3 < d6 }
{ cmp.w d4,d3 }
{ blo.s @med4 }
{ ; d4 <= d3 }
{ move.w d3,d0 }
{ ; bra.s done }
{done: }
{ MOVEM.L (A7)+,D3-D7 }
{ MOVE.W D0,(A7) }
{endcode: }
{ ENDPROC }
{ END }
{}
	function median9x16u (vals: ptr): integer;
	inline
		$205F, $48E7, $1F00, $4C98, $00FF, $B041, $6502, $C340,{}
		$B443, $6502, $C742, $B243, $6504, $C540, $C741, $B845,{}
		$6502, $CB44, $BC47, $6502, $CF46, $BA47, $6504, $CD44,{}
		$CF45, $B245, $6508, $CF43, $CD42, $CB41, $C940, $3E10,{}
		$BC47, $6502, $CF46, $BA47, $6504, $CD44, $CF45, $B245,{}
		$6508, $CF43, $CD42, $CB41, $C940, $B246, $6534, $B242,{}
		$6514, $B244, $6504, $3001, $6062, $B644, $6504, $3004,{}
		$605A, $3003, $6056, $B444, $650C, $B445, $6504, $3005,{}
		$604A, $3002, $6046, $B644, $6504, $3004, $603E, $3003,{}
		$603A, $B645, $6504, $C942, $CB43, $B846, $651C, $B644,{}
		$650C, $B444, $6504, $3002, $6022, $3004, $601E, $B646,{}
		$6504, $3003, $6016, $3006, $6012, $B646, $6508, $B446,{}
		$65F4, $3002, $6006, $B644, $65E0, $3003, $4CDF, $00F8,{}
		$3E80;

	procedure testMedian;
		var
			vals: array[1..9] of integer;
			i1, i2, i3, i4, i5, i6, i7, i8, i9: integer;
	begin
		for i1 := 1 to 9 do
			vals[i1] := 0;
		for i1 := 1 to 9 do
			if vals[i1] = 0 then begin
					vals[i1] := 1;
					for i2 := 1 to 9 do
						if vals[i2] = 0 then begin
								vals[i2] := 2;
								for i3 := 1 to 9 do
									if vals[i3] = 0 then begin
											vals[i3] := 3;
											for i4 := 1 to 9 do
												if vals[i4] = 0 then begin
														vals[i4] := 4;
														for i5 := 1 to 9 do
															if vals[i5] = 0 then begin
																	vals[i5] := 5;
																	for i6 := 1 to 9 do
																		if vals[i6] = 0 then begin
																				vals[i6] := 6;
																				for i7 := 1 to 9 do
																					if vals[i7] = 0 then begin
																							vals[i7] := 7;
																							for i8 := 1 to 9 do
																								if vals[i8] = 0 then begin
																										vals[i8] := 8;
																										for i9 := 1 to 9 do
																											if vals[i9] = 0 then begin
																													vals[i9] := 9;
																													if median9x16u(@vals) <> 5 then
																														putMessage('bad median');
																													vals[i9] := 0;
																												end;
																										vals[i8] := 0;
																									end;
																							vals[i7] := 0;
																						end;
																				vals[i6] := 0;
																			end;
																	vals[i5] := 0;
																end;
														vals[i4] := 0;
													end;
											vals[i3] := 0;
										end;
								vals[i2] := 0;
							end;
					vals[i1] := 0;
				end;
	end;

{;/* median16u.c */ }
{;/* Caller must guarantee that the region of interest */ }
{;/* is inset by 1 pixel from boundaries of image. */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut; }
{;    unsigned short *baseIn, *baseOut; }
{;    unsigned short array[9]; }
{;] median16uArg; }
{; }
{;pascal median16u( }
{;    register median16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out, *a, *i; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut, skipI; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    skipI = wpix - 2; }
{;    skipI *= sizeof(short); }
{;    skipI += skipIn; }
{;    (char * )in -= skipI; }
{;    in -= 3; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            a = arg->array; }
{;            *a++ = *in++; }
{;            i = in; }
{;            *a++ = *i++; }
{;            *a++ = *i; }
{;            (char * )i += skipI; }
{;            *a++ = *i++; }
{;            *a++ = *i++; }
{;            *a++ = *i; }
{;            (char * )i += skipI; }
{;            *a++ = *i++; }
{;            *a++ = *i++; }
{;            *a = *i; }
{;            *out++ = median9x16u(arg->array); }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type median16uarg = record',13 }
{ DC.B 'wpix, height, skipIn, skipOut: LongInt;',13 }
{ DC.B 'baseIn, baseOut: Ptr;',13 }
{ DC.B 'arrayx: array[0..8] of Integer;',13 }
{ DC.B 'end;',13 }
{ DC.B 'procedure median16u(arg: median16uarg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVE.L (A7)+,A0 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVE.L (A0),D4 }
{ MOVE.L $0004(A0),D2 }
{ MOVE.L $0008(A0),D5 }
{ MOVE.L $000C(A0),D3 }
{ MOVEA.L $0010(A0),A2 }
{ MOVE.L $0014(A0),A1 }
{ MOVE.L D4,D7 }
{ SUBQ.L #$2,D7 }
{ ADD.L D7,D7 }
{ ADD.L D5,D7 }
{ SUBA.L D7,A2 }
{ SUBQ.W #$6,A2 }
{L0032 MOVE.L D4,D6 }
{L0034 LEA $0018(A0),A3 }
{ MOVE.W (A2)+,(A3)+ }
{ MOVEA.L A2,A4 }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4),(A3)+ }
{ ADDA.L D7,A4 }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4),(A3)+ }
{ ADDA.L D7,A4 }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4),(A3) }
{; median9x16u(arg->array) }
{ MOVEM.L D2-D7,-(A7) }
{ LEA $0018(A0),A3 }
{ movem.w (a3)+,d0-d7 }
{ cmp.w d1,d0 }
{ blo.s @1 }
{ exg d1,d0 }
{@1 ;d0 <= d1 }
{ cmp.w d3,d2 }
{ blo.s @2 }
{ exg d3,d2 }
{@2 ;d2 <= d3 }
{ cmp.w d3,d1 }
{ blo.s @3 }
{ exg d2,d0 }
{ exg d3,d1 }
{@3 ;d0 <= d1, d1 <= d3, d2 <= d3 }
{ cmp.w d5,d4 }
{ blo.s @4 }
{ exg d5,d4 }
{@4 ;d4 <= d5 }
{ cmp.w d7,d6 }
{ blo.s @5 }
{ exg d7,d6 }
{@5 ;d6 <= d7 }
{ cmp.w d7,d5 }
{ blo.s @6 }
{ exg d6,d4 }
{ exg d7,d5 }
{@6 ;d4 <= d5, d5 <= d7, d6 <= d7 }
{ cmp.w d5,d1 }
{ blo.s @7 }
{ exg d7,d3 }
{ exg d6,d2 }
{ exg d5,d1 }
{ exg d4,d0 }
{@7 ;d0 <= d1, d1 <= d5, d4 <= d5, d5 <= d7, d6 <= d7 }
{ ; (also, d1 <= d3, d2 <= d3) }
{ ; hence, d0, d1, d4, d5, and d6 are all <= d7 }
{ ; hence d7 cannot be the median. }
{ move.w (a3),d7 ;pick up the 9th value into d7 }
{ cmp.w d7,d6 }
{ blo.s @8 }
{ exg d7,d6 }
{@8 ;d6 <= d7 }
{ cmp.w d7,d5 }
{ blo.s @9 }
{ exg d6,d4 }
{ exg d7,d5 }
{@9 ;d4 <= d5, d5 <= d7, d6 <= d7 }
{ cmp.w d5,d1 }
{ blo.s @10 }
{ exg d7,d3 }
{ exg d6,d2 }
{ exg d5,d1 }
{ exg d4,d0 }
{@10 ;d0 <= d1, d1 <= d5, d4 <= d5, d5 <= d7, d6 <= d7 }
{ ; (also, d1 <= d3, d2 <= d3) }
{ ; hence, d0, d1, d4, d5, and d6 are all <= d7 }
{ ; hence 5 values are smaller than d7 }
{ ; hence d7 cannot be the median. }
{ ; also, d0 <= all of d1, d3, d5, d7, old d7 }
{ ; hence 5 values are larger than d0 }
{ ; hence d0 cannot be the median. }
{ ; possible medians are d1, d2, d3, d4, d5, d6 }
{ cmp.w d6,d1 }
{ blo.s medof5 }
{ ; d6 <= d1 }
{ ; hence d6 <= all of d1, d3, d5, d7, old d7 }
{ ; possible medians are d1, d2, d3, d4, d5 }
{ ; d1 <= d3, d2 <= d3, d1 <= d5, d4 <= d5 }
{ cmp.w d2,d1 }
{ blo.s @11 }
{ ; d2 <= all of d1, d3, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; leaving d1, d3, d4 }
{ cmp.w d4,d1 }
{ blo.s @10a }
{ ; d4 <= d1, the median is d1. }
{ ; d4 <= all of d1, d3, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ move.w d1,d0 }
{ bra.s done }
{ }
{@10a ; d1 < d4 }
{ ; d1 <= all of d3, d4, d5, d7, old d7 }
{ ; leaving d3, d4 }
{ cmp.w d4,d3 }
{ blo.s @10b }
{ ; d4 <= d3, the median is d4. }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ move.w d4,d0 }
{ bra.s done }
{ }
{@10b ; d3 < d4, the median is d3. }
{ ; d0, d1, d2, d3, d6 all <= d4 }
{ move.w d3,d0 }
{ bra.s done }
{ }
{@11 ;d1 < d2 }
{ ; d1 <= all of d2, d3, d5, d7, old d7 }
{ ; leaving d2, d3, d4, d5 }
{ ; d2 <= d3, d4 <= d5 }
{ cmp.w d4,d2 }
{ blo.s @12 }
{ ; d4 <= all of d2, d3, d5, d7, old d7 }
{ ; leaving d2, d3, d5 }
{ cmp.w d5,d2 }
{ blo.s @11a }
{ ; d5 <= d2 }
{ ; d0, d1, d4, d5, d6 all <= d2 }
{ ; d0, d1, d2, d4, d5, d6 all <= d3 }
{ ; median is d5 }
{ move.w d5,d0 }
{ bra.s done }
{  }
{@11a ; d2 < d5 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ ; median is d2 }
{ move.w d2,d0 }
{ bra.s done }
{ }
{@12 ; d2 < d4 }
{ ; d2 <= all of d3, d4, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; leaving d3, d4 }
{ cmp.w d4,d3 }
{ blo.s @12a }
{ ; d4 <= d3 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ ; median is d4 }
{ move.w d4,d0 }
{ bra.s done }
{@12a ; d3 < d4 }
{ ; d0, d1, d2, d3, d6 all <= d4 }
{ ; median is d3 }
{ move.w d3,d0 }
{ bra.s done }
{ }
{medof5 ;d1 < d6 }
{ ; d1 <= all of d3, d5, d6, d7, old d7 }
{ ; leaving d2, d3, d4, d5, d6 }
{ ; and the median is the third largest of these }
{ ; d2 <= d3, d4 <= d5 }
{ cmp.w d5,d3 }
{ blo.s @1 }
{ exg d4,d2 }
{ exg d5,d3 }
{@1 ;d2 <= d3, d3 <= d5, d4 <= d5 }
{ cmp.w d6,d4 }
{ blo.s @cmp36 }
{ ; d6 <= d4 }
{ cmp.w d4,d3 }
{ blo.s @cmp36a }
{ ; d4 <= d3 }
{ cmp.w d4,d2 }
{ blo.s @med4 }
{ ; d4 <= d2 }
{ move.w d2,d0 }
{ bra.s done }
{@med4 move.w d4,d0 }
{ bra.s done }
{@cmp36a ;d3 < d4 }
{ cmp.w d6,d3 }
{ blo.s @med6 }
{ ; d6 <= d3 }
{ move.w d3,d0 }
{ bra.s done }
{@med6 move.w d6,d0 }
{ bra.s done }
{@cmp36 ;d4 < d6 }
{ cmp.w d6,d3 }
{ blo.s @cmp34 }
{ ; d6 <= d3 }
{ cmp.w d6,d2 }
{ blo.s @med6 }
{ move.w d2,d0 }
{ bra.s done }
{@cmp34 ;d3 < d6 }
{ cmp.w d4,d3 }
{ blo.s @med4 }
{ ; d4 <= d3 }
{ move.w d3,d0 }
{ ; bra.s done }
{done: }
{ MOVEM.L (A7)+,D2-D7 }
{; end median9x16u(arg->array) }
{ MOVE.W D0,(A1)+ }
{ SUBQ.L #$1,D6 }
{ BGT.W L0034 }
{ ADDA.L D5,A2 }
{ ADDA.L D3,A1 }
{ SUBQ.L #$1,D2 }
{ BGT.W L0032 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		median16uarg = record
				wpix, height, skipIn, skipOut: LongInt;
				baseIn, baseOut: Ptr;
				arrayx: array[0..8] of Integer;
			end;
	procedure median16u (arg: median16uarg);
	inline
		$205F, $48E7, $1F38, $2810, $2428, $0004, $2A28, $0008,{}
		$2628, $000C, $2468, $0010, $2268, $0014, $2E04, $5587,{}
		$DE87, $DE85, $95C7, $5D4A, $2C04, $47E8, $0018, $36DA,{}
		$284A, $36DC, $36D4, $D9C7, $36DC, $36DC, $36D4, $D9C7,{}
		$36DC, $36DC, $3694, $48E7, $3F00, $47E8, $0018, $4C9B,{}
		$00FF, $B041, $6502, $C340, $B443, $6502, $C742, $B243,{}
		$6504, $C540, $C741, $B845, $6502, $CB44, $BC47, $6502,{}
		$CF46, $BA47, $6504, $CD44, $CF45, $B245, $6508, $CF43,{}
		$CD42, $CB41, $C940, $3E13, $BC47, $6502, $CF46, $BA47,{}
		$6504, $CD44, $CF45, $B245, $6508, $CF43, $CD42, $CB41,{}
		$C940, $B246, $6534, $B242, $6514, $B244, $6504, $3001,{}
		$6062, $B644, $6504, $3004, $605A, $3003, $6056, $B444,{}
		$650C, $B445, $6504, $3005, $604A, $3002, $6046, $B644,{}
		$6504, $3004, $603E, $3003, $603A, $B645, $6504, $C942,{}
		$CB43, $B846, $651C, $B644, $650C, $B444, $6504, $3002,{}
		$6022, $3004, $601E, $B646, $6504, $3003, $6016, $3006,{}
		$6012, $B646, $6508, $B446, $65F4, $3002, $6006, $B644,{}
		$65E0, $3003, $4CDF, $00FC, $32C0, $5386, $6E00, $FF0C,{}
		$D5C5, $D3C3, $5382, $6E00, $FF00, $4CDF, $1CF8;

{;/* radMedian16u.c */ }
{;/* Radial median filter.  Output pixel is median of 9 pixels */ }
{;/* distributed radially (or however caller wants) from the input. */ }
{;/* Offsets is an array of 9 offsets to pixels which contribute */ }
{;/* to the output pixel.  The region of interest of the output */ }
{;/* image must be inset from the edges so that no offsets go outside */ }
{;/* of the image. */ }
{; }
{;typedef unsigned short pixel_type; }
{;typedef unsigned short array_type; }
{;/* offsets are in bytes. */ }
{;typedef long offset_type; }
{; }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut; }
{;    pixel_type *baseIn; }
{;    pixel_type *baseOut; }
{;    offset_type offsets[9]; }
{;    array_type array[9]; }
{;] radMedian16uArg; }
{; }
{;pascal radMedian16u( }
{;    register radMedian16uArg *arg }
{;) [ }
{;    register char *charin; }
{;    register pixel_type *out; }
{;    register long cols; }
{;    register array_type *a; }
{;    register offset_type *off; }
{; }
{;    charin = (char * )arg->baseIn; }
{;    out = arg->baseOut; }
{; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            a = arg->array; }
{;            off = arg->offsets; }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            *a++ = *(pixel_type * )(charin + *off++); }
{;            charin += sizeof(pixel_type); }
{;            *out++ = median9x16u(arg->array); }
{;        ] while (--cols > 0); }
{;        charin += arg->skipIn; }
{;        (char * )out += arg->skipOut; }
{;    ] while (--arg->height > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type radMedian16uarg = record',13 }
{ DC.B 'wpix, height, skipIn, skipOut: LongInt;',13 }
{ DC.B 'baseIn, baseOut: Ptr;',13 }
{ DC.B 'offsets: array[0..8] of LongInt;',13 }
{ DC.B 'arrayx: array[0..8] of Integer;',13 }
{ DC.B 'end;',13 }
{ DC.B 'procedure radMedian16u(arg: radMedian16uarg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVE.L (A7)+,A0 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVEA.L $0010(A0),A4 }
{ MOVE.L $0014(A0),A1 }
{L0016 MOVE.L (A0),D7 }
{L001C LEA $003C(A0),A2 }
{ LEA $0018(A0),A3 }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ MOVE.L (A3)+,D0 }
{ MOVE.W 0(A4,D0.L),(A2)+ }
{ ADDQ.L #$2,A4 }
{; median9x16u(arg->array) }
{ MOVE.L D7,-(A7) }
{ LEA $003C(A0),A3 }
{ movem.w (a3)+,d0-d7 }
{ cmp.w d1,d0 }
{ blo.s @1 }
{ exg d1,d0 }
{@1 ;d0 <= d1 }
{ cmp.w d3,d2 }
{ blo.s @2 }
{ exg d3,d2 }
{@2 ;d2 <= d3 }
{ cmp.w d3,d1 }
{ blo.s @3 }
{ exg d2,d0 }
{ exg d3,d1 }
{@3 ;d0 <= d1, d1 <= d3, d2 <= d3 }
{ cmp.w d5,d4 }
{ blo.s @4 }
{ exg d5,d4 }
{@4 ;d4 <= d5 }
{ cmp.w d7,d6 }
{ blo.s @5 }
{ exg d7,d6 }
{@5 ;d6 <= d7 }
{ cmp.w d7,d5 }
{ blo.s @6 }
{ exg d6,d4 }
{ exg d7,d5 }
{@6 ;d4 <= d5, d5 <= d7, d6 <= d7 }
{ cmp.w d5,d1 }
{ blo.s @7 }
{ exg d7,d3 }
{ exg d6,d2 }
{ exg d5,d1 }
{ exg d4,d0 }
{@7 ;d0 <= d1, d1 <= d5, d4 <= d5, d5 <= d7, d6 <= d7 }
{ ; (also, d1 <= d3, d2 <= d3) }
{ ; hence, d0, d1, d4, d5, and d6 are all <= d7 }
{ ; hence d7 cannot be the median. }
{ move.w (a3),d7 ;pick up the 9th value into d7 }
{ cmp.w d7,d6 }
{ blo.s @8 }
{ exg d7,d6 }
{@8 ;d6 <= d7 }
{ cmp.w d7,d5 }
{ blo.s @9 }
{ exg d6,d4 }
{ exg d7,d5 }
{@9 ;d4 <= d5, d5 <= d7, d6 <= d7 }
{ cmp.w d5,d1 }
{ blo.s @10 }
{ exg d7,d3 }
{ exg d6,d2 }
{ exg d5,d1 }
{ exg d4,d0 }
{@10 ;d0 <= d1, d1 <= d5, d4 <= d5, d5 <= d7, d6 <= d7 }
{ ; (also, d1 <= d3, d2 <= d3) }
{ ; hence, d0, d1, d4, d5, and d6 are all <= d7 }
{ ; hence 5 values are smaller than d7 }
{ ; hence d7 cannot be the median. }
{ ; also, d0 <= all of d1, d3, d5, d7, old d7 }
{ ; hence 5 values are larger than d0 }
{ ; hence d0 cannot be the median. }
{ ; possible medians are d1, d2, d3, d4, d5, d6 }
{ cmp.w d6,d1 }
{ blo.s medof5 }
{ ; d6 <= d1 }
{ ; hence d6 <= all of d1, d3, d5, d7, old d7 }
{ ; possible medians are d1, d2, d3, d4, d5 }
{ ; d1 <= d3, d2 <= d3, d1 <= d5, d4 <= d5 }
{ cmp.w d2,d1 }
{ blo.s @11 }
{ ; d2 <= all of d1, d3, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; leaving d1, d3, d4 }
{ cmp.w d4,d1 }
{ blo.s @10a }
{ ; d4 <= d1, the median is d1. }
{ ; d4 <= all of d1, d3, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ move.w d1,d0 }
{ bra.s done }
{ }
{@10a ; d1 < d4 }
{ ; d1 <= all of d3, d4, d5, d7, old d7 }
{ ; leaving d3, d4 }
{ cmp.w d4,d3 }
{ blo.s @10b }
{ ; d4 <= d3, the median is d4. }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ move.w d4,d0 }
{ bra.s done }
{ }
{@10b ; d3 < d4, the median is d3. }
{ ; d0, d1, d2, d3, d6 all <= d4 }
{ move.w d3,d0 }
{ bra.s done }
{ }
{@11 ;d1 < d2 }
{ ; d1 <= all of d2, d3, d5, d7, old d7 }
{ ; leaving d2, d3, d4, d5 }
{ ; d2 <= d3, d4 <= d5 }
{ cmp.w d4,d2 }
{ blo.s @12 }
{ ; d4 <= all of d2, d3, d5, d7, old d7 }
{ ; leaving d2, d3, d5 }
{ cmp.w d5,d2 }
{ blo.s @11a }
{ ; d5 <= d2 }
{ ; d0, d1, d4, d5, d6 all <= d2 }
{ ; d0, d1, d2, d4, d5, d6 all <= d3 }
{ ; median is d5 }
{ move.w d5,d0 }
{ bra.s done }
{  }
{@11a ; d2 < d5 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ ; median is d2 }
{ move.w d2,d0 }
{ bra.s done }
{ }
{@12 ; d2 < d4 }
{ ; d2 <= all of d3, d4, d5, d7, old d7 }
{ ; d0, d1, d2, d4, d6 all <= d5 }
{ ; leaving d3, d4 }
{ cmp.w d4,d3 }
{ blo.s @12a }
{ ; d4 <= d3 }
{ ; d0, d1, d2, d4, d6 all <= d3 }
{ ; median is d4 }
{ move.w d4,d0 }
{ bra.s done }
{@12a ; d3 < d4 }
{ ; d0, d1, d2, d3, d6 all <= d4 }
{ ; median is d3 }
{ move.w d3,d0 }
{ bra.s done }
{ }
{medof5 ;d1 < d6 }
{ ; d1 <= all of d3, d5, d6, d7, old d7 }
{ ; leaving d2, d3, d4, d5, d6 }
{ ; and the median is the third largest of these }
{ ; d2 <= d3, d4 <= d5 }
{ cmp.w d5,d3 }
{ blo.s @1 }
{ exg d4,d2 }
{ exg d5,d3 }
{@1 ;d2 <= d3, d3 <= d5, d4 <= d5 }
{ cmp.w d6,d4 }
{ blo.s @cmp36 }
{ ; d6 <= d4 }
{ cmp.w d4,d3 }
{ blo.s @cmp36a }
{ ; d4 <= d3 }
{ cmp.w d4,d2 }
{ blo.s @med4 }
{ ; d4 <= d2 }
{ move.w d2,d0 }
{ bra.s done }
{@med4 move.w d4,d0 }
{ bra.s done }
{@cmp36a ;d3 < d4 }
{ cmp.w d6,d3 }
{ blo.s @med6 }
{ ; d6 <= d3 }
{ move.w d3,d0 }
{ bra.s done }
{@med6 move.w d6,d0 }
{ bra.s done }
{@cmp36 ;d4 < d6 }
{ cmp.w d6,d3 }
{ blo.s @cmp34 }
{ ; d6 <= d3 }
{ cmp.w d6,d2 }
{ blo.s @med6 }
{ move.w d2,d0 }
{ bra.s done }
{@cmp34 ;d3 < d6 }
{ cmp.w d4,d3 }
{ blo.s @med4 }
{ ; d4 <= d3 }
{ move.w d3,d0 }
{ ; bra.s done }
{done: }
{ MOVE.L (A7)+,D7 }
{; end median9x16u(arg->array) }
{ MOVE.W D0,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT L001C }
{ ADDA.L $0008(A0),A4 }
{ ADDA.L $000C(A0),A1 }
{ SUBQ.L #$1,$0004(A0) }
{ BGT L0016 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		radMedian16uarg = record
				wpix, height, skipIn, skipOut: LongInt;
				baseIn, baseOut: Ptr;
				offsets: array[0..8] of LongInt;
				arrayx: array[0..8] of Integer;
			end;
	procedure radMedian16u (arg: radMedian16uarg);
	inline
		$205F, $48E7, $1F38, $2868, $0010, $2268, $0014, $2E10,{}
		$45E8, $003C, $47E8, $0018, $201B, $34F4, $0800, $201B,{}
		$34F4, $0800, $201B, $34F4, $0800, $201B, $34F4, $0800,{}
		$201B, $34F4, $0800, $201B, $34F4, $0800, $201B, $34F4,{}
		$0800, $201B, $34F4, $0800, $201B, $34F4, $0800, $548C,{}
		$2F07, $47E8, $003C, $4C9B, $00FF, $B041, $6502, $C340,{}
		$B443, $6502, $C742, $B243, $6504, $C540, $C741, $B845,{}
		$6502, $CB44, $BC47, $6502, $CF46, $BA47, $6504, $CD44,{}
		$CF45, $B245, $6508, $CF43, $CD42, $CB41, $C940, $3E13,{}
		$BC47, $6502, $CF46, $BA47, $6504, $CD44, $CF45, $B245,{}
		$6508, $CF43, $CD42, $CB41, $C940, $B246, $6534, $B242,{}
		$6514, $B244, $6504, $3001, $6062, $B644, $6504, $3004,{}
		$605A, $3003, $6056, $B444, $650C, $B445, $6504, $3005,{}
		$604A, $3002, $6046, $B644, $6504, $3004, $603E, $3003,{}
		$603A, $B645, $6504, $C942, $CB43, $B846, $651C, $B644,{}
		$650C, $B444, $6504, $3002, $6022, $3004, $601E, $B646,{}
		$6504, $3003, $6016, $3006, $6012, $B646, $6508, $B446,{}
		$65F4, $3002, $6006, $B644, $65E0, $3003, $2E1F, $32C0,{}
		$5387, $6E00, $FEEC, $D9E8, $0008, $D3E8, $000C, $53A8,{}
		$0004, $6E00, $FEDA, $4CDF, $1CF8;

{;/* minspatial16u.c */ }
{;/* Caller must guarantee that the region of interest */ }
{;/* is inset by 1 pixel from boundaries of image. */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut; }
{;    unsigned short *baseIn, *baseOut; }
{;    unsigned short array[9]; }
{;] minspatial16uArg; }
{; }
{;pascal minspatial16u( }
{;    register minspatial16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out, *a, *i; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut, skipI; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    skipI = wpix - 2; }
{;    skipI *= sizeof(short); }
{;    skipI += skipIn; }
{;    (char * )in -= skipI; }
{;    in -= 3; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            a = arg->array; }
{;            *a++ = *in++; }
{;            i = in; }
{;            *a++ = *i++; }
{;            *a++ = *i; }
{;            (char * )i += skipI; }
{;            *a++ = *i++; }
{;            *a++ = *i++; }
{;            *a++ = *i; }
{;            (char * )i += skipI; }
{;            *a++ = *i++; }
{;            *a++ = *i++; }
{;            *a = *i; }
{;            *out++ = minspatial9x16u(arg->array); }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type minspatial16uarg = record',13 }
{ DC.B 'wpix, height, skipIn, skipOut: LongInt;',13 }
{ DC.B 'baseIn, baseOut: Ptr;',13 }
{ DC.B 'arrayx: array[0..8] of Integer;',13 }
{ DC.B 'end;',13 }
{ DC.B 'procedure minspatial16u(arg: minspatial16uarg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVE.L (A7)+,A0 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVE.L (A0),D4 }
{ MOVE.L $0004(A0),D2 }
{ MOVE.L $0008(A0),D5 }
{ MOVE.L $000C(A0),D3 }
{ MOVEA.L $0010(A0),A2 }
{ MOVE.L $0014(A0),A1 }
{ MOVE.L D4,D7 }
{ SUBQ.L #$2,D7 }
{ ADD.L D7,D7 }
{ ADD.L D5,D7 }
{ SUBA.L D7,A2 }
{ SUBQ.W #$6,A2 }
{L0032 MOVE.L D4,D6 }
{L0034 LEA $0018(A0),A3 }
{ MOVE.W (A2)+,(A3)+ }
{ MOVEA.L A2,A4 }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4),(A3)+ }
{ ADDA.L D7,A4 }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4),(A3)+ }
{ ADDA.L D7,A4 }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4)+,(A3)+ }
{ MOVE.W (A4),(A3) }
{; minspatial9x16u(arg->array) }
{ MOVEM.L D2-D7,-(A7) }
{ LEA $0018(A0),A3 }
{ movem.w (a3)+,d0-d7 }
{ cmp.w d1,d0 }
{ blo.s @1 }
{ exg d1,d0 }
{@1 ;d0 <= d1 }
{ cmp.w d2,d0 }
{ blo.s @2 }
{ exg d2,d0 }
{@2 ;d0 <= d1, d0 <= d2 }
{ cmp.w d3,d0 }
{ blo.s @3 }
{ exg d3,d0 }
{@3 ;d0 <= d1, d0 <= d2, d0 <= d3 }
{ cmp.w d4,d0 }
{ blo.s @4 }
{ exg d4,d0 }
{@4 ;d0 <= d1, d0 <= d2, d0 <= d3, d0 <= d4 }
{ cmp.w d5,d0 }
{ blo.s @5 }
{ exg d5,d0 }
{@5 ;..., d0 <= d5 }
{ cmp.w d6,d0 }
{ blo.s @6 }
{ exg d6,d0 }
{@6 ;..., d0 <= d6 }
{ cmp.w d7,d0 }
{ blo.s @7 }
{ exg d7,d0 }
{@7 ;..., d0 <= d7 }
{ move.w (a3),d7 ;pick up the 9th value into d7 }
{ cmp.w d7,d0 }
{ blo.s @8 }
{ exg d7,d0 }
{@8 ;d0 <= "d8" }
{ MOVEM.L (A7)+,D2-D7 }
{; end minspatial9x16u(arg->array) }
{ MOVE.W D0,(A1)+ }
{ SUBQ.L #$1,D6 }
{ BGT.S L0034 }
{ ADDA.L D5,A2 }
{ ADDA.L D3,A1 }
{ SUBQ.L #$1,D2 }
{ BGT.S L0032 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		minspatial16uarg = record
				wpix, height, skipIn, skipOut: LongInt;
				baseIn, baseOut: Ptr;
				arrayx: array[0..8] of Integer;
			end;
	procedure minspatial16u (arg: minspatial16uarg);
	inline
		$205F, $48E7, $1F38, $2810, $2428, $0004, $2A28, $0008,{}
		$2628, $000C, $2468, $0010, $2268, $0014, $2E04, $5587,{}
		$DE87, $DE85, $95C7, $5D4A, $2C04, $47E8, $0018, $36DA,{}
		$284A, $36DC, $36D4, $D9C7, $36DC, $36DC, $36D4, $D9C7,{}
		$36DC, $36DC, $3694, $48E7, $3F00, $47E8, $0018, $4C9B,{}
		$00FF, $B041, $6502, $C340, $B042, $6502, $C540, $B043,{}
		$6502, $C740, $B044, $6502, $C940, $B045, $6502, $CB40,{}
		$B046, $6502, $CD40, $B047, $6502, $CF40, $3E13, $B047,{}
		$6502, $CF40, $4CDF, $00FC, $32C0, $5386, $6E9C, $D5C5,{}
		$D3C3, $5382, $6E92, $4CDF, $1CF8;

{;/* GGDilate16u.c  See GGErode16u.c for more info. */ }
{;/* }
{; }
{;The output image must be filled with 0 for correct results. }
{; }
{;The structure element is used in the same order compared }
{;to GGErode16u.c. }
{; }
{;In the Richard Alan Peters II package, in GrayGrayFctDilate }
{;in morph/2d/mdilate.c, the SE is used in reverse order. }
{;If this is necessary, the caller must reverse it (invert }
{;about the origin, swap topMargin and bottomMargin, etc). }
{;This only matters if the SE is not symmetrical. }
{; }
{;*/ }
{; }
{;typedef struct [ }
{;    long value; }
{;    long row; }
{;    long skipLeft; }
{;    long outOffset; }
{;    long skipRight; }
{;] graySEValue; }
{; }
{;typedef struct [ }
{;    long wbytes, hpix, bprIn, bprOut, topMargin, bottomMargin; }
{;    graySEValue *baseSE; }
{;    unsigned short *baseIn; }
{;    unsigned short *baseOut; }
{;] GGMorph16uarg; }
{; }
{;GGDilate16u( }
{;    register GGMorph16uarg *a }
{;) [ }
{;    register long *se; }
{;    register unsigned short *in; }
{;    register unsigned short *out; }
{;    register unsigned long inRow; }
{;    register unsigned long outRow; }
{;    register long nbytes; }
{;    register long t; }
{;    register long v; }
{;    register long row; }
{; }
{;    inRow = (unsigned long) a->baseIn; }
{;    outRow = (unsigned long) a->baseOut; }
{; }
{;    row = 0; }
{;    do [ }
{;        se = (long * )a->baseSE; }
{;        v = *se++; }
{;        do [ }
{;            t = row + *se++; }
{;            if ((t < a->topMargin) || (t >= a->bottomMargin)) [ }
{;                se += 3; }
{;            ] else [ }
{;                t = *se++; }
{;                in = (unsigned short * )(inRow + t); }
{;                out = (unsigned short * )(outRow + t + *se++); }
{;                nbytes = a->wbytes - t - *se++; }
{;                do [ }
{;                    t = *in++ + v; }
{;                    if ( *out++ < t) }
{;                        out[-1] = t; }
{;                ] while ((nbytes -= sizeof(short)) > 0); }
{;            ] }
{;        ] while ((v = *se++) >= 0); }
{;        inRow += a->bprIn; }
{;        outRow += a->bprOut; }
{;    ] while (++row < a->hpix); }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type graySEValue = record value, row, skipLeft, outOffset, skipRight: LongInt;' }
{ DC.B 'end;graySEValuePtr = ^graySEValue;' }
{ DC.B 'GGMorph16uArg = record wbytes, hpix, bprIn,' }
{ DC.B ' bprOut, topMargin, bottomMargin: LongInt;baseSE: graySEValuePtr;baseIn,' }
{ DC.B ' baseOut: Ptr;end; procedure GGDilate16u(var arg: GGMorph16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVE.L $001C(A1),D2 }
{ MOVE.L $0020(A1),D3 }
{ MOVEQ #$00,D4 }
{ MOVEQ #$00,D0 }
{ MOVE.L (A1),D1 }
{L0016 MOVEA.L $0018(A1),A2 }
{ MOVE.L (A2)+,D6 }
{L001C MOVE.L (A2)+,D7 }
{ ADD.L D4,D7 }
{ CMP.L $0010(A1),D7 }
{ BLT.S L002C }
{ CMP.L $0014(A1),D7 }
{ BLT.S L0032 }
{L002C ADDA.W #$000C,A2 }
{ BRA.S L0062 }
{L0032 MOVE.L (A2)+,D7 }
{ MOVEA.L D2,A3 }
{ ADDA.L D7,A3 }
{ MOVEA.L D3,A4 }
{ ADDA.L D7,A4 }
{ ADDA.L (A2)+,A4 }
{ MOVE.L D1,D5 }
{ SUB.L D7,D5 }
{ SUB.L (A2)+,D5 }
{L0048 MOVEQ #$00,D7 }
{ MOVE.W (A3)+,D7 }
{ ADD.L D6,D7 }
{ MOVE.W (A4)+,D0 }
{ CMP.L D0,D7 }
{ BLE.S L005C }
{ MOVE.W D7,-$0002(A4) }
{L005C SUBQ.L #$2,D5 }
{ BGT.S L0048 }
{L0062 MOVE.L (A2)+,D6 }
{ BGE.S L001C }
{ ADD.L $0008(A1),D2 }
{ ADD.L $000C(A1),D3 }
{ ADDQ.L #$1,D4 }
{ CMP.L $0004(A1),D4 }
{ BLT.S L0016 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		graySEValue = record
				value, row, skipLeft, outOffset, skipRight: LongInt;
			end;
		graySEValuePtr = ^graySEValue;
		GGMorph16uArg = record
				wbytes, hpix, bprIn, bprOut, topMargin, bottomMargin: LongInt;
				baseSE: graySEValuePtr;
				baseIn, baseOut: Ptr;
			end;
	procedure GGDilate16u (var arg: GGMorph16uArg);
	inline
		$225F, $48E7, $1F38, $2429, $001C, $2629, $0020, $7800,{}
		$7000, $2211, $2469, $0018, $2C1A, $2E1A, $DE84, $BEA9,{}
		$0010, $6D06, $BEA9, $0014, $6D06, $45EA, $000C, $6026,{}
		$2E1A, $2642, $D7C7, $2843, $D9C7, $D9DA, $2A01, $9A87,{}
		$9A9A, $7E00, $3E1B, $DE86, $301C, $BE80, $6F04, $3947,{}
		$FFFE, $5585, $6EEC, $2C1A, $6CC0, $D4A9, $0008, $D6A9,{}
		$000C, $5284, $B8A9, $0004, $6DAA, $4CDF, $1CF8;

{;/* GGErode16u.c */ }
{; }
{;/* }
{; }
{;This is the morphological function erosion of a grascale image }
{;using a grayscale structure element (SE). }
{; }
{;The arrangement of loops derives from the rolling ball c program }
{;by Ben Verwer and Henri Vrooman posted to Usenet: }
{; }
{;    From: ben@ph.tn.tudelft.nl (Ben Verwer) }
{;    Newsgroups: sci.image.processing }
{;    Subject: Re: image processing loops: a c programming question }
{;    Message-ID: <ben.714157437@galaxy> }
{;    Date: 18 Aug 92 17:03:57 GMT }
{; }
{;Verwer and Vrooman suggest that the outer loop should }
{;be over rows of input image.  The middle loop is over the SE }
{;(structure element), and the inner loop is over pixels of the }
{;input row, so that a particular SE value is loaded and used }
{;over a whole row of input before another SE value is used. }
{; }
{;See also the references supplied with morph }
{;(ftp to image.vanderbilt.edu and get morph.tar.Z) }
{; }
{; morph version 4.0    10 May 1993 }
{; image morphology program }
{; }
{; by Richard Alan Peters II }
{; Department of Electrical Engineering }
{; Vanderbilt University School of Engineering }
{; Nashville, TN 37235 }
{; rap2@vuse.vanderbilt.edu }
{; }
{;e.g. Serra, J., "Introduction to mathematical morphology," }
{;Comp. Vision, Graph., Image Process., vol. 35, pp. 283-305, 1986. }
{; }
{;The function GGErode was named after GrayGrayFctErode }
{;in morph/2d/merode.c of that package. }
{; }
{; }
{; }
{;This algorithm produces an output image which is smaller than }
{;the input image, so that every pixel of the output was constructed }
{;using a full set of input pixels.  It is possible to construct }
{;an output image using multiple calls to this routine, with no }
{;duplicated calculations, for example, if only the diagonal of }
{;the output image is needed.  However, efficiency drops if the }
{;number of pixels per row is low, so that it may be faster to }
{;use a smaller number of calls which cover a wider area than to }
{;use a large number of calls which cover exactly the needed area. }
{; }
{; }
{;Margin specifications:  top margin and bottom margin specify }
{;the position of the first used and first unused rows of the output }
{;image relative to its ROI.  For no margins, top margin would }
{;be zero and bottom margin would be equal to the height. }
{;The left and right margin values are encoded into the SE array. }
{;These margins should match the SE dimensions. }
{; }
{; }
{;SE Array:  array of structs, each with value and byte offsets. }
{;"Dont't care" values are simply omitted. }
{;The last entry (not used) has a negative value. }
{; }
{;The SE is preprocessed by the caller and passed in as a array }
{;of structs which contain the SE value and byte offset to the }
{;output pixel which corresponds to the value.  Only positive }
{;or zero SE entries are placed in the array.  The end of the }
{;array is signaled by a positive value.  The offset encodes }
{;knowledge about the bytes per row and bytes per pixel of the }
{;output image. }
{; }
{;The SE struct also contains values derived from the row and }
{;column of the point.  Row is negative when the offset }
{;points to an output row above the input row, and col is }
{;negative when the offset points to an output column to }
{;the left of the input column.  The row number is stored directly. }
{;The column number is encoded into skipLeft and skipRight: }
{; }
{;The constraings are: }
{;(1) skipLeft >= 0, skipRight >= 0 }
{;(2) skipLeft + col >= leftMargin }
{;(3) skipRight - col >= rightMargin }
{; }
{;    skipLeft = max(0,leftMargin-col) }
{;    skipRight = max(0,rightMargin+col) }
{; }
{; }
{;Input Data Image:  16 bit unsigned. }
{; }
{; }
{;Output Data Image:  16 bit unsigned. }
{; }
{;The output image must be cleared to 65535 for correct results, since }
{;output pixels are only changed if the new value is smaller than }
{;the old value. }
{; }
{;The ROI of the output image must be the same size as the ROI of the }
{;input image.  The margins of the output image (inside the ROI) will }
{;not be changed. }
{; }
{;Algorithm (produces output image smaller than input image): }
{; }
{;loop over each row of input and output }
{;    loop over each SE record }
{;        value = se->value }
{;        if the output row is within the output image, }
{;        i.e. (top margin <= row + se->row) }
{;        and (row + se->row < bottom margin) }
{;            input scan = input row + se->skipLeft }
{;            output scan = output row + se->offset + se->skipLeft }
{;            nbytes = wbytes - se->skipLeft - se->skipRight }
{;            loop over nbytes bytes of input and output rows }
{;                t = input pixel - value }
{;                if output pixel > t then }
{;                    output pixel = t }
{;                end }
{;            end }
{;        end }
{;    end }
{;end }
{; }
{;*/ }
{; }
{;typedef struct [ }
{;    long value; }
{;    long row; }
{;    long skipLeft; }
{;    long outOffset; }
{;    long skipRight; }
{;] graySEValue; }
{; }
{;typedef struct [ }
{;    long wbytes, hpix, bprIn, bprOut, topMargin, bottomMargin; }
{;    graySEValue *baseSE; }
{;    unsigned short *baseIn; }
{;    unsigned short *baseOut; }
{;] GGMorph16uarg; }
{; }
{;GGErode16u( }
{;    register GGMorph16uarg *a }
{;) [ }
{;    register long *se; }
{;    register unsigned short *in; }
{;    register unsigned short *out; }
{;    register unsigned long inRow; }
{;    register unsigned long outRow; }
{;    register long nbytes; }
{;    register long t; }
{;    register long v; }
{;    register long row; }
{; }
{;    inRow = (unsigned long) a->baseIn; }
{;    outRow = (unsigned long) a->baseOut; }
{; }
{;    row = 0; }
{;    do [ }
{;        se = (long * )a->baseSE; }
{;        v = *se++; }
{;        do [ }
{;            t = row + *se++; }
{;            if ((t < a->topMargin) || (t >= a->bottomMargin)) [ }
{;                se += 3; }
{;            ] else [ }
{;                t = *se++; }
{;                in = (unsigned short * )(inRow + t); }
{;                out = (unsigned short * )(outRow + t + *se++); }
{;                nbytes = a->wbytes - t - *se++; }
{;                do [ }
{;                    t = *in++ - v; }
{;                    if ( *out++ > t) }
{;                        out[-1] = t; }
{;                ] while ((nbytes -= sizeof(short)) > 0); }
{;            ] }
{;        ] while ((v = *se++) >= 0); }
{;        inRow += a->bprIn; }
{;        outRow += a->bprOut; }
{;    ] while (++row < a->hpix); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type graySEValue = record value, row, skipLeft, outOffset, skipRight: LongInt;' }
{ DC.B 'end;graySEValuePtr = ^graySEValue;' }
{ DC.B 'GGMorph16uArg = record wbytes, hpix, bprIn,' }
{ DC.B ' bprOut, topMargin, bottomMargin: LongInt;baseSE: graySEValuePtr;baseIn,' }
{ DC.B ' baseOut: Ptr;end; procedure GGErode16u(var arg: GGMorph16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A1 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVE.L $001C(A1),D2 }
{ MOVE.L $0020(A1),D3 }
{ MOVEQ #$00,D4 }
{ MOVEQ #$00,D0 }
{ MOVE.L (A1),D1 }
{L0016 MOVEA.L $0018(A1),A2 }
{ MOVE.L (A2)+,D6 }
{L001C MOVE.L (A2)+,D7 }
{ ADD.L D4,D7 }
{ CMP.L $0010(A1),D7 }
{ BLT.S L002C }
{ CMP.L $0014(A1),D7 }
{ BLT.S L0032 }
{L002C ADDA.W #$000C,A2 }
{ BRA.S L0062 }
{L0032 MOVE.L (A2)+,D7 }
{ MOVEA.L D2,A3 }
{ ADDA.L D7,A3 }
{ MOVEA.L D3,A4 }
{ ADDA.L D7,A4 }
{ ADDA.L (A2)+,A4 }
{ MOVE.L D1,D5 }
{ SUB.L D7,D5 }
{ SUB.L (A2)+,D5 }
{L0048 MOVEQ #$00,D7 }
{ MOVE.W (A3)+,D7 }
{ SUB.L D6,D7 }
{ MOVE.W (A4)+,D0 }
{ CMP.L D0,D7 }
{ BGE.S L005C }
{ MOVE.W D7,-$0002(A4) }
{L005C SUBQ.L #$2,D5 }
{ BGT.S L0048 }
{L0062 MOVE.L (A2)+,D6 }
{ BGE.S L001C }
{ ADD.L $0008(A1),D2 }
{ ADD.L $000C(A1),D3 }
{ ADDQ.L #$1,D4 }
{ CMP.L $0004(A1),D4 }
{ BLT.S L0016 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	procedure GGErode16u (var arg: GGMorph16uArg);
	inline
		$225F, $48E7, $1F38, $2429, $001C, $2629, $0020, $7800,{}
		$7000, $2211, $2469, $0018, $2C1A, $2E1A, $DE84, $BEA9,{}
		$0010, $6D06, $BEA9, $0014, $6D06, $45EA, $000C, $6026,{}
		$2E1A, $2642, $D7C7, $2843, $D9C7, $D9DA, $2A01, $9A87,{}
		$9A9A, $7E00, $3E1B, $9E86, $301C, $BE80, $6C04, $3947,{}
		$FFFE, $5585, $6EEC, $2C1A, $6CC0, $D4A9, $0008, $D6A9,{}
		$000C, $5284, $B8A9, $0004, $6DAA, $4CDF, $1CF8;


	procedure UMPixel16uInit;
	begin
	end;


	procedure UMPixel16uFinal;
	begin
	end;

	procedure UMPixel16uAdd;
	begin
		AddUMSym('minMax16u', UserCommandT, minMax16uUC);
		AddUMSym('minMax32s', UserCommandT, minMax32sUC);
		AddUMSym('LinLUT16uTo8', UserCommandT, LinLUT16uTo8UC);
		AddUMSym('Cnvrt16uTo8', UserCommandT, Cnvrt16uTo8UC);
		AddUMSym('Cnvrt8To16u', UserCommandT, Cnvrt8To16uUC);
		AddUMSym('Convolve16u', UserCommandT, Convolve16uUC);
		AddUMSym('Median16u', UserCommandT, Median16uUC);
		AddUMSym('radMedian16u', UserCommandT, radMedian16uUC);
		AddUMSym('MinSpat16u', UserCommandT, MinSpatial16uUC);
		AddUMSym('GGDilate16u', UserCommandT, GGDilate16uUC);
		AddUMSym('GGErode16u', UserCommandT, GGErode16uUC);
		AddUMSym('Add16uTo32s', UserCommandT, Add16uTo32sUC);
		AddUMSym('Cnvrt32sT16u', UserCommandT, Cnvrt32sT16uUC);
		AddUMSym('Add16u', UserCommandT, Add16uUC);
		AddUMSym('Sub16u', UserCommandT, Sub16uUC);
		AddUMSym('Mpy16u', UserCommandT, Mpy16uUC);
		AddUMSym('Div16u', UserCommandT, Div16uUC);
		AddUMSym('Ratio16u', UserCommandT, Ratio16uUC);
		AddUMSym('Lrg16u', UserCommandT, Lrg16uUC);
		AddUMSym('Sml16u', UserCommandT, Sml16uUC);
		AddUMSym('AddK16u', UserCommandT, AddK16uUC);
		AddUMSym('SubK16u', UserCommandT, SubK16uUC);
		AddUMSym('MpyK16u', UserCommandT, MpyK16uUC);
		AddUMSym('DivK16u', UserCommandT, DivK16uUC);
		AddUMSym('MpyDivK16u', UserCommandT, MpyDivK16uUC);
		AddUMSym('LrgK16u', UserCommandT, LrgK16uUC);
		AddUMSym('SmlK16u', UserCommandT, SmlK16uUC);
		AddUMSym('SqzMask16u', UserCommandT, SqzMask16uUC);
		AddUMSym('ExpMask16u', UserCommandT, ExpMask16uUC);
		AddUMSym('CnvMsk16uTo8', UserCommandT, CnvMsk16uTo8UC);
		AddUMSym('SqzMask8u', UserCommandT, SqzMask8uUC);
		AddUMSym('ExpMask8u', UserCommandT, ExpMask8uUC);
		AddUMSym('NewView16u', UserCommandT, NewView16uUC);
		AddUMSym('NMaskView16u', UserCommandT, NMaskView16uUC);
		AddUMSym('FindView16u', UserCommandT, FindView16uUC);
		AddUMSym('GaussRand16u', UserCommandT, GaussRand16uUC);
		AddUMSym('NormSInv', UserFuncT, NormSInvUC);
		AddUMSym('Fill16u', UserCommandT, Fill16uUC);
		AddUMSym('ApplyLUT16u', UserCommandT, ApplyLUT16uUC);
	end;


	procedure UMPixel16uLookup (var uma: UserMacroArgs);
		var
			i: integer;
	begin
		with uma do
			case UserMacroCommand of
				minMax16uUC, minMax32sUC:  begin {(image: pidNumber;var min,max: integer)}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATintvar;
						arg[3].atype := UMATintvar;
					end;
				LinLUT16uTo8UC:  begin {(image: pidNumber; xmin,xmax,ymin,ymax: integer)}
						nArgs := 5;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATinteger;
						arg[3].atype := UMATinteger;
						arg[4].atype := UMATinteger;
						arg[5].atype := UMATinteger;
					end;
				Cnvrt16uTo8UC:  begin {in,lut16uTo8,out: pidNumber}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
					end;
				Cnvrt8To16uUC:  begin {in, lut8To16u,out: pidNumber}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
					end;
				Convolve16uUC:  begin
						nArgs := 7;
						for i := 1 to 7 do
							arg[i].atype := UMATpic;
						arg[4].atype := UMATinteger;
						arg[5].atype := UMATinteger;
					end;
				Median16uUC, MinSpatial16uUC:  begin {in, out: pidNumber}
						nArgs := 2;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
					end;
				radMedian16uUC:  begin {in, out: pidNumber, radius: real}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATreal;
					end;
				GGDilate16uUC, GGErode16uUC:  begin {in, kernel: pidNumber; kx, ky: Integer; out: pidNumber}
						nArgs := 5;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATinteger;
						arg[4].atype := UMATinteger;
						arg[5].atype := UMATpic;
					end;
				Add16uTo32sUC:  begin {in16, in32, out32: pidNumber}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
					end;
				Cnvrt32sT16uUC:  begin {in32, out16: pidNumber; var offset, divisor: integer);}
						nArgs := 4;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATintvar;
						arg[4].atype := UMATintvar;
					end;
				Add16uUC, Sub16uUC, Mpy16uUC, Div16uUC, Lrg16uUC, Sml16uUC:  begin
           {ina, inb, out: pidNumber}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
					end;
				Ratio16uUC:  begin
          {ina, inb, out: pidNumber; scale: integer}
						nArgs := 4;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
						arg[4].atype := UMATinteger;
					end;
				AddK16uUC, SubK16uUC, MpyK16uUC, DivK16uUC, LrgK16uUC, SmlK16uUC:  begin
          {in, out: pidNumber;cons: integer}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATinteger;
					end;
				MpyDivK16uUC:  begin
         {in, out: pidNumber; numerator, denominator: integer}
						nArgs := 4;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATinteger;
						arg[4].atype := UMATinteger;
					end;
				SqzMask16uUC, ExpMask16uUC, SqzMask8uUC, ExpMask8uUC:  begin
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
					end;
				CnvMsk16uTo8UC:  begin {in, LUT, mask, out}
						nArgs := 4;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
						arg[4].atype := UMATpic;
					end;
				NewView16uUC:  begin {in,LUT}
						nArgs := 2;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
					end;
				NMaskView16uUC:  begin {in,LUT,mask}
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
					end;
				FindView16uUC:  begin {in}
						nArgs := 1;
						arg[1].atype := UMATpic;
					end;
				GaussRand16uUC:  begin {mu,sigma,seed,out}
						nArgs := 4;
						arg[1].atype := UMATreal;
						arg[2].atype := UMATreal;
						arg[3].atype := UMATrealvar;
						arg[4].atype := UMATpic;
					end;
				NormSInvUC:  begin {probability}
						nArgs := 1;
						arg[1].atype := UMATreal;
					end;
				Fill16uUC:  begin
						nArgs := 2;
						arg[1].atype := UMATinteger;
						arg[2].atype := UMATpic;
					end;
				ApplyLUT16uUC:  begin
						nArgs := 3;
						arg[1].atype := UMATpic;
						arg[2].atype := UMATpic;
						arg[3].atype := UMATpic;
					end;
				otherwise begin
						ErrorOccurred := true;
						str := 'UMPixel16u.p';
					end;
			end;
	end;

	procedure checkRoiSize (var uma: UserMacroArgs; i, j: integer);
		var
			argi, argj: ^UserMacroArg;
	begin
		with uma do begin
				argi := @arg[i];
				argj := @arg[j];
				if (argi^.atype <> UMATpic) or (argj^.atype <> UMATpic) then begin
						errorOccurred := true;
						str := 'UMPixel16u.p';
					end
				else if (argi^.roi.Width <> argj^.roi.Width) or (argi^.roi.Height <> argj^.roi.Height) then begin
						errorOccurred := true;
						str := 'All selection sizes must be equal';
					end
			end;
	end;

	procedure doCnvrt16uTo8 (var uma: UserMacroArgs);
		var
			cnvrtArg: cnvrt16uTo8Arg;
	begin
       {in, lut16uTo8, out: pidNumber}
       {in and out must have same size ROI}
       {lut16uTo8 must be 256x256x8 bits}
		with uma do begin
				if (arg[1].atype <> UMATpic) or (arg[2].atype <> UMATpic) or (arg[3].atype <> UMATpic) then begin
						errorOccurred := true;
						str := 'UMPixel16u.p';
					end;
				checkPixelWidth(2, uma, 1);
				if arg[1].roi.Width <> arg[3].roi.width * 2 then begin
						errorOccurred := true;
						str := 'Output width must be half input width';
					end
				else if arg[1].roi.Height <> arg[3].roi.Height then begin
						errorOccurred := true;
						str := 'Input and output heights must be equal';
					end;
				with arg[2] do begin
						if (roi.Width <> 256) or (roi.Height <> 256) or (roi.Skip <> 0) then begin
								errorOccurred := true;
								str := 'LUT must be 256x256';
							end;
					end;
				checkOutputConflict(uma, 3);
				if errorOccurred then
					exit(doCnvrt16uTo8);
				with cnvrtArg do begin
						height := arg[3].roi.Height;
						wpix := arg[3].roi.Width;
						with arg[1].roi do begin
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseLUT := Base;
							end;
						with arg[3].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				Cnvrt16uTo8(cnvrtArg);
			end; {with uma}
	end;

	procedure doCnvrt8To16u (var uma: UserMacroArgs);
		var
			cnvrtArg: cnvrt8To16uArg;
	begin
       {in, lut8To16u, out: pidNumber}
       {in and out must have same size ROI}
       {lut8To16u must be 256x16 bits}
		with uma do begin
				if (arg[1].atype <> UMATpic) or (arg[2].atype <> UMATpic) or (arg[3].atype <> UMATpic) then begin
						errorOccurred := true;
						str := 'UMPixel16u.p';
					end
				else if arg[1].roi.Width * 2 <> arg[3].roi.width then begin
						errorOccurred := true;
						str := 'Input width must be double output width';
					end
				else if arg[1].roi.Height <> arg[3].roi.Height then begin
						errorOccurred := true;
						str := 'Input and output heights must be equal';
					end
				else
					with arg[2] do begin
							if (roi.Width <> 512) or (roi.Height <> 1) or (roi.Skip <> 0) then begin
									errorOccurred := true;
									str := 'LUT must be 512x1';
								end;
						end;
				checkPixelWidth(2, uma, 2);
				checkPixelWidth(2, uma, 3);
				checkOutputConflict(uma, 3);
				if errorOccurred then
					exit(doCnvrt8To16u);
				with cnvrtArg do begin
						height := arg[1].roi.Height;
						wpix := arg[1].roi.Width;
						with arg[1].roi do begin
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseLUT := Base;
							end;
						with arg[3].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				Cnvrt8To16u(cnvrtArg);
			end; {with uma}
	end;

{;/* Cnvrt32sTo16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut; }
{;    unsigned long offset, divisor; }
{;    long *baseIn; }
{;    unsigned short *baseOut; }
{;] Cnvrt32sTo16uArg; }
{; }
{;pascal Cnvrt32sTo16u( }
{;    register Cnvrt32sTo16uArg *arg }
{;) [ }
{;    register long *in; }
{;    register unsigned short *out; }
{;    register long cols; }
{;    register long skipIn, skipOut; }
{;    register unsigned long offset, divisor, value, v65535; }
{; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    offset = arg->offset; }
{;    divisor = arg->divisor; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    v65535 = 65535; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            value = *in++; }
{;            if ((long)value < (long)offset) [ }
{;                value = 0; }
{;            ] else [ }
{;                value = (value - offset) / divisor; }
{;                if (value > v65535) [ }
{;                    value = v65535; }
{;                ] }
{;            ] }
{;            *out++ = value; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--arg->height > 0); }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type Cnvrt32sTo16uArg = record',13 }
{ DC.B ' wpix, height, skipIn, skipOut, offset, divisor: longint;',13 }
{ DC.B ' baseIn, baseOut: ptr; end;',13 }
{ DC.B ' procedure Cnvrt32sTo16u (var arg: Cnvrt32sTo16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6/A2,-(A7) }
{ MOVEM.L 8(A0),D0-D3/A1-A2 }
{ MOVE.L #$0000FFFF,D5 }
{L002A MOVE.L (A0),D4 }
{L002C MOVE.L (A1)+,D6 }
{ CMP.L D6,D2 }
{ BLE.S L0036 }
{ MOVEQ #$00,D6 }
{ BRA.S L0046 }
{L0036 SUB.L D2,D6 }
{ DIVU.L D3,D6 }
{ CMP.L D6,D5 }
{ BCC.S L0046 }
{ MOVE.L D5,D6 }
{L0046 MOVE.W D6,(A2)+ }
{ SUBQ.L #$1,D4 }
{ BGT.S L002C }
{ ADDA.L D0,A1 }
{ ADDA.L D1,A2 }
{ SUBQ.L #$1,$0004(A0) }
{ BGT.S L002A }
{ MOVEM.L (A7)+,D3-D6/A2 }
{endcode: }
{ ENDPROC }
{ END }
{ }
{}
	type
		Cnvrt32sTo16uArg = record
				wpix, height, skipIn, skipOut, offset, divisor: longint;
				baseIn, baseOut: ptr;
			end;
	procedure Cnvrt32sTo16u (var arg: Cnvrt32sTo16uArg);
	inline
		$205F, $48E7, $1E20, $4CE8, $060F, $0008, $2A3C, $0000,{}
		$FFFF, $2810, $2C19, $B486, $6F04, $7C00, $600C, $9C82,{}
		$4C43, $6006, $BA86, $6402, $2C05, $34C6, $5384, $6EE4,{}
		$D3C0, $D5C1, $53A8, $0004, $6ED8, $4CDF, $0478;

	procedure doCnvrt32sT16u (var uma: UserMacroArgs);
		var
			cnvrtArg: cnvrt32sTo16uArg;
	begin
       {in, out: pidNumber; var min, max: integer}
       {in and out must have same size ROI}
		with uma do begin
				if (arg[1].atype <> UMATpic) or (arg[2].atype <> UMATpic) then begin
						errorOccurred := true;
						str := 'UMPixel16u.p';
					end;
				checkPixelWidth(4, uma, 1);
				checkPixelWidth(2, uma, 2);
				if arg[1].roi.Width <> arg[2].roi.width * 2 then begin
						errorOccurred := true;
						str := 'Output width must be half input width';
					end
				else if arg[1].roi.Height <> arg[2].roi.Height then begin
						errorOccurred := true;
						str := 'Input and output heights must be equal';
					end;
				if errorOccurred then
					exit(doCnvrt32sT16u);
				with cnvrtArg do begin
						height := arg[2].roi.Height;
						wpix := arg[2].roi.Width div 2;
						with arg[1].roi do begin
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
						offset := arg[3].ival;
						divisor := arg[4].ival;
						if divisor < 1 then begin
								errorOccurred := true;
								str := 'divisor must be positive';
								exit(doCnvrt32sT16u);
							end;
					end;
				Cnvrt32sTo16u(cnvrtArg);
			end; {with uma}
	end;


	procedure doConvolve16u (var uma: UserMacroArgs);
		var
			kp: KernelValuePtr;
			kx, ky, kn, lines, cols: integer;
			kw, kh: integer;
			x, y, maskBpr, inBpr: LongInt;
			ker: s32p;
			kSkip: LongInt;
			convolveArg: Convolve16uArg;
			h: handle;
	begin
    {arguments are in alphabetical order:  flag=1, in=2, kernel=3, kx=4, ky=5, mask=6, out=7}
		h := nil;
		with uma do begin
				checkPixelWidth(2, uma, 2);
				checkPixelWidth(2, uma, 7);
				checkOutputConflict(uma, 7);
				if ErrorOccurred then
					exit(doConvolve16u);
				with convolveArg do begin
						wpix := arg[2].roi.Width div 2;
						height := arg[2].roi.Height;
						with arg[1].roi do begin
								baseFlag := Base;
								skipFlag := Skip;
							end;
						with arg[2].roi do begin
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[6].roi do begin
								baseMask := Base;
								skipMask := Skip;
							end;
						with arg[7].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end; {with convolveArg}
				inBpr := arg[2].infop^.BytesPerRow;
				kx := arg[4].ival;
				ky := arg[5].ival;
				maskBpr := arg[6].infop^.BytesPerRow;
				with arg[3], infop^ do begin
						if band(PixelsPerLine, 3) <> 0 then begin
								errorOccurred := true;
								str := 'Kernel pixels per line not multiple of 4';
								exit(doConvolve16u);
							end;
						if band(BytesPerRow, 3) <> 0 then begin
								errorOccurred := true;
								str := 'Kernel bytes per row not multiple of 4';
								exit(doConvolve16u);
							end;
						if WasRoi then begin
								if band(RoiRect.left, 3) <> 0 then begin
										errorOccurred := true;
										str := 'Kernel selection left edge not multiple of 4';
										exit(doConvolve16u);
									end;
								if band(RoiRect.right, 3) <> 0 then begin
										errorOccurred := true;
										str := 'Kernel selection width not multiple of 4';
										exit(doConvolve16u);
									end;
							end;
					end; {with arg[3], infop^}

				with arg[3].roi do begin
						kw := Width div 4;
						kh := Height;
						kSkip := Skip;
						if Width <> kw * 4 then begin
								errorOccurred := true;
								str := 'UMPixel16u.p';
								exit(doConvolve16u);
							end;
					end; {with arg[3].roi}
        {count number of nonzero kernel entries}
				if (kx < 0) or (kx >= kw) or (ky < 0) or (ky >= kh) then begin
						errorOccurred := true;
						str := 'kernel center must be inside kernel';
						exit(doConvolve16u);
					end;
				with arg[6], infop^.RoiRect, convolveArg do begin
            {verify that mask image is big enough}
            {roi must be same size as input image, allowing for pixel size.}
						if (wpix <> roi.Width) or (height <> roi.Height) then begin
								errorOccurred := true;
								str := 'mask selection must be same size as input selection';
								exit(doConvolve16u);
							end;
            {roi top left must be at least kx pixels from left edge and ky from top of image.}
            {roi bottom right must be at least kw-kx-1 pixels from right edge }
            {and kh-ky-1  from bottom of image.}
						if (top < ky) or (left < kx) or (infop^.nlines - bottom < kh - ky - 1) or (infop^.PixelsPerLine - right < kw - kx - 1) then begin
								errorOccurred := true;
								str := 'mask margins must match or exceed kernel margins';
								exit(doConvolve16u);
							end;
					end; {with arg[6], infop^.RoiRect, convolveArg}
				kn := 0;
				ker := s32p(arg[3].roi.Base);
				lines := kh;
				while lines > 0 do begin
						cols := kw;
						while cols > 0 do begin
								if ker^ <> 0 then
									kn := kn + 1;
								ker := s32p(ord4(ker) + sizeof(LongInt));
								cols := cols - 1;
							end;
						ker := s32p(ord4(ker) + kSkip);
						lines := lines - 1;
					end;
				if kn = 0 then begin
            {convolve16u inline does not deal with completely zero kernel}
						errorOccurred := true;
						str := 'Kernel is all zero';
						exit(doConvolve16u);
					end;
				h := NewHandle((kn + 1) * sizeof(KernelValue));
				if h = nil then begin
						errorOccurred := true;
						str := 'Out of memory';
						exit(doConvolve16u);
					end;
				HLock(h);
				kp := KernelValuePtr(h^);
				convolveArg.baseK := kp;
				ker := s32p(arg[3].roi.Base);
				lines := kh;
				y := -ky;
				while lines > 0 do begin
						cols := kw;
						x := -kx;
						while cols > 0 do begin
								if ker^ <> 0 then begin
										with kp^ do begin
												value := ker^;
												maskOffset := y * maskBpr + x;
												inOffset := y * inBpr + x * sizeof(Integer);
											end;
										kp := KernelValuePtr(ord4(kp) + sizeof(KernelValue));
									end;
								ker := s32p(ord4(ker) + sizeof(LongInt));
								cols := cols - 1;
								x := x + 1;
							end;
						ker := s32p(ord4(ker) + kSkip);
						lines := lines - 1;
						y := y + 1;
					end;
				kp^.value := 0;
			end; {with uma}
		Convolve16u(convolveArg);
		DisposHandle(h);
	end;

	procedure doMedian16u (var uma: UserMacroArgs);
		var
			medArg: median16uarg;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkRoiSize(uma, 1, 2);
				checkOutputConflict(uma, 2);
				if errorOccurred then
					exit(doMedian16u);
				with arg[1], infop^.roiRect do begin
						if (top < 1) or (left < 2) or (infop^.nlines - bottom < 1) or (infop^.PixelsPerLine - right < 2) then begin
								errorOccurred := true;
								str := 'median input image must have a one pixel border';
								exit(doMedian16u);
							end;
					end;
				medArg.height := arg[1].roi.Height;
				with medArg do begin
						with arg[1].roi do begin
								wpix := Width div 2;
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				median16u(medArg);
			end;
	end;

	procedure doRadMedian16u (var uma: UserMacroArgs);
		var
			radMedArg: radMedian16uarg;
			radius, theta: real;
			i, x, y, minx, maxx, miny, maxy, bpr: longInt;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkRoiSize(uma, 1, 2);
				checkOutputConflict(uma, 2);
				if errorOccurred then
					exit(doRadMedian16u);
				bpr := arg[1].infop^.BytesPerRow;
				radius := arg[3].aval; {real argument value}
				theta := 0;
				minx := 0;
				miny := 0;
				maxx := 0;
				maxy := 0;
				for i := 0 to 8 do begin
						theta := (i / 9.0) * 2 * 3.1415926;
						x := round(radius * cos(theta));
						y := round(radius * sin(theta));
						if minx > x then
							minx := x;
						if maxx < x then
							maxx := x;
						if miny > y then
							miny := y;
						if maxy < y then
							maxy := y;
						radMedArg.offsets[i] := y * bpr + sizeof(integer) * x;
					end;
				with arg[1], infop^.roiRect do begin
						if (top < -miny) or (left < 2 * (-minx)) or (infop^.nlines - bottom < maxy) or (infop^.PixelsPerLine - right < 2 * maxx) then begin
								errorOccurred := true;
								str := 'radial median input image border too small';
								exit(doRadMedian16u);
							end;
					end;
				radMedArg.height := arg[1].roi.Height;
				with radMedArg do begin
						with arg[1].roi do begin
								wpix := Width div 2;
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				radMedian16u(radMedArg);
			end;
	end;

	procedure doMinSpatial16u (var uma: UserMacroArgs);
		var
			minspatArg: MinSpatial16uarg;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkRoiSize(uma, 1, 2);
				checkOutputConflict(uma, 2);
				if errorOccurred then
					exit(doMinSpatial16u);
				with arg[1], infop^.roiRect do begin
						if (top < 1) or (left < 2) or (infop^.nlines - bottom < 1) or (infop^.PixelsPerLine - right < 2) then begin
								errorOccurred := true;
								str := 'minspat16u input image must have a one pixel border';
								exit(doMinSpatial16u);
							end;
					end;
				minspatArg.height := arg[1].roi.Height;
				with minspatArg do begin
						with arg[1].roi do begin
								wpix := Width div 2;
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				minspatial16u(minspatArg);
			end;
	end;

	procedure doGGMorph16u (var uma: UserMacroArgs);
		var
			kp: graySEValuePtr;
			kx, ky, lines, cols: integer;
			kn: longint;
			kw, kh: integer;
			kr, mw: Rect;
			x, y: LongInt;
			ker: u16p;
			kSkip: LongInt;
			GGMorphArg: GGMorph16uArg;
			h: handle;
	begin
    {arguments are in=1, kernel=2, kx = 3, ky = 4, out=5}
		h := nil;
		with uma do begin
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkPixelWidth(2, uma, 5);
				checkOutputConflict(uma, 5);
				if ErrorOccurred then
					exit(doGGMorph16u);
				with GGMorphArg do begin
						with arg[1].roi do begin
								wbytes := Width;
								hpix := Height;
								baseIn := Base;
							end;
						bprIn := arg[1].infop^.BytesPerRow;
						with arg[5].roi do begin
								baseOut := Base;
							end;
						bprOut := arg[5].infop^.BytesPerRow;
					end; {with GGMorphArg}
				with arg[2].roi do begin
						kw := Width div 2;
						kh := Height;
						kSkip := Skip;
					end; {with arg[2].roi}
				kx := arg[3].ival;
				ky := arg[4].ival;
				if (kx < 0) or (kx >= kw) or (ky < 0) or (ky >= kh) then begin
						errorOccurred := true;
						str := 'Structure Element center must be inside SE';
						exit(doGGMorph16u);
					end;
				with arg[5], infop^.RoiRect, GGMorphArg do begin
            {verify that output image is big enough}
            {roi must be same size as input image, allowing for pixel size.}
						if (wbytes <> roi.Width) or (hpix <> roi.Height) then begin
								errorOccurred := true;
								str := 'output selection must be same size as input selection';
								exit(doGGMorph16u);
							end;
            {roi top left must be at least kx pixels from left edge and ky from top of image.}
            {roi bottom right must be at least kw-kx-1 pixels from right edge }
            {and kh-ky-1  from bottom of image.}
						if false then {don't need this}
							if (top < ky) or (left < kx * 2) or (infop^.nlines - bottom < kh - ky - 1) or (infop^.PixelsPerLine - right < (kw - kx - 1) * 2) then begin
									errorOccurred := true;
									str := 'output margins must match or exceed kernel margins';
									exit(doGGMorph16u);
								end;
					end; {with arg[5], infop^.RoiRect, GGMorphArg}

        {count number of nonzero kernel entries}
				kn := 0;
				ker := u16p(arg[2].roi.Base);
				with kr do begin
						left := kw;
						top := kh;
						right := 0;
						bottom := 0;
						lines := kh;
						y := 0;
						while lines > 0 do begin
								x := 0;
								cols := kw;
								while cols > 0 do begin
										if ker^.u <> 0 then begin
												kn := kn + 1;
												if x < left then
													left := x;
												if x + 1 > right then
													right := x + 1;
												if y < top then
													top := y;
												if y + 1 > bottom then
													bottom := y + 1;
											end;
										ker := u16p(ord4(ker) + sizeof(Integer));
										cols := cols - 1;
										x := x + 1;
									end;
								ker := u16p(ord4(ker) + kSkip);
								lines := lines - 1;
								y := y + 1;
							end;
					end;
				if kn = 0 then begin
            {GGMorph16u inline does not deal with completely negative kernel}
						errorOccurred := true;
						str := 'Structure Element is all zero';
						exit(doGGMorph16u);
					end;
				if (kx < kr.left) or (kx >= kr.right) or (ky < kr.top) or (ky >= kr.bottom) then begin
						errorOccurred := true;
						str := 'Structure Element center must be inside nonzero part of SE';
						exit(doGGMorph16u);
					end;
        {mw.top is top margin width, etc.}
				mw.top := ky - kr.top;
				mw.left := kx - kr.left;
				mw.bottom := kr.bottom - ky - 1;
				mw.right := kr.right - kx - 1;
				with GGMorphArg do begin
						topMargin := mw.top;
						bottomMargin := hpix - mw.bottom;
					end;
				h := NewHandle((kn + 1) * sizeof(graySEValue));
				if h = nil then begin
						errorOccurred := true;
						str := 'Out of memory';
						exit(doGGMorph16u);
					end;
				HLock(h);
				kp := graySEValuePtr(h^);
				GGMorphArg.baseSE := kp;
				ker := u16p(arg[2].roi.Base);
				lines := kh;
				y := -ky;
				while lines > 0 do begin
						cols := kw;
						x := -kx;
						while cols > 0 do begin
								if ker^.u <> 0 then begin
										with kp^ do begin
												value := ker^.u - 1;
												row := y;
												skipLeft := (mw.left - x) * sizeof(Integer);
												if skipLeft < 0 then
													skipLeft := 0;
												outOffset := y * GGMorphArg.bprOut + x * sizeof(Integer);
												skipRight := (mw.right + x) * sizeof(Integer);
												if skipRight < 0 then
													skipRight := 0;
											end;
										kp := graySEValuePtr(ord4(kp) + sizeof(graySEValue));
									end;
								ker := u16p(ord4(ker) + sizeof(Integer));
								cols := cols - 1;
								x := x + 1;
							end;
						ker := u16p(ord4(ker) + kSkip);
						lines := lines - 1;
						y := y + 1;
					end;
				kp^.value := -1; {end of kernel signal}
				case UserMacroCommand of
					GGDilate16uUC: 
						GGDilate16u(GGMorphArg);
					GGErode16uUC: 
						GGErode16u(GGMorphArg);
				end;
			end; {with uma}
		DisposHandle(h);
	end;


{    type }
{      Pixel16uPair = record }
{        wpix, height, skipA, skipB, skipOut: longint;}
{        baseA, baseB, baseOut: ptr;}
{      end;}

	procedure pairOp (var uma: UserMacroArgs);
		var
			pairArg: Pixel16uPair;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkPixelWidth(2, uma, 3);
{checkOutputConflict(uma, 3);output can be one of the inputs}
				checkRoiSize(uma, 1, 2);
				checkRoiSize(uma, 1, 3);
        {checkRoiSize(uma,2,3);redundant}
				if errorOccurred then
					exit(pairOp);
				with arg[1].roi do begin
						pairArg.wpix := Width div 2;
						pairArg.height := Height;
					end;
				with pairArg do begin
						with arg[1].roi do begin
								baseA := Base;
								skipA := Skip;
							end;
						with arg[2].roi do begin
								baseB := Base;
								skipB := Skip;
							end;
						with arg[3].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				case UserMacroCommand of
					Add16uUC: 
						add16u(pairArg);
					Sub16uUC: 
						sub16u(pairArg);
					Mpy16uUC: 
						mpy16u(pairArg);
					Div16uUC: 
						div16u(pairArg);
					Lrg16uUC: 
						lrg16u(pairArg);
					Sml16uUC: 
						sml16u(pairArg);
				end;
			end;
	end;

{;/* Add16uTo32s.c */ }
{; }
{;typedef struct [ }
{;    long wpix, hpix, skipA, skipB, skipOut; }
{;    unsigned short *baseA; }
{;    long *baseB, *baseOut; }
{;] Add16uTo32sArg; }
{; }
{;pascal Add16uTo32s( }
{;    register Add16uTo32sArg *arg }
{;) [ }
{;    register unsigned short *a; }
{;    register long *b, *out; }
{;    register long cols; }
{;    register unsigned long skipA, skipB, skipOut; }
{;    register long bval, oval; }
{; }
{;    a = arg->baseA; }
{;    b = arg->baseB; }
{;    out = arg->baseOut; }
{;    skipA = arg->skipA; }
{;    skipB = arg->skipB; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            bval = *b++; }
{;            oval = *a++ + bval; }
{;            if (bval > 0 && oval < 0) [ }
{;                oval = 0x7FFFFFFF; }
{;            ] }
{;            *out++ = oval; }
{;        ] while (--cols > 0); }
{;        (char * )a += skipA; }
{;        (char * )b += skipB; }
{;        (char * )out += skipOut; }
{;    ] while (--arg->hpix > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type Add16uTo32sArg = record ',13 }
{ DC.B 'wpix, hpix, skipA, skipB, skipOut: LongInt;',13 }
{ DC.B 'baseA, baseB, baseOut: Ptr;end;',13 }
{ DC.B 'procedure Add16uTo32s (var arg: Add16uTo32sArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7/A2-A4,-(A7) }
{ MOVEM.L 8(A0),D2-D4/A2-A4 }
{L0024 MOVE.L (A0),D5 }
{L0026 MOVE.L (A3)+,D6 }
{ MOVEQ #$00,D7 }
{ MOVE.W (A2)+,D7 }
{ ADD.L D6,D7 }
{ BVC.S L003E }
{ MOVE.L #$7FFFFFFF,D7 }
{L003E MOVE.L D7,(A4)+ }
{ SUBQ.L #$1,D5 }
{ BGT.S L0026 }
{ ADDA.L D2,A2 }
{ ADDA.L D3,A3 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,$0004(A0) }
{ BGT.S L0024 }
{ MOVEM.L (A7)+,D3-D7/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		Add16uTo32sArg = record
				wpix, hpix, skipA, skipB, skipOut: LongInt;
				baseA, baseB, baseOut: Ptr;
			end;
	procedure Add16uTo32s (var arg: Add16uTo32sArg);
	inline
		$205F, $48E7, $1F38, $4CE8, $1C1C, $0008, $2A10, $2C1B,{}
		$7E00, $3E1A, $DE86, $6806, $2E3C, $7FFF, $FFFF, $28C7,{}
		$5385, $6EEA, $D5C2, $D7C3, $D9C4, $53A8, $0004, $6EDC,{}
		$4CDF, $1CF8;

	procedure doAdd16uTo32s (var uma: UserMacroArgs);
		var
			a1632Arg: Add16uTo32sArg;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(4, uma, 2);
				checkPixelWidth(4, uma, 3);
				if (arg[1].roi.Width * 2 <> arg[2].roi.Width) or (arg[1].roi.Height <> arg[2].roi.Height) then begin
						errorOccurred := true;
						str := 'All selection sizes must be equal';
						exit(doAdd16uTo32s);
					end;
				checkRoiSize(uma, 2, 3);
				if errorOccurred then
					exit(doAdd16uTo32s);
				with arg[1].roi do begin
						a1632Arg.wpix := Width div 2;
						a1632Arg.hpix := Height;
					end;
				with a1632Arg do begin
						with arg[1].roi do begin
								baseA := Base;
								skipA := Skip;
							end;
						with arg[2].roi do begin
								baseB := Base;
								skipB := Skip;
							end;
						with arg[3].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				Add16uTo32s(a1632Arg);
			end;
	end;

	procedure doRatio16u (var uma: UserMacroArgs);
		var
			ratioArg: ratio16uArg;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkPixelWidth(2, uma, 3);
{checkOutputConflict(uma, 3);output can be one of the inputs}
				checkRoiSize(uma, 1, 2);
				checkRoiSize(uma, 1, 3);
        {checkRoiSize(uma,2,3);redundant}
				if errorOccurred then
					exit(doRatio16u);
				with arg[1].roi do begin
						ratioArg.wpix := Width div 2;
						ratioArg.height := Height;
					end;
				with ratioArg do begin
						with arg[1].roi do begin
								baseA := Base;
								skipA := Skip;
							end;
						with arg[2].roi do begin
								baseB := Base;
								skipB := Skip;
							end;
						with arg[3].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
						scale := arg[4].ival;
					end;
				ratio16u(ratioArg);
			end;
	end;


	type
		PixelK16uArg = record
				wpix, height, skipIn, skipOut, value: longint;
				baseIn, baseOut: ptr;
			end;
{;/* addK16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut, value; }
{;    unsigned short *baseIn, *baseOut; }
{;] addK16uArg; }
{; }
{;pascal addK16u( }
{;    register addK16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out; }
{;    register unsigned long value; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{;    register unsigned long acc; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    value = arg->value; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            acc = *in++ + value; }
{;            if (acc <= 65535) }
{;                *out++ = acc; }
{;            else }
{;                *out++ = 65535; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type addK16uArg = record' }
{ DC.B ' wpix, height, skipIn, skipOut, value: longint;' }
{ DC.B ' baseIn, baseOut: ptr; end;' }
{ DC.B ' procedure addK16u (var arg: addK16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7,-(A7) }
{ MOVEM.L (A0),D2-D6/A0/A1 }
{L1: MOVE.L D2,D7 }
{L2: MOVE.W D6,D0 }
{ ADD.W (A0)+,D0 }
{ BCS.S L3 }
{ MOVE.W D0,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{ BRA.S L4 }
{L3: MOVE.W #$FFFF,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{L4: ADDA.L D4,A0 }
{ ADDA.L D5,A1 }
{ SUBQ.L #$1,D3 }
{ BGT.S L1 }
{ MOVEM.L (A7)+,D3-D7 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		addK16uArg = record
				wpix, height, skipIn, skipOut, value: longint;
				baseIn, baseOut: ptr;
			end;
	procedure addK16u (var arg: PixelK16uArg);
	inline
		$205F, $48E7, $1F00, $4CD0, $037C, $2E02, $3006, $D058,{}
		$6508, $32C0, $5387, $6EF4, $6008, $32FC, $FFFF, $5387,{}
		$6EEA, $D1C4, $D3C5, $5383, $6EE0, $4CDF, $00F8;
{;/* subK16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut, value; }
{;    unsigned short *baseIn, *baseOut; }
{;] subK16uArg; }
{; }
{;pascal subK16u( }
{;    register subK16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out; }
{;    register unsigned long value; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{;    register unsigned long acc; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    value = arg->value; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            acc = *in++; }
{;            acc -= value; }
{;            if (acc <= 65535) }
{;                *out++ = acc; }
{;            else }
{;                *out++ = 0; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type subK16uArg = record' }
{ DC.B ' wpix, height, skipIn, skipOut, value: longint;' }
{ DC.B ' baseIn, baseOut: ptr; end;' }
{ DC.B ' procedure subK16u (var arg: subK16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7,-(A7) }
{ MOVEM.L (A0),D2-D6/A0/A1 }
{ MOVEQ.L #0,D1 }
{L1: MOVE.L D2,D7 }
{L2: MOVE.W (A0)+,D0 }
{ SUB.W D6,D0 }
{ BCS.S L3 }
{ MOVE.W D0,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{ BRA.S L4 }
{L3: MOVE.W D1,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{L4: ADDA.L D4,A0 }
{ ADDA.L D5,A1 }
{ SUBQ.L #$1,D3 }
{ BGT.S L1 }
{ MOVEM.L (A7)+,D3-D7 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		subK16uArg = record
				wpix, height, skipIn, skipOut, value: longint;
				baseIn, baseOut: ptr;
			end;
	procedure subK16u (var arg: PixelK16uArg);
	inline
		$205F, $48E7, $1F00, $4CD0, $037C, $7200, $2E02, $3018,{}
		$9046, $6508, $32C0, $5387, $6EF4, $6006, $32C1, $5387,{}
		$6EEC, $D1C4, $D3C5, $5383, $6EE2, $4CDF, $00F8;
{;/* mpyK16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut, value; }
{;    unsigned short *baseIn, *baseOut; }
{;] mpyK16uArg; }
{; }
{;pascal mpyK16u( }
{;    register mpyK16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out, value; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    value = arg->value; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            *out++ = *in++ * value; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type mpyK16uArg = record' }
{ DC.B ' wpix, height, skipIn, skipOut, value: longint;' }
{ DC.B ' baseIn, baseOut: ptr; end;' }
{ DC.B ' procedure mpyK16u (var arg: mpyK16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7,-(A7) }
{ MOVEM.L (A0),D2-D6/A0/A1 }
{L1: MOVE.L D2,D7 }
{L2: MOVE.W D6,D0 }
{ MULU.W (A0)+,D0 }
{ MOVE.W D0,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{ ADDA.L D4,A0 }
{ ADDA.L D5,A1 }
{ SUBQ.L #$1,D3 }
{ BGT.S L1 }
{ MOVEM.L (A7)+,D3-D7 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		mpyK16uArg = record
				wpix, height, skipIn, skipOut, value: longint;
				baseIn, baseOut: ptr;
			end;
	procedure mpyK16u (var arg: PixelK16uArg);
	inline
		$205F, $48E7, $1F00, $4CD0, $037C, $2E02, $3006, $C0D8,{}
		$32C0, $5387, $6EF6, $D1C4, $D3C5, $5383, $6EEC, $4CDF,{}
		$00F8;
{;/* divK16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut, value; }
{;    unsigned short *baseIn, *baseOut; }
{;] divK16uArg; }
{; }
{;pascal divK16u( }
{;    register divK16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out, value; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    value = arg->value; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            *out++ = *in++ / value; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type divK16uArg = record' }
{ DC.B ' wpix, height, skipIn, skipOut, value: longint;' }
{ DC.B ' baseIn, baseOut: ptr; end;' }
{ DC.B ' procedure divK16u (var arg: divK16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7,-(A7) }
{ MOVEM.L (A0),D2-D6/A0/A1 }
{L1: MOVE.L D2,D7 }
{L2: MOVEQ #$00,D0 }
{ MOVE.W (A0)+,D0 }
{ DIVU.W D6,D0 }
{ MOVE.W D0,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{ ADDA.L D4,A0 }
{ ADDA.L D5,A1 }
{ SUBQ.L #$1,D3 }
{ BGT.S L1 }
{ MOVEM.L (A7)+,D3-D7 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		divK16uArg = record
				wpix, height, skipIn, skipOut, value: longint;
				baseIn, baseOut: ptr;
			end;
	procedure divK16u (var arg: PixelK16uArg);
	inline
		$205F, $48E7, $1F00, $4CD0, $037C, $2E02, $7000, $3018,{}
		$80C6, $32C0, $5387, $6EF4, $D1C4, $D3C5, $5383, $6EEA,{}
		$4CDF, $00F8;
{;/* mpydivK16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut; }
{;    unsigned long numerator, denominator; }
{;    unsigned short *baseIn, *baseOut; }
{;] mpydivK16uArg; }
{; }
{;pascal mpydivK16u( }
{;    register mpydivK16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out; }
{;    register unsigned long numerator, denominator, roundv; }
{;    register long lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    numerator = arg->numerator; }
{;    denominator = arg->denominator; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    roundv = denominator >> 1; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            *out++ = ( *in++ * numerator + roundv) / denominator; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type mpydivK16uArg = record' }
{ DC.B ' wpix, height, skipIn, skipOut, numerator, denominator: longint;' }
{ DC.B ' baseIn, baseOut: ptr; end;' }
{ DC.B ' procedure mpydivK16u (var arg: mpydivK16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7/A2,-(A7) }
{ MOVEM.L 4(A0),D1-D5/A1/A2 }
{ MOVE.L D5,D6 }
{ LSR.L #$1,D6 }
{L002C MOVE.L (A0),D7 }
{L002E MOVEQ #$00,D0 }
{ MOVE.W (A1)+,D0 }
{ MULU.L D4,D0 }
{ ADD.L D6,D0 }
{ DIVU.L D5,D0 }
{ MOVE.W D0,(A2)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L002E }
{ ADDA.L D2,A1 }
{ ADDA.L D3,A2 }
{ SUBQ.L #$1,D1 }
{ BGT.S L002C }
{ MOVEM.L (A7)+,D3-D7/A2 }
{endcode: }
{ ENDPROC }
{ END }
{ }
{}
	type
		mpydivK16uArg = record
				wpix, height, skipIn, skipOut, numerator, denominator: longint;
				baseIn, baseOut: ptr;
			end;
	procedure mpydivK16u (var arg: mpydivK16uArg);
	inline
		$205F, $48E7, $1F20, $4CE8, $063E, $0004, $2C05, $E28E,{}
		$2E10, $7000, $3019, $4C04, $0000, $D086, $4C45, $0000,{}
		$34C0, $5387, $6EEC, $D3C2, $D5C3, $5381, $6EE2, $4CDF,{}
		$04F8;
{;/* lrgK16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut, value; }
{;    unsigned short *baseIn, *baseOut; }
{;] lrgK16uArg; }
{; }
{;pascal lrgK16u( }
{;    register lrgK16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out, value, inv; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    value = arg->value; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            inv = *in++; }
{;            if (value > inv) }
{;                inv = value; }
{;            *out++ = inv; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type lrgK16uArg = record' }
{ DC.B ' wpix, height, skipIn, skipOut, value: longint;' }
{ DC.B ' baseIn, baseOut: ptr; end;' }
{ DC.B ' procedure lrgK16u (var arg: lrgK16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7,-(A7) }
{ MOVEM.L (A0),D1-D5/A0/A1 }
{L1: MOVE.L D1,D7 }
{L2: MOVE.W (A0)+,D6 }
{ CMP.W D5,D6 }
{ BCC.S L3 }
{ MOVE.W D5,D6 }
{L3: MOVE.W D6,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{ ADDA.L D3,A0 }
{ ADDA.L D4,A1 }
{ SUBQ.L #$1,D2 }
{ BGT.S L1 }
{ MOVEM.L (A7)+,D3-D7 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		lrgK16uArg = record
				wpix, height, skipIn, skipOut, value: longint;
				baseIn, baseOut: ptr;
			end;
	procedure lrgK16u (var arg: PixelK16uArg);
	inline
		$205F, $48E7, $1F00, $4CD0, $033E, $2E01, $3C18, $BC45,{}
		$6402, $3C05, $32C6, $5387, $6EF2, $D1C3, $D3C4, $5382,{}
		$6EE8, $4CDF, $00F8;
{;/* smlK16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn, skipOut, value; }
{;    unsigned short *baseIn, *baseOut; }
{;] smlK16uArg; }
{; }
{;pascal smlK16u( }
{;    register smlK16uArg *arg }
{;) [ }
{;    register unsigned short *in, *out, value, inv; }
{;    register long wpix, lines, cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    value = arg->value; }
{;    in = arg->baseIn; }
{;    out = arg->baseOut; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            inv = *in++; }
{;            if (value < inv) }
{;                inv = value; }
{;            *out++ = inv; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--lines > 0); }
{;] }
{; }
{; }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type smlK16uArg = record' }
{ DC.B ' wpix, height, skipIn, skipOut, value: longint;' }
{ DC.B ' baseIn, baseOut: ptr; end;' }
{ DC.B ' procedure smlK16u (var arg: smlK16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D7,-(A7) }
{ MOVEM.L (A0),D1-D5/A0/A1 }
{L1: MOVE.L D1,D7 }
{L2: MOVE.W (A0)+,D6 }
{ CMP.W D5,D6 }
{ BLS.S L3 }
{ MOVE.W D5,D6 }
{L3: MOVE.W D6,(A1)+ }
{ SUBQ.L #$1,D7 }
{ BGT.S L2 }
{ ADDA.L D3,A0 }
{ ADDA.L D4,A1 }
{ SUBQ.L #$1,D2 }
{ BGT.S L1 }
{ MOVEM.L (A7)+,D3-D7 }
{endcode: }
{ ENDPROC }
{ END }
{ }
	type
		smlK16uArg = record
				wpix, height, skipIn, skipOut, value: longint;
				baseIn, baseOut: ptr;
			end;
	procedure smlK16u (var arg: PixelK16uArg);
	inline
		$205F, $48E7, $1F00, $4CD0, $033E, $2E01, $3C18, $BC45,{}
		$6302, $3C05, $32C6, $5387, $6EF2, $D1C3, $D3C4, $5382,{}
		$6EE8, $4CDF, $00F8;

	procedure unaryOp (var uma: UserMacroArgs);
		var
			KArg: PixelK16uArg;
	begin
		with uma do begin {in, out: pidNumber;cons: integer}
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkRoiSize(uma, 1, 2);
{checkOutputConflict(uma, 2);output can be same as input}
				if errorOccurred then
					exit(unaryOp);
				with arg[1].roi do begin
						KArg.wpix := Width div 2;
						KArg.height := Height;
					end;
				with KArg do begin
						with arg[1].roi do begin
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
						value := arg[3].ival;
					end;
				case UserMacroCommand of
					AddK16uUC: 
						AddK16u(KArg);
					SubK16uUC: 
						SubK16u(KArg);
					MpyK16uUC: 
						MpyK16u(KArg);
					DivK16uUC: 
						DivK16u(KArg);
					LrgK16uUC: 
						LrgK16u(KArg);
					SmlK16uUC: 
						SmlK16u(KArg);
				end;
			end;
	end;

	procedure doMpyDivK16u (var uma: UserMacroArgs);
		var
			K2Arg: MpyDivK16uArg;
	begin
		with uma do begin {in, out: pidNumber;cons: integer}
				checkPixelWidth(2, uma, 1);
				checkPixelWidth(2, uma, 2);
				checkRoiSize(uma, 1, 2);
{checkOutputConflict(uma, 2);output can be same as input}
				if errorOccurred then
					exit(doMpyDivK16u);
				with arg[1].roi do begin
						K2Arg.wpix := Width div 2;
						K2Arg.height := Height;
					end;
				with K2Arg do begin
						with arg[1].roi do begin
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
						numerator := arg[3].ival;
						denominator := arg[4].ival;
					end;
				MpyDivK16u(K2Arg);
			end;
	end;

{;/* minmax16u.c */ }
{; }
{;typedef struct [ }
{;    long wpix, height, skipIn; }
{;    unsigned short *baseIn; }
{;    unsigned long minv, maxv; }
{;] minmax16uarg; }
{; }
{;pascal minmax16u( }
{;    register minmax16uarg *arg }
{;) [ }
{;    register unsigned short *in; }
{;    register long lines, cols, wpix; }
{;    register unsigned long skipIn; }
{;    register unsigned short minv, maxv, v; }
{; }
{;    wpix = arg->wpix; }
{;    lines = arg->height; }
{;    skipIn = arg->skipIn; }
{;    in = arg->baseIn; }
{; }
{;    minv = 65535; }
{;    maxv = 0; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            v = *in++; }
{;            if (v < minv) }
{;                minv = v; }
{;            if (v > maxv) }
{;                maxv = v; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;    ] while (--lines > 0); }
{; }
{;    arg->minv = minv; }
{;    arg->maxv = maxv; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type minmax16uarg = record ' }
{ DC.B 'wpix, height, skipIn: LongInt;' }
{ DC.B 'baseIn: Ptr;' }
{ DC.B 'minv, maxv: LongInt;end;' }
{ DC.B 'procedure minmax16u (var arg: minmax16uarg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6,-(A7) }
{ MOVEM.L (A0),D1-D3/A1 }
{ MOVE.W #$FFFF,D5 ;minv = 65535 }
{ CLR.W D6 ;maxv = 0 }
{L1: MOVE.L D1,D4 ;do [ cols = wpix }
{L2: MOVE.W (A1)+,D0 ; do [ v = *in++ }
{ CMP.W D0,D5 ; if (v < minv) }
{ BLS.S L3 }
{ MOVE.W D0,D5 ; minv = v }
{L3: CMP.W D0,D6 ; if (v > maxv) }
{ BCC.S L4 }
{ MOVE.W D0,D6 ; maxv = v }
{L4: SUBQ.L #$1,D4 ; ] while (--cols > 0); }
{ BGT.S L2 }
{ ADDA.L D3,A1 ; (char * )in += skipIn; }
{ SUBQ.L #$1,D2 ;] while (--lines > 0); }
{ BGT.S L1 }
{ MOVEQ.L #$00,D0 }
{ MOVE.W D5,D0 ;arg->minv = minv }
{ MOVE.L D0,$0010(A0) }
{ MOVE.W D6,D0 ;arg->maxv = maxv }
{ MOVE.L D0,$0014(A0) }
{ MOVEM.L (A7)+,D3-D6 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		minmax16uarg = record
				wpix, height, skipIn: LongInt;
				baseIn: Ptr;
				minv, maxv: LongInt;
			end;
	procedure minmax16u (var arg: minmax16uarg);
	inline
		$205F, $48E7, $1E00, $4CD0, $020E, $3A3C, $FFFF, $4246,{}
		$2801, $3019, $BA40, $6302, $3A00, $BC40, $6402, $3C00,{}
		$5384, $6EEE, $D3C3, $5382, $6EE6, $7000, $3005, $2140,{}
		$0010, $3006, $2140, $0014, $4CDF, $0078;


	procedure doMinMax16u (var uma: UserMacroArgs);
		var
			mxarg: minmax16uarg;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				with arg[1].roi do begin
						mxarg.wpix := Width div 2;
						mxarg.height := Height;
						mxarg.skipIn := Skip;
						mxarg.baseIn := Base;
						minmax16u(mxarg);
						arg[2].ival := mxarg.minv;
						arg[3].ival := mxarg.maxv;
					end;
			end;
	end;


{;/* minmax32s.c */ }
{; }
{;typedef struct [ }
{;    long wpix, hpix, skipIn; }
{;    long *baseIn; }
{;    long minv, maxv; }
{;] minmax32sArg; }
{; }
{;pascal minmax32s( }
{;    register minmax32sArg *arg }
{;) [ }
{;    register long *in; }
{;    register long cols; }
{;    register long skipIn; }
{;    register long minv, maxv, v; }
{; }
{;    skipIn = arg->skipIn; }
{;    in = arg->baseIn; }
{; }
{;    minv = 0x7FFFFFFF; /* +2^31-1 */ }
{;    maxv = 0x80000000; /* -2^31 */ }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            v = *in++; }
{;            if (v < minv) }
{;                minv = v; }
{;            if (v > maxv) }
{;                maxv = v; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;    ] while (--arg->hpix > 0); }
{; }
{;    arg->minv = minv; }
{;    arg->maxv = maxv; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type minmax32sArg = record ',13 }
{ DC.B 'wpix, hpix, skipIn: LongInt;',13 }
{ DC.B 'baseIn: Ptr;',13 }
{ DC.B 'minv, maxv: LongInt;end;',13 }
{ DC.B 'procedure minmax32s (var arg: minmax32sArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D4,-(A7) }
{ MOVEM.L 8(A0),D2/A1 }
{ MOVE.L #$7FFFFFFF,D4 }
{ MOVE.L #$80000000,D1 }
{L0020 MOVE.L (A0),D3 }
{L0022 MOVE.L (A1)+,D0 }
{ CMP.L D0,D4 }
{ BLE.S L002A }
{ MOVE.L D0,D4 }
{L002A CMP.L D0,D1 }
{ BGE.S L0030 }
{ MOVE.L D0,D1 }
{L0030 SUBQ.L #$1,D3 }
{ BGT.S L0022 }
{ ADDA.L D2,A1 }
{ SUBQ.L #$1,$0004(A0) }
{ BGT.S L0020 }
{ MOVE.L D4,$0010(A0) }
{ MOVE.L D1,$0014(A0) }
{ MOVEM.L (A7)+,D3-D4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		minmax32sArg = record
				wpix, hpix, skipIn: LongInt;
				baseIn: Ptr;
				minv, maxv: LongInt;
			end;
	procedure minmax32s (var arg: minmax32sArg);
	inline
		$205F, $48E7, $1800, $4CE8, $0204, $0008, $283C, $7FFF,{}
		$FFFF, $223C, $8000, $0000, $2610, $2019, $B880, $6F02,{}
		$2800, $B280, $6C02, $2200, $5383, $6EEE, $D3C2, $53A8,{}
		$0004, $6EE4, $2144, $0010, $2141, $0014, $4CDF, $0018;

	procedure doMinMax32s (var uma: UserMacroArgs);
		var
			mxarg: minmax32sArg;
	begin
		with uma do begin
				checkPixelWidth(4, uma, 1);
				with arg[1].roi do begin
						mxarg.wpix := Width div 4;
						mxarg.hpix := Height;
						mxarg.skipIn := Skip;
						mxarg.baseIn := Base;
						minmax32s(mxarg);
						arg[2].ival := mxarg.minv;
						arg[3].ival := mxarg.maxv;
					end;
			end;
	end;

{;/* LinLUT16uTo8.c */ }
{;/* }
{; }
{; }
{;Constructs look up table for a piecewise linear function }
{; }
{;    LUT(x) = ymin when y(x) <= 0 }
{;    LUT(x) = ymin + trunc(y(x) * (ymax + 1 - ymin)) when 0 <= y(x) < 1 }
{;    LUT(x) = ymax when 1 <= y(x) }
{; }
{;where }
{; }
{;    y(x) = (x - xmin) / (xmax + 1 - xmin), }
{;    x runs from 0 to 65535, }
{;    0 <= ymin <= ymax <= 255, }
{;    xmin and xmax are arbitrary but when }
{;    xmin > xmax, the formula is xmax - 1 - xmin, }
{; }
{;This is calculated using truncating integer division: }
{; }
{;    rise = ymax + 1 - ymin }
{;    if xmax >= xmin }
{;        run = xmax + 1 - xmin }
{;    else }
{;        run = xmax - 1 - xmin }
{;    q = ymin + ((x - xmin) * rise) / run }
{;    if q < ymin then lut = ymin }
{;    else if q > ymax than lut = ymax }
{;    else lut = q }
{; }
{;    This requires that -1/-2 = 0, not -1. }
{; }
{; }
{;*/ }
{; }
{; }
{;typedef struct [ }
{;    long ymin, ymax; }
{;    unsigned char *baseLUT; }
{;    long xmin, xmax; }
{;] LinLUT16uTo8arg; }
{; }
{;pascal LinLUT16uTo8( }
{;    register LinLUT16uTo8arg *arg }
{;) [ }
{;    register unsigned char *LUT; }
{;    register long rise, run, ymin, ymax, n, num, q; }
{; }
{;    ymin = arg->ymin; }
{;    ymax = arg->ymax; }
{;    LUT = arg->baseLUT; }
{;    run = arg->xmax - arg->xmin; }
{;    if (run >= 0) run++; }
{;    else run--; }
{;    rise = ymax + 1 - ymin; }
{;    n = 65536; }
{;    num = (-arg->xmin) * rise; }
{;    while (--n >= 0) [ }
{;        q = ymin + num / run; }
{;        num += rise; }
{;        if (q < ymin) q = ymin; }
{;        else if (q > ymax) q = ymax; }
{;        *LUT++ = q; }
{;    ] }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type LinLUT16uTo8arg = record ' }
{ DC.B 'ymin, ymax: LongInt;' }
{ DC.B 'baseLUT: Ptr;' }
{ DC.B 'xmin, xmax: LongInt;end;' }
{ DC.B 'procedure LinLUT16uTo8(var arg: LinLUT16uTo8arg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6,-(A7) }
{ MOVEM.L (A0),D5/D6/A1 }
{ MOVE.L $0010(A0),D3 ;run = arg->xmax - arg->xmin }
{ SUB.L $000C(A0),D3 }
{ BLT.S L1 ;if (run >= 0) run++ }
{ ADDQ.L #$1,D3 }
{ BRA.S L1a }
{L1: SUBQ.L #$1,D3 }
{L1a: MOVE.L D6,D2 ;rise = ymax + 1 - ymin }
{ ADDQ.L #$1,D2 }
{ SUB.L D5,D2 }
{ MOVE.L #$00010000,D1 ;n = 65536 }
{ MOVE.L $000C(A0),D4 ;num = (-arg->xmin) * rise }
{ NEG.L D4 }
{ MULS.L D2,D4 }
{ BRA.S L5 ;while (--n >= 0) [ }
{L2: MOVE.L D4,D0 ;q = ymin + num / run }
{ DIVS.L D3,D0 }
{ ADD.L D5,D0 }
{ ADD.L D2,D4 ;num += rise; }
{ CMP.L D0,D5 ;if (q < ymin) }
{ BLE.S L3 }
{ MOVE.L D5,D0 ;q = ymin }
{ BRA.S L4 }
{L3: CMP.L D0,D6 ;else if (q < ymax) }
{ BGE.S L4 }
{ MOVE.L D6,D0 ;q = ymax }
{L4: MOVE.B D0,(A1)+ ;*LUT++ = q }
{L5: SUBQ.L #$1,D1 }
{ BGE.S L2 }
{ MOVEM.L (A7)+,D3-D6 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		LinLUT16uTo8arg = record
				ymin, ymax: LongInt;
				baseLUT: Ptr;
				xmin, xmax: LongInt;
			end;
	procedure LinLUT16uTo8 (var arg: LinLUT16uTo8arg);
	inline
		$205F, $48E7, $1E00, $4CD0, $0260, $2628, $0010, $96A8,{}
		$000C, $6D04, $5283, $6002, $5383, $2406, $5282, $9485,{}
		$223C, $0001, $0000, $2828, $000C, $4484, $4C02, $4804,{}
		$601A, $2004, $4C43, $0800, $D085, $D882, $BA80, $6F04,{}
		$2005, $6006, $BC80, $6C02, $2006, $12C0, $5381, $6CE2,{}
		$4CDF, $0078;


	procedure doLinLUT16uTo8 (var uma: UserMacroArgs);
		var
			LUTarg: LinLUT16uTo8arg;
			p: u16p;
	begin
		with uma do begin
				checkPixelWidth(2, uma, 1);
				with arg[1].roi do begin
						if (Width <> 256) or (Height <> 256) or (Skip <> 0) then begin
								errorOccurred := true;
								str := 'LUT must be 256x256';
								exit(doLinLUT16uTo8);
							end;
						LUTarg.baseLUT := Base;
					end;
				with LUTarg do begin
						xmin := arg[2].ival;
						xmax := arg[3].ival;
						ymin := arg[4].ival;
						ymax := arg[5].ival;
					end;
				LinLUT16uTo8(LUTarg);
			end;
	end;

{;/* SqzMask8u16u.c */ }
{; }
{;/* }
{; }
{;Copy ROI of 16 bit input image to output vector, under control of }
{;an 8 bit mask image with same size ROI.  All pixels of the }
{;input image which correspond to nonzero mask pixels will }
{;be copied to the output vector. }
{; }
{;The input image is a 16 bit image. }
{; }
{;The mask image is an 8 bit image. }
{; }
{;The output image is a 16 bit vector (i.e. row boundaries ignored). }
{;It must not have an ROI.  It should have at least as many elements }
{;as the number of nozero mask pixels.  The number of unused elements }
{;is reported in the sizeVect field of the argument. }
{; }
{;The ROI sizes of the input and mask images must match allowing for }
{;pixel size. }
{; }
{;*/ }
{; }
{;typedef unsigned short vect_type; }
{;typedef unsigned short pixel_type; }
{;typedef unsigned char mask_type; }
{; }
{;typedef struct [ }
{;    long sizeVect, wpix, height, skipData, skipMask; }
{;    vect_type *baseVect; }
{;    mask_type *baseMask; }
{;    pixel_type *baseData; }
{;] SqzMaskArg; }
{; }
{;SqzMask8u16u( }
{;    SqzMaskArg *a }
{;) [ }
{;    register mask_type *mask; }
{;    register pixel_type *data; }
{;    register vect_type *vect; }
{;    register long sizeVect; }
{;    register long wpix; }
{;    register long rows; }
{;    register long skipData, skipMask; }
{;    register long cols; }
{; }
{;    sizeVect = a->sizeVect; }
{;    wpix = a->wpix; }
{;    rows = a->height; }
{;    skipData = a->skipData; }
{;    skipMask = a->skipMask; }
{;    vect = a->baseVect; }
{;    mask = a->baseMask; }
{;    data = a->baseData; }
{; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            *vect = *data++; }
{;            if ( *mask++) [ }
{;                ++vect; }
{;                if (--sizeVect == 0) [ }
{;                    a->sizeVect = sizeVect; }
{;                    return; }
{;                ] }
{;            ] }
{;        ] while (--cols > 0); }
{;        (char * )mask += skipMask; }
{;        (char * )data += skipData; }
{;    ] while (--rows > 0); }
{;    a->sizeVect = sizeVect; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type SqzMaskArg = record ' }
{ DC.B 'sizeVect, wpix, height, skipData, skipMask: LongInt;' }
{ DC.B 'baseVect, baseMask, baseData: ptr;' }
{ DC.B 'end;' }
{ DC.B 'procedure SqzMask8u16u(a: SqzMaskArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6/A2-A3,-(A7) }
{ MOVEM.L (A0),D1-D5/A1-A3 }
{L2A MOVE.L D2,D6 }
{L2C MOVE.W (A3)+,(A1) }
{ TST.B (A2)+ }
{ BEQ.S L3C }
{ ADDQ.W #$2,A1 }
{ SUBQ.L #$1,D1 }
{ BEQ.S L48 }
{L3C SUBQ.L #$1,D6 }
{ BGT.S L2C }
{ ADDA.L D5,A2 }
{ ADDA.L D4,A3 }
{ SUBQ.L #$1,D3 }
{ BGT.S L2A }
{L48 MOVE.L D1,(A0) }
{ MOVEM.L (A7)+,D3-D6/A2-A3 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		SqzMaskArg = record
				sizeVect, wpix, height, skipData, skipMask: LongInt;
				baseVect, baseMask, baseData: ptr;
			end;
	procedure SqzMask8u16u (a: SqzMaskArg);
	inline
		$205F, $48E7, $1E30, $4CD0, $0E3E, $2C02, $329B, $4A1A,{}
		$6706, $5449, $5381, $670C, $5386, $6EF0, $D5C5, $D7C4,{}
		$5383, $6EE6, $2081, $4CDF, $0C78;

	procedure doSqzMask16u (var uma: UserMacroArgs);
		var
			a: SqzMaskArg;
			markpix: Integer;
	begin {in, mask, out}
		with uma do begin
				with a do begin
						checkPixelWidth(2, uma, 1);
						checkPixelWidth(2, uma, 3);
						checkOutputConflict(uma, 3);
						if errorOccurred then
							exit(doSqzMask16u);
						height := arg[1].roi.Height;
						with arg[1].roi do begin
								baseData := Base;
								skipData := Skip;
							end;
						with arg[2].roi do begin
								wpix := Width;
								baseMask := Base;
								skipMask := Skip;
							end;
						with arg[3].infop^ do begin
								baseVect := PicBaseAddr;
								sizeVect := PixMapSize div 2;
							end;
						if (height <> arg[2].roi.Height) or (wpix * 2 <> arg[1].roi.Width) then begin
								errorOccurred := true;
								str := 'mask selection must be same size as input selection';
								exit(doSqzMask16u);
							end;
					end;
				SqzMask8u16u(a)
			end;
	end;


{;/* SqzMask8u8u.c */ }
{; }
{;/* }
{; }
{;Copy ROI of 8 bit input image to output vector, under control of }
{;an 8 bit mask image with same size ROI.  All pixels of the }
{;input image which correspond to nonzero mask pixels will }
{;be copied to the output vector. }
{; }
{;The input image is an 8 bit image. }
{; }
{;The mask image is an 8 bit image. }
{; }
{;The output image is an 8 bit vector (i.e. row boundaries ignored). }
{;It must not have an ROI.  It should have at least as many elements }
{;as the number of nozero mask pixels.  The number of unused elements }
{;is reported in the sizeVect field of the argument. }
{; }
{;The ROI sizes of the input and mask images must match allowing for }
{;pixel size. }
{; }
{;*/ }
{; }
{;typedef unsigned char vect_type; }
{;typedef unsigned char pixel_type; }
{;typedef unsigned char mask_type; }
{; }
{;typedef struct [ }
{;    long sizeVect, wpix, height, skipData, skipMask; }
{;    vect_type *baseVect; }
{;    mask_type *baseMask; }
{;    pixel_type *baseData; }
{;] SqzMaskArg; }
{; }
{;SqzMask8u8u( }
{;    SqzMaskArg *a }
{;) [ }
{;    register mask_type *mask; }
{;    register pixel_type *data; }
{;    register vect_type *vect; }
{;    register long sizeVect; }
{;    register long wpix; }
{;    register long rows; }
{;    register long skipData, skipMask; }
{;    register long cols; }
{; }
{;    sizeVect = a->sizeVect; }
{;    wpix = a->wpix; }
{;    rows = a->height; }
{;    skipData = a->skipData; }
{;    skipMask = a->skipMask; }
{;    vect = a->baseVect; }
{;    mask = a->baseMask; }
{;    data = a->baseData; }
{; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            *vect = *data++; }
{;            if ( *mask++) [ }
{;                ++vect; }
{;                if (--sizeVect == 0) [ }
{;                    a->sizeVect = sizeVect; }
{;                    return; }
{;                ] }
{;            ] }
{;        ] while (--cols > 0); }
{;        (char * )mask += skipMask; }
{;        (char * )data += skipData; }
{;    ] while (--rows > 0); }
{;    a->sizeVect = sizeVect; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type SqzMaskArg8 = record ' }
{ DC.B 'sizeVect, wpix, height, skipData, skipMask: LongInt;' }
{ DC.B 'baseVect, baseMask, baseData: ptr;' }
{ DC.B 'end;' }
{ DC.B 'procedure SqzMask8u8u(a: SqzMaskArg8); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6/A2-A3,-(A7) }
{ MOVEM.L (A0),D1-D5/A1-A3 }
{L2A MOVE.L D2,D6 }
{L2C MOVE.B (A3)+,(A1) }
{ TST.B (A2)+ }
{ BEQ.S L3C }
{ ADDQ.W #$1,A1 }
{ SUBQ.L #$1,D1 }
{ BEQ.S L48 }
{L3C SUBQ.L #$1,D6 }
{ BGT.S L2C }
{ ADDA.L D5,A2 }
{ ADDA.L D4,A3 }
{ SUBQ.L #$1,D3 }
{ BGT.S L2A }
{L48 MOVE.L D1,(A0) }
{ MOVEM.L (A7)+,D3-D6/A2-A3 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		SqzMaskArg8 = record
				sizeVect, wpix, height, skipData, skipMask: LongInt;
				baseVect, baseMask, baseData: ptr;
			end;
	procedure SqzMask8u8u (a: SqzMaskArg8);
	inline
		$205F, $48E7, $1E30, $4CD0, $0E3E, $2C02, $129B, $4A1A,{}
		$6706, $5249, $5381, $670C, $5386, $6EF0, $D5C5, $D7C4,{}
		$5383, $6EE6, $2081, $4CDF, $0C78;

	procedure doSqzMask8u (var uma: UserMacroArgs);
		var
			a: SqzMaskArg8;
			markpix: Integer;
	begin {in, mask, out}
		with uma do begin
				with a do begin
						checkOutputConflict(uma, 3);
						if errorOccurred then
							exit(doSqzMask8u);
						height := arg[1].roi.Height;
						with arg[1].roi do begin
								baseData := Base;
								skipData := Skip;
							end;
						with arg[2].roi do begin
								wpix := Width;
								baseMask := Base;
								skipMask := Skip;
							end;
						with arg[3].infop^ do begin
								baseVect := PicBaseAddr;
								sizeVect := PixMapSize;
							end;
						if (height <> arg[2].roi.Height) or (wpix <> arg[1].roi.Width) then begin
								errorOccurred := true;
								str := 'mask selection must be same size as input selection';
								exit(doSqzMask8u);
							end;
					end;
				SqzMask8u8u(a)
			end;
	end;


{;/* ExpMask8u16u.c */ }
{; }
{;/* }
{; }
{;Copy input vector to the ROI of 16 bit output image, under control of }
{;an 8 bit mask image with same size ROI.  All pixels of the }
{;output image which correspond to nonzero mask pixels will }
{;be copied from the input vector. }
{; }
{;The input image is a 16 bit vector (i.e. row boundaries ignored). }
{;It must not have an ROI.  It should have at least as many elements }
{;as the number of nozero mask pixels.  The number of unused elements }
{;is reported in the sizeVect field of the argument. }
{; }
{;The mask image is an 8 bit image. }
{; }
{;The output image is a 16 bit image. }
{; }
{;The ROI sizes of the output and mask images must match allowing for }
{;pixel size. }
{; }
{;*/ }
{; }
{;typedef unsigned short vect_type; }
{;typedef unsigned short pixel_type; }
{;typedef unsigned char mask_type; }
{; }
{;typedef struct [ }
{;    long sizeVect, wpix, height, skipData, skipMask; }
{;    vect_type *baseVect; }
{;    mask_type *baseMask; }
{;    pixel_type *baseData; }
{;] ExpMaskArg; }
{; }
{;ExpMask8u16u( }
{;    ExpMaskArg *a }
{;) [ }
{;    register mask_type *mask; }
{;    register pixel_type *data; }
{;    register vect_type *vect; }
{;    register long sizeVect; }
{;    register long wpix; }
{;    register long rows; }
{;    register long skipData, skipMask; }
{;    register long cols; }
{; }
{;    sizeVect = a->sizeVect; }
{;    wpix = a->wpix; }
{;    rows = a->height; }
{;    skipData = a->skipData; }
{;    skipMask = a->skipMask; }
{;    vect = a->baseVect; }
{;    mask = a->baseMask; }
{;    data = a->baseData; }
{; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            if ( *mask++) [ }
{;                *data++ = *vect++; }
{;                if (--sizeVect == 0) [ }
{;                    a->sizeVect = sizeVect; }
{;                    return; }
{;                ] }
{;            ] else [ }
{;                *data++ = 0; }
{;            ] }
{;        ] while (--cols > 0); }
{;        (char * )mask += skipMask; }
{;        (char * )data += skipData; }
{;    ] while (--rows > 0); }
{;    a->sizeVect = sizeVect; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type ExpMaskArg = record ' }
{ DC.B 'sizeVect, wpix, height, skipData, skipMask: LongInt;' }
{ DC.B 'baseVect, baseMask, baseData: ptr;' }
{ DC.B 'end;' }
{ DC.B 'procedure ExpMask8u16u(a: ExpMaskArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6/A2-A4,-(A7) }
{ MOVEM.L (A0),D1-D5/A2-A4 }
{L2A MOVE.L D2,D6 }
{L2C TST.B (A3)+ }
{ BEQ.S L3A }
{ MOVE.W (A2)+,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BNE.S L3C }
{ BRA.S L48 }
{L3A CLR.W (A4)+ }
{L3C SUBQ.L #$1,D6 }
{ BGT.S L2C }
{ ADDA.L D5,A3 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,D3 }
{ BGT.S L2A }
{L48 MOVE.L D1,(A0) }
{ MOVEM.L (A7)+,D3-D6/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		ExpMaskArg = record
				sizeVect, wpix, height, skipData, skipMask: LongInt;
				baseVect, baseMask, baseData: ptr;
			end;
	procedure ExpMask8u16u (a: ExpMaskArg);
	inline
		$205F, $48E7, $1E38, $4CD0, $1C3E, $2C02, $4A1B, $6708,{}
		$38DA, $5381, $6604, $600E, $425C, $5386, $6EEE, $D7C5,{}
		$D9C4, $5383, $6EE4, $2081, $4CDF, $1C78;

	procedure doExpMask16u (var uma: UserMacroArgs);
		var
			a: ExpMaskArg;
			markpix: Integer;
	begin {in, mask, out}
		with uma do begin
				with a do begin
						checkPixelWidth(2, uma, 1);
						checkPixelWidth(2, uma, 3);
						checkOutputConflict(uma, 3);
						if errorOccurred then
							exit(doExpMask16u);
						height := arg[2].roi.Height;
						with arg[1].infop^ do begin
								baseVect := PicBaseAddr;
								sizeVect := PixMapSize div 2;
							end;
						with arg[2].roi do begin
								wpix := Width;
								baseMask := Base;
								skipMask := Skip;
							end;
						with arg[3].roi do begin
								baseData := Base;
								skipData := Skip;
							end;
						if (height <> arg[3].roi.Height) or (wpix * 2 <> arg[3].roi.Width) then begin
								errorOccurred := true;
								str := 'mask selection must be same size as output selection';
								exit(doExpMask16u);
							end;
					end;
				ExpMask8u16u(a)
			end;
	end;

{;/* ExpMask8u8u.c */ }
{; }
{;/* }
{; }
{;Copy input vector to the ROI of 8 bit output image, under control of }
{;an 8 bit mask image with same size ROI.  All pixels of the }
{;output image which correspond to nonzero mask pixels will }
{;be copied from the input vector. }
{; }
{;The input image is a 8 bit vector (i.e. row boundaries ignored). }
{;It must not have an ROI.  It should have at least as many elements }
{;as the number of nozero mask pixels.  The number of unused elements }
{;is reported in the sizeVect field of the argument. }
{; }
{;The mask image is an 8 bit image. }
{; }
{;The output image is a 8 bit image. }
{; }
{;The ROI sizes of the output and mask images must match allowing for }
{;pixel size. }
{; }
{;*/ }
{; }
{;typedef unsigned char vect_type; }
{;typedef unsigned char pixel_type; }
{;typedef unsigned char mask_type; }
{; }
{;typedef struct [ }
{;    long sizeVect, wpix, height, skipData, skipMask; }
{;    vect_type *baseVect; }
{;    mask_type *baseMask; }
{;    pixel_type *baseData; }
{;] ExpMaskArg; }
{; }
{;ExpMask8u8u( }
{;    ExpMaskArg *a }
{;) [ }
{;    register mask_type *mask; }
{;    register pixel_type *data; }
{;    register vect_type *vect; }
{;    register long sizeVect; }
{;    register long wpix; }
{;    register long rows; }
{;    register long skipData, skipMask; }
{;    register long cols; }
{; }
{;    sizeVect = a->sizeVect; }
{;    wpix = a->wpix; }
{;    rows = a->height; }
{;    skipData = a->skipData; }
{;    skipMask = a->skipMask; }
{;    vect = a->baseVect; }
{;    mask = a->baseMask; }
{;    data = a->baseData; }
{; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            if ( *mask++) [ }
{;                *data++ = *vect++; }
{;                if (--sizeVect == 0) [ }
{;                    a->sizeVect = sizeVect; }
{;                    return; }
{;                ] }
{;            ] else [ }
{;                *data++ = 0; }
{;            ] }
{;        ] while (--cols > 0); }
{;        (char * )mask += skipMask; }
{;        (char * )data += skipData; }
{;    ] while (--rows > 0); }
{;    a->sizeVect = sizeVect; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type ExpMaskArg = record ' }
{ DC.B 'sizeVect, wpix, height, skipData, skipMask: LongInt;' }
{ DC.B 'baseVect, baseMask, baseData: ptr;' }
{ DC.B 'end;' }
{ DC.B 'procedure ExpMask8u8u(a: ExpMaskArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6/A2-A4,-(A7) }
{ MOVEM.L (A0),D1-D5/A2-A4 }
{L2A MOVE.L D2,D6 }
{L2C TST.B (A3)+ }
{ BEQ.S L3A }
{ MOVE.B (A2)+,(A4)+ }
{ SUBQ.L #$1,D1 }
{ BNE.S L3C }
{ BRA.S L48 }
{L3A CLR.B (A4)+ }
{L3C SUBQ.L #$1,D6 }
{ BGT.S L2C }
{ ADDA.L D5,A3 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,D3 }
{ BGT.S L2A }
{L48 MOVE.L D1,(A0) }
{ MOVEM.L (A7)+,D3-D6/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		ExpMaskArg8 = record
				sizeVect, wpix, height, skipData, skipMask: LongInt;
				baseVect, baseMask, baseData: ptr;
			end;
	procedure ExpMask8u8u (a: ExpMaskArg8);
	inline
		$205F, $48E7, $1E38, $4CD0, $1C3E, $2C02, $4A1B, $6708,{}
		$18DA, $5381, $6604, $600E, $421C, $5386, $6EEE, $D7C5,{}
		$D9C4, $5383, $6EE4, $2081, $4CDF, $1C78;
	procedure doExpMask8u (var uma: UserMacroArgs);
		var
			a: ExpMaskArg8;
			markpix: Integer;
	begin {in, mask, out}
		with uma do begin
				with a do begin
						checkOutputConflict(uma, 3);
						if errorOccurred then
							exit(doExpMask8u);
						height := arg[2].roi.Height;
						with arg[1].infop^ do begin
								baseVect := PicBaseAddr;
								sizeVect := PixMapSize;
							end;
						with arg[2].roi do begin
								wpix := Width;
								baseMask := Base;
								skipMask := Skip;
							end;
						with arg[3].roi do begin
								baseData := Base;
								skipData := Skip;
							end;
						if (height <> arg[3].roi.Height) or (wpix <> arg[3].roi.Width) then begin
								errorOccurred := true;
								str := 'mask selection must be same size as output selection';
								exit(doExpMask8u);
							end;
					end;
				ExpMask8u8u(a)
			end;
	end;


{;/* CnvMsk16uTo8.c */ }
{; }
{;/* }
{; }
{;Translate 16 bit unsigned input vector to the ROI of 8 bit output image, }
{;under control of an 8 bit mask image with same size ROI, using a translate }
{;table.  All pixels of the output image which correspond to nonzero mask }
{;pixels will be translated from the input vector. }
{; }
{;The input image is a 16 bit vector (i.e. row boundaries ignored). }
{;It must not have an ROI.  It should have at least as many elements }
{;as the number of nozero mask pixels.  The number of unused elements }
{;is reported in the sizeVect field of the argument. }
{; }
{;The mask image is an 8 bit image. }
{; }
{;The output image is an 8 bit image. }
{; }
{;The translate table is a 256 x 265 8 bit image. }
{; }
{;The ROI sizes of the output and mask images must match allowing for }
{;pixel size. }
{; }
{;*/ }
{; }
{;typedef unsigned short vect_type; }
{;typedef unsigned char pixel_type; }
{;typedef unsigned char mask_type; }
{; }
{;typedef struct [ }
{;    long sizeVect, wpix, height, skipData, skipMask; }
{;    vect_type *baseVect; }
{;    pixel_type *baseLUT; }
{;    mask_type *baseMask; }
{;    pixel_type *baseData; }
{;] CnvMaskArg; }
{; }
{;CnvMask8u16u( }
{;    CnvMaskArg *a }
{;) [ }
{;    register mask_type *mask; }
{;    register pixel_type *data; }
{;    register vect_type *vect; }
{;    register pixel_type *LUT; }
{;    register long sizeVect; }
{;    register long wpix; }
{;    register long rows; }
{;    register long skipData, skipMask; }
{;    register long cols; }
{; }
{;    sizeVect = a->sizeVect; }
{;    wpix = a->wpix; }
{;    rows = a->height; }
{;    skipData = a->skipData; }
{;    skipMask = a->skipMask; }
{;    vect = a->baseVect; }
{;    mask = a->baseMask; }
{;    data = a->baseData; }
{;    LUT = a->baseLUT; }
{; }
{;    do [ }
{;        cols = wpix; }
{;        do [ }
{;            if ( *mask++) [ }
{;                *data++ = LUT[*vect++]; }
{;                if (--sizeVect == 0) [ }
{;                    a->sizeVect = sizeVect; }
{;                    return; }
{;                ] }
{;            ] else [ }
{;                *data++ = 0; }
{;            ] }
{;        ] while (--cols > 0); }
{;        (char * )mask += skipMask; }
{;        (char * )data += skipData; }
{;    ] while (--rows > 0); }
{;    a->sizeVect = sizeVect; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'type CnvMaskArg = record ',13 }
{ DC.B 'sizeVect, wpix, height, skipData, skipMask: LongInt;',13 }
{ DC.B 'baseVect, baseLUT, baseMask, baseData: ptr;',13 }
{ DC.B 'end;',13 }
{ DC.B 'procedure CnvMsk16uTo8(a: CnvMaskArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVEA.L (A7)+,A0 }
{ MOVEM.L D3-D6/A2-A4,-(A7) }
{ MOVEM.L (A0),D1-D5/A1-A4 }
{ MOVEQ #$00,D0 }
{L2E MOVE.L D2,D6 }
{L30 TST.B (A3)+ }
{ BEQ.S L48 }
{ MOVE.W (A1)+,D0 }
{ MOVE.B $00(A2,D0.L),(A4)+ }
{ SUBQ.L #$1,D1 }
{ BNE.S L4A }
{ BRA.S L5A }
{L48 CLR.B (A4)+ }
{L4A SUBQ.L #$1,D6 }
{ BGT.S L30 }
{ ADDA.L D5,A3 }
{ ADDA.L D4,A4 }
{ SUBQ.L #$1,D3 }
{ BGT.S L2E }
{L5A MOVE.L D1,(A0) }
{ MOVEM.L (A7)+,D3-D6/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		CnvMaskArg = record
				sizeVect, wpix, height, skipData, skipMask: LongInt;
				baseVect, baseLUT, baseMask, baseData: ptr;
			end;
	procedure CnvMsk16uTo8 (a: CnvMaskArg);
	inline
		$205F, $48E7, $1E38, $4CD0, $1E3E, $7000, $2C02, $4A1B,{}
		$670C, $3019, $18F2, $0800, $5381, $6604, $600E, $421C,{}
		$5386, $6EEA, $D7C5, $D9C4, $5383, $6EE0, $2081, $4CDF,{}
		$1C78;

	procedure doCnvMsk16uTo8 (var uma: UserMacroArgs);
		var
			a: CnvMaskArg;
			markpix: Integer;
	begin {in, LUT, mask, out}
		with uma do begin
				with a do begin
						checkPixelWidth(2, uma, 1);
						checkOutputConflict(uma, 4);
						with arg[2] do begin
								if (roi.Width <> 256) or (roi.Height <> 256) or (roi.Skip <> 0) then begin
										errorOccurred := true;
										str := 'LUT must be 256x256';
									end;
							end;
						if errorOccurred then
							exit(doCnvMsk16uTo8);
						with arg[1].infop^ do begin
								baseVect := PicBaseAddr;
								sizeVect := PixMapSize div 2;
							end;
						with arg[2].infop^ do begin
								baseLUT := PicBaseAddr;
							end;
						height := arg[3].roi.Height;
						with arg[3].roi do begin
								wpix := Width;
								baseMask := Base;
								skipMask := Skip;
							end;
						with arg[4].roi do begin
								baseData := Base;
								skipData := Skip;
							end;
						if (height <> arg[4].roi.Height) or (wpix <> arg[4].roi.Width) then begin
								errorOccurred := true;
								str := 'mask selection must be same size as output selection';
								exit(doCnvMsk16uTo8);
							end;
					end;
				CnvMsk16uTo8(a)
			end;
	end;

{From StatLib (lib.stat.cmu.edu) general/cdflib.shar invnor.f}
{Uses the rational function on page 95 of Kennedy  and  Gentle,}
{Statistical Computing , Marcel Dekker , NY , 1980.}
{The function name is taken from Microsoft Excel}
{normsinv(0.908789) is 1.3333}
	function normsinv (p: extended): extended;
		var
			sign, x: extended;
	begin
		if p < 1.0e-20 then
			normsinv := -10.0
		else if p >= 1.0 then
			normsinv := 10.0
		else begin
				if p <= 0.5 then begin
						sign := -1.0;
						x := p;
					end
				else begin
						sign := 1.0;
						x := 1.0 - p;
					end;
				x := sqrt(-2.0 * ln(x));
				normsinv := sign * (x + (-0.322232431088 + x * (-1.0 + x * (-0.342242088547 + x * (-0.204231210245e-1 + x * (-0.453642210148e-4))))) / (0.993484626060e-1 + x * (0.588581570495 + x * (0.531103462366 + x * (0.103537752850 + x * (0.38560700634e-2))))));
			end;
	end;

	procedure doNormSInv (var uma: UserMacroArgs);{probability}
	begin
		with uma do begin
				funcResult := normsinv(arg[1].aval);
			end;
	end;

	procedure doGaussRand16u (var uma: UserMacroArgs); {mu, sigma, seed, out}
		var
			mu, sigma, x, v: extended;
			i, skp, h, wpix, w: LongInt;
			p: u16p;
	begin
		with uma do begin
				mu := arg[1].aval; {mean}
				sigma := arg[2].aval; {standard deviation}
				x := arg[3].aval; {random number generator seed}
				if x < 1.0 then
					x := 1.0;
				if x > 2147483646.0 then
					x := 2147483646.0;
				checkPixelWidth(2, uma, 4);
				if errorOccurred then
					exit(doGaussRand16u);
				with arg[4].roi do begin
						p := u16p(Base);
						skp := Skip;
						h := Height;
						wpix := Width div 2;
					end;
				while h > 0 do begin
						h := h - 1;
						w := wpix;
						while w > 0 do begin
								w := w - 1;
								v := normsinv(randomx(x) / 2147483646.0) * sigma + mu;
								if v < 0.0 then
									v := 0.0
								else if v > 65535.0 then
									v := 65535.0;
								p^.u := trunc(v);
								p := u16p(ord4(p) + sizeof(Integer));
							end;
						p := u16p(ord4(p) + skp);
					end;
				arg[3].aval := x;
			end;
	end;

	type
		Fill16uArg = record
				wpix, hpix, skipOut: LongInt;
				baseOut: Ptr;
				FillValue: LongInt;
			end;

	procedure Fill16u (var FillArg: Fill16uArg);
		var
			outp: u16p;
			w: longInt;
			v: longInt;
	begin
		with FillArg do begin
				outp := u16p(baseOut);
				v := FillValue;
				repeat
					w := wpix;
					repeat
						outp^.u := v;
						outp := u16p(ord4(outp) + sizeof(integer));
						w := w - 1;
					until w <= 0;
					outp := u16p(ord4(outp) + skipOut);
					hpix := hpix - 1;
				until hpix <= 0;
			end;
	end;

	procedure doFill16u (var uma: UserMacroArgs);
		var
			FillArg: Fill16uArg;
	begin
		with uma, FillArg do begin
				checkPixelWidth(sizeof(integer), uma, 2);
				if errorOccurred then
					exit(doFill16u);
				with arg[2].roi do begin
						wpix := Width div sizeof(integer);
						hpix := Height;
						baseOut := Base;
						skipOut := Skip;
					end;
				FillValue := arg[1].ival;
				Fill16u(FillArg);
			end;
	end;

{from File1.p }
{ procedure WarnUserWindows;}
{   var}
{     UserInfo, NextUI: UserInfoHandle;}
{ begin}
{    UserInfo := UserInfoList;}
{    while UserInfo <> nil do begin}
{      NextUI := UserInfo^^.Link;}
{      doUserWindow(UserInfo, UserInfo^^.UserCloseWarning); {might call DisposeUserWindow}
{      UserInfo := NextUI;}
{    end;}
{ end;}

	procedure unlockHandles16u (userInfo: userInfoHandle);
	begin
		with userInfo^^ do
			if UserData <> nil then begin
					with view16uHandle(UserData)^^ do begin
							if PicBaseHandle <> nil then begin
									HUnlock(PicBaseHandle);
								end;
						end;
					HUnlock(UserData);
         {WARNING:  Using this HUnlock means that care must be taken to prevent}
         {calls to getBigHandle inside any with userData^^ statement.}
				end;
     {WARNING:  Using this HUnlock means that care must be taken to prevent}
     {calls to getBigHandle inside any with userInfo^^ statement.}
		HUnlock(Handle(userInfo));
	end;

	procedure lockHandles16u (userInfo: userInfoHandle);
	begin
		MoveHHI(Handle(userInfo));
		HLock(Handle(userInfo));{essential}
		with userInfo^^ do
			if UserData <> nil then begin
					MoveHHI(UserData);
					HLock(UserData);{essential}
					with view16uHandle(UserData)^^ do begin
							if PicBaseHandle <> nil then begin
									HLock(PicBaseHandle);{essential}
									if OsPort <> nil then
										OsPort^.PortPixMap^^.BaseAddr := StripAddress(PicBaseHandle^);
								end;
						end;
				end;
	end;

	function View16uReady (userInfo: userInfoHandle): Boolean;
	begin
		View16uReady := false;
	end;

	procedure ActivateView16u (userInfo: userInfoHandle);
	begin
		with userInfo^^ do
			if UserData <> nil then
				with view16uHandle(UserData)^^ do begin
						if Active <> UserActivating then
							if View16uReady(userInfo) then begin
									Active := UserActivating;
									if Active then begin
{RefreshView16uOffscreen;}
										end;
								end;
					end;
	end;


	procedure ResizeView16u (userInfo: userInfoHandle; Width, Height: integer);
	begin
	end;


	procedure nilUserWindowProc (userInfo: userInfoHandle);
	begin
	end;


	procedure DoMouseDownInView16u (userInfo: userInfoHandle);
	begin
		HLock(Handle(userInfo));{extra}
		with userInfo^^ do
			if UserData <> nil then begin
					HLock(UserData);{extra}
					with view16uHandle(UserData)^^ do begin
						end;
				end;
	end;


	procedure DoView16uCursor (userInfo: userInfoHandle);
	begin
		HLock(Handle(userInfo));{extra}
		with userInfo^^ do
			if UserData <> nil then begin
					HLock(UserData);{extra}
					with view16uHandle(UserData)^^ do begin
						end;
				end;
	end;


	procedure GrowView16u (userInfo: userInfoHandle);
	begin
		with userInfo^^ do
			ResizeView16u(userInfo, LoWord(UserNewSize), hiWord(UserNewSize));
	end;

{Will not work for osport not same size as onscreen.}
	procedure UpdateView16uRect (userInfo: userInfoHandle; r: Rect);
		var
			SavePort: GrafPtr;
			onScreenRect: Rect;
	begin
{Copybits bug:  if the source is outside the source pixmap but dest is not, then}
{it copies junk.  Observed for case where source was top = -1, bottom = 0.}
{Fixed by testing for bottom > 0, since the offscreen pixmap has top = 0. }
		HLock(Handle(userInfo));{extra}
		with userInfo^^ do
			if UserData <> nil then begin
					HLock(UserData);{extra}
					with view16uHandle(UserData)^^ do
						if UserWindowPtr <> nil then
							if OsPort <> nil then
								if (r.bottom > 0) then begin
										onScreenRect := r;
										getPort(SavePort);
										SetPort(UserWindowPtr);
										pmForeColor(BlackIndex);
										pmBackColor(WhiteIndex);
										hlock(handle(OsPort^.portPixMap));
										hlock(handle(CGrafPort(UserWindowPtr^).PortPixMap));
										CopyBits(BitMapHandle(OsPort^.PortPixMap)^^, BitMapHandle(CGrafPort(UserWindowPtr^).PortPixMap)^^, r, onScreenRect, SrcCopy, nil);
										hunlock(handle(OsPort^.portPixMap));
										hunlock(handle(CGrafPort(UserWindowPtr^).PortPixMap));
										DrawMyGrowIcon(UserWindowPtr);
										SetPort(SavePort);
									end;
				end;
	end;


{ Called for an update event in the view16u window }
{ Copies the whole offscreen pixmap to the window }
	procedure UpdateView16u (userInfo: userInfoHandle);
	begin
		HLock(Handle(userInfo));{extra}
		with userInfo^^ do
			if UserData <> nil then begin
					HLock(UserData);{extra}
					with view16uHandle(UserData)^^ do
						if UserWindowPtr <> nil then
							if OsPort <> nil then begin
									UpdateView16uRect(userInfo, OsPort^.PortRect);
                  {DrawControls(UserWindowPtr);}
								end;
				end;
	end;

{ Called if view16u window itself is closed }
{ Called via WarnUserWindows if subsidiary windows are closed.}
{ Must not call CloseAWindow.}
	procedure CloseView16u (userInfo: userInfoHandle);
	begin
		HLock(Handle(userInfo));{extra}
		with userInfo^^ do begin
				if UserWindowPtr <> nil then
					DisposeWindow(UserWindowPtr);
				UserWindowPtr := nil;
				if UserData <> nil then begin
						HLock(UserData);{extra}
						with view16uHandle(UserData)^^ do begin
								if OsPort <> nil then begin
										CloseCPort(OsPort);
										DisposPtr(pointer(OsPort));
									end;
                {This handle would be equal to theGDevice^^.GDPMap if it were an onscreen port.}
                {CloseCPort does not dispose of it.}
								if PicBaseHandle <> nil then begin
										DisposHandle(PicBaseHandle);
									end;
							end;
						DisposHandle(UserData);
					end;
				DisposeUserWindow(userInfo);
			end;
	end;


	procedure CloseWarning16u (userInfo: UserInfoHandle);
	begin
		HLock(Handle(userInfo));{extra}
		with userInfo^^ do
			if UserData <> nil then begin
					HLock(UserData);{extra}
					with view16uHandle(UserData)^^ do
						if (info = inPic) or (info = maskPic) then
							CloseView16u(userInfo);
				end;
	end;


	procedure AllocateOffscreen (userInfo: UserInfoHandle);
		var
			SavePort: GrafPtr;
			neededSize: LongInt;
			PicRect: Rect;
			allocating: Boolean;
			h: Handle;
	begin
		allocating := false;
		HLock(Handle(userInfo));{extra}
		with userInfo^^ do
			if UserData <> nil then begin
					HLock(UserData);{extra}
					with view16uHandle(UserData)^^ do begin
							getPort(SavePort);
							PixelsPerLine := inPic^.PixelsPerLine div 2;{not for mask version...}
							BytesPerRow := PixelsPerLine;
							if odd(BytesPerRow) then
								BytesPerRow := BytesPerRow + 1;
							nlines := inPic^.nlines;
							neededSize := LongInt(nLines) * BytesPerRow;
							SetRect(PicRect, 0, 0, PixelsPerLine, nlines);
							if OsPort = nil then begin
									OsPort := CGrafPtr(newPtr(sizeof(CGrafPort)));
									if OsPort <> nil then
										OpenCPort(OsPort);
								end;
							if OsPort <> nil then begin
									SetPort(GrafPtr(OsPort));
									if PicBaseHandle <> nil then
										DisposHandle(PicBaseHandle);
									PicBaseHandle := nil; {in case GetBigHandle calls unlockHandles16u}
									allocating := true;
								end;
						end;
				end;
{This complication is required because of optional HUnlock calls in unlockHandles16u.}
{Any with x^^ statements must be ended and restarted because the value of x^^ might change.}
{If userInfo and UserData are simply locked when first created and never unlocked then}
{this is unnecessary.}
		if allocating then begin
				h := GetBigHandle(neededSize); {May call unlockHandles16u}
				HLock(Handle(userInfo));{extra}
				with userInfo^^ do begin
						HLock(UserData);{extra}
						with view16uHandle(UserData)^^ do begin
								PicBaseHandle := h;
								if PicBaseHandle <> nil then begin
										HLock(PicBaseHandle);
										with OsPort^ do begin
												with PortPixMap^^ do begin
														BaseAddr := StripAddress(PicBaseHandle^);
														bounds := PicRect;
														RowBytes := BitOr(BytesPerRow, $8000);
													end;
												PortRect := PicRect;
												RectRgn(visRgn, PicRect);
											end;
										SetPalette(WindowPtr(OsPort), ExplicitPalette, false);
										pmForeColor(BlackIndex);
										pmBackColor(WhiteIndex);
										EraseRect(OsPort^.PortRect);
									end;
								SetPort(SavePort);
							end;
					end;
			end;
	end;

	procedure newView (var uma: UserMacroArgs);
		var
			wrect: rect;
			userInfo: UserInfoHandle;
			View16uWindow: WindowPtr;
	begin
		with uma do begin
				GetWindowRect(arg[1].infop^.wptr, wrect);
				View16uWindow := NewCWindow(nil, wrect, 'View16u', true, DocumentProc, Pointer(-1), true, 0);
				if View16uWindow <> nil then begin
						userInfo := NewUserWindow;
						if userInfo = nil then begin
								DisposeWindow(View16uWindow);
							end
						else begin
								with userInfo^^ do begin
										UserWindowPtr := View16uWindow;
										UKind := View16uUKind;
										InitUserWindow(userInfo);
										UserUnlockHandles := @unlockHandles16u;
										UserLockHandles := @lockHandles16u;
										UserDispose := @nilUserWindowProc;
										UserActivate := @ActivateView16u;
										UserUpdate := @UpdateView16u;
										UserGrow := @GrowView16u;
										UserDrag := @nilUserWindowProc;
										UserClose := @CloseView16u;
										UserZoom := @nilUserWindowProc;
										UserMouseDown := @DoMouseDownInView16u;
										UserCursor := @DoView16uCursor;
										UserUndo := @nilUserWindowProc;
										UserCut := @nilUserWindowProc;
										UserCopy := @nilUserWindowProc;
										UserPaste := @nilUserWindowProc;
										UserClear := @nilUserWindowProc;
										UserCloseWarning := @CloseWarning16u;
										UserData := newHandle(sizeof(View16uRec));
										if UserData = nil then begin
												CloseView16u(userInfo);
											end
										else begin
												MoveHHI(UserData);
												HLock(UserData);
												with view16uHandle(UserData)^^ do begin
														inPic := arg[1].infop;
														maskPic := nil;
														PicBaseHandle := nil;
														osPort := nil;
														Active := false;
														AllocateOffscreen(userInfo);
													end;
											end;
									end;
							end;
					end;
			end;
	end;


	procedure doNewView16u (var uma: UserMacroArgs);
	begin
		with uma do begin
				errorOccurred := true;
				str := 'NMaskView16u not implemented';
				with arg[2] do begin
						if (roi.Width <> 256) or (roi.Height <> 256) or (roi.Skip <> 0) then begin
								errorOccurred := true;
								str := 'LUT must be 256x256';
							end;
					end;
				if not errorOccurred then
					newView(uma);
			end;
	end;

	procedure doNMaskView16u (var uma: UserMacroArgs);
	begin
		with uma do begin
				errorOccurred := true;
				str := 'NMaskView16u not implemented';
			end;
	end;

	procedure doFindView16u (var uma: UserMacroArgs);
		var
			UserInfo, NextUI: UserInfoHandle;
	begin
		UserInfo := UserInfoList;
		while UserInfo <> nil do begin
				with UserInfo^^ do begin
						NextUI := Link;
						if UKind = View16uUKind then
							if UserWindowPtr <> nil then
								if UserData <> nil then
									with uma, view16uHandle(UserData)^^ do
										if inPic = arg[1].infop then
											SelectWindow(UserWindowPtr);
					end;
				UserInfo := NextUI;
			end;
	end;

{;/* ApplyLUT16u.c */ }
{; }
{;typedef struct [ }
{;    unsigned long wpix, height, skipIn, skipOut; }
{;    unsigned short *baseIn; }
{;    unsigned short *baseLUT, *baseOut; }
{;] ApplyLUT16uArg; }
{; }
{;pascal ApplyLUT16u( }
{;    register ApplyLUT16uArg *arg }
{;) [ }
{;    register unsigned short *in; }
{;    register unsigned short *LUT; }
{;    register unsigned short *out; }
{;    register unsigned long cols; }
{;    register unsigned long skipIn, skipOut; }
{; }
{;    in = arg->baseIn; }
{;    LUT = arg->baseLUT; }
{;    out = arg->baseOut; }
{;    skipIn = arg->skipIn; }
{;    skipOut = arg->skipOut; }
{;    do [ }
{;        cols = arg->wpix; }
{;        do [ }
{;            *out++ = LUT[*in++]; }
{;        ] while (--cols > 0); }
{;        (char * )in += skipIn; }
{;        (char * )out += skipOut; }
{;    ] while (--arg->height > 0); }
{; }
{;] }
{; }
{ CASE YES }
{ MACHINE MC68020 }
{decl PROC EXPORT }
{ LEA str,A0 }
{ MOVE.L A0,D0 }
{ RTS }
{ DATA }
{ STRING ASIS }
{str DC.B 'ApplyLUT16uArg = record wpix, hpix, skipIn, skipOut: LongInt;',13 }
{ DC.B 'baseIn, baseLUT, baseOut: Ptr;end;',13 }
{ DC.B 'procedure ApplyLUT16u(var a: ApplyLUT16uArg); inline' }
{ DC.B 0 }
{ ENDPROC }
{ }
{code PROC EXPORT }
{ EXPORT endcode }
{ MOVE.L (A7)+,A1 }
{ MOVEM.L D5/A2-A4,-(A7) }
{ MOVEA.L $0010(A1),A3 }
{ MOVEA.L $0014(A1),A2 }
{ MOVEA.L $0018(A1),A4 }
{ MOVE.L $0008(A1),D5 }
{ MOVE.L $000C(A1),D2 }
{ MOVEQ #$00,D0 }
{L0020 MOVE.L (A1),D1 }
{L0022 MOVE.W (A3)+,D0 }
{ MOVE.W $00(A2,D0.L*2),(A4)+ }
{ SUBQ.L #$1,D1 }
{ BHI.S L0022 }
{ ADDA.L D5,A3 }
{ ADDA.L D2,A4 }
{ SUBQ.L #$1,$0004(A1) }
{ BHI.S L0020 }
{ MOVEM.L -$0014(A6),D5/A2-A4 }
{endcode: }
{ ENDPROC }
{ END }
{}
	type
		ApplyLUT16uArg = record
				wpix, hpix, skipIn, skipOut: LongInt;
				baseIn, baseLUT, baseOut: Ptr;
			end;
	procedure ApplyLUT16u (var a: ApplyLUT16uArg);
	inline
		$225F, $48E7, $0438, $2669, $0010, $2469, $0014, $2869,{}
		$0018, $2A29, $0008, $2429, $000C, $7000, $2211, $301B,{}
		$38F2, $0A00, $5381, $62F6, $D7C5, $D9C2, $53A9, $0004,{}
		$62EA, $4CEE, $1C20, $FFEC;

	procedure doApplyLUT16u (var uma: UserMacroArgs);
		var
			ApplyLUTarg: ApplyLUT16uArg;
	begin
      {in, lut16u16u, out: pidNumber}
       {in and out must have same size ROI}
       {lut16u16u must be 256x512x8 bits}
		with uma do begin
				if (arg[1].atype <> UMATpic) or (arg[2].atype <> UMATpic) or (arg[3].atype <> UMATpic) then begin
						errorOccurred := true;
						str := 'UMPixel16u.p';
					end;
				checkPixelWidth(2, uma, 1);
				if arg[1].roi.Width <> arg[3].roi.width * 2 then begin
						errorOccurred := true;
						str := 'Output width must be half input width';
					end
				else if arg[1].roi.Height <> arg[3].roi.Height then begin
						errorOccurred := true;
						str := 'Input and output heights must be equal';
					end;
				with arg[2] do begin
						if (roi.Width <> 512) or (roi.Height <> 256) or (roi.Skip <> 0) then begin
								errorOccurred := true;
								str := 'LUT must be 512x256';
							end;
					end;
				checkOutputConflict(uma, 3);
				if errorOccurred then
					exit(doApplyLUT16u);
				with ApplyLUTarg do begin
						hpix := arg[3].roi.Height;
						wpix := arg[3].roi.Width;
						with arg[1].roi do begin
								baseIn := Base;
								skipIn := Skip;
							end;
						with arg[2].roi do begin
								baseLUT := Base;
							end;
						with arg[3].roi do begin
								baseOut := Base;
								skipOut := Skip;
							end;
					end;
				ApplyLUT16u(ApplyLUTarg);
			end; {with uma}
	end;

	procedure UMPixel16uRun (var uma: UserMacroArgs);
	begin
		with uma do
			case UserMacroCommand of
				minMax16uUC: 
					doMinMax16u(uma);
				minMax32sUC: 
					doMinMax32s(uma);
				LinLUT16uTo8UC: 
					doLinLUT16uTo8(uma);
				Cnvrt16uTo8UC: 
					doCnvrt16uTo8(uma);
				Cnvrt8To16uUC: 
					doCnvrt8To16u(uma);
				Convolve16uUC: 
					doConvolve16u(uma);
				Median16uUC: 
					doMedian16u(uma);
				radMedian16uUC: 
					doRadMedian16u(uma);
				MinSpatial16uUC: 
					doMinSpatial16u(uma);
				GGDilate16uUC, GGErode16uUC: 
					doGGMorph16u(uma);
				Add16uTo32sUC: 
					doAdd16uTo32s(uma);
				Cnvrt32sT16uUC: 
					doCnvrt32sT16u(uma);
				Add16uUC, Sub16uUC, Mpy16uUC, Div16uUC, Lrg16uUC, Sml16uUC: 
					PairOp(uma);
				Ratio16uUC: 
					doRatio16u(uma);
				AddK16uUC, SubK16uUC, MpyK16uUC, DivK16uUC, LrgK16uUC, SmlK16uUC: 
					UnaryOp(uma);
				MpyDivK16uUC: 
					doMpyDivK16u(uma);
				SqzMask16uUC: 
					doSqzMask16u(uma);
				ExpMask16uUC: 
					doExpMask16u(uma);
				SqzMask8uUC: 
					doSqzMask8u(uma);
				ExpMask8uUC: 
					doExpMask8u(uma);
				CnvMsk16uTo8UC: 
					doCnvMsk16uTo8(uma);
				NewView16uUC: 
					doNewView16u(uma);
				NMaskView16uUC: 
					doNMaskView16u(uma);
				FindView16uUC: 
					doFindView16u(uma);
				GaussRand16uUC: 
					doGaussRand16u(uma);
				NormSInvUC: 
					doNormSInv(uma);
				Fill16uUC: 
					doFill16u(uma);
				ApplyLUT16uUC: 
					doApplyLUT16u(uma);
				otherwise begin
						ErrorOccurred := true;
						str := 'UMPixel16u.p';
					end;
			end;
	end;

end.