⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dicom.pas

📁 用Delphi做的读取医学图片的控件及代码
💻 PAS
📖 第 1 页 / 共 5 页
字号:
           lDicomRA[lnImages] := lDicomData;
           lSliceTimeReportedRA[lnImages] := lSliceTimeReported;
        end;
    end; //valid image
  until  ((lINPos+2) >= lLen);
  if (lImageFormatOK) and (lnImages > 0) and lConvertToAnalyze  then begin
     FileMode := 0; //set to readonly
     AssignFile(fp, lFileName);
     Reset(fp, 1);
     lInPos := 1;
     lVolumes := 1;
     lOutputFiles := 1;
     repeat
         if lnImages = 1 then
            lTmpStr := ''
         else
             lTmpStr := '.'+inttostr(lOutputFiles);
         lTmpStr := lTmpStr+'.img';
         lTmpStr := changefileext(lFilename,lTmpStr);
         if not fileexists(lTmpStr) then begin
            AssignFile(lOutFile, lTmpStr);
            Rewrite(lOutFile, 1);
            lVolumes := 1;
            lTimeSlices := 1;
            lOutputSlices := lDicomRA[lInPos].XYZdim[3]; //3rd dimension
            lOutputVolumes := 1; //4th dimension
            lVolumeSz := lDicomRA[lInPos].XYZdim[1]*lDicomRA[lInPos].XYZdim[2]*lDicomRA[lInPos].XYZdim[3]*(lDicomRA[lInPos].Allocbits_per_pixel div 8);
            if lSliceTimeReportedRA[lInPos] then begin //Lipsia saves datasets XYTimeZ, while Analyze is XYZTime, so we need to reorder
                lZSlices := 1;
                lTimeSlices := lDicomRA[lInPos].XYZdim[3];
                lVolumes := lInPos;
                repeat
                      inc(lVolumes);
                until (lVolumes > lnImages) or (not lSliceTimeReportedRA[lVolumes{-1}]);
                lVolumes := lVolumes - lInPos;
                lOutputSlices := lVolumes; //3rd dimension
                lOutputVolumes := lDicomRA[lInPos].XYZdim[3]; //4th dimension
            end else begin
                lZSlices := lDicomRA[lInPos].XYZdim[3];
            end;
            inc(lOutputFiles);
            lImageSz := lDicomRA[lInPos].XYZdim[1]*lDicomRA[lInPos].XYZdim[2]*lZSlices*(lDicomRA[lInPos].Allocbits_per_pixel div 8);
            GetMem( lP, lImageSz );
            l2DSz := lDicomRA[lInPos].XYZdim[1]*lDicomRA[lInPos].XYZdim[2]* (lDicomRA[lInPos].Allocbits_per_pixel div 8);
            lLineLen := lDicomRA[lInPos].XYZdim[1]* (lDicomRA[lInPos].Allocbits_per_pixel div 8);
            lHalfLines := lDicomRA[lInPos].XYZdim[2] div 2;
            GetMem(lLineP,lLineLen);
            for lTimeSlice := 1 to lTimeSlices do begin //read each time series
                for lVolume := 1 to lVolumes do begin  //read from each slice
                    //Read Image Data
                    FileMode := 0; //set read only
                    seek(fp,lDicomRA[lInPos].ImageStart+((lVolume-1)*lVolumeSz)+((lTimeSlice-1)*lImageSz)  );
                    BlockRead(fp, lP^, lImageSz);
                    //Analyze goes Bottom-to-Top, so flip line order
                    for lZSlice := 1 to lZSlices do begin
                        lLowLine := 1+(l2DSz*(lZSlice-1));
                        lHighLine := l2DSz-lLineLen+1+(l2DSz*(lZSlice-1));
                        for lLine := 1 to lHalfLines do begin
                            Move(lP[lLowLine],lLineP^,lLineLen);
                            Move(lP[lHighLine],lP[lLowLine],lLineLen);
                            Move(lLineP^,lP[lHighLine],lLineLen);
                            lLowLine := lLowLine+lLineLen;
                            lHighLine := lHighLine-lLineLen;
                        end;
                    end;
                    //Write Image Data
                    FileMode := 2; //set read/write
                    BlockWrite(lOutFile,lP^,lImageSz);
                end;
            end;
            close(lOutFile);
            //lLine,lHalfLines,lLineLen,
            freemem(lLineP);
            freemem(lP);//
            //Next: write a header...
            Filemode := 2; //1366
            DICOM2AnzHdr(lAnalyzeHdr,lAnonymize,lFilename,lDicomRA[lInPos]);
            lAnalyzeHdr.Dim[3] := lOutputSlices;
            lAnalyzeHdr.Dim[4] := lOutputVolumes;
            lTmpStr := changefileext(lTmpStr,'.hdr');
            if not fileexists(lTmpStr) then begin
               if lDicomRA[lInPos].little_endian <> 1 then
                  SwapBytes(lAnalyzeHdr);
               AssignFile(lOutFile, lTmpStr);
               Rewrite(lOutFile,SizeOf(lAnalyzeHdr));
               BlockWrite(lOutFile,lAnalyzeHdr, 1  {, NumWritten});
               CloseFile(lOutFile);
            end; //Header file named TmpStr does not exist
         end; //Image File named TmpStr does not exist
         lInPos := lInPos + lVolumes;
     until lInPos > lnImages;
     CloseFile(fp);
  end //ConvertToAnalyze
  else if (lImageFormatOK) and (lnImages > 1) then
       showmessage('Note: Only first volume of multivolume image will be displayed. Use MRIcro''s ''Convert Vista/Lipsia to Analyze'' command to see all volumes.');
  lDicomData := lDicomRA[1];
  lDynStr := lDynStr+   'VISTA Format'
    +kCR+ 'XYZ dim: ' +inttostr(lDicomData.XYZdim[1])+'/'+inttostr(lDicomData.XYZdim[2])+'/'+inttostr(lDicomData.XYZdim[3])
     +kCR+'Volumes: ' +inttostr(lDicomData.XYZdim[4])
     +kCR+'Image offset: ' +inttostr(lDicomData.ImageStart)
     +kCR+'XYZ mm: '+floattostrf(lDicomData.XYZmm[1],ffFixed,8,2)+'/'
     +floattostrf(lDicomData.XYZmm[2],ffFixed,8,2)+'/'+floattostrf(lDicomData.XYZmm[3],ffFixed,8,2);
