123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- // Copyright (c) 2012-2020 fo-dicom contributors.
- // Licensed under the Microsoft Public License (MS-PL).
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Windows.Forms;
- using Dicom.IO.Buffer;
- namespace Dicom.Compare
- {
- public partial class MainForm : Form
- {
- private static readonly Color None = Color.Transparent;
- private static readonly Color Green = Color.FromArgb(190, 240, 190);
- private static readonly Color Yellow = Color.FromArgb(255, 255, 217);
- private static readonly Color Red = Color.FromArgb(255, 200, 200);
- private static readonly Color Gray = Color.FromArgb(200, 200, 200);
- private DicomFile _file1;
- private DicomFile _file2;
- private int _level = 0;
- private string _indent = string.Empty;
- public MainForm()
- {
- InitializeComponent();
- }
- private void MainForm_Load(object sender, EventArgs e)
- {
- }
- public int Level
- {
- get => _level;
- set
- {
- _level = value;
- _indent = "".PadRight(_level * 4);
- }
- }
- private void OnClickSelect(object sender, EventArgs e)
- {
- DicomFile file1;
- while (true)
- {
- var ofd = new OpenFileDialog
- {
- Title = "Choose first DICOM file",
- Filter = "DICOM Files (*.dcm;*.dic)|*.dcm;*.dic|All Files (*.*)|*.*"
- };
- if (ofd.ShowDialog(this) == DialogResult.Cancel) return;
- try
- {
- file1 = DicomFile.Open(ofd.FileName);
- break;
- }
- catch (Exception ex)
- {
- MessageBox.Show(
- this,
- ex.Message,
- "Error opening DICOM file",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
- }
- }
- DicomFile file2;
- while (true)
- {
- var ofd = new OpenFileDialog
- {
- Title = "Choose second DICOM file",
- Filter = "DICOM Files (*.dcm;*.dic)|*.dcm;*.dic|All Files (*.*)|*.*"
- };
- if (ofd.ShowDialog(this) == DialogResult.Cancel) return;
- try
- {
- file2 = DicomFile.Open(ofd.FileName);
- break;
- }
- catch (Exception ex)
- {
- MessageBox.Show(
- this,
- ex.Message,
- "Error opening DICOM file",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
- }
- }
- _file1 = file1;
- _file2 = file2;
- lblFile1.Text = _file1.File.Name;
- lblFile2.Text = _file2.File.Name;
- CompareFiles();
- }
- private void CompareFiles()
- {
- Level = 0;
- try
- {
- lvFile1.BeginUpdate();
- lvFile2.BeginUpdate();
- lvFile1.Items.Clear();
- lvFile2.Items.Clear();
- CompareDatasets(_file1.FileMetaInfo, _file2.FileMetaInfo);
- CompareDatasets(_file1.Dataset, _file2.Dataset);
- OnSizeChanged(lvFile1, EventArgs.Empty);
- OnSizeChanged(lvFile2, EventArgs.Empty);
- }
- catch (Exception ex)
- {
- MessageBox.Show(
- this,
- ex.Message,
- "Error comparing DICOM files",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
- }
- finally
- {
- lvFile1.EndUpdate();
- lvFile2.EndUpdate();
- }
- }
- private void CompareDatasets(DicomDataset d1, DicomDataset d2)
- {
- var e1 = new Queue<DicomItem>(d1 ?? new DicomDataset());
- var e2 = new Queue<DicomItem>(d2 ?? new DicomDataset());
- while (e1.Count > 0 || e2.Count > 0)
- {
- DicomItem i1 = null;
- if (e1.Count > 0) i1 = e1.Peek();
- DicomItem i2 = null;
- if (e2.Count > 0) i2 = e2.Peek();
- if (i1 != null && i2 != null)
- {
- if (i1.Tag.Group < i2.Tag.Group)
- {
- AddItem(i1, null);
- e1.Dequeue();
- continue;
- }
- if (i1.Tag.Group == i2.Tag.Group && i1.Tag.Element < i2.Tag.Element)
- {
- AddItem(i1, null);
- e1.Dequeue();
- continue;
- }
- }
- if (i2 != null && i1 != null)
- {
- if (i2.Tag.Group < i1.Tag.Group)
- {
- AddItem(null, i2);
- e2.Dequeue();
- continue;
- }
- if (i2.Tag.Group == i1.Tag.Group && i2.Tag.Element < i1.Tag.Element)
- {
- AddItem(null, i2);
- e2.Dequeue();
- continue;
- }
- }
- AddItem(i1, i2);
- if (i1 != null) e1.Dequeue();
- if (i2 != null) e2.Dequeue();
- }
- }
- private void CompareSequences(DicomSequence s1, DicomSequence s2)
- {
- if (s1 == null)
- {
- AddItem(s1, lvFile1, Gray);
- AddItem(s2, lvFile2, Green);
- }
- else if (s2 == null)
- {
- AddItem(s1, lvFile1, Green);
- AddItem(s2, lvFile2, Gray);
- }
- else
- {
- AddItem(s1, lvFile1, None);
- AddItem(s2, lvFile2, None);
- }
- Level++;
- int count = 0;
- if (s1 != null) count = s1.Items.Count;
- if (s2 != null && s2.Items.Count > count) count = s2.Items.Count;
- for (int i = 0; i < count; i++)
- {
- DicomDataset d1 = null;
- if (s1 != null && i < s1.Items.Count) d1 = s1.Items[i];
- DicomDataset d2 = null;
- if (s2 != null && i < s2.Items.Count) d2 = s2.Items[i];
- if (d1 == null)
- {
- AddItem(string.Empty, uint.MaxValue, string.Empty, lvFile1, Gray);
- AddItem(GetTagName(DicomTag.Item), uint.MaxValue, string.Empty, lvFile2, Green);
- }
- else if (d2 == null)
- {
- AddItem(GetTagName(DicomTag.Item), uint.MaxValue, string.Empty, lvFile1, Green);
- AddItem(string.Empty, uint.MaxValue, string.Empty, lvFile2, Gray);
- }
- else
- {
- AddItem(GetTagName(DicomTag.Item), uint.MaxValue, string.Empty, lvFile1, None);
- AddItem(GetTagName(DicomTag.Item), uint.MaxValue, string.Empty, lvFile2, None);
- }
- Level++;
- CompareDatasets(d1, d2);
- Level--;
- }
- Level--;
- }
- private void CompareFragments(DicomItem i1, DicomItem i2)
- {
- DicomFragmentSequence s1 = null;
- DicomFragmentSequence s2 = null;
- bool pixel = cbIgnorePixelData.Checked && i1.Tag == DicomTag.PixelData;
- if (i1 == null)
- {
- AddItem(i1, lvFile1, Gray);
- AddItem(i2, lvFile2, Green);
- s2 = i2 as DicomFragmentSequence;
- }
- else if (i2 == null)
- {
- AddItem(i1, lvFile1, Green);
- AddItem(i2, lvFile2, Gray);
- s1 = i1 as DicomFragmentSequence;
- }
- else if (!(i1 is DicomFragmentSequence))
- {
- AddItem(i1, lvFile1, pixel ? Yellow : Red);
- AddItem(i2, lvFile2, pixel ? Yellow : Red);
- s2 = i2 as DicomFragmentSequence;
- }
- else if (!(i2 is DicomFragmentSequence))
- {
- AddItem(i1, lvFile1, pixel ? Yellow : Red);
- AddItem(i2, lvFile2, pixel ? Yellow : Red);
- s1 = i1 as DicomFragmentSequence;
- }
- else
- {
- AddItem(i1, lvFile1, pixel ? Yellow : None);
- AddItem(i2, lvFile2, pixel ? Yellow : None);
- s1 = i1 as DicomFragmentSequence;
- s2 = i2 as DicomFragmentSequence;
- }
- Level++;
- if (s1 == null)
- {
- AddItem(string.Empty, uint.MaxValue, string.Empty, lvFile1, Gray);
- AddItem(
- _indent + "Offset Table",
- (uint)s2.OffsetTable.Count * 4,
- string.Format("@entries={0}", s2.OffsetTable.Count),
- lvFile2,
- pixel ? Yellow : Red);
- }
- else if (s2 == null)
- {
- AddItem(
- _indent + "Offset Table",
- (uint)s1.OffsetTable.Count * 4,
- string.Format("@entries={0}", s1.OffsetTable.Count),
- lvFile1,
- pixel ? Yellow : Red);
- AddItem(string.Empty, uint.MaxValue, string.Empty, lvFile2, Gray);
- }
- else
- {
- Color c = None;
- if (s1.OffsetTable.Count != s2.OffsetTable.Count) c = Red;
- else
- {
- for (int i = 0; i < s1.OffsetTable.Count; i++)
- {
- if (s1.OffsetTable[i] != s2.OffsetTable[i])
- {
- c = Red;
- break;
- }
- }
- }
- AddItem(
- _indent + "Offset Table",
- (uint)s2.OffsetTable.Count * 4,
- string.Format("@entries={0}", s1.OffsetTable.Count),
- lvFile1,
- pixel ? Yellow : c);
- AddItem(
- _indent + "Offset Table",
- (uint)s2.OffsetTable.Count * 4,
- string.Format("@entries={0}", s2.OffsetTable.Count),
- lvFile2,
- pixel ? Yellow : c);
- }
- int count = 0;
- if (s1 != null) count = s1.Fragments.Count;
- if (s2 != null && s2.Fragments.Count > count) count = s2.Fragments.Count;
- string name = _indent + "Fragment";
- for (int i = 0; i < count; i++)
- {
- IByteBuffer b1 = null;
- if (s1 != null && i < s1.Fragments.Count) b1 = s1.Fragments[i];
- IByteBuffer b2 = null;
- if (s2 != null && i < s2.Fragments.Count) b2 = s2.Fragments[i];
- if (b1 == null)
- {
- AddItem(string.Empty, uint.MaxValue, string.Empty, lvFile1, Gray);
- AddItem(name, (uint)b2.Size, string.Empty, lvFile2, pixel ? Yellow : Red);
- continue;
- }
- else if (b2 == null)
- {
- AddItem(name, (uint)b1.Size, string.Empty, lvFile1, pixel ? Yellow : Red);
- AddItem(string.Empty, uint.MaxValue, string.Empty, lvFile2, Gray);
- continue;
- }
- Color c = None;
- if (pixel) c = Yellow;
- else if (!Compare(b1.Data, b2.Data)) c = Red;
- AddItem(name, (uint)b1.Size, string.Empty, lvFile1, c);
- AddItem(name, (uint)b2.Size, string.Empty, lvFile2, c);
- }
- Level--;
- }
- private string GetTagName(DicomTag t)
- {
- return string.Format("{0}{1} {2}", _indent, t.ToString().ToUpper(), t.DictionaryEntry.Name);
- }
- private void AddItem(string t, uint l, string v, ListView lv, Color c)
- {
- var lvi = lv.Items.Add(t);
- lvi.SubItems.Add(!string.IsNullOrEmpty(t) ? "--" : string.Empty);
- if (l == uint.MaxValue) lvi.SubItems.Add(!string.IsNullOrEmpty(t) ? "-" : string.Empty);
- else lvi.SubItems.Add(l.ToString());
- lvi.SubItems.Add(v);
- lvi.UseItemStyleForSubItems = true;
- lvi.BackColor = c;
- }
- private void AddItem(DicomItem i, ListView lv, Color c)
- {
- ListViewItem lvi = null;
- if (i != null)
- {
- var tag = GetTagName(i.Tag);
- lvi = lv.Items.Add(tag);
- lvi.SubItems.Add(i.ValueRepresentation.Code);
- if (i is DicomElement)
- {
- var e = i as DicomElement;
- lvi.SubItems.Add(e.Length.ToString());
- string value = "<large value not displayed>";
- if (e.Length <= 2048) value = string.Join("\\", e.Get<string[]>());
- lvi.SubItems.Add(value);
- }
- else
- {
- lvi.SubItems.Add("-");
- lvi.SubItems.Add(string.Empty);
- }
- lvi.Tag = i;
- }
- else
- {
- lvi = lv.Items.Add(string.Empty);
- lvi.SubItems.Add(string.Empty);
- lvi.SubItems.Add(string.Empty);
- lvi.SubItems.Add(string.Empty);
- }
- lvi.UseItemStyleForSubItems = true;
- lvi.BackColor = c;
- }
- private void AddItem(DicomItem i1, DicomItem i2)
- {
- if (i1 is DicomSequence || i2 is DicomSequence)
- {
- CompareSequences(i1 as DicomSequence, i2 as DicomSequence);
- return;
- }
- if (i2 == null)
- {
- AddItem(i1, lvFile1, Green);
- AddItem(i2, lvFile2, Gray);
- return;
- }
- if (i1 == null)
- {
- AddItem(i1, lvFile1, Gray);
- AddItem(i2, lvFile2, Green);
- return;
- }
- if (i1 is DicomElement && i2 is DicomElement)
- {
- var e1 = i1 as DicomElement;
- var e2 = i2 as DicomElement;
- var c = None;
- if (!cbIgnoreVR.Checked && e1.ValueRepresentation != e2.ValueRepresentation) c = Red;
- else if (!Compare(e1.Buffer.Data, e2.Buffer.Data)) c = Red;
- if (cbIgnoreGroupLengths.Checked && e1.Tag.Element == 0x0000) c = Yellow;
- if (cbIgnoreUIDs.Checked && e1.ValueRepresentation == DicomVR.UI)
- {
- var uid = (i1 as DicomElement).Get<DicomUID>(0);
- if (uid != null && (uid.Type == DicomUidType.SOPInstance || uid.Type == DicomUidType.Unknown)) c = Yellow;
- }
- if (cbIgnorePixelData.Checked && i1.Tag == DicomTag.PixelData) c = Yellow;
- AddItem(i1, lvFile1, c);
- AddItem(i2, lvFile2, c);
- return;
- }
- if (i1 is DicomFragmentSequence || i2 is DicomFragmentSequence)
- {
- CompareFragments(i1, i2);
- return;
- }
- if (i1 is DicomElement || i2 is DicomElement)
- {
- AddItem(i1, lvFile1, Red);
- AddItem(i2, lvFile2, Red);
- return;
- }
- AddItem(i1, lvFile1, Yellow);
- AddItem(i2, lvFile2, Yellow);
- }
- private static bool Compare(byte[] b1, byte[] b2)
- {
- if (b1.Length != b2.Length) return false;
- for (int i = 0; i < b1.Length; i++)
- {
- if (b1[i] != b2[i]) return false;
- }
- return true;
- }
- private void OnScroll(object sender, ScrollEventArgs e)
- {
- if (sender == lvFile1)
- {
- int index = lvFile1.TopItem.Index;
- lvFile2.TopItem = lvFile2.Items[index];
- }
- else
- {
- int index = lvFile2.TopItem.Index;
- lvFile1.TopItem = lvFile1.Items[index];
- }
- }
- private void OnSelect(object sender, EventArgs e)
- {
- if (sender == lvFile1)
- {
- if (lvFile1.SelectedIndices.Count > 0)
- {
- int index = lvFile1.SelectedIndices[0];
- lvFile2.Items[index].Selected = true;
- }
- }
- else
- {
- if (lvFile2.SelectedIndices.Count > 0)
- {
- int index = lvFile2.SelectedIndices[0];
- lvFile1.Items[index].Selected = true;
- }
- }
- }
- private void OnMouseEnter(object sender, EventArgs e)
- {
- ((Control)sender).Focus();
- }
- private void OnSizeChanged(object sender, EventArgs e)
- {
- var lv = (ListViewEx)sender;
- var width = lv.Columns[0].Width + lv.Columns[1].Width + lv.Columns[2].Width;
- lv.Columns[3].Width = Math.Max(lv.ClientSize.Width - width, 440);
- }
- private void OnOptionChanged(object sender, EventArgs e)
- {
- int index = -1;
- if (lvFile1.TopItem != null) index = lvFile1.TopItem.Index;
- CompareFiles();
- if (index != -1 && index < lvFile1.Items.Count)
- {
- lvFile1.TopItem = lvFile1.Items[index];
- lvFile2.TopItem = lvFile2.Items[index];
- }
- }
- }
- }
|