private void ReadInlineBinary ( fo.DicomTag tag, fo.DicomVR vr, JsonTextReader reader, fo.DicomDataset dataset, int level ) { if (reader.Read( )) { fo.IO.Buffer.MemoryByteBuffer buffer = null; byte[] data = new byte[0]; string base64 = (string)reader.Value; if (!string.IsNullOrEmpty(base64)) { buffer = new fo.IO.Buffer.MemoryByteBuffer(System.Convert.FromBase64String(base64)); } if (tag == fo.DicomTag.PixelData && level == 0) { dataset.AddOrUpdatePixelData(vr, buffer, fo.DicomTransferSyntax.Parse(TransferSyntaxUID)); } else { dataset.AddOrUpdate <fo.IO.Buffer.IByteBuffer> (vr, tag, buffer); } } }
private void ReadInlineBinary ( DicomTag tag, DicomVR vr, JsonTextReader reader, DicomDataset dataset, int level ) { if (reader.Read( )) { Dicom.IO.Buffer.MemoryByteBuffer buffer = null; string base64 = (string)reader.Value; if (!string.IsNullOrEmpty(base64)) { buffer = new Dicom.IO.Buffer.MemoryByteBuffer(System.Convert.FromBase64String(base64)); } if (tag == DicomTag.PixelData && level == 0) { var pixelData = DicomPixelData.Create(dataset, true); //2nd parameter is true since we are adding new data here pixelData.AddFrame(buffer); } else { dataset.AddOrUpdate <Dicom.IO.Buffer.IByteBuffer> (vr, tag, buffer); } } }
private void AddGreyscaleImage(Bitmap bitmap, int index) { if (_currentFilmBox == null) { throw new InvalidOperationException("Start film box first!"); } if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count) { throw new ArgumentOutOfRangeException("Image box index out of range"); } if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb && bitmap.PixelFormat != PixelFormat.Format32bppRgb ) { throw new ArgumentException("Not supported bitmap format"); } var dataset = new DicomDataset(); dataset.Add <ushort>(DicomTag.Columns, (ushort)bitmap.Width) .Add <ushort>(DicomTag.Rows, (ushort)bitmap.Height) .Add <ushort>(DicomTag.BitsAllocated, 8) .Add <ushort>(DicomTag.BitsStored, 8) .Add <ushort>(DicomTag.HighBit, 7) .Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned) .Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved) .Add <ushort>(DicomTag.SamplesPerPixel, 1) .Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Monochrome2.Value); var pixelData = DicomPixelData.Create(dataset, true); var pixels = GetGreyBytes(bitmap); var buffer = new Dicom.IO.Buffer.MemoryByteBuffer(pixels.Data); pixelData.AddFrame(buffer); var imageBox = _currentFilmBox.BasicImageBoxes[index]; imageBox.ImageSequence = dataset; pixels.Dispose(); }
private void AddGreyscaleImage(Bitmap bitmap, int index) { if (_currentFilmBox == null) { throw new InvalidOperationException("Start film box first!"); } if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count) { throw new ArgumentOutOfRangeException("Image box index out of range"); } if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb && bitmap.PixelFormat != PixelFormat.Format32bppRgb ) { throw new ArgumentException("Not supported bitmap format"); } var dataset = new DicomDataset(); dataset.Add<ushort>(DicomTag.Columns, (ushort)bitmap.Width) .Add<ushort>(DicomTag.Rows, (ushort)bitmap.Height) .Add<ushort>(DicomTag.BitsAllocated, 8) .Add<ushort>(DicomTag.BitsStored, 8) .Add<ushort>(DicomTag.HighBit, 7) .Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned) .Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved) .Add<ushort>(DicomTag.SamplesPerPixel, 1) .Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Monochrome2.Value); var pixelData = DicomPixelData.Create(dataset, true); var pixels = GetGreyBytes(bitmap); var buffer = new Dicom.IO.Buffer.MemoryByteBuffer(pixels.Data); pixelData.AddFrame(buffer); var imageBox = _currentFilmBox.BasicImageBoxes[index]; imageBox.ImageSequence = dataset; pixels.Dispose(); }
string WorkerFunc(Tuple <string, Tuple <int, int, int, int>, List <string> > param, BackgroundWorker worker, DoWorkEventArgs e) { List <string> lFailed = new List <string>(); string strPath = param.Item1; Tuple <int, int, int, int> lCrop = param.Item2; List <string> files = param.Item3; bool bCrop = lCrop.Item1 + lCrop.Item2 + lCrop.Item3 + lCrop.Item4 > 0 ? true : false; DicomUIDGenerator uidGen = new DicomUIDGenerator(); List <Tuple <string, string, string, string> > listDCM = new List <Tuple <string, string, string, string> >(); int i = 0, k = 0; // Randomize input list Random rand = new Random(); // For each spot in the array, pick // a random item to swap into that spot. for (k = 0; k < files.Count - 1; k++) { int j = rand.Next(k, files.Count); string temp = files[k]; files[k] = files[j]; files[j] = temp; } DateTime dt = DateTime.Now; int nSuccess = 0; foreach (string strFile in files) { i++; DicomFile file; try { file = DicomFile.Open(strFile); } catch (Exception ex) { // Transmit message back with worker? lFailed.Add(strFile); System.Diagnostics.Debug.WriteLine(ex.ToString()); continue; } string strOriginalPatientID = ""; try { strOriginalPatientID = file.Dataset.GetValue <string>(DicomTag.PatientID, 0); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } DicomAnonymizer anon = new DicomAnonymizer(); DicomFile fileAnon; try { fileAnon = anon.Anonymize(file); } catch (Exception ex) { // Transmit message back with worker? lFailed.Add(strFile); System.Diagnostics.Debug.WriteLine(ex.ToString()); continue; } DicomTag[] tagsToRemove = { DicomTag.StudyDate, DicomTag.StudyTime, DicomTag.PatientID, DicomTag.StudyID, DicomTag.StudyInstanceUID }; foreach (DicomTag d in tagsToRemove) { try { fileAnon.Dataset.Remove(d); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Error removing element: " + ex.ToString()); } } fileAnon.Dataset.Add(DicomTag.StudyInstanceUID, DicomUID.Generate()); fileAnon.Dataset.Add(DicomTag.StudyDate, dt.Year.ToString("0000") + dt.Month.ToString("00") + dt.Day.ToString("00")); fileAnon.Dataset.Add(DicomTag.StudyTime, dt.Hour.ToString("00") + dt.Minute.ToString("00") + dt.Second.ToString("00")); fileAnon.Dataset.Add(DicomTag.PatientID, i.ToString()); fileAnon.Dataset.Add(DicomTag.StudyID, i.ToString()); string strStudyID = fileAnon.Dataset.GetValue <string>(DicomTag.StudyInstanceUID, 0); try { var header = DicomPixelData.Create(fileAnon.Dataset); var pixelData = PixelDataFactory.Create(header, header.NumberOfFrames - 1); int rows = header.Height; int columns = header.Width; Array a; byte[] result; bool b16bit = false; if (pixelData is GrayscalePixelDataU16) { ushort[] pixels = ((GrayscalePixelDataU16)pixelData).Data; a = pixels; b16bit = true; } else if (pixelData is GrayscalePixelDataS16) { short[] pixels = ((GrayscalePixelDataS16)pixelData).Data; a = pixels; b16bit = true; } else if (pixelData is GrayscalePixelDataU32) { uint[] pixels = ((GrayscalePixelDataU32)pixelData).Data; a = pixels; } else if (pixelData is GrayscalePixelDataS32) { int[] pixels = ((GrayscalePixelDataS32)pixelData).Data; a = pixels; } else if (pixelData is GrayscalePixelDataU8) { byte[] pixels = ((GrayscalePixelDataU8)pixelData).Data; a = pixels; } else { throw new Exception("DICOM image format not supported (this program only supports greyscale)."); } // Can't seem to figure out the byte formatting between 16-bit greyscale DCM versus C#'s 16-bit greyscale. //b16bit = false; if (bCrop) { // Top if (lCrop.Item1 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (columns * lCrop.Item1)); Array.Copy(a, columns * lCrop.Item1, cropped, 0, cropped.Length); a = cropped; rows -= lCrop.Item1; } // Right if (lCrop.Item2 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (rows * lCrop.Item2)); for (k = 0; k < rows; k++) { Array.Copy(a, k * columns, cropped, k * (columns - lCrop.Item2), columns - lCrop.Item2); } a = cropped; columns -= lCrop.Item2; } // Bottom if (lCrop.Item3 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (columns * lCrop.Item3)); Array.Copy(a, 0, cropped, 0, cropped.Length); a = cropped; rows -= lCrop.Item3; } // Left if (lCrop.Item4 > 0) { Array cropped = Array.CreateInstance(a.GetValue(0).GetType(), a.Length - (rows * lCrop.Item4)); for (k = 0; k < rows; k++) { Array.Copy(a, k * columns + lCrop.Item4, cropped, k * (columns - lCrop.Item4), columns - lCrop.Item4); } a = cropped; columns -= lCrop.Item4; } // Now we need to copy the Array "a" into a byte array. // But first! Should we make sure that it's actually a 16-bit array? int nBytes = a.Length * System.Runtime.InteropServices.Marshal.SizeOf(a.GetValue(0)); result = new byte[nBytes]; Buffer.BlockCopy(a, 0, result, 0, nBytes); Dicom.IO.Buffer.MemoryByteBuffer buffer = new Dicom.IO.Buffer.MemoryByteBuffer(result); DicomDataset dataset = new DicomDataset(); dataset = fileAnon.Dataset.Clone(); dataset.AddOrUpdate(DicomTag.Rows, (ushort)rows); dataset.AddOrUpdate(DicomTag.Columns, (ushort)columns); DicomPixelData newPixelData = DicomPixelData.Create(dataset, true); newPixelData.BitsStored = header.BitsStored; newPixelData.SamplesPerPixel = header.SamplesPerPixel; newPixelData.HighBit = header.HighBit; newPixelData.PhotometricInterpretation = header.PhotometricInterpretation; newPixelData.PixelRepresentation = header.PixelRepresentation; newPixelData.PlanarConfiguration = header.PlanarConfiguration; newPixelData.Height = (ushort)rows; newPixelData.Width = (ushort)columns; newPixelData.AddFrame(buffer); fileAnon = new DicomFile(dataset); } // Only do this if it's a 16bit file that we want a 16bit png for if (b16bit) { int nBytes = a.Length * System.Runtime.InteropServices.Marshal.SizeOf(a.GetValue(0)); result = new byte[nBytes]; // If we're using a format that's "16bit" but actually less, scale the values? if (header.BitsStored < header.BitsAllocated) { int nShift = header.BitsAllocated - header.BitsStored; int nFlag = (0x1 << header.BitsStored) - 1; for (k = 0; k < a.Length; k++) { a.SetValue((ushort)(((nFlag - ((ushort)a.GetValue(k) & nFlag)) << nShift) & 0xFFFF), k); } } Buffer.BlockCopy(a, 0, result, 0, nBytes); unsafe { fixed(byte *ptr = result) { using (Bitmap img16 = new Bitmap(columns, rows, 4 * ((2 * columns + 3) / 4), System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, new IntPtr(ptr))) { SaveBmp(img16, strPath + "/Anonymised/" + strStudyID + "-16bitGreyscale.tif"); //img16.Save(strPath + "/Anonymised/" + strStudyID + "-16bitGreyscale.png"); } } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Failed to crop image"); System.Diagnostics.Debug.WriteLine(ex.ToString()); } fileAnon.Save(strPath + "/Anonymised/" + strStudyID + ".dcm"); listDCM.Add(new Tuple <string, string, string, string>(i.ToString(), strStudyID, strFile, strOriginalPatientID)); var img = new DicomImage(strPath + "/Anonymised/" + strStudyID + ".dcm"); // Convert DCM to a 32-bit per pixel (8-bit per each color RGB + 8-bit unused) PNG file try { Dicom.IO.PinnedIntArray px = img.RenderImage().Pixels; int[] pxi = px.Data; byte[] result = new byte[px.ByteSize]; Buffer.BlockCopy(pxi, 0, result, 0, result.Length); unsafe { fixed(byte *ptr = result) { using (Bitmap image = new Bitmap(img.Width, img.Height, img.Width * 4, System.Drawing.Imaging.PixelFormat.Format32bppRgb, new IntPtr(ptr))) { image.Save(strPath + "/Anonymised/" + strStudyID + ".png"); } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } worker.ReportProgress(i * 100 / files.Count); nSuccess++; //Console.WriteLine("Anonymized image " + i + " (of " + nFrames + " frame" + (nFrames == 1 ? "" : "s") + "): " + strFile); } // Create a map file using (System.IO.StreamWriter file = new System.IO.StreamWriter(new FileStream(strPath + "/Anonymised/Map.csv", FileMode.Create, FileAccess.ReadWrite), Encoding.UTF8)) { file.WriteLine("NewPatientID,NewStudyInstanceUID,OriginalFile,OriginalPatientID"); foreach (Tuple <string, string, string, string> line in listDCM) { file.WriteLine(line.Item1 + "," + line.Item2 + "," + line.Item3 + "," + line.Item4); } } string strRet = nSuccess.ToString() + " images successfully anonymised, Map.csv created.\nOutput at:\n" + strPath + "\\Anonymised"; if (lFailed.Count > 0) { strRet += "\nThese files failed to anonymise:"; foreach (string sf in lFailed) { strRet += "\n" + sf; } } return(strRet); }
private void ReadElement ( fo.DicomDataset ds, XElement element, fo.DicomTag tag, fo.DicomVR dicomVr, int level ) { if (dicomVr == fo.DicomVR.PN) { string personNameValue = ""; foreach (var personNameElementValue in element.Elements( ).OrderBy(n => n.Attribute(Constants.ATTRIBUTE_NUMBER))) { foreach (var personNameComponent in personNameElementValue.Elements( )) { if (personNameComponent.Name == Utilities.PersonNameComponents.PN_COMP_ALPHABETIC || personNameComponent.Name == Utilities.PersonNameComponents.PN_COMP_IDEOGRAPHIC || personNameComponent.Name == Utilities.PersonNameComponents.PN_COMP_PHONETIC) { personNameValue = UpdatePersonName(personNameValue, personNameComponent, Utilities.PersonNameParts.PN_Family); personNameValue = UpdatePersonName(personNameValue, personNameComponent, Utilities.PersonNameParts.PN_Given); personNameValue = UpdatePersonName(personNameValue, personNameComponent, Utilities.PersonNameParts.PN_Midlle); personNameValue = UpdatePersonName(personNameValue, personNameComponent, Utilities.PersonNameParts.PN_Prefix); personNameValue = UpdatePersonName(personNameValue, personNameComponent, Utilities.PersonNameParts.PN_Suffix, true); personNameValue = personNameValue.TrimEnd('^'); // extra cleanup personNameValue += "="; } } personNameValue = personNameValue.TrimEnd('='); personNameValue += "\\"; } personNameValue = personNameValue.TrimEnd('\\'); ds.AddOrUpdate <string> (dicomVr, tag, personNameValue); } else if (Utilities.IsBinaryVR(dicomVr)) { var dataElement = element.Elements( ).OfType <XElement> ( ).FirstOrDefault( ); if (null != dataElement) { fo.IO.Buffer.IByteBuffer data; if (dataElement.Name == Constants.ELEMENT_BULKDATA) { string uri = dataElement.Attribute(Constants.ATTRIBUTE_BULKDATAURI).Value; data = new fo.IO.Buffer.BulkDataUriByteBuffer(uri); } else { var base64 = System.Convert.FromBase64String(dataElement.Value); data = new fo.IO.Buffer.MemoryByteBuffer(base64); } if (tag == fo.DicomTag.PixelData && level == 0) { ds.AddOrUpdatePixelData(dicomVr, data, TransferSyntax); } else { ds.AddOrUpdate <fo.IO.Buffer.IByteBuffer> (dicomVr, tag, data); } } } else { var values = ReadValue(element); if (tag == fo.DicomTag.TransferSyntaxUID) { TransferSyntax = fo.DicomTransferSyntax.Parse(values.FirstOrDefault( )); } ds.AddOrUpdate <string> (dicomVr, tag, values.ToArray( )); } }