{from Globals.header} var Raw16Pid, Raw8Pid, RawANDPid, RawB16Pid: integer; RawHeight, RawMaskPid, RawWidth, rawDirID, rawVRefNum: integer; frameType, firstFrame, lastFrame, nextFrame, skipFrame: integer; fore, foredef, cropheight, cropwidth, maskheight: integer; maskwidth, b16Pid, i16Pid, s16Pid, m16Pid: integer; o16Pid, i8Pid, referencePid, smoothPid, markPid: integer; maskPid, mask1Pid, mask2Pid, mask3Pid, dilatePid: integer; flagPid, kernelPid, rbKerPid, xlate16uTo8P, std65535Pid: integer; std8191Pid, customLUTPid, xmax, xmin, ymax: integer; ymin, pack16Pid, packDirID, packMarkPid, packVRefNum: integer; {initialize global variables} begin requiresUser('Pixel16u',2); requiresUser('GetPutPixel',1); requiresUser('timer',1); requiresUser('utilities',1); requiresUser('markup',1); {info about the raw data} Raw16Pid := GetMemo('Raw16Pid'); Raw8Pid := GetMemo('Raw8Pid'); RawANDPid := GetMemo('RawANDPid'); RawB16Pid := GetMemo('RawB16Pid'); RawHeight := GetMemo('RawHeight'); RawMaskPid := GetMemo('RawMaskPid'); RawWidth := GetMemo('RawWidth'); rawDirID := GetMemo('rawDirID'); rawVRefNum := GetMemo('rawVRefNum'); {raw data frame numbers} frameType := GetMemo('frameType'); firstFrame := GetMemo('firstFrame'); lastFrame := GetMemo('lastFrame'); nextFrame := GetMemo('nextFrame'); skipFrame := GetMemo('skipFrame'); {mark color} fore := GetMemo('fore'); foredef := GetMemo('foredef'); {cropped image dimensions} cropheight := GetMemo('cropheight'); cropwidth := GetMemo('cropwidth'); maskheight := GetMemo('maskheight'); maskwidth := GetMemo('maskwidth'); {scratch image pidNumbers} b16Pid := GetMemo('b16Pid'); i16Pid := GetMemo('i16Pid'); s16Pid := GetMemo('s16Pid'); m16Pid := GetMemo('m16Pid'); o16Pid := GetMemo('o16Pid'); i8Pid := GetMemo('i8Pid'); referencePid := GetMemo('referencePid'); smoothPid := GetMemo('smoothPid'); markPid := GetMemo('markPid'); maskPid := GetMemo('maskPid'); mask1Pid := GetMemo('mask1Pid'); mask2Pid := GetMemo('mask2Pid'); mask3Pid := GetMemo('mask3Pid'); dilatePid := GetMemo('dilatePid'); flagPid := GetMemo('flagPid'); {kernel information} kernelPid := GetMemo('kernelPid'); rbKerPid := GetMemo('rbKerPid'); xlate16uTo8P := GetMemo('xlate16uTo8P'); std65535Pid := GetMemo('std65535Pid'); std8191Pid := GetMemo('std8191Pid'); customLUTPid := GetMemo('customLUTPid'); xmax := GetMemo('xmax'); xmin := GetMemo('xmin'); ymax := GetMemo('ymax'); ymin := GetMemo('ymin'); {packed stack info} pack16Pid := GetMemo('pack16Pid'); packDirID := GetMemo('packDirID'); packMarkPid := GetMemo('packMarkPid'); packVRefNum := GetMemo('packVRefNum'); if pidExists(GetMemo('frontPid')) then selectPic(GetMemo('frontPid')); {end from Globals.header} end; macro '[F5] 16 bit arithmetic'; begin SetMemo('frontPid', pidNumber); SelectWindow('16 bit arithmetic'); LoadMacros; end; macro '([F6] Adjust 16 bit LUT'; begin end; macro '[F7] Calculate Intensity'; begin SetMemo('frontPid', pidNumber); SelectWindow('Calculate Intensity'); LoadMacros; end; macro '[F8] Create Kernels'; begin SetMemo('frontPid', pidNumber); SelectWindow('Create Kernels'); LoadMacros; end; macro '[F9] Examine Old 16 bit Stacks'; begin SetMemo('frontPid', pidNumber); SelectWindow('Examine Old 16 bit Stacks'); LoadMacros; end; macro '[F10] Examine Packed 16 bit stack'; begin SetMemo('frontPid', pidNumber); SelectWindow('Examine Packed 16 bit stack'); LoadMacros; end; macro '[F11] Examine Raw Data'; begin SetMemo('frontPid', pidNumber); SelectWindow('Examine Raw Data'); LoadMacros; end; macro '[F12] Front Image Is ...'; begin SetMemo('frontPid', pidNumber); SelectWindow('Front Image Is ...'); LoadMacros; end; macro '(-'; begin end; { Adjust 16 bit LUT macros } macro '[q]Use 65535 LUT -- 16 bits'; begin xlate16uTo8P := std65535Pid; xmin := 0; xmax := 65535; ymin := 1; ymax := 254; SetMemo('xmin', xmin); SetMemo('xmax', xmax); SetMemo('ymin', ymin); SetMemo('ymax', ymax); SetMemo('xlate16uTo8P', xlate16uTo8P); end; macro '[w]Use 8191 LUT -- 13 bits'; begin xlate16uTo8P := std8191Pid; xmin := 0; xmax := 8191; ymin := 1; ymax := 254; SetMemo('xmin', xmin); SetMemo('xmax', xmax); SetMemo('ymin', ymin); SetMemo('ymax', ymax); SetMemo('xlate16uTo8P', xlate16uTo8P); end; macro 'Use Custom LUT'; begin xlate16uTo8P := customLUTPid; SetMemo('xlate16uTo8P', xlate16uTo8P); end; macro 'Front image is 16 to 8 conversion table'; begin xlate16uTo8P := pidNumber; SetMemo('xlate16uTo8P', xlate16uTo8P); end; macro 'Front image is 8 bit image buffer'; begin i8Pid := pidNumber; SetMemo('i8Pid', i8Pid); end; macro 'Front image is 16 bit image buffer'; begin i16Pid := pidNumber; SetMemo('i16Pid', i16Pid); end; macro '-)'; begin end; macro 'Bring 16 to 8 conversion table to front'; begin selectPic(xlate16uTo8P); end; macro 'Bring 8 bit image buffer to front'; begin selectPic(i8Pid); end; macro 'Bring 16 bit image buffer to front'; begin selectPic(i16Pid); end; {16 bit LUT macros} macro '-)'; begin end; {searches for left end of target values} procedure binarySearch; var i, j, v, p: integer; begin i := 32768; j := i div 2; while j > 0 do begin v := getPixVec8(xlate16uTo8P,i); p := getPixVec8(xlate16uTo8P,i-1); if p >= target then begin i := i - j; end else begin if v < target then i := i + j; end; j := j div 2; end; found := i; end; {This is off by one for xmin = 10, xmax = 10000, ymin = 10, ymax = 200} {It gives xmin = 11 and xmax = 10001} procedure analyze16to8; var target, found, swap : integer; begin {figure out parameters that would recreate this LUT} ymin := getPixVec8(xlate16uTo8P,0); SetMemo('ymin', ymin); ymax := getPixVec8(xlate16uTo8P,65535); SetMemo('ymax', ymax); target := ymin+1; binarySearch; xmin := found; SetMemo('xmin', xmin); target := ymin+2; binarySearch; xmin := xmin - (found - xmin); SetMemo('xmin', xmin); target := ymax; binarySearch; xmax := found; SetMemo('xmax', xmax); target := ymax-1; binarySearch; xmax := xmax - (found - xmax); SetMemo('xmax', xmax); if ymin > ymax then begin swap := ymin; ymin := ymax; SetMemo('ymin', ymin); ymax := swap; SetMemo('ymax', ymax); swap := xmin; xmin := xmax; SetMemo('xmin', xmin); xmax := swap; SetMemo('xmax', xmax); end; showMessage('xmin = ',xmin,' xmax = ',xmax,' ymin = ',ymin,' ymax = ',ymax); end; macro 'Front image is 16 to 8 conversion table'; begin xlate16uTo8P := pidNumber; SetMemo('xlate16uTo8P', xlate16uTo8P); analyze16to8; end; macro 'make new 16 to 8 LUT'; var swap: integer; begin RequiresUser('getputpixel', 1); RequiresUser('pixel16u', 1); if (ymin = 0) and (ymax = 0) then begin ymin := 0; SetMemo('ymin', ymin); ymax := 255; SetMemo('ymax', ymax); end; if (xmin = 0) and (xmax = 0) then begin xmin := 0; SetMemo('xmin', xmin); xmax := 65535; SetMemo('xmax', xmax); end; ymin := GetNumber('minimum 8 bit pixel value', ymin); SetMemo('ymin', ymin); ymax := GetNumber('maximum 8 bit pixel value', ymax); SetMemo('ymax', ymax); xmin := GetNumber('minimum 16 bit pixel value', xmin); SetMemo('xmin', xmin); xmax := GetNumber('maximum 16 bit pixel value', xmax); SetMemo('xmax', xmax); SaveState; SetNewSize(256, 256); SetBackgroundColor(0); MakeNewWindow('16 to 8 conversion table'); RestoreState; xlate16uTo8P := pidNumber; SetMemo('xlate16uTo8P', xlate16uTo8P); {xmin and xmax are arbitrary, 0 <= ymin <= ymax <= 255} if ymin > ymax then begin swap := ymin; ymin := ymax; SetMemo('ymin', ymin); ymax := swap; SetMemo('ymax', ymax); swap := xmin; xmin := xmax; SetMemo('xmin', xmin); xmax := swap; SetMemo('xmax', xmax); end; linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); end; procedure limityminmax; begin ymin := round(ymin); if ymin < 0 then ymin := 0; if ymin > 255 then ymin := 255; SetMemo('ymin', ymin); ymax := round(ymax); if ymax < ymin then ymax := ymin; if ymax > 255 then ymax := 255; SetMemo('ymax', ymax); end; macro 'set 8 bit min max to 0 -- 255'; begin ymin := 0; ymax := 255; limityminmax; end; macro 'set 8 bit min max to 1 -- 254'; begin ymin := 1; ymax := 254; limityminmax; end; macro 'set 8 bit min max to arbitrary values'; begin ymin := GetNumber('minimum 8 bit pixel value', ymin); ymax := GetNumber('maximum 8 bit pixel value', ymax); limityminmax; end; macro 'modify 16 to 8 LUT by numbers'; var swap: integer; begin if (xlate16uTo8P = std65535Pid) or (xlate16uTo8P = std8191Pid) then xlate16uTo8P := customLUTPid; limityminmax; {analyze16to8;} xmin := GetNumber('minimum 16 bit pixel value', xmin); SetMemo('xmin', xmin); xmax := GetNumber('maximum 16 bit pixel value', xmax); SetMemo('xmax', xmax); {xmin and xmax are arbitrary, 0 <= ymin <= ymax <= 255} if ymin > ymax then begin putmessage('ymax too small'); exit; {this is never what I really want to do. Make special macro for reversed LUT} swap := ymin; ymin := ymax; SetMemo('ymin', ymin); ymax := swap; SetMemo('ymax', ymax); swap := xmin; xmin := xmax; SetMemo('xmin', xmin); xmax := swap; SetMemo('xmax', xmax); end; linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); showMessage('xmin = ',xmin,' xmax = ',xmax,' ymin = ',ymin,' ymax = ',ymax); end; macro '[e] modify 16 to 8 LUT to enhance ROI'; var i: integer; mean, sigma: real; oldMid, oldRange: integer; begin if (xlate16uTo8P = std65535Pid) or (xlate16uTo8P = std8191Pid) then xlate16uTo8P := customLUTPid; limityminmax; SetOptions('Area,Mean,Std. Dev.'); oldmid := (xmax + xmin) div 2; oldRange := xmax - xmin; measure; mean := rMean[rCount] / 256 * oldRange + xmin; sigma := rStdDev[rCount] / 256 * oldRange; xmin := mean - 2*sigma; xmax := mean + 4*sigma; SetMemo('xmin', xmin); SetMemo('xmax', xmax); linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); showMessage('xmin = ',xmin,' xmax = ',xmax,' ymin = ',ymin,' ymax = ',ymax); end; macro '[-]shift 16 to 8 LUT 10% lower ' var oldMid, newMid, oldRange: integer; begin if (xlate16uTo8P = std65535Pid) or (xlate16uTo8P = std8191Pid) then xlate16uTo8P := customLUTPid; limityminmax; oldMid := (xmax + xmin) div 2; oldRange := xmax - xmin; newMid := oldMid - oldRange / 10.0; if newMid = oldMid then newMid := oldMid - 1; oldRange := oldRange div 2; xmin := newMid - oldRange; xmax := newMid + oldRange; SetMemo('xmin', xmin); SetMemo('xmax', xmax); linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); showMessage('xmin = ',xmin,' xmax = ',xmax,' ymin = ',ymin,' ymax = ',ymax); end; macro '[=]shift 16 to 8 LUT 10% higher ' var oldMid, newMid, oldRange: integer; begin if (xlate16uTo8P = std65535Pid) or (xlate16uTo8P = std8191Pid) then xlate16uTo8P := customLUTPid; limityminmax; oldMid := (xmax + xmin) div 2; oldRange := xmax - xmin; newMid := oldMid + oldRange / 10.0; if newMid = oldMid then newMid := oldMid + 1; oldRange := oldRange div 2; xmin := newMid - oldRange; xmax := newMid + oldRange; SetMemo('xmin', xmin); SetMemo('xmax', xmax); linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); showMessage('xmin = ',xmin,' xmax = ',xmax,' ymin = ',ymin,' ymax = ',ymax); end; macro '[_]narrow 16 to 8 LUT'; var oldMid, oldRange: integer; begin if (xlate16uTo8P = std65535Pid) or (xlate16uTo8P = std8191Pid) then xlate16uTo8P := customLUTPid; limityminmax; oldmid := (xmax + xmin) div 2; oldRange := xmax - xmin; oldRange := oldRange *0.45; xmin := oldmid - oldRange; xmax := oldmid + oldRange; SetMemo('xmin', xmin); SetMemo('xmax', xmax); linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); showMessage('xmin = ',xmin,' xmax = ',xmax,' ymin = ',ymin,' ymax = ',ymax); end; macro '[+]widen 16 to 8 LUT'; var oldMid, oldRange: integer; begin if (xlate16uTo8P = std65535Pid) or (xlate16uTo8P = std8191Pid) then xlate16uTo8P := customLUTPid; limityminmax; oldmid := (xmax + xmin) div 2; oldRange := xmax - xmin; oldRange := oldRange *0.55; if oldRange = 0 then oldRange := 1; xmin := oldmid - oldRange; xmax := oldmid + oldRange; SetMemo('xmin', xmin); SetMemo('xmax', xmax); linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); showMessage('xmin = ',xmin,' xmax = ',xmax,' ymin = ',ymin,' ymax = ',ymax); end; macro 'modify 16 to 8 LUT to match 8 bit LUT'; {will not change ymin or ymax, however} var x8min,x8max,y8min,y8max, i, j, swap: integer; slope8,slope16: real; oldxmin,oldxmax: integer; begin {analyze16to8;} if (xlate16uTo8P = std65535Pid) or (xlate16uTo8P = std8191Pid) then xlate16uTo8P := customLUTPid; y8min := RedLUT[1]; y8max := RedLUT[254]; i := 1; while (RedLUT[i] = y8min) and (i < 255) do i := i + 1; j := i; while (RedLUT[j] = RedLUT[i]) and (j < 255) do j := j + 1; x8min := i - (j - i); if x8min < 0 then x8min := 0; i := 254; while (RedLUT[i] = y8max) and (i > 0) do i := i - 1; j := i; while (RedLUT[j] = RedLUT[i]) and (j > 0) do j := j - 1; x8max := i + (i - j); if x8max > 255 then x8max := 255; y8min := 255 - y8min; y8max := 255 - y8max; slope8 := (y8max - y8min) / (x8max - x8min); slope16 := (ymax - ymin) / (xmax - xmin); oldxmin := xmin; oldxmax := xmax; if x8min > 0 then begin {larger xmin} xmin := xmin + x8min/slope16; SetMemo('xmin', xmin); end; if y8min > 0 then begin {smaller xmin} xmin := xmin - y8min/slope16; SetMemo('xmin', xmin); end; if x8max < 255 then begin {smaller xmax} xmax := xmax - (255-x8max)/slope16; SetMemo('xmax', xmax); end; if y8max < 255 then begin {larger xmax} xmax := xmax + (255-y8max)/slope16; SetMemo('xmax', xmax); end; {xmin and xmax are arbitrary, 0 <= ymin <= ymax <= 255} {note: integers are really reals in this macro language...} xmin := round(xmin); SetMemo('xmin', xmin); xmax := round(xmax); SetMemo('xmax', xmax); if ymin > ymax then begin swap := ymin; ymin := ymax; SetMemo('ymin', ymin); ymax := swap; SetMemo('ymax', ymax); swap := xmin; xmin := xmax; SetMemo('xmin', xmin); xmax := swap; SetMemo('xmax', xmax); end; showMessage('xmin = ',oldxmin,' ',xmin,' xmax = ',oldxmax,' ',xmax,' ymin = ',ymin,' ymax = ',ymax,' x8min = ',x8min,' x8max = ',x8max,' y8min = ',y8min,' y8max = ',y8max,' slope8 = ',slope8:0:4,' slope16 = ',slope16:0:6); linLUT16uto8(xlate16uTo8P, xmin, xmax, ymin, ymax); end; macro '-)'; begin end; macro 'convert front 8 bit image to 16 bits'; var i: integer; inPid, xlatePid, outPid: integer; width, height: integer; begin SaveState; inPid := pidNumber; GetPicSize(width, height); SetNewSize(512, 1); SetBackgroundColor(0); MakeNewWindow('8 to 16 conversion table'); xlatePid := pidNumber; for i := 0 to 255 do putpixel(i * 2, 0, i); MakeRoi(0, 0, 512, 1); SetNewSize(width * 2, height); MakeNewWindow('16 bit image from ', inPid : 0); outPid := pidNumber; RestoreState; Cnvrt8to16u(inPid, xlatePid, outPid); choosePic(xlatePid); Dispose; end; macro '[8]convert front 16 bit image to 8 bits'; var i, j, x, y: integer; inPid, outPid: integer; width, height: integer; min, max: integer; begin RequiresUser('pixel16u', 1); inPid := pidNumber; GetPicSize(width, height); SaveState; ChoosePic(xlate16uTo8P); MakeRoi(0, 0, 256, 256); SetNewSize(width div 2, height); ChoosePic(inPid); MakeNewWindow(GetPicName,'.8'); outPid := pidNumber; RestoreState; MakeRoi(0,0,width div 2, height); Cnvrt16uto8(inPid, xlate16uTo8P, outPid); end;