Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 02:44
    JiangWeian closed #1160
  • 01:34
    JiangWeian opened #1160
  • 01:34
    JiangWeian labeled #1160
  • Feb 24 13:37
    timetogo2 commented #1157
  • Feb 24 11:18
    Jarekw69 commented #1159
  • Feb 24 10:02
    Jarekw69 labeled #1159
  • Feb 24 10:02
    Jarekw69 opened #1159
  • Feb 24 09:10
    JiangWeian closed #1158
  • Feb 24 09:10
    JiangWeian commented #1158
  • Feb 24 09:09
    gofal commented #1158
  • Feb 24 09:08
    gofal commented #1158
  • Feb 24 08:35
    JiangWeian reopened #1158
  • Feb 24 08:35
    JiangWeian closed #1158
  • Feb 24 08:35
    JiangWeian commented #1158
  • Feb 24 08:31
    JiangWeian reopened #1158
  • Feb 24 08:22
    JiangWeian closed #1158
  • Feb 24 08:09
    nguyenvuduc closed #1149
  • Feb 24 08:09
    nguyenvuduc commented #1149
  • Feb 24 07:34
    CountJung commented #1148
  • Feb 24 07:29
    gofal unlabeled #1158
Reinhard Gruber
@gofal
@PelnarPetr_twitter I see, the Clone-method, that takes the transfersyntax as parameter is an extension method in namespace Dicom.Imaging.Codec;
Reinhard Gruber
@gofal
And of course contributing is always welcome! :-)
Reinhard Gruber
@gofal
@r-uhlig you should be more precise. If you have some US miltiframe, then something like that could work: get the DicomPixelData from dataset by var pixelData = DicomPixelData.Create(multiframeDataset, false);, then retrieve the n-th frame like var data = pixelData.GetFrame(n);, then you clone the old dataset and remove the multiframe-pixels with var singleDataset = multiframeDataset.Clone(); singelDataset.Remove(DicomTag.PixelData);. Then you create new pixeldata instance and add the data of the n-th frame there: var singleframePixelData = DicomPixelData.Create(singleDataset, true); singleframePixelData.AddFrame(data); And then you save the new file.
BUT: there are so many other things to consider:
  • your multiframe dataset hat a InstanceUID that has to be uniuqe. if you now create several single frames, then you have to give them new instanceuids each.
  • there can be some other files like presentation states or structured reports referring to the multiframe image and the frame number, those will not work any more after that.
  • if you have some enhanced multiframe image like EnhancedCT, EnhancedMR, BreastThomosynthesisObject or similar, then there are the functional groups, there some per-frame-information is stored within sequences. You would have to extract those and fill then in the new dataset correctly.
So what exactly do you want to do? what kind of multiframe image is it that you want to split up?
arunjoshtech
@arunjoshtech
@gofal . I am using the project to receive images from Modality .While save the it will be converted as JPEGlossy, today When I install package to receive images at a CT machine site, found saved files with RAW images and found following error. The solutions provided to fix the issues is not working. The PC I installed was "Windows 7". Encoding dataset to transfer syntax: JPEG-LS Lossy (Near-Lossless) Image Compression is not supported. See here to get help resolving the reason: https://github.com/fo-dicom/fo-dicom/wiki/Native-codecs-on-.NET
Maher Jendoubi
@MaherJendoubi
@gofal do you plan any investment in using .net5 for fo-dicom :) ?
Reinhard Gruber
@gofal
@MaherJendoubi I have not planed anything special about .net5. fo-dicom 5 is completely netstandard2.0 and will run in net5 without any problems.
r-uhlig
@r-uhlig
@gofal thank you for your answer. I would like to export standard MR images from Enhanced MR Images. The way I see it, I have to move the infos from the shared functional groups sequence (5200,9229), per-frame functional groups sequence (5200,9230), and the pixel data to the single-frame MR image (when possible). After that I have to assign new UIDs and convert/remove all the additional data of the enhanced image. Am I right?
It would be nice to keep the frame number somehow, e.g. by counting up the instance number(?). The single-frame images will not be archived or used clinically afterwards, but should have as much valid information as possible.
SunTai(三台)
@a44281071
how to display dicom image in WPF?
AsWriteableBitmap will create new instance, poor performance.
r-uhlig
@r-uhlig
@a44281071 The images are saved as Base64-encoded byte array of uint16 values in the range of a uint12 (at least in the MR images I know). WPF cannot display this natively, so you have to convert it to a bitmap.
Petr Pelnar
@PelnarPetr_twitter
Hi @gofal and all, I am still troubleshooting the issue with transfer syntax while sending MPEG4 video to PACS. Does anyone has experience with this? Do you know what SOPClassUID should I use, VideoPhotographicImageStorage or SecondaryCaptureImageStorage?
The company creating PACS sais that we are sending data using incorrect syntax "Implicit VR Little Endian", while I am setting the MPEG4AVCH264HighProfileLevel41.
Could this be related to something else not being set correctly, such as SOP Class UID or someting else?
Petr Pelnar
@PelnarPetr_twitter
I have found out that in the association (in the AssociationAccepted events) on both my testing "PACS" and workstation, there are 2 items in the PresentationContexts collection, first of them with the transfer syntax that should be used for the video transfer - "MPEG-4 AVC/H.264 High Profile / Level 4.1", the second one is "Implicit VR Little Endian: Default Transfer Syntax for DICOM". Is this correct, any reason why there should be the second one and not only the first - MPEG-4 AVC/H.264 High Profile / Level 4.1?
Petr Pelnar
@PelnarPetr_twitter
to be more specific, the proposed Presentation Contexts look like this:
Presentation Contexts: 2
Presentation Context: 1 [Proposed]
Abstract Syntax: Secondary Capture Image Storage
Transfer Syntax: MPEG-4 AVC/H.264 High Profile / Level 4.1
Presentation Context: 3 [Proposed]
Abstract Syntax: Secondary Capture Image Storage
Transfer Syntax: Implicit VR Little Endian: Default Transfer Syntax for DICOM
3 replies
Andrew Scott
@adscott1982