333:
FreeMem( lCharRA);
end; //vista


//afni start
function ParseFileName (lFilewExt:String): string;
var
   lLen,lInc: integer;
   lName: String;
begin
	lName := '';
     lLen := length(lFilewExt);
	lInc := lLen+1;
     if  lLen > 0 then
	   repeat
              dec(lInc);
        until (lFileWExt[lInc] = '.') or (lInc = 1);
     if lInc > 1 then
        for lLen := 1 to (lInc - 1) do
            lName := lName + lFileWExt[lLen]
     else
         lName := lFilewExt; //no extension
        ParseFileName := lName;
end;

procedure read_afni_data(var lDICOMdata: DICOMdata; var lHdrOK, lImageFormatOK: boolean; var lDynStr: string;var lFileName: string; var lRotation1,lRotation2,lRotation3: integer);
//label 333;
const UNIXeoln = chr(10);
kTab = ord(chr(9));
kSpace = ord(' ');
var lTmpStr,lInStr,lUpCaseStr: string;
lHdrEnd: boolean;
lMSBch: char;
lOri : array [1..4] of single;
lTmpInt,lPos,lLen,FileSz,linPos: integer;
fp: file;
lCharRA: bytep;
procedure readAFNIeoln;
begin
  while (linPos < FileSz) and (lCharRA[linPos] <> ord(kCR)) and (lCharRA[linPos] <> ord(UNIXeoln)) do
      inc(linPos);
  inc(lInPos);  //read EOLN
end;
function readAFNIFloat:real;
var lStr: string;
lCh:char;
begin
  lStr := '';
  while (linPos < FileSz) and ((lStr='') or ((lCharRA[lInPos] <> kTab) and (lCharRA[lInPos] <> kSpace))) do begin
        lCh:= chr(lCharRA[linPos]);
        if lCh in ['+','-','e','E','.','0'..'9'] then
           lStr := lStr+lCh;
      inc(linPos);
  end;
  //showmessage(lStr);
  //exit;
  if lStr = '' then exit;
    try
       result := strtofloat(lStr);
    except
          on EConvertError do begin
             showmessage('Unable to convert the string '+lStr+' to a number');
             result := 1;
             exit;
          end;
    end; {except}
  end;
