unit User; {This module is a good place to put user additions to NIH Image. You will need } {to uncomment the call to InitUser in Image.p.} interface uses Memory, QuickDraw, Palettes, Printing, {} VDigitizerDefs, globals, Utilities, Graphics, Filters, Analysis; procedure InitUser; procedure DoUserCommand1; procedure DoUserCommand2; procedure DoUserCommand3; procedure DoUserCommand4; procedure DoUserCommand5; procedure DoUserCommand6; procedure DoUserCommand7; procedure DoUserCommand8; procedure DoUserMenuEvent (MenuItem: integer); procedure OldUserMacroCode (CodeNumber: integer; Param1, Param2, Param3: extended); procedure UserMacroCode (str: str255; Param1, Param2, Param3: extended); implementation const MaxChain = 10000; MinDelta = 50; MaxEdges = 2047; MaxEdgeTraces = 20; type EdgeLineRec = record h, v: Integer; count: Integer; chain: Ptr; end; {User global variables go here.} var defaultMinDelta, curMinDelta: Integer; minDeltaEntered: Boolean; edgeFirstColumn: packed array [0..MaxEdges] of Integer; edgeLastColumn: packed array [0..MaxEdges] of Integer; edgeChain: packed array [0..MaxChain] of byte; edgeStartX, edgeStartY, edgePixels: Integer; minEdgeStrength: Integer; procedure InitUser; var i: integer; begin UserMenuH := GetMenu(UserMenu); InsertMenu(UserMenuH, 0); DrawMenuBar; {Additional user initialization code goes here.} defaultMinDelta := MinDelta; minDeltaEntered := false; curMinDelta := defaultMinDelta; minEdgeStrength := 10; end; function QuickerGetPixel (h, v: integer): integer; begin with Info^ do QuickerGetPixel := ImageP(PicBaseAddr)^[v * BytesPerRow + h]; end; function FindFirstColumnEdge(line, startCol, endCol: Integer): Integer; var x: integer; sum1, sum2, sum3, sum4, sum5, edgeX, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin with info^ do begin { Sum the first five columns before starting into the loop. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 1)) + startCol); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line)) + startCol); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 1)) + startCol); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); edgeX := 0; delta := curMinDelta; for x := startCol + 5 to endCol - 1 do begin if (sum3 < (sum1 - delta)) and (sum3 < (sum2 - delta)) and (sum3 > (sum4 + delta)) and (sum3 > (sum5 + delta)) then begin edgeX := x - 3; line2Ptr := ImageP(ord4(line2Ptr) - 2); line2Ptr^[0] := 0; leave; end; sum1 := sum2; sum2 := sum3; sum3 := sum4; sum4 := sum5; sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); end; FindFirstColumnEdge := edgeX; end; end; function FindLastColumnEdge(line, startCol, endCol: Integer): Integer; var x: integer; sum1, sum2, sum3, sum4, sum5, edgeX, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin with info^ do begin { Sum the last five columns before starting into the loop. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 1)) + endCol - 1); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line)) + endCol - 1); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 1)) + endCol - 1); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); edgeX := 0; delta := curMinDelta; for x := (endCol - 6) downto startCol do begin if (sum3 < (sum1 - delta)) and (sum3 < (sum2 - delta)) and (sum3 > (sum4 + delta)) and (sum3 > (sum5 + delta)) then begin edgeX := x + 3; line2Ptr := ImageP(ord4(line2Ptr) + 2); line2Ptr^[0] := 0; leave; end; sum1 := sum2; sum2 := sum3; sum3 := sum4; sum4 := sum5; sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); end; FindLastColumnEdge := edgeX; end; end; function N0EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: xxx xxx xxP xxx xxx } with info^ do begin { Sum the five columns around the left neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 2)) + column - 2); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 2)) + column - 1); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 2)) + column); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N0EdgeStrength := delta; end; end; function N1EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: xx xxxx xxxxx xxP x } with info^ do begin { Sum the five columns around the upper left neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 1)) + column - 3); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 0)) + column - 2); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 1)) + column - 1); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N1EdgeStrength := delta; end; end; function N2EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: xxxxx xxxxx xxPxx } with info^ do begin { Sum the five columns around the upper neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 2)) + column - 2); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 1)) + column - 2); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line)) + column - 2); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N2EdgeStrength := delta; end; end; function N3EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: xx xxxx xxxxx Pxx x } with info^ do begin { Sum the five columns around the upper right neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 3)) + column + 1); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 2)) + column + 0); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 1)) + column - 1); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + 1); line2Ptr := ImageP(ord4(line2Ptr) + 1); line3Ptr := ImageP(ord4(line3Ptr) + 1); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N3EdgeStrength := delta; end; end; function N4EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: xxx xxx Pxx xxx xxx } with info^ do begin { Sum the five columns around the right neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 2)) + column); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 2)) + column + 1); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 2)) + column + 2); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N4EdgeStrength := delta; end; end; function N5EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: x Pxx xxxxx xxxx xx } with info^ do begin { Sum the five columns around the lower right neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line - 1)) + column + 1); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 0)) + column + 2); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 1)) + column + 3); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) + offset); line2Ptr := ImageP(ord4(line2Ptr) + offset); line3Ptr := ImageP(ord4(line3Ptr) + offset); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N5EdgeStrength := delta; end; end; function N6EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: xxPxx xxxxx xxxxx } with info^ do begin { Sum the five columns around the lower neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 0)) + column + 2); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 1)) + column + 2); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 2)) + column + 2); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N6EdgeStrength := delta; end; end; function N7EdgeStrength(line, column: Integer): Integer; var sum1, sum2, sum3, sum4, sum5, delta: integer; line1Ptr, line2Ptr, line3Ptr, line4Ptr, line5Ptr: ImageP; offset: LongInt; begin { Consider the pixels: x xxP xxxxx xxxx xx } with info^ do begin { Sum the five columns around the lower left neighbor. } offset := LongInt(BytesPerRow); line1Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 1)) + column + 1); line2Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 2)) + column + 0); line3Ptr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(line + 3)) + column - 1); sum1 := line1Ptr^[0]; sum1 := sum1 + line2Ptr^[0]; sum1 := sum1 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum2 := line1Ptr^[0]; sum2 := sum2 + line2Ptr^[0]; sum2 := sum2 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum3 := line1Ptr^[0]; sum3 := sum3 + line2Ptr^[0]; sum3 := sum3 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - 1); line2Ptr := ImageP(ord4(line2Ptr) - 1); line3Ptr := ImageP(ord4(line3Ptr) - 1); sum4 := line1Ptr^[0]; sum4 := sum4 + line2Ptr^[0]; sum4 := sum4 + line3Ptr^[0]; line1Ptr := ImageP(ord4(line1Ptr) - offset); line2Ptr := ImageP(ord4(line2Ptr) - offset); line3Ptr := ImageP(ord4(line3Ptr) - offset); sum5 := line1Ptr^[0]; sum5 := sum5 + line2Ptr^[0]; sum5 := sum5 + line3Ptr^[0]; delta := abs (sum3 - sum1); delta := delta + abs (sum3 - sum2); delta := delta + abs (sum3 - sum4); delta := delta + abs (sum3 - sum5); N7EdgeStrength := delta; end; end; function StrongestEdge(N1, N2, N3, N4, N5, N6, N7: Integer): Integer; begin { Compare the edge strength value and determine the strongest edge. } if (N1 >= N2) and (N1 >= N3) and (N1 >= N4) and (N1 >= N5) and (N1 >= N6) and (N1 >= N7) then StrongestEdge := 1 else if (N2 >= N1) and (N2 >= N3) and (N2 >= N4) and (N2 >= N5) and (N2 >= N6) and (N2 >= N7) then StrongestEdge := 2 else if (N3 >= N1) and (N3 >= N2) and (N3 >= N4) and (N3 >= N5) and (N3 >= N6) and (N3 >= N7) then StrongestEdge := 3 else if (N4 >= N1) and (N4 >= N2) and (N4 >= N3) and (N4 >= N5) and (N4 >= N6) and (N4 >= N7) then StrongestEdge := 4 else if (N5 >= N1) and (N5 >= N2) and (N5 >= N3) and (N5 >= N4) and (N5 >= N6) and (N5 >= N7) then StrongestEdge := 5 else if (N6 >= N1) and (N6 >= N2) and (N6 >= N3) and (N6 >= N4) and (N6 >= N5) and (N6 >= N7) then StrongestEdge := 6 else StrongestEdge := 7; end; function EdgeStrength(direction, v, h: Integer): Integer; begin { Compute the edge strength value for the given edge. } case direction of 0: begin EdgeStrength := N0EdgeStrength(v,h); end; 1: begin EdgeStrength := N1EdgeStrength(v,h); end; 2: begin EdgeStrength := N2EdgeStrength(v,h); end; 3: begin EdgeStrength := N3EdgeStrength(v,h); end; 4: begin EdgeStrength := N4EdgeStrength(v,h); end; 5: begin EdgeStrength := N5EdgeStrength(v,h); end; 6: begin EdgeStrength := N6EdgeStrength(v,h); end; 7: begin EdgeStrength := N7EdgeStrength(v,h); end; otherwise EdgeStrength := 0; end; { case } end; { Compute a chain code for an edge, given a starting point and incoming direction. The chain code is a series of numbers from 0 to 7 indicating the next neighbor in the chain, where the neighbors have the numbers: 1 2 3 0 x 4 7 6 5 } procedure FindEdgeChain(edge,startH,startV,direction: Integer; boundingRect: Rect); var h,v, n: integer; nextH, nextV: Integer; fromDirection, toDirection: Integer; foundAnEdge: Boolean; firstLine, firstColumn, lastLine, lastColumn: Integer; N0Strength, N1Strength, N2Strength, N3Strength: Integer; N4Strength, N5Strength, N6Strength, N7Strength: Integer; begin { Get the limits of the image area to process. } firstLine := boundingRect.top; firstColumn := boundingRect.left; lastLine := boundingRect.bottom; lastColumn := boundingRect.right; { Clear the chain for this edge. } edgeStartX := startH; edgeStartY := startV; edgePixels := 0; for n := 0 to MaxChain-1 do begin edgeChain[n] := 9; end; { Find the chain of edge pixels from the starting point, back to the same point. } h := startH; v := startV; nextH := 0; nextV := 0; fromDirection := direction; repeat ShowMessage(concat('Chain @', cr, long2str(h), ', ', long2str(v))); N0Strength := N0EdgeStrength(v,h); N1Strength := N1EdgeStrength(v,h); N2Strength := N2EdgeStrength(v,h); N3Strength := N3EdgeStrength(v,h); N4Strength := N4EdgeStrength(v,h); N5Strength := N5EdgeStrength(v,h); N6Strength := N6EdgeStrength(v,h); N7Strength := N7EdgeStrength(v,h); { Find the next edge pixel from the previous point. } case fromDirection of 0: begin if N4Strength >= N0Strength then toDirection := 4 else if N2Strength >= N0Strength then toDirection := 2 else if N6Strength >= N0Strength then toDirection := 6 else if N3Strength >= N0Strength then toDirection := 3 else if N5Strength >= N0Strength then toDirection := 5 {else if N1Strength >= N0Strength then toDirection := 1 else if N7Strength >= N0Strength then toDirection := 7} else begin toDirection := StrongestEdge(N1Strength, N2Strength, N3Strength, N4Strength, N5Strength, N6Strength, N7Strength); end; end; 1: begin if N5Strength >= N1Strength then toDirection := 5 else if N3Strength >= N1Strength then toDirection := 3 else if N7Strength >= N1Strength then toDirection := 7 else if N4Strength >= N1Strength then toDirection := 4 else if N6Strength >= N1Strength then toDirection := 6 {else if N2Strength >= N1Strength then toDirection := 2 else if N0Strength >= N1Strength then toDirection := 0} else begin toDirection := StrongestEdge(N0Strength, N2Strength, N3Strength, N4Strength, N5Strength, N6Strength, N7Strength); end; end; 2: begin if N6Strength >= N2Strength then toDirection := 6 else if N4Strength >= N2Strength then toDirection := 4 else if N0Strength >= N2Strength then toDirection := 0 else if N5Strength >= N2Strength then toDirection := 5 else if N7Strength >= N2Strength then toDirection := 7 {else if N3Strength >= N2Strength then toDirection := 3 else if N1Strength >= N2Strength then toDirection := 1} else begin toDirection := StrongestEdge(N0Strength, N1Strength, N3Strength, N4Strength, N5Strength, N6Strength, N7Strength); end; end; 3: begin if N7Strength >= N3Strength then toDirection := 7 else if N5Strength >= N3Strength then toDirection := 5 else if N1Strength >= N3Strength then toDirection := 1 else if N6Strength >= N3Strength then toDirection := 6 else if N0Strength >= N3Strength then toDirection := 0 {else if N4Strength >= N3Strength then toDirection := 4 else if N2Strength >= N3Strength then toDirection := 2} else begin toDirection := StrongestEdge(N0Strength, N1Strength, N2Strength, N4Strength, N5Strength, N6Strength, N7Strength); end; end; 4: begin if N0Strength >= N4Strength then toDirection := 0 else if N6Strength >= N4Strength then toDirection := 6 else if N2Strength >= N4Strength then toDirection := 2 else if N7Strength >= N4Strength then toDirection := 7 else if N1Strength >= N4Strength then toDirection := 1 {else if N5Strength >= N4Strength then toDirection := 5 else if N3Strength >= N4Strength then toDirection := 3} else begin toDirection := StrongestEdge(N0Strength, N1Strength, N2Strength, N3Strength, N5Strength, N6Strength, N7Strength); end; end; 5: begin if N1Strength >= N5Strength then toDirection := 1 else if N7Strength >= N5Strength then toDirection := 7 else if N3Strength >= N5Strength then toDirection := 3 else if N0Strength >= N5Strength then toDirection := 0 else if N2Strength >= N5Strength then toDirection := 2 {else if N6Strength >= N5Strength then toDirection := 6 else if N4Strength >= N5Strength then toDirection := 4} else begin toDirection := StrongestEdge(N0Strength, N1Strength, N2Strength, N3Strength, N4Strength, N6Strength, N7Strength); end; end; 6: begin if N2Strength >= N6Strength then toDirection := 2 else if N0Strength >= N6Strength then toDirection := 0 else if N4Strength >= N6Strength then toDirection := 4 else if N1Strength >= N6Strength then toDirection := 1 else if N3Strength >= N6Strength then toDirection := 3 {else if N7Strength >= N6Strength then toDirection := 7 else if N5Strength >= N6Strength then toDirection := 5} else begin toDirection := StrongestEdge(N0Strength, N1Strength, N2Strength, N3Strength, N4Strength, N5Strength, N7Strength); end; end; 7: begin if N3Strength >= N7Strength then toDirection := 3 else if N1Strength >= N7Strength then toDirection := 1 else if N5Strength >= N7Strength then toDirection := 5 else if N2Strength >= N7Strength then toDirection := 2 else if N4Strength >= N7Strength then toDirection := 4 {else if N0Strength >= N7Strength then toDirection := 0 else if N6Strength >= N7Strength then toDirection := 6} else begin toDirection := StrongestEdge(N0Strength, N1Strength, N2Strength, N3Strength, N4Strength, N5Strength, N6Strength); end; end; end; { case } { Make sure the selected direction is valid. } if (toDirection < 0) or (toDirection > 7) then begin foundAnEdge := false; end else begin if (EdgeStrength(toDirection,v,h) > minEdgeStrength) then begin foundAnEdge := true; edgeChain[edgePixels] := toDirection; edgePixels := edgePixels + 1; case toDirection of 0: begin nextH := h - 1; nextV := v; fromDirection := 4; end; 1: begin nextH := h - 1; nextV := v - 1; fromDirection := 5; end; 2: begin nextH := h; nextV := v - 1; fromDirection := 6; end; 3: begin nextH := h + 1; nextV := v - 1; fromDirection := 7; end; 4: begin nextH := h + 1; nextV := v; fromDirection := 0; end; 5: begin nextH := h + 1; nextV := v + 1; fromDirection := 1; end; 6: begin nextH := h; nextV := v + 1; fromDirection := 2; end; 7: begin nextH := h - 1; nextV := v + 1; fromDirection := 3; end; end; { case } end else foundAnEdge := false; end; h := nextH; v := nextV; until ((nextH = startH) and (nextV = startV)) or (not foundAnEdge) or (edgePixels >= MaxChain); end; procedure DrawEdgeChain(edge: Integer); var x, y, n: integer; offset: LongInt; linePtr: ImageP; begin with info^ do begin { Get the starting pixel. } x := edgeStartX; y := edgeStartY; offset := LongInt(BytesPerRow); linePtr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(y)) + x); for n := 0 to edgePixels - 1 do begin linePtr^[0] := 0; case edgeChain[n] of 0: begin linePtr := ImageP(ord4(linePtr) - 1); end; 1: begin linePtr := ImageP(ord4(linePtr) - offset - 1); end; 2: begin linePtr := ImageP(ord4(linePtr) - offset); end; 3: begin linePtr := ImageP(ord4(linePtr) - offset + 1); end; 4: begin linePtr := ImageP(ord4(linePtr) + 1); end; 5: begin linePtr := ImageP(ord4(linePtr) + offset + 1); end; 6: begin linePtr := ImageP(ord4(linePtr) + offset); end; 7: begin linePtr := ImageP(ord4(linePtr) + offset - 1); end; otherwise leave; end; { case } end; end; end; procedure FindPackageEdge; var y: integer; edgeX: integer; Saveport: GrafPtr; SaveBackground: integer; firstLine, firstColumn, lastLine, lastColumn: Integer; WasRoi: Boolean; SaveRoiRect, boundingRect: Rect; begin GetPort(SavePort); SetPort(GrafPtr(info^.osPort)); SetupUndo; WhatToUndo := UndoFilter; with info^ do begin if RoiShowing and (RoiType = RectRoi) then begin WasRoi := true; firstLine := RoiRect.top; firstColumn := RoiRect.left; lastLine := RoiRect.bottom - 1; lastColumn := RoiRect.right - 1; SaveRoiRect := RoiRect; KillROI; end else begin WasRoi := false; firstLine := 0; firstColumn := 0; lastLine := nLines - 1; lastColumn := PixelsPerLine - 1; end; { Adjust the limits to avoid edges of image. } firstLine := firstLine + 2; firstColumn := firstColumn + 2; lastLine := lastLine - 3; lastColumn := lastColumn - 3; SetRect(boundingRect, firstColumn, firstLine, lastColumn, lastLine); { Clear the edges arrays. } { edgeX := 0; for y := 0 to MaxEdges do begin edgeFirstColumn[y] := 0; edgeLastColumn[y] := 0; end;} { Find the first edge in each line. } { for y := firstLine + 1 to lastLine - 2 do begin edgeX := FindFirstColumnEdge(y, firstColumn, lastColumn); if (edgeX <> 0) then begin edgeFirstColumn[y] := edgeX; ShowMessage(concat('First edge found at:', cr, long2str(y), ', ', long2str(edgeX))); end; end;} { ...then the last edge in each line. } { for y := firstLine + 1 to lastLine - 2 do begin edgeX := FindLastColumnEdge(y, firstColumn, lastColumn); if (edgeX <> 0) then begin edgeLastColumn[y] := edgeX; ShowMessage(concat('Last edge found at:', cr, long2str(y), ', ', long2str(edgeX))); end; end;} { Find an edge beginning from the left, at the middle of the image. } y := firstLine + ((firstLine + lastLine) div 2); edgeX := FindFirstColumnEdge(y, firstColumn, lastColumn); if (edgeX <> 0) then begin ShowMessage(concat('Starting edge found at:', cr, long2str(y), ', ', long2str(edgeX))); FindEdgeChain(0, edgeX, y, 0, boundingRect); DrawEdgeChain(0); end; if WasRoi then begin RoiType := RectRoi; RoiRect := SaveRoiRect; MakeRegion; RoiShowing := true; end; UpdateScreen(PicRect); end; SetPort(SavePort); end; procedure ClearOutsidePackage; var x, y: integer; edgeX: integer; Saveport: GrafPtr; SaveBackground: integer; firstLine, firstColumn, lastLine, lastColumn: Integer; WasRoi: Boolean; SaveRoiRect: Rect; linePtr: ImageP; offset: LongInt; begin GetPort(SavePort); SetPort(GrafPtr(info^.osPort)); SetupUndo; WhatToUndo := UndoFilter; with info^ do begin if RoiShowing and (RoiType = RectRoi) then begin WasRoi := true; firstLine := RoiRect.top; firstColumn := RoiRect.left; lastLine := RoiRect.bottom - 1; lastColumn := RoiRect.right - 1; SaveRoiRect := RoiRect; KillROI; end else begin WasRoi := false; firstLine := 0; firstColumn := 0; lastLine := nLines - 1; lastColumn := PixelsPerLine - 1; end; { Clear up to the first edge in each line. } offset := LongInt(BytesPerRow); for y := firstLine + 1 to lastLine - 2 do begin edgeX := edgeFirstColumn[y] - 1; if edgeX > firstColumn then begin linePtr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(y)) + firstColumn); for x:= firstColumn to edgeX do begin linePtr^[0] := 45; linePtr := ImageP(ord4(linePtr) + 1); end; end; end; { ...then from the last edge to the end of the line. } for y := firstLine + 1 to lastLine - 2 do begin edgeX := edgeLastColumn[y]; if (edgeX > 0) and (edgeX <= lastColumn) then begin linePtr := ImageP(ord4(PicBaseAddr) + (offset * LongInt(y)) + lastColumn - 1); for x:= lastColumn - 1 downto edgeX do begin linePtr^[0] := 45; linePtr := ImageP(ord4(linePtr) - 1); end; end; end; if WasRoi then begin RoiType := RectRoi; RoiRect := SaveRoiRect; MakeRegion; RoiShowing := true; end; UpdateScreen(PicRect); end; SetPort(SavePort); end; procedure TracePackageEdge(h, v: Integer); begin PutMessage('TBD'); end; procedure CreatePackageROI(h, v: Integer); begin PutMessage('TBD'); end; procedure SetParameters(delta, edgeMinStrength: Integer); begin curMinDelta := delta; minEdgeStrength := edgeMinStrength; end; procedure ShowNoCodeMessage; begin PutMessage('Requires user written Think Pascal routine. '); end; procedure DoUserCommand1; begin FindPackageEdge; end; procedure DoUserCommand2; begin ClearOutsidePackage; end; procedure DoUserCommand3; begin TracePackageEdge(0,0); end; procedure DoUserCommand4; begin CreatePackageROI(0,0); end; procedure DoUserCommand5; begin SetParameters(defaultMinDelta, 10); end; procedure DoUserCommand6; begin ShowNoCodeMessage; end; procedure DoUserCommand7; begin ShowNoCodeMessage; end; procedure DoUserCommand8; begin ShowNoCodeMessage; end; procedure DoUserMenuEvent (MenuItem: integer); begin case MenuItem of 1: DoUserCommand1; 2: DoUserCommand2; 3: DoUserCommand3; 4: DoUserCommand4; 5: DoUserCommand5; 6: DoUserCommand6; 7: DoUserCommand7; 8: DoUserCommand8; end; end; procedure OldUserMacroCode (CodeNumber: integer; Param1, Param2, Param3: extended); {Obsolete version kept for backward compatibilty.} begin case CodeNumber of 1: FindPackageEdge; 2: ClearOutsidePackage; 3: TracePackageEdge(trunc(Param1), trunc(Param2)); 4: CreatePackageROI(trunc(Param1), trunc(Param2)); 5: SetParameters(trunc(Param1), trunc(Param2)); 6: DoUserCommand6; 7: DoUserCommand7; 8: DoUserCommand8; otherwise ShowNoCodeMessage; end; end; procedure UserMacroCode (str: str255; Param1, Param2, Param3: extended); var gridFileName: Str255; begin MakeLowerCase(str); if pos('scale', str) <> 0 then begin ScaleToFit; exit(UserMacroCode); end; if pos('findpack', str) <> 0 then begin FindPackageEdge; exit(UserMacroCode); end; if pos('setpara', str) <> 0 then begin SetParameters(trunc(Param1), trunc(Param2)); exit(UserMacroCode); end; if pos('clearoutside', str) <> 0 then begin ClearOutsidePackage; exit(UserMacroCode); end; if pos('tracepack', str) <> 0 then begin TracePackageEdge(trunc(Param1), trunc(Param2)); exit(UserMacroCode); end; if pos('createpack', str) <> 0 then begin CreatePackageROI(trunc(Param1), trunc(Param2)); exit(UserMacroCode); end; ShowNoCodeMessage; end; end.