can anyone point me in the direction of some learning materials regarding "MaskTag" in private tags?

I am adding private tags to my dataset. In my example file the tag was (nnnn,1001).

I created a private dictionary to parse all the private tags from the example file using tags such as (nnnn,xx01), as per the wiki page: https://github.com/fo-dicom/fo-dicom/wiki/Adding-private-tags-to-dictionary.

This worked fine, but a the time I wasn't quite sure what the purpose of the 'xx' was in the entries. I had to do the same to get my entries working.

Now I am creating private tags, and I have got it working, but the final tag value is (nnnn,0001), but I want it to be the same as my example file e.g. (nnnn,1001).

5 replies
Imaxeon Stellinity
@stellinity_gitlab

Hello all, I am evaluating using fo-dicom in a legacy application. The app is not very DICOM heavy, it has fairly modest needs. It originally used Merge OpenEyes, then introduced a "DicomWrapper" layer to allow use of either OpenEyes or dcmtk (which was in turn given a C# friendly wrapper). In these days of medical device regulations regarding SOUP and OTS software, we have dropped support for OpenEyes (it is quite old and expensive and relied on Microsoft Visual J# which is long dead).

I kind of hate the codebase that we have now, layers of wrappers and cruft, and am debating ripping it all out and just using fo-dicom. To this end, I will be adding fo-dicom as a 3rd implementation under the existing wrapper. This will allow us to learn fo-dicom, selectively enable it for testing and give us a transition period. I have the obvious newbie questions...

#1) Can anyone state that they have fo-dicom being used in "production" systems or in commercial products? This seems like a live community, so I assume it is being used, but had to ask.


#2) And, of course I am immediately feeling stupid as I attempt to do a CEchoRequest... our wrapper returns different failure reasons (bad address/port, bad AE, etc). And I look at the example code for fo-dicom and... the examples only show sending the request, not determining any of the failure reasons... Of course, I see the OnTimeout and OnResponseRecieved delegates, and I see the various exception types... It appears that if I want to know the reason (so that I can communicate it to the person configuring the product's DICOM connecton) I will need to have a fairly long set to catch blocks... and then switch on the Abort/Reject Reasons?

2 replies
Chris Caldwell
@cjcaldwell
So I'm running
for (var i = 0; i < dicomImage.NumberOfFrames; ++i){ using (var renderImage = dicomImage.RenderImage(i)){ //do what I'm doing with the pixel data here } }
and I'm getting quite a lot of images that come to this service throw Offset and count cannot be greater than 0 in EmptyBuffer (Parameter 'offset') on their first .RenderImage call. Any ideas?
9 replies
I'm using fo-dicom.NetCore v4.0.0 in a netcoreapp3.1 project.
It was working well for a long time, then about a month ago it started having these failures. It didn't come back to me until just now so it's a little harder to put my finger on what might have changed.
Imaxeon Stellinity
@stellinity_gitlab
I seem to have successfully added fo-dicom as an alternative implementation for our (very limited) DICOM needs, we can now use OpenEyes, dcmtk, or fo-dicom and things appear to work just fine. Thank you all for a very nicely designed .NET DICOM toolkit!
mail2hjain
@mail2hjain
Hello all, I have a question regarding Specific Character Set handling. What DicomEncoding to use when there are more than one character set mentioned as part of 008,005 attribute? Currently I tried with first non-empty one, but that seems to not work properly for certain languages like korean / japanese. Any help is much appreciated.
1 reply
Imaxeon Stellinity
@stellinity_gitlab
Is there any fo committer who might be interested in a consulting role to add/implement the WG-6 Supplement 168 CA SR? Any work done in fo-dicom would remain with the community of course. I know that there are folks in dcmtk who provide consulting services, just wondering if that is the case for anyone here.
1 reply
Cheryl Rock
@lladioll_gitlab
Hey all, quick question, I wanted to create a way to parse existing SR reports to some text output, is this something fo-dicom can do? I've seen another C++ tool which claims to do a dump, but I haven't tried it yet. I'd prefer to stick with C#. I've seen examples of others creating and sending SR report to DICOM via fo-dicom, but I can't find a way to do it in reverse. Unless I'm fundamentally missing how to transverse the tags properly of the SR report to get measurements etc. Would be great if anyone could confirm this is possible or not and if so, provide maybe some documentation or examples. Thanks!
Reinhard Gruber
@gofal
@lladioll_gitlab Hi, it's easy to parse a SR with fo-dicom. When loading a dicom file, then you have a DicomDataset, which is basically a list of DicomItems. See here some sample code how to recursively traverse a dicomdataset and output every item as text: https://gist.github.com/gofal/0aef12e9edd7c405b49534d608b7c0a5
And I recommend to look at github and search for issues containing "structured report" (also the closed issues), there you will also find quite some code examples regarding reading structured reports.
If performance is not cruical (so if you do not have to parse thousands of files per minute), then you could use the DicomToXml or DicomToJson conversions and do Xml (XPath, Xslt) or Json manipulations to get the desired values or desired output.
Cheryl Rock
@lladioll_gitlab
@gofal Thank you so much for your quick and helpful response! I will definitely try to work with this some more Monday. I figured it was possible with a higher understanding of traversing the structures, I just needed a direction to head in before I go down the wrong rabbit hole. Happy New Year, cheers.
Laredo Tirnanic
@laredoza
Hi, I hope you are all doing well. I've been looking at your worklist scp example and I wonder if you could point me in the correct direction with the following issue:
When OnReceiveAssociationRequestAsync(DicomAssociation association) is called I'm able to identify a network partner device from it's CallingAET. I would like to pass these details to public IEnumerable<DicomCFindResponse> OnCFindRequest(DicomCFindRequest request) as I would like to do different queries bassed on the network device connecting. What would be the best way to do this?
Laredo Tirnanic
@laredoza
I see DicomService has an Association property. Could I use this property? What would happen if you have several calls to the worklist scp at the same time?
Reinhard Gruber
@gofal
@laredoza You found the solution. the DicomService has the Association property. You can access it within any On...Request method. There you will see the AETitle. On every tcp connection to the scp server, the server create a new instance of Association and a new instance of DicomService. Then every communication and callback that happens in this tcp connection ( = within the same association) is injected into the same DicomService instance.
Laredo Tirnanic
@laredoza
Awesome, thanks for the help
katMav
@katMav
Hello, I'm using the DicomFile class to open a dicom series as such: var dicomFile = Dicom.DicomFile.Open(fileName); I don't see any Close or Dispose methods in the DicomFile class API. Do I need to do anything special to free the resources?
Reinhard Gruber
@gofal
@katMav No, you do not have to do anything special. For technical reasons DicomFile cannot dispose resources directly. DicomFile does not hold any resources directly, but it is a wrapper holding many interfaces, and the implementations on these interface depend on the platform build you are using (netframework, mono, netcore, android,...). So you just have to give the DicomFile to the GarbageCollector. This will be better in fo-dicom version 5 (completely built in netstandard2.0) where DicomFile then has direct access to the underlying resources.
One hint I can give you: DicomFile.Open has a optional parameter: FileReadOption. By default the DicomFile does not read large tags but keeps a handle to the open file. This is for performance and memory consumption reasons. Only if these tags are accessed (e.g. when rendering the image) then these are loaded and the file handle is released. If you pass the parameters FileReadOption.ReadAll or FileReadOption.SkipLargeTags, then there will not be a handle to the file and the file is closed immediatelly. With this option you can tell if you either want all the huge tags (when you want to render the image) or if the large tags should be skipped (if you only want to read some values from the header).
1 reply
zhan2016
@zhan2016
Is there a demo or solution to implement a dicom viewer based on fodicom with some overlay functions such as lines, polylines, rectanges and circles? @gofal
Reinhard Gruber
@gofal
@zhan2016 to deal with overlay objects and measurement, then fo-dicom's FrameGeometry class is your friend. But for rendering this and handling mouse and keyboard input etc. I do not have a demo I could give to you. This is all about programming WinForms and WPF objects and is rather out of scope of handling DICOM. Did you take a look at the projects on github that are referencing fo-dicom? There are some viewer belong them, but I do not know if they also have overlays implemented.
CountJung
@CountJung
does fo dicom support DicomTag(0x8, 0x5), "ISO_IR 149" ? if not, will it be updated?
Ali.H
@aria321
Hello all, I am using below snipped code to compress and transfer Dicom file, but I will get Unable to create JPEG Process 1 codec for bits stored == 12, Should I cast it as 16 bit store and then try to change transfer syntax?
var file = DicomFile.Open(@"E:\Reference Line\GHADERMAZI NADIYEH-37 624366\SR 301\IM00001.dcm");
var newFile = file.Clone(DicomTransferSyntax.JPEGProcess1);
newFile.Save(@"E:\Reference Line\GHADERMAZI NADIYEH-37 624366\SR 301\fo-IM00001.dcm");
Joey Meyer
@joeymeyer1986_gitlab

Hello all,
I am trying to save images stored in a .dic file to jpeg or other file formats by looping through a new bitmap built from the height and width of the frames in the .dic file. However I am not sure what to make of the double value I get from the GetPixel method. How would I convert that to a RGB value to use in the SetPixel Method of the Bitmap class from system drawing?

Any assistance is very much appreciated. Thanks!

Current example of what I've tried.
            var file = DicomFile.Open(@"file.dic");

            var patientName = file.Dataset.GetString(DicomTag.PatientName);

            var header = DicomPixelData.Create(file.Dataset);
            var pixelData = PixelDataFactory.Create(header, 0);

            Bitmap bmp = new Bitmap(pixelData.Width, pixelData.Height);

            for (int i = 0; i < pixelData.Width; i++)
            {
                for (int j = 0; j < pixelData.Height; j++)
                {
                    double color = pixelData.GetPixel(i, j);
                    int red = Math.Min((int)(color * 256), 255);
                    int green = Math.Min((int)((color * 256 - red) * 256), 255);
                    int blue = Math.Min((int)(((color * 256 - red) * 256 - green) * 256), 255);
                    Color color2 = Color.FromArgb(red, blue, green);
                    bmp.SetPixel(i, j, color2);
                }
            }

            bmp.Save(patientName+".png", ImageFormat.Jpeg);
Reinhard Gruber
@gofal
@CountJung I am affraid currently not. fo-dicom internally only uses System.Text.Encoding. So every encoding can be supported where there is a corrensponding implementation in .net. See here: https://github.com/fo-dicom/fo-dicom/blob/e2f79d477c84937c69d167e05a4ad860ef2b5daa/DICOM/DicomEncoding.cs#L26
So you should be able to make a pull request easily.
Reinhard Gruber
@gofal
@aria321 transfersyntax JPEGProcess1 (aka JPEG Baseline) only supports 8 bit. There is an other JPEGProcess2_4 (aka JPEG Extended), which is pretty much the same, but this supports 12 bits. You should use JPEGProcess2_4.
18 replies
Reinhard Gruber
@gofal
@joeymeyer1986_gitlab Your code is accessing the raw pixel data. In DICOM the pixel data may be stored in many different formats: there can be color-pixels with 3 bytes per pixel (rgb), most of the time there are grayscale values in 12 bit depth with 2 bytes per pixel, sometimes there are only grayscale values in 8 bit depth with 1 byte per pixel. You have to evaluate some values from DICOM header to get to know how to interpret hte pixel data.
So using the PixelData directly is an option if you pretty much know how to interpret the pixel data. If you "only" want to render the image, then use the rendering engine. Fo-dicom does all this interpretataion for you then. See here: https://github.com/fo-dicom/fo-dicom/wiki/Image-rendering
kchicagualar
@kchicagualar
Hello, I have a Structured Report that I have parsed from XML to .dcm, and now I have to add this report into an existing study in my PACS, I don't understand how to accomplish this, do I have to add it to a dicomdirectory?, create a new serie from the study UID? Thanks in advance...
Reinhard Gruber
@gofal
@kchicagualar the second one is true. Create a new series with the same Patient-Data (0010,*) and the same StudyInstanceUID and the same study-related data, but with a new SeriesInstanceUID and new appropriate series-related data. The dicomdirectory is then later created by a CD burning machine.