unit UMPixel16u; {Contributed by Edward J. Huff } {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: } {; 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.