/// <summary>Anonymizes a Dicom file (dataset + metadata)</summary> /// <param name="file">The file containing the dataset to be altered</param> public DicomFile Anonymize(DicomFile file) { file = file ?? throw new ArgumentNullException(nameof(file)); var transferSyntax = file.FileMetaInfo.Contains(DicomTag.TransferSyntaxUID) ? file.FileMetaInfo.TransferSyntax : null; var m = _mode; if (m == Mode.clone) { file = file.Clone(); m = Mode.inplace; } var ds = DoAnonymization(file.Dataset, new Stack <TagOrIndex>(), m); if (file.FileMetaInfo != null) { file = new DicomFile(ds); file.FileMetaInfo.ImplementationVersionName = ""; file.FileMetaInfo.SourceApplicationEntityTitle = ""; if (transferSyntax != null) { file.FileMetaInfo.AddOrUpdate(DicomTag.TransferSyntaxUID, transferSyntax); } } return(file); }
public void EncodeDecodeRLE16() { var files = Directory.GetFiles(@"Test Data"); foreach (var testFile in files) { try { var myOriginalDicomFilePath = testFile; DicomFile myOriginalDicomFile = DicomFile.Open(myOriginalDicomFilePath); DicomFile myNewFile = myOriginalDicomFile.Clone(DicomTransferSyntax.RLELossless); DicomFile myResFile = myNewFile.Clone(myOriginalDicomFile.Dataset.InternalTransferSyntax); // Supporting 16bit encoded images var myBitsAllocated = myResFile.Dataset.GetSingleValue <ushort>(DicomTag.BitsAllocated); if (myBitsAllocated == 16) { byte[] myOriginalBytes = DicomPixelData.Create(myOriginalDicomFile.Dataset).GetFrame(0).Data; byte[] myResBytes = DicomPixelData.Create(myResFile.Dataset).GetFrame(0).Data; if (!myOriginalBytes.SequenceEqual(myResBytes)) { // Number of different bytes int myDiffCount = myResBytes.Where((inT, inI) => inT != myOriginalBytes[inI]).Count(); Assert.Equal(0, myDiffCount); Trace.WriteLine("Diff count " + myDiffCount); // Run through all image for (var myIndex = 0; myIndex < myOriginalBytes.Length; myIndex += 2) { // Get Pixel value from Original image byte myOriginalByte1 = myOriginalBytes[myIndex]; byte myOrginalByte2 = myOriginalBytes[myIndex + 1]; ushort myOriginalPixelValue = BitConverter.ToUInt16(new byte[] { myOriginalByte1, myOrginalByte2 }, 0); // Get Pixel value from RoundTrip image byte myResByte1 = myResBytes[myIndex]; byte myResByte2 = myResBytes[myIndex + 1]; ushort myResPixelValue = BitConverter.ToUInt16(new byte[] { myResByte1, myResByte2 }, 0); // If Value are different if (myOriginalPixelValue != myResPixelValue) { Trace.Write("Diff:" + Math.Abs(myOriginalPixelValue - myResPixelValue)); Trace.Write( $" Original Value: {myOriginalPixelValue} ({myOriginalByte1}, {myOrginalByte2})"); Trace.WriteLine($" Res Value: {myResPixelValue} ({myResByte1}, {myResByte2})"); break; } } } } } catch (Exception) { // ignore } } }
public void AddFile(string FileName) { if (!File.Exists(FileName) || !DicomFile.HasValidHeader(FileName)) { return; } DicomFile dcmFile = DicomFile.Open(FileName); DicomFile tmpFile = dcmFile.Clone(); var item = tmpFile.Dataset.Get <DicomItem>(DicomTag.PixelData); if (item == null) { return; } DicomImage dcmImage = new DicomImage(tmpFile.Dataset); _frame = dcmFile.Dataset.Get(DicomTag.NumberOfFrames, 0);//如果该字段不存在,则默认值为1 // Image img = dcmImage.RenderImage(0); Image img = ZoomPicture(dcmImage.RenderImage(0), 150, 150); img = SetIconInfo(img, _frame, m_IconList.Count); DicomIcon icon = new DicomIcon(); icon.m_Img = img; icon.m_FileName = FileName; icon.m_DicomFile = dcmFile; icon.m_DicomImage = dcmImage; m_IconList.Add(icon); }
public static List <string> ExtractMultiframes2Singleframe(string src) { List <string> destFiles = new List <string>(); DicomFile dcmFile = DicomFile.Open(src); DicomDataset dcmDataset = dcmFile.Dataset; int frames = dcmFile.Dataset.Get <int>(DicomTag.NumberOfFrames); if (frames > 1) { for (int i = 0; i < frames; ++i) { try { DicomFile tmpFile = dcmFile.Clone(); string seriesiuid = tmpFile.Dataset.Get <string>(DicomTag.SeriesInstanceUID, "1.2.3.4.5.6.7.8.9.2234"); tmpFile.Dataset.Remove(new DicomTag[] { DicomTag.InstanceNumber, DicomTag.NumberOfFrames, DicomTag.SOPInstanceUID, DicomTag.PixelData }); tmpFile.Dataset.Add <int>(DicomTag.NumberOfFrames, 1); tmpFile.Dataset.Add <string>(DicomTag.SOPInstanceUID, string.Format("{0}.{1}", seriesiuid, i)); tmpFile.Dataset.Add <int>(DicomTag.InstanceNumber, i + 1); IByteBuffer pixelData = ExtractSingleFrame(dcmDataset, i); CreateAndAddPixelData(tmpFile.Dataset, pixelData); string srcName = Path.GetFileName(src); string tmpFileName = string.Format(@"{2}linkingmed.{1}.frame{0}.dcm", i, srcName.Split('.')[0], Path.GetTempPath()); tmpFile.Save(tmpFileName); destFiles.Add(tmpFileName); } catch (Exception e) { Console.WriteLine(string.Format("Errors:{0},Details:{1}", e.Message + e.StackTrace)); } } } return(destFiles); }
/// <summary> /// returns dicomFile in the content type given by finalContentType in a HttpResponseMessage. /// If content type is dicom, transfer syntax must be set to the given transferSyntax parameter. /// </summary> /// <param name="dicomFile"></param> /// <param name="finalContentType"></param> /// <param name="transferSyntax"></param> /// <returns></returns> private HttpResponseMessage ReturnImageAsHttpResponse(DicomFile dicomFile, string finalContentType, string transferSyntax) { MediaTypeHeaderValue header = null; Stream streamContent = null; if (finalContentType == JpegImageContentType) { DicomImage image = new DicomImage(dicomFile.Dataset); Bitmap bmp = image.RenderImage(0).As <Bitmap>(); //When an image/jpeg MIME type is returned, the image shall be encoded using the JPEG baseline lossy 8 //bit Huffman encoded non-hierarchical non-sequential process ISO/IEC 10918. //TODO Is it the case with default Jpeg format from Bitmap? header = new MediaTypeHeaderValue(JpegImageContentType); streamContent = new MemoryStream(); bmp.Save(streamContent, ImageFormat.Jpeg); streamContent.Seek(0, SeekOrigin.Begin); } else if (finalContentType == AppDicomContentType) { //By default, the transfer syntax shall be //"Explicit VR Little Endian". //Note: This implies that retrieved images are sent un-compressed by default. DicomTransferSyntax requestedTransferSyntax = DicomTransferSyntax.ExplicitVRLittleEndian; if (transferSyntax != null) { requestedTransferSyntax = GetTransferSyntaxFromString(transferSyntax); } bool transferSyntaxIsTheSameAsSourceFile = dicomFile.FileMetaInfo.TransferSyntax == requestedTransferSyntax; //we only change transfer syntax if we need to DicomFile dicomFileToStream; if (!transferSyntaxIsTheSameAsSourceFile) { dicomFileToStream = dicomFile.Clone(requestedTransferSyntax); } else { dicomFileToStream = dicomFile; } header = new MediaTypeHeaderValue(AppDicomContentType); streamContent = new MemoryStream(); dicomFileToStream.Save(streamContent); streamContent.Seek(0, SeekOrigin.Begin); } var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(streamContent) }; result.Content.Headers.ContentType = header; return(result); }
public IList <TestInstanceInfo> Save(string destDir, string filenamePrefix, DicomTransferSyntax transferSyntax, int instancesToGenerate = 1, string sopClassUid = "1.2.840.10008.5.1.4.1.1.11.1") { Console.Write("Generating test files."); if (!Directory.Exists(destDir)) { Directory.CreateDirectory(destDir); } var dataset = new DicomDataset(); baseDataset.CopyTo(dataset); dataset.AddOrUpdate(DicomTag.SOPClassUID, sopClassUid); var dicomFile = new DicomFile(dataset); if (transferSyntax != dicomFile.Dataset.InternalTransferSyntax) { var transcoder = new DicomTranscoder(dicomFile.Dataset.InternalTransferSyntax, transferSyntax, outputCodecParams: new DicomJpegParams() { Quality = 100, ConvertColorspaceToRGB = true }); dicomFile = transcoder.Transcode(dicomFile); } var instancesCreated = new List <TestInstanceInfo>(); for (int i = 0; i < instancesToGenerate; i++) { Console.Write("."); var sopInstanceUid = DicomUIDGenerator.GenerateDerivedFromUUID(); var filePath = Path.Combine(destDir, $"{filenamePrefix}-{i:00000}.dcm"); dicomFile.Dataset.AddOrUpdate(DicomTag.SOPInstanceUID, sopInstanceUid); dicomFile.FileMetaInfo.AddOrUpdate(DicomTag.MediaStorageSOPInstanceUID, sopInstanceUid); dicomFile.FileMetaInfo.AddOrUpdate(DicomTag.MediaStorageSOPClassUID, sopClassUid); dicomFile.Clone().Save(filePath); instancesCreated.Add(new TestInstanceInfo { PatientId = dicomFile.Dataset.GetSingleValue <string>(DicomTag.PatientID), StudyInstanceUid = dicomFile.Dataset.GetSingleValue <string>(DicomTag.StudyInstanceUID), SeriesInstanceUid = dicomFile.Dataset.GetSingleValue <string>(DicomTag.SeriesInstanceUID), SopInstanceUid = dicomFile.Dataset.GetSingleValue <string>(DicomTag.SOPInstanceUID), FilePath = filePath }); } Console.WriteLine("."); return(instancesCreated); }
private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { if (listView1.SelectedItems.Count > 0) { DicomFile dcmFile = new DicomFile(); dcmFile = ((DicomIcon)(e.Item.Tag)).m_DicomFile; int frames = dcmFile.Dataset.Get(DicomTag.NumberOfFrames, 0);//如果该字段不存在,则默认值为1 DicomFile tmpFile = dcmFile.Clone(); DicomImage dcmSingleImg = new DicomImage(tmpFile.Dataset); Image img = dcmSingleImg.RenderImage(0); Image process_img = ZoomPicture(img, pictureBox_Display.Width, pictureBox_Display.Height); pictureBox_Display.Image = process_img; _image = dcmSingleImg; dcmFile.Dataset.Get(DicomTag.NumberOfFrames, 0); _grayscale = !_image.PhotometricInterpretation.IsColor; if (_grayscale) { _windowWidth = _image.WindowWidth; _windowCenter = _image.WindowCenter; } int nRate = GetFrameRate(dcmSingleImg);//设置默认播放速度 numericUpDown1.Value = nRate; ushort group = ushort.Parse("0028", System.Globalization.NumberStyles.HexNumber); ushort element = ushort.Parse("0008", System.Globalization.NumberStyles.HexNumber); int frame_count = Convert.ToInt16(_image.Dataset.Get <string>(new DicomTag(group, element)));//设置进度条 trackBar1.Maximum = frame_count; StartPlay();//开启播放 } if (radiobtn1.Checked) //设置标签 { ShowDicomInfo(false); } else { ShowDicomInfo(true); } }
private void insertFrame() { try { var result = bmDialog.ShowDialog(); if (result == DialogResult.OK) { var bitmap = new Bitmap(bmDialog.FileName); if (bitmap.Width != img.Width || bitmap.Height != img.Height) { result = MessageBox.Show($"The size of selected image is not matched with current frame sequence, continue inserting?\nImage source: {bitmap.Width}x{bitmap.Height}\nFrame sequence: {img.Width}x{img.Height}", PROGRAM_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { result = MessageBox.Show("Scale image to fit the frame sequence?\nIf choose no, the frame will looks strange.", PROGRAM_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { bitmap = ImageUtil.ResizeImage(bitmap, img.Width, img.Height); } } else { return; } } byte[] pixels = ImageUtil.GetPixels(bitmap); //TODO: very bad perfomance, needs improvement var fileDecode = file.Clone(DicomTransferSyntax.ExplicitVRLittleEndian); var pixelData = DicomPixelData.Create(fileDecode.Dataset); var buffer = new MemoryByteBuffer(pixels); pixelData.AddFrame(buffer); file = fileDecode.Clone(file.Dataset.InternalTransferSyntax); initImage(); initFrameList(); } } catch (Exception) { MessageBox.Show("Image invaild, insertion failed.", PROGRAM_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// returns dicomFile in the content type given by finalContentType in a HttpResponseMessage. /// If content type is dicom, transfer syntax must be set to the given transferSyntax parameter. /// </summary> /// <param name="dicomFile"></param> /// <param name="finalContentType"></param> /// <param name="transferSyntax"></param> /// <param name="frameIndex"></param> /// <returns></returns> private ActionResult ReturnImageAsHttpResponse(DicomFile dicomFile, string finalContentType, string transferSyntax, int frameIndex) { MediaTypeHeaderValue header = null; Stream streamContent = null; if (finalContentType == JpegImageContentType) { DicomImage image = new DicomImage(dicomFile.Dataset); Bitmap bmp = image.RenderImage(frameIndex).As <Bitmap>(); //When an image/jpeg MIME type is returned, the image shall be encoded using the JPEG baseline lossy 8 //bit Huffman encoded non-hierarchical non-sequential process ISO/IEC 10918. //TODO Is it the case with default Jpeg format from Bitmap? header = new MediaTypeHeaderValue(JpegImageContentType); streamContent = new MemoryStream(); bmp.Save(streamContent, ImageFormat.Jpeg); streamContent.Seek(0, SeekOrigin.Begin); } else if (finalContentType == AppDicomContentType) { //By default, the transfer syntax shall be //"Explicit VR Little Endian". //Note: This implies that retrieved images are sent un-compressed by default. //DicomTransferSyntax requestedTransferSyntax = DicomTransferSyntax.JPEG2000Lossless; DicomTransferSyntax requestedTransferSyntax = DicomTransferSyntax.ExplicitVRLittleEndian; if (transferSyntax != null) { requestedTransferSyntax = GetTransferSyntaxFromString(transferSyntax); } bool transferSyntaxIsTheSameAsSourceFile = dicomFile.FileMetaInfo.TransferSyntax == requestedTransferSyntax; //we only change transfer syntax if we need to DicomFile dicomFileToStream; if (!transferSyntaxIsTheSameAsSourceFile) { dicomFileToStream = dicomFile.Clone(requestedTransferSyntax); } else { dicomFileToStream = dicomFile; } // Check if this is a multiframe image int numberOfFrame = 1; dicomFileToStream.Dataset.TryGetValue <int>(DicomTag.NumberOfFrames, 0, out numberOfFrame); if (numberOfFrame > 1) { // This is a multiframe image, only return the speicify frame var bytesImage = DicomPixelData.Create(dicomFileToStream.Dataset).GetFrame(frameIndex).Data; dicomFileToStream.Dataset.AddOrUpdatePixelData(DicomVR.OB, new Dicom.IO.Buffer.MemoryByteBuffer(bytesImage)); } else { // This must be a single frame image Debug.Assert(frameIndex == 0); } header = new MediaTypeHeaderValue(AppDicomContentType); streamContent = new MemoryStream(); dicomFileToStream.Save(streamContent); streamContent.Seek(0, SeekOrigin.Begin); } //HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); //result.Content = new StreamContent(streamContent); //result.Content.Headers.ContentType = header; //Response.ContentType = header; return(File(streamContent, AppDicomContentType));; }
private void ChangeSyntax(DicomTransferSyntax syntax, DicomCodecParams param = null) { var file = _file.Clone(syntax, param); OpenFile(file); }
void ExtractMultiframes2Singleframe(object o) { float nPercent = 0; ConvertProcessEventArgs ev = new ConvertProcessEventArgs(0); JpegFileList.Clear(); if (!File.Exists(SourceFileName)) { return; } DicomFile dcmFile = DicomFile.Open(SourceFileName); DicomDataset dcmDataset = dcmFile.Dataset; int frames = dcmFile.Dataset.Get <int>(DicomTag.NumberOfFrames); if (frames == 0) { frames = 1; } string srcName = Path.GetFileName(SourceFileName); string tmpPath = AppDomain.CurrentDomain.BaseDirectory + "tmpframe\\"; if (!Directory.Exists(tmpPath)) { Directory.CreateDirectory(tmpPath); } else { DeleteDir(tmpPath); } for (int i = 0; i < frames; i++) { try { DicomFile tmpFile = dcmFile.Clone(); string sopinstanceuid = tmpFile.Dataset.Get <string>(DicomTag.SOPInstanceUID, ""); DicomImage dcmSingleImg = new DicomImage(tmpFile.Dataset); Image img = dcmSingleImg.RenderImage(i); string tmpJpgName = string.Format(sopinstanceuid + "-{0}.jpg", i.ToString().PadLeft(5, '0'), tmpPath); tmpJpgName = tmpPath + tmpJpgName; if (img != null) { img.Save(tmpJpgName); } JpegFileList.Add(tmpJpgName); nPercent = (i + 1.0f) / frames * 100; string s = nPercent.ToString(("#.##")); callback(nPercent); Thread.Sleep(1); } catch (Exception e) { //MessageBox.Show(string.Format("Errors:{0},Details:{1}", e.Message + e.StackTrace)); } ev.Percent = 100; } }
void ConvertDicom2AVIFormat(object o) { float nPercent = 0; ConvertProcessEventArgs ev = new ConvertProcessEventArgs(0); #region 多帧文件存在 if (File.Exists(strMultiFrameDicomFileName)) { AVIWriter aviWriter = new AVIWriter(); DicomFile dcmFile = DicomFile.Open(strMultiFrameDicomFileName); dcmFile.Dataset.Get <string>(DicomTag.SOPInstanceUID, ""); int bmWidth = Convert.ToInt16(dcmFile.Dataset.Get <string>(DicomTag.Columns, "")); int bmHeight = Convert.ToInt16(dcmFile.Dataset.Get <string>(DicomTag.Rows, "")); string strDestFile = strOutPutAVIName; aviWriter.Create(strDestFile, (UInt16)nFrs, bmWidth, bmHeight); try { for (int i = nBeginFrame; i < nEndFrame; i++) { DicomFile tmpFile = dcmFile.Clone(); DicomImage dcmSingleImg = new DicomImage(tmpFile.Dataset); Image img = dcmSingleImg.RenderImage(i); Bitmap bmp = new Bitmap(img); bmp.RotateFlip(RotateFlipType.Rotate180FlipX); aviWriter.LoadFrame(bmp); aviWriter.AddFrame(); if (nEndFrame == 0) { nEndFrame = Convert.ToInt16(dcmFile.Dataset.Get <string>(DicomTag.NumberOfFrames, "")); } float f = (float)100 / (float)nEndFrame - nBeginFrame; nPercent += f; string s = nPercent.ToString(("#.##")); ev.LastPercent = ev.Percent; ev.Percent = Convert.ToSingle(s); callback(nPercent); Thread.Sleep(1); } } catch (Exception e) { MessageBox.Show(e.ToString()); } finally { aviWriter.Close(); } } #endregion #region 单帧文件列表存在 if (listSingleFrameFileName.Count > 0) { AVIWriter aviWriter = new AVIWriter(); DicomFile tmp_dcmFile = DicomFile.Open(listSingleFrameFileName[0]); int bmWidth = Convert.ToInt16(tmp_dcmFile.Dataset.Get <string>(DicomTag.Columns, "")); int bmHeight = Convert.ToInt16(tmp_dcmFile.Dataset.Get <string>(DicomTag.Rows, "")); string strDestFile = strOutPutAVIName; aviWriter.Create(strDestFile, (UInt16)nFrs, bmWidth, bmHeight); try { for (int i = 0; i < listSingleFrameFileName.Count; i++) { tmp_dcmFile = DicomFile.Open(listSingleFrameFileName[0]); DicomFile tmpFile = tmp_dcmFile.Clone(); DicomImage dcmSingleImg = new DicomImage(tmpFile.Dataset); Image img = dcmSingleImg.RenderImage(0); Bitmap bmp = new Bitmap(img); bmp.RotateFlip(RotateFlipType.Rotate180FlipX); aviWriter.LoadFrame(bmp); aviWriter.AddFrame(); float f = (float)100 / (float)listSingleFrameFileName.Count; nPercent += f; string s = nPercent.ToString(("#.##")); ev.LastPercent = ev.Percent; ev.Percent = Convert.ToSingle(s); callback(nPercent); Thread.Sleep(1); } } catch (Exception e) { MessageBox.Show(e.ToString()); } finally { aviWriter.Close(); } #endregion } ev.Percent = 100; }
/// <summary> /// Convert single file to a set of files acording the number of frames /// </summary> /// <param name="filePath"></param> /// <param name="outRoot"></param> static void ConvertFile(string fileFullName, string outRoot) { try { Console.WriteLine("Reading file: " + fileFullName); DicomFile file = DicomFile.Open(fileFullName); ushort nframes = file.Dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, (ushort)1); // If file ocoursanally has only one frame we copy it with new name according to converter policy. if (nframes <= 1) { Console.WriteLine("Copying"); var fname = outRoot + CreateImageFileName(file); CreatePathToFileIfNeeded(fname); file.Save(fname); } else { Console.WriteLine("Converting"); // // The most Important part !!! // // Here is going multiframe file spliting logic. // We copy all dicom tags from original file except that we know in advance decribse frames. // Than we add image position, orientation and number, taken from frames description sequences. // Than we replace pixel data with particular frame. // // Clone dicom object, which we will use as a template var templateObject = file.Clone(); // Base for instance uids var mediaSopInstUid = file.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty); var sopInstUid = file.Dataset.GetSingleValueOrDefault(DicomTag.SOPInstanceUID, string.Empty); // One frame in output templateObject.Dataset.AddOrUpdate(DicomTag.NumberOfFrames, 1); // Sequence with data to copy to output image if (!file.Dataset.TryGetSequence(DicomTag.PerFrameFunctionalGroupsSequence, out DicomSequence mfseq)) { throw new ApplicationException("Shared Functional Groups Sequence (0x5200, 0x9230) is expected to get sencitive information"); } // Remove multiframe Shared Functional Groups Sequence templateObject.Dataset.Remove(DicomTag.PerFrameFunctionalGroupsSequence); // Original file pixel data var oldPixelData = DicomPixelData.Create(file.Dataset, false); // Frames iteration for (ushort i = 0; i < nframes; i++) { // Instance UID is formed from original file plus dot and frame number templateObject.FileMetaInfo.AddOrUpdate(DicomTag.MediaStorageSOPInstanceUID, mediaSopInstUid + '.' + i.ToString()); templateObject.Dataset.AddOrUpdate(DicomTag.SOPInstanceUID, sopInstUid + '.' + i.ToString()); templateObject.Dataset.AddOrUpdate(DicomTag.InstanceNumber, i + 1); // Technical information var sqitem = mfseq.Items[i]; foreach (var element in sqitem) { if (element.ValueRepresentation == DicomVR.SQ) { var sq = element as DicomSequence; foreach (var ds in sq) { ds.CopyTo(templateObject.Dataset); } } else { templateObject.Dataset.AddOrUpdate(element); } } // Pixel data var pixelData = DicomPixelData.Create(templateObject.Dataset, true); var framepixels = oldPixelData.GetFrame(i); pixelData.AddFrame(framepixels); // Save to file var fname = outRoot + CreateImageFileName(templateObject); CreatePathToFileIfNeeded(fname); templateObject.Save(fname); } } } catch (Exception e) { Console.WriteLine("Error in processing file: " + fileFullName + " / " + e.Message); } }