[update 24 March 2023: Latest releases of HRZ software can be found on HRZ website - www.hrzkit.com]
The little code that do the trick follows.
img = new DCXIMG();
img.LoadFile(dcmfile.Text);
Size imageSize = new Size(img.width, img.Height); // Known size.
// Set bitmap known image's metadata.
bitmap = new Bitmap(imageSize.Width, imageSize.Height, imagePixelFormat);
// Prepare working rectangle.
wholeBitmap = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
// Lock all bitmap's pixels.
bitmapData = bitmap.LockBits(wholeBitmap, ImageLockMode.WriteOnly, imagePixelFormat);
img.GetBitmap(0, bitmapData.Stride * bitmapData.Height, (uint)bitmapData.Scan0);
bitmap.UnlockBits(bitmapData);
pictureBox1.Image = bitmap;
Now you can play with it a bit more, for example by adding window center and window width handlers to the mouse move events. Before, you should keep somewhere the initial values, as here we have two members called center and width and we also need to keep a boolean for mouseDown and two more integers for lastX and lastY:
img.GetWindow(out center, out width);
And then the mouse handlers can be something like this:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
lastX = e.X;
lastY = e.Y;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (mouseDown && img != null)
{
int diffX = e.X - lastX;
int diffY = e.Y - lastY;
width += diffX;
center += diffY;
if (width < 0)
width = 0;
if (width > 65536)
width = 65536;
if (center < 0)
center = 0;
if (center > 65536)
center = 65536;
img.SetWindow(center, width);
bitmapData = bitmap.LockBits(wholeBitmap, ImageLockMode.WriteOnly, imagePixelFormat);
img.GetBitmap(0, bitmapData.Stride * bitmapData.Height, (uint)bitmapData.Scan0);
bitmap.UnlockBits(bitmapData);
pictureBox1.Image = bitmap;
lastX = e.X;
lastY = e.Y;
}
}
}
That's a simplified version, of course, just to get the idea. One last advise is to call ScaleImage just before if you are dealing with mammograms because they are some big to fit into the screen anyway and then your response times will be much much faster.
And now for the subject. Looking back into this blog I see that the very first post that looked a bit like DICOM Tutorial dealt exactly with this subject when RZDCX 1.0.1.4 was released so long ago but this is a good subject and questions keeps coming so it's worth dealing with it again.
You have a bunch of files and you want to know if they are DICOM or not? One way is to call DCXOBJ.openFile and see if it passes but that may be too much for your needs as you don't really want to read the files, just know if they are DICOM or not. If your'e on Windows you probably think of checking the suffix, ha? So it's not ".dcm" and even if it is, so what? the dcm or DCM or whatever suffix is all but standard. If you're unix i.e. everything else that is not windows you'll be looking for magic number and it's in bytes 128-131. A DICOM file should start with a preamble: 128 0x0 bytes and then the 4 bytes with characters 'DICM' (ASCII) and there you go. Of course by accident you may fall on a file that has "DICM"there that is not a DICOM file so if you want to add extra security to that you can go the extra mile and check the next two bytes that should be the group 0002 of the file meta info and check that bytes 128-133 of the file are 0x44 0x49 0x43 0x4D 0x02 0x00. I would fill quite confident that it is a DICOM file if there's a match. If you're still in doubt, you can go all the way up to the UL characters of the group 0002 length and even two bytes beyond that that should always be 0x04 0x00 but not further then this as the header length value is the first thing to change from file to file. Matching the 12 bytes from 128-139 is defiantly good though it will perform slower then just matching just the 4 bytes of 128-131 using a single call to compare an int with the constant 0x4D434944.
Identifying a DICOM file using bytes 128-131 |
There's also the case of DICOM files that does not have the preamble and file meta information though this becomes very rare and it's not standard. In this case you have no better way then trying to parse it. Most likely it will start with 0x08 0x00 for group 0008 element but that's only a heuristic.
I came here hoping to learn what MATLAB meant by FileMetaInformationVersion = [0;1].
ReplyDeleteIts very simple. This is the value that should be set to this tag. It has never changed. If at some point the standard specifications for the DICOM File Meta Header are going to change, then I guess this will be used but for now the first tag in every DICOM file (after the group length of group 0002) is (0002,0001) OB 00\01
DeleteOn the example of the simplified version it is much easier to understand the meaning of the program and figure out how it works in practice.
ReplyDelete