(*function readInterStr:string;
var lStr: string;
begin
  lStr := '';
  While (lPos <= lLen) and (lInStr[lPos] = ' ') do begin
        inc(lPos);
  end;
  While (lPos <= lLen) and (lInStr[lPos] <> ';') do begin
        lStr := lStr+upcase(linStr[lPos]); //zebra upcase
        inc(lPos);
  end;
  result := lStr;
end; //interstr func*)
begin
  lHdrOK := false;
  lImageFormatOK := true;
  Clear_Dicom_Data(lDicomData);
  lDynStr := '';
  lTmpStr := string(StrUpper(PChar(ExtractFileExt(lFileName))));
  if lTmpStr <> '.HEAD' then exit;
  for lInPos := 1 to 3 do
      lOri[lInPos] := -6666;
  FileMode := 0; //set to readonly
  AssignFile(fp, lFileName);
  Reset(fp, 1);
  FileSz := FileSize(fp);
  lHdrEnd := false;
  //lDicomData.ImageStart := FileSz;
  GetMem( lCharRA, FileSz+1 );
  BlockRead(fp, lCharRA^, FileSz, linpos);
  if lInPos <> FileSz then showmessage('Disk error: Unable to read full input file.');
  linPos := 1;
  CloseFile(fp);
  FileMode := 2; //set to read/write
repeat
  linstr := '';
  while (linPos < FileSz) and (lCharRA[linPos] <> ord(kCR)) and (lCharRA[linPos] <> ord(UNIXeoln)) do begin
      lInStr := lInstr + chr(lCharRA[linPos]);
      inc(linPos);
  end;
  inc(lInPos);  //read EOLN
  lLen := length(lInStr);
  lPos := 1;
  lUpcaseStr := '';
  While (lPos <= lLen) do begin
        if lInStr[lPos] in ['_','[',']','(',')','/','+','-','=',{' ',} '0'..'9','a'..'z','A'..'Z'] then
           lUpCaseStr := lUpCaseStr+upcase(linStr[lPos]);
        inc(lPos);
  end;
  inc(lPos); {read equal sign in := statement}
  if lUpCaseStr ='NAME=DATASET_DIMENSIONS'then begin
     lImageFormatOK := true;
     lHdrOK := true;
     lFileName := parsefilename(lFilename)+'.BRIK'; //always UPPERcase
     readAFNIeoln;
     lDICOMdata.XYZdim[1] := round(readAFNIFloat);
     lDICOMdata.XYZdim[2] := round(readAFNIFloat);
     lDICOMdata.XYZdim[3] := round(readAFNIFloat);
     //lDicomData.ImageStart := 2048 * round(readInterFloat);
  end;
  if lUpCaseStr ='NAME=BRICK_FLOAT_FACS'then begin
     readAFNIeoln;
     lDICOMdata.IntenScale :=  readAFNIFloat; //1380 read slope of intensity
  end;
  if lUpCaseStr ='NAME=DATASET_RANK'then begin
     readAFNIeoln;
     //2nd value is number of volumes
     readAFNIFloat;
     lDICOMdata.XYZdim[4] := round(readAFNIFloat);
     //showmessage(inttostr((lDICOMdata.XYZdim[4])));
  end;
  if lUpCaseStr ='NAME=BRICK_TYPES'then begin
     readAFNIeoln;
     lTmpInt := round(readAFNIFloat);
     case lTmpInt of
          0:lDicomData.Allocbits_per_pixel := 8;
          1:begin
                 lDicomData.Allocbits_per_pixel := 16;
                 //lDicomData.MaxIntensity := 65535; //Old AFNI were UNSIGNED, new ones are SIGNED???
          end;
          3:begin
                 lDicomData.Allocbits_per_pixel := 32;
                 lDicomData.Float := true;
          end;
          else begin
              lHdrEnd := true;
              showmessage('Unsupported AFNI BRICK_TYPES: '+inttostr(lTmpInt));
          end;

     end; //case
     {datatype
     0 = byte    (unsigned char; 1 byte)
                1 = short   (2 bytes, signed)
                3 = float   (4 bytes, assumed to be IEEE format)
                5 = complex (8 bytes: real+imaginary parts)}
  end;
  if lUpCaseStr ='NAME=BYTEORDER_STRING'then begin
     readAFNIeoln;
     if ((linPos+2) < FileSz) then begin
      lMSBch := chr(lCharRA[linPos+1]);
      //showmessage(lMSBch);
      if lMSBCh = 'L' then lDicomData.Little_Endian := 1;
      if lMSBCh = 'M' then begin
         lDicomData.Little_Endian := 0;
      end;
      linPos := lInPos + 2;
     end;
     //littleendian
  end;
  if lUpCaseStr ='NAME=ORIGIN'then begin
     readAFNIeoln;
     lOri[1] := (abs(readAFNIFloat));
     lOri[2] := (abs(readAFNIFloat));
     lOri[3] := (abs(readAFNIFloat));
     {     lDICOMdata.XYZori[1] := round(abs(readAFNIFloat));
     lDICOMdata.XYZori[2] := round(abs(readAFNIFloat));
     lDICOMdata.XYZori[3] := round(abs(readAFNIFloat));
}     //Xori,YOri,ZOri
  end;
  if lUpCaseStr ='NAME=DELTA'then begin
     readAFNIeoln;
     lDICOMdata.XYZmm[1] := abs(readAFNIFloat);
     lDICOMdata.XYZmm[2] := abs(readAFNIFloat);
     lDICOMdata.XYZmm[3] := abs(readAFNIFloat);
     //showmessage('xxx');
     //Xmm,Ymm,Zmm
  end;
  if lUpCaseStr ='NAME=ORIENT_SPECIFIC'then begin
     readAFNIeoln;
     lRotation1 := round(readAFNIFloat);
     lRotation2 := round(readAFNIFloat);
     lRotation3 := round(readAFNIFloat);
  end; //ORIENT_SPECIFIC rotation details
  if lInStr <> '' then
     lDynStr := lDynStr + lInStr+kCr;
until (linPos >= FileSz) or (lHdrEnd){EOF(fp)};
lDicomData.Storedbits_per_pixel := lDicomData.Allocbits_per_pixel;
for lInPos := 1 to 3 do begin
    //showmessage(

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -