{ View Station macros for GE 4.x/5.x MR Images } { } { Eun-Kee Jeong, Ph.D. } { Dept. of Diagnostic Radiology, } { Yonsei Univ. College of Medicine, } { Seoul, Korea 120-752 } { e-mail : ekj@howdy.wustl.edu } { ekj@phya.yonsei.ac.kr } { Put this file on the same level as NIH Image executable } { with the name "Image Macros", then it will be automatically } { loaded when launching NIH Image } { GE MR images will be imported, and the patient information } { and scan parameters are read and written on a separate text } { window with the window name "s'series number'.des". When } { 'import' GE 4.x or 5.x is selected from special menu, one will be } { asked if [m]all images in a series or [s]single image to be read. } { For multiple image import, a series directory should contain } { nothing but images with same format. If it has GE 4.x image } { and, say, a text file in the same directory, and [m] is typed in } { one will see the program keeps trying to read that text as a } { image -- NO GOOD } { And the image(s) will be read and displayed, and another } { box appears and asks if you want to creat a new description } { file, or open an existing description file. } { } { ONE thing I like to do with this macros is to view my personal } { GE MRI data later, and I like to have some way to link this to } { a data base program. I could not figure it out yet. If someone } { knows how or has an idea, please let me know. } VAR {Global variable, initially zero} CharLoc: integer; width,height,FE,PE,depth,offset: Integer; plane,TG,R1,R2,flip,pls: Integer; TR,TI,TE,NmbrEcho,EchoNmbr,ETL,ImgOpt: Integer; Location,Thickness,NEX,FOVx,FOVy: Real; hospital,patientName,ID,coil: String; plnmode,plsmode,plsseq: String; SerName,SerDes,StudyDes: String; AnatomicRef: String; yr,mon,day,hr,min,sec,DayOfWeek: integer; name,ms,NO: String; IValue: Integer; SValue: String; FValue: Real; buffer: String; {global variables FOR Image Fusion} x1,x2,y1,y2,LineWidth,firstAngle,dx,dy: Real; SecondAngle,deltaAngle,ThisAngle,SinA: Real; x,y,ImageToRegister,RegistrationImage: Integer; OrigTop,OrigLeft,OrigWidth,OrigHeight,stage: Integer; Procedure LookUpPls4(n: Integer); BEGIN IF (n = 0) THEN plsmode := 'MEMP'; IF (n = 1) THEN plsmode := 'IR'; IF (n = 2) THEN plsmode := 'PS'; IF (n = 4) THEN plsmode := 'RMGE'; IF (n = 5) THEN plsmode := 'GRE'; IF (n = 6) THEN plsmode := 'VEMP'; IF (n = 7) THEN plsmode := 'MPGR'; IF (n = 13) THEN plsmode := 'SPGR'; IF (n = 17) THEN plsmode := 'FSE'; IF (n = 18) THEN plsmode := 'FVE'; IF (n = 19) THEN plsmode := 'FSPGR'; IF (n = 21) THEN plsmode := 'FMPSPGR'; IF (n = 22) THEN plsmode := 'FMPGR'; END; Procedure LookUpPls5(n: Integer); { reading 5.x } BEGIN IF (n = 0) THEN plsmode := 'SE'; IF (n = 1) THEN plsmode := 'IR'; IF (n = 2) THEN plsmode := 'RM:RM'; IF (n = 3) THEN plsmode := 'RMGE'; IF (n = 4) THEN plsmode := 'GRE:GR'; IF (n = 5) THEN plsmode := 'MPGR'; IF (n = 7) THEN plsmode := 'MPGR'; IF (n = 10) THEN plsmode := 'SPGR'; IF (n = 12) THEN plsmode := 'TF:TOF'; IF (n = 13) THEN plsmode := 'PC'; IF (n = 19) THEN plsmode := 'FSE'; IF (n = 20) THEN plsmode := 'FGR'; IF (n = 21) THEN plsmode := 'FMPGR'; IF (n = 23) THEN plsmode := 'FMPSPGR'; IF (n = 22) THEN plsmode := 'FSPGR'; END; Procedure GetSInt(m,n:Integer); { Read DG 2 Bytes Integer number } BEGIN IValue := GetPixel(m,n)*256 + GetPixel(m+1,n); ShowMessage(IValue); ShowMessage('IVALUE'); END; Procedure GetInt(m,n:Integer); { Read DG 2 Bytes Integer number } BEGIN IValue := GetPixel(m,n)*16777216+GetPixel(m+1,n)*65536+GetPixel(m+2,n)*256+ GetPixel(m+3,n);; END; Procedure ReadString(m,n,l:Integer);{ Read string } VAR kk: Integer; BEGIN SValue := ''; FOR kk := 0 TO l-1 DO BEGIN buffer := chr(GetPixel(m + kk,n)); SValue := concat(SValue,buffer); END; ShowMessage(SValue); END; Procedure GetDGFloat(m,n:Integer);{ Read DG floating point number } VAR exponent,mantissa: Real; k,pow: Integer; BEGIN pow := 1; mantissa := GetPixel(m+1,n)*65536+GetPixel(m+2,n)*256+GetPixel(m+3,n); exponent := GetPixel(m,n) - 64; FOR k := 1 TO exponent DO BEGIN pow := pow * 16; END; FValue := mantissa * Pow/16777216; END; Procedure GetSUNFloat(m,n:Integer);{ Read SUN floating point number } VAR exponent,mantissa: Real; k,pow,tmp,sign: Integer; BEGIN pow := 1; sign := 1; tmp := GetPixel(m,n); IF ( tmp > 127 ) THEN BEGIN exponent := 2 * (tmp - 128 ) -127; sign := -1; END ELSE exponent := 2*tmp -127; tmp := GetPixel(m+1,n); IF ( tmp > 127 ) THEN BEGIN mantissa := (tmp-128)*65536+GetPixel(m+2,n)*256+GetPixel(m+3,n); exponent := exponent + 1; END ELSE mantissa := GetPixel(m+1,n)*65536+GetPixel(m+2,n)*256+GetPixel(m+3,n); FOR k := 1 TO exponent DO BEGIN pow := pow * 2; END; FValue := sign * (1 + mantissa/8388608) * Pow; END; Procedure CheckForSelection; VAR x1,y1,x2,y2,LineWidth:integer; BEGIN GetRoi(RoiLeft,RoiTop,RoiWidth,RoiHeight); GetLine(x1,y1,x2,y2,LineWidth); IF (RoiWidth=0) or (x1>=0) THEN BEGIN PutMessage('Please make a rectangular selection.'); exit; END; END; Procedure CropAndScale(fast:Boolean; angle:Real); VAR i,NewWidth: Integer; width,height: Integer; RoiLeft,RoiTop,RoiWidth,RoiHeight: Integer; ScaleFactor: Real; OneToOne: Boolean; BEGIN CheckForSelection; SaveState; GetPicSize(width,height); ScaleFactor:= GetNumber('Scale factor(0.05..25):',1.0); OneToOne:=ScaleFactor=1.0; NewWidth:=round(RoiWidth*ScaleFactor); IF odd(NewWidth) THEN BEGIN NewWidth:=NewWidth-1; ScaleFactor:=NewWidth/RoiWidth; END; SetNewSize(RoiWidth*ScaleFactor,RoiHeight*ScaleFactor); IF NOT OneToOne THEN BEGIN IF fast THEN SetScaling('Nearest; Creat New Window') ELSE SetScaling('Bilinear; Creat New Window'); END; FOR i:= 1 TO nPics DO BEGIN SelectPic(i); RestoreROI; IF OneToOne AND (angle=0.0) THEN Duplicate('Temp') ELSE ScaleAndRotate(ScaleFactor,ScaleFactor,angle); SetPicName(i); END; RestoreState; END; END; macro '[4] Input GE 4.x MRI'; {Import GE MR image and scan/patient header: Written by EKJ - March 1995 } VAR TR,TE: real; date,study,image,series,age,sex: String; i,j: Integer; BEGIN RequiresVersion(1.56); patientName := ''; study := ''; hospital := ''; ID := ''; image := ''; series := ''; coil := ''; date := ''; plnmode := ''; plsmode := ''; plsseq := ''; age := ''; sex := ''; SerDes := ''; StudyDes := ''; SerName := ''; AnatomicRef := ''; SetImport('8-bit'); SetCustom(512,6,3072); Import(''); ReadString(446,0,32); hospital := SValue; ReadString(108,0,32); patientName := SValue; ReadString(78,0,9); date := SValue; ReadString(140,0,12); ID := SValue; ReadString(262,0,61); StudyDes := SValue; ReadString(104,2,120); SerDes := SValue; ReadString(228,2,16); coil := SValue; ReadString(410,2,12); plsseq := SValue; ReadString(64,0,5); study := SValue; ReadString(62,2,3); series := SValue; ReadString(88,4,4); image := SValue; ReadString(156,0,3); age := SValue; sex := chr( GetPixel(160,0) ); plane := GetPixel(277,2); IF (plane = 0) THEN plnmode := 'Axial'; IF (plane = 1) THEN plnmode := 'Sagittal'; IF (plane = 2) THEN plnmode := 'Coronal'; IF (plane = 3) THEN plnmode := 'Oblique'; pls := GetPixel(299,2); LookUpPls4(pls); GetDGFloat(164,4); TR := FValue/1000; GetDGFloat(172,4); TE := FValue/1000; GetDGFloat(302,2); FOVx := FValue; GetDGFloat(154,4); Thickness := FValue; GetDGFloat(146,4); Location := FValue; { Get NEX value } NEX := GetPixel(203,4); IF (NEX = 0) THEN BEGIN GetSUNFloat(292,4); NEX := FValue; END; GetSInt(398,2); FE := IValue; GetSInt(400,2); PE := IValue; GetSInt(402,2); width := IValue; height := width; SetScale(width/FOVx,'mm'); GetSInt(350,4); flip := IValue; GetSInt(324,4); TG := IValue; GetSInt(58,5); R1 := IValue; GetSInt(60,5); R2 := IValue; Dispose; {Dispose header image} Beep; ms := ''; ms := GetString('Single/Multi Image?(s/m) ','m'); IF ( ms = 'm' ) THEN BEGIN SetImport('16-bit Unsigned,Calibrate,OpenAll'); SerName := concat('s',series,'.des') END ELSE IF ( ms = 's' ) THEN BEGIN SetImport('16-bit Unsigned,Calibrate'); SerName := concat('s',series,'/i',image,'.des') END; offset:=14336; SetCustom(width,height,offset); Import(''); TileWindows; Beep; Beep; NO := ''; NO := GetString('NEW/OLD Des. File ?(n/o) ','n'); IF (NO = 'n') THEN BEGIN NewTextWindow(SerName,200,400); GetTime(yr,mon,day,hr,min,sec,DayOfWeek); SelectWindow(SerName); SetFont('Monaco'); SetFontSize(9); MoveWindow(480,40); Writeln(patientName); Writeln(date); Writeln('Pat ID = ',ID); Writeln('Study = ',study); Writeln('Age/Sex = ',age,sex); Writeln('Study Des.: ',StudyDes); Writeln('Ser.Des.: ',SerDes); Writeln('AnatomicRef :',AnatomicRef); Writeln('Scan matix = ',FE:3,'x',PE:3,'/ ',NEX:1:2,'NEX'); IF ( ms = 's' ) THEN Writeln('Series/image = ',series:3,'/',image:3) ELSE IF ( ms = 'm' ) THEN Writeln('Series/image = ',series:3); Writeln('RF coil = ',coil); Writeln('Plane type = ',plnmode); Writeln('Pulse seq. = ',plsmode,' ',plsseq); Writeln('FOV =',FOVx,' mm'); Writeln('Thickness = ',Thickness:2:1,'mm'); Writeln('Location = ',Location:3:1,'mm'); Writeln('R1/R2/TG = ',R1:1,'/',R2:2,'/',TG:3); Writeln('Flip angle = ',flip:2); Writeln('TR/TE = ',TR:2:1,'/',TE:2:1,' msec'); Writeln(''); Writeln('======= COMMENT ========'); Writeln('Date: ',yr-1900:2,'-',mon:1,'-',day:2) END { Record GE MR header } ELSE Open(SerName); END;{ Import GE 4.x MRI } macro '[5] Input GE 5.x MR,CT'; {ImportsGE MR images: Written by EKJ - May 1995 } VAR TR,TE,study,series,image,date,age,sex: Integer; MF: String; i,j,HdrOffset: Integer; StudyPtr,SerPtr,ImgPtr: Integer; BEGIN RequiresVersion(1.56); patientName := ''; hospital := ''; ID := ''; coil := ''; date := ''; MF := ''; plnmode := ''; plsmode := ''; plsseq := ''; SerDes := ''; StudyDes := ''; SerName := ''; AnatomicRef := ''; SetImport('8-bit'); SetCustom(156,1,0); Import(''); GetInt(4,0); offset := IValue; GetInt(8,0); width := IValue; GetInt(12,0); height := IValue; GetInt(16,0); depth := IValue; GetInt(132,0); StudyPtr := IValue; GetInt(140,0); SerPtr := IValue; GetInt(148,0); ImgPtr := IValue; HdrOffset := StudyPtr; Dispose;{ Dispose Control header } SetImport('8-bit'); SetCustom(511,6,HdrOffset);{ Read MR parameters } Import(''); GetSInt(8,0); study := IValue; ReadString(10,0,33); hospital := SValue; ReadString(84,0,13); ID := SValue; ReadString(97,0,25); patientName := SValue; GetSInt(122,0); age := IValue; GetSInt(126,0); sex := IValue; IF ( sex = 1 ) THEN MF := 'M' ELSE IF ( sex = 2 ) THEN MF := 'F'; { GetInt(208,0); date := IValue;} GetInt(15,4); date := IValue; ReadString(282,0,23); StudyDes := SValue; GetSInt(12,2); Series := IValue; ReadString(22,2,30); SerDes := SValue; ReadString(86,2,3); AnatomicRef := SValue; GetSInt(12,4); Image := IValue; GetSUNFloat(26,4); Thickness := FValue; GetSInt(30,4); FE := IValue; GetSInt(32,4); PE := IValue; GetSUNFloat(34,4); FOVx := FValue; GetSUNFloat(38,4); FOVy := FValue; GetSUNFloat(125,4); Location := FValue; GetInt(194,4); TR := IValue/1000; GetInt(198,4); TI := IValue/1000; GetInt(202,4); TE := IValue/1000; GetSInt(210,4); NmbrEcho := IValue;{ Number of Echoes } GetSInt(212,4); EchoNmbr := IValue;{ Echo Number } GetSUNFloat(218,4); NEX := FValue; GetSInt(248,4); TG := IValue; GetSInt(250,4); R1 := IValue; GetSInt(252,4); R2 := IValue; GetSInt(254,4); flip := IValue; GetInt(300,4); ImgOpt := IValue; GetSInt(304,4); pls := IValue; LookUpPls5(pls); { ReadString(308,4,33); plsseq := SValue;} ReadString(362,4,17); coil := SValue; GetSInt(129,5); ETL := IValue; { For FSE } GetSInt(114,4); plane := IValue; IF (plane = 0) THEN plnmode := 'Axial'; IF (plane = 1) THEN plnmode := 'Sagittal'; IF (plane = 2) THEN plnmode := 'Coronal'; IF (plane = 3) THEN plnmode := 'Oblique'; SetScale(width/FOVx,'mm'); Dispose; {Dispose header image} Beep; ms := ''; ms := GetString('Single/Multi Image?(s/m) ','m'); IF ( ms = 'm' ) THEN BEGIN SetImport('16-bit Unsigned,Calibrate,OpenAll'); SerName := concat('s',series,'.des') END ELSE IF ( ms = 's' ) THEN BEGIN SetImport('16-bit Unsigned,Calibrate'); SerName := concat('s',series,'/i',image,'.des') END; SetCustom(width,height,offset); Import(''); TileWindows; Beep; Beep; NO := ''; NO := GetString('NEW/OLD Des. File ?(n/o) ','n'); IF (NO = 'n') THEN BEGIN NewTextWindow(SerName,200,440); GetTime(yr,mon,day,hr,min,sec,DayOfWeek); SelectWindow(SerName); SetFont('Monaco'); SetFontSize(9); MoveWindow(440,40); Writeln(patientName); Writeln('Exam. Date : ',date); Writeln('Pat ID = ',ID); Writeln('Study = ',study); Writeln('Age/Sex = ',age,MF); Writeln('Study Des.: ',StudyDes); Writeln('Ser.Des.: ',SerDes); Writeln('AnatomicRef :',AnatomicRef); Writeln('Image Option.: ',ImgOpt); Writeln(''); Writeln('Scan matix = ',FE:3,'x',PE:3,'/ ',NEX:1:2,'NEX'); IF ( ms = 's' ) THEN Writeln('Series/image = ',series:2,'/',image:2) ELSE IF ( ms = 'm' ) THEN Writeln('Series/image = ',series:3); Writeln('RF coil = ',coil); Writeln('Plane type = ',plnmode); Writeln('Pulse seq. = ',plsmode); Writeln('FOVx/FOVy =',FOVx,'/',FOVy,' mm'); Writeln('Thickness = ',Thickness:2:1,'mm'); Writeln('Location = ',Location:3:1,'mm'); Writeln('R1/R2/TG = ',R1:1,'/',R2:2,'/',TG:3); Writeln('Flip angle = ',flip:2); Writeln('TR/TE = ',TR:2:1,'/',TE:2:1,' msec'); Writeln('Echo #/# of Echoes = ',EchoNmbr,'/',NmbrEcho); Writeln(''); Writeln('======= COMMENT ========'); Writeln('Date: ',yr-1900:2,'-',mon:1,'-',day:2) END { Record GE MR header } ELSE Open(SerName); END;{ Import GE 5.x MRI } macro '[D] Dispose All Images'; VAR i: integer; BEGIN DisposeAll; END; macro '[F] CropScale-FastÉ'; BEGIN CropAndScale(true, 0); TileWindows; EnhanceContrast; END; macro '[S] CropScale-SmoothÉ'; BEGIN CropAndScale(false, 0); TileWindows; EnhanceContrast; END;