Exemplo n.º 1
0
            /// <summary>
            /// Gets pixel data in normalized form (8 or 16-bit grayscale, or ARGB).
            /// </summary>
            /// <returns></returns>
            /// <remarks>
            /// <i>Normalized</i> pixel data means that:
            /// <list type="Bullet">
            /// <item>
            /// <description>Grayscale pixel data has embedded overlays removed and each pixel value
            /// is padded so that it can be cast directly to the appropriate type (e.g. byte, sbyte, ushort, short).</description>
            /// </item>
            /// <item>
            /// <description>Colour pixel data is always converted into ARGB format.</description>
            /// </item>
            /// <item>
            /// <description>Pixel data is always uncompressed.</description>
            /// </item>
            /// </list>
            /// <para>
            /// Ensuring that the pixel data always meets the above criteria
            /// allows clients to easily consume pixel data without having
            /// to worry about the the multitude of DICOM photometric interpretations
            /// and transfer syntaxes.
            /// </para>
            /// <para>
            /// Pixel data is reloaded when this method is called after a
            /// call to <see cref="ISopFrameData.Unload"/>.
            /// </para>
            /// </remarks>
            public override byte[] GetNormalizedPixelData()
            {
                _largeObjectContainerData.UpdateLastAccessTime();

                byte[] pixelData = _pixelData;
                if (pixelData == null)
                {
                    lock (this.SyncLock)
                    {
                        pixelData = _pixelData;
                        if (pixelData == null)
                        {
                            pixelData = _pixelData = CreateNormalizedPixelData();
                            if (pixelData != null)
                            {
                                //Platform.Log(LogLevel.Debug, "Created pixel data of length {0}", pixelData.Length);
                                UpdateLargeObjectInfo();
                                MemoryManager.Add(this);
                                Diagnostics.OnLargeObjectAllocated(pixelData.Length);
                            }
                        }
                    }
                }

                return(pixelData);
            }
Exemplo n.º 2
0
            /// <summary>
            /// Gets the normalized overlay data buffer for a particular overlay group (8-bit grayscale).
            /// </summary>
            /// <remarks>
            /// <para>
            /// <i>Normalized</i> overlay data means that the 1-bit overlay pixel data is extracted and
            /// unpacked as necessary to form an 8-bit-per-pixel buffer with values of either 0 or 255.
            /// </para>
            /// <para>
            /// Ensuring that the overlay data always meets the above criteria allows clients to easily
            /// consume overlay data without having to worry about the storage of overlay data, whether
            /// embedded in unused bits of the pixel data or in a separate packed bits buffer.
            /// </para>
            /// <para>
            /// Overlay data is reloaded when this method is called after a call to <see cref="ISopFrameData.Unload"/>.
            /// The pixel data will also be reloaded if this method is called before
            /// <see cref="ISopFrameData.GetNormalizedPixelData"/> and there are overlays stored in unused bits of the
            /// pixel data.
            /// </para>
            /// </remarks>
            /// <param name="overlayNumber">The 1-based overlay plane number.</param>
            /// <returns>A byte buffer containing the normalized overlay pixel data.</returns>
            /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="overlayNumber"/> is not a positive non-zero number.</exception>
            public override byte[] GetNormalizedOverlayData(int overlayNumber)
            {
                _largeObjectContainerData.UpdateLastAccessTime();

                if (overlayNumber < 1)
                {
                    throw new ArgumentOutOfRangeException("overlayNumber", overlayNumber, "Overlay number must be a positive, non-zero number.");
                }

                lock (SyncLock)
                {
                    byte[] data;
                    if (!_overlayData.TryGetValue(overlayNumber, out data) || data == null)
                    {
                        _overlayData[overlayNumber] = data = CreateNormalizedOverlayData(overlayNumber);
                        if (data != null)
                        {
                            UpdateLargeObjectInfo();
                            MemoryManager.Add(this);
                            Diagnostics.OnLargeObjectAllocated(data.Length);
                        }
                    }

                    return(data);
                }
            }
            private byte[] GetPixelData()
            {
                _largeObjectData.UpdateLastAccessTime();

                byte[] buffer = _buffer;
                if (buffer != null)
                {
                    return(buffer);
                }

                lock (_syncLock)
                {
                    buffer = _buffer;
                    if (buffer == null)
                    {
                        buffer = _buffer = CreateShutter(_key);
                        _largeObjectData.BytesHeldCount   = buffer.Length;
                        _largeObjectData.LargeObjectCount = 1;
                        MemoryManager.Add(this);

                        //Trace.WriteLine(String.Format("Loading: {0}", _key), "Memory");
                        //Trace.WriteLine("", "Memory");
                    }
                }

                return(buffer);
            }
Exemplo n.º 4
0
            public IComposedLut GetLut(LutCollection sourceLuts)
            {
                IComposedLut lut = _realComposedLut;

                if (lut != null)
                {
                    return(lut);
                }

                lock (_syncLock)
                {
                    if (_realComposedLut != null)
                    {
                        return(_realComposedLut);
                    }

                    //Trace.WriteLine(String.Format("Creating Composed Lut '{0}'", Key), "LUT");

                    _realComposedLut = new ComposedLut(sourceLuts, _bufferCache);
                    //just use the creation time as the "last access time", otherwise it can get expensive when called in a tight loop.
                    _largeObjectData.UpdateLastAccessTime();
                    _largeObjectData.BytesHeldCount   = _realComposedLut.Data.Length * sizeof(int);
                    _largeObjectData.LargeObjectCount = 1;
                    MemoryManager.Add(this);
                    Diagnostics.OnLargeObjectAllocated(_largeObjectData.BytesHeldCount);

                    return(_realComposedLut);
                }
            }
Exemplo n.º 5
0
        //TODO (CR Sept 2010): CreatePixelData?
        private byte[] LoadPixelData()
        {
            // wait for synchronized access
            lock (_syncPixelDataLock)
            {
                // if the data is now available, return it immediately
                // (i.e. we were blocked because we were already reading the data)
                if (_overlayPixelData != null)
                {
                    return(_overlayPixelData);
                }

                // load the pixel data
                _overlayPixelData = _overlayDataReference.FusionOverlayData.GetOverlay(_baseFrameReference.Frame, out _overlayFrameParams);

                // update our stats
                _largeObjectData.BytesHeldCount   = _overlayPixelData.Length;
                _largeObjectData.LargeObjectCount = 1;
                _largeObjectData.UpdateLastAccessTime();

                // regenerating the volume data is easy when the source frames are already in memory!
                _largeObjectData.RegenerationCost = RegenerationCost.Low;

                // register with memory manager
                MemoryManager.Add(this);

                return(_overlayPixelData);
            }
        }
Exemplo n.º 6
0
            public LargeObject(byte[] bytes)
            {
                _bytes = bytes;
                _data  = new LargeObjectContainerData(Guid.NewGuid())
                {
                    BytesHeldCount   = _bytes.Length,
                    LargeObjectCount = 1,
                    RegenerationCost = RegenerationCost.Low
                };
                _data.UpdateLastAccessTime();

                MemoryManager.Add(this);
            }
Exemplo n.º 7
0
        private VolumeData LoadVolume(IBackgroundTaskContext context)
        {
            // TODO (CR Apr 2013): Ideally, loading and unloading could be done with minimal locking; this way,
            // Unload actually has to wait for Load to finish and vice versa. I think a quicker way would be to
            // have a _loading field - have this method set it inside the lock, then proceed to do the load,
            // then set the _volume field when done. Have Unload check _loading and just return, otherwise set _volume to null.
            // Basically, you don't need to lock the entire load operation - you only need to guarantee that multiple loads
            // can't occur at once, and that Unload actually unloads it.

            // wait for synchronized access
            lock (_syncVolumeDataLock)
            {
                _largeObjectData.Lock();
                try
                {
                    // if the data is now available, return it immediately
                    // (i.e. we were blocked because we were already reading the data)
                    if (_volume != null)
                    {
                        return(_volume);
                    }

                    // load the volume data
                    if (context == null)
                    {
                        _volume = VolumeData.Create(_frames);
                    }
                    else
                    {
                        _volume = VolumeData.Create(_frames, (n, count) => context.ReportProgress(new BackgroundTaskProgress(n, count, SR.MessageFusionInProgress)));
                    }

                    // update our stats
                    _largeObjectData.BytesHeldCount   = 2 * _volume.SizeInVoxels;
                    _largeObjectData.LargeObjectCount = 1;
                    _largeObjectData.UpdateLastAccessTime();

                    // regenerating the volume data takes a few seconds
                    _largeObjectData.RegenerationCost = LargeObjectContainerData.PresetComputedData;

                    // register with memory manager
                    MemoryManager.Add(this);

                    return(_volume);
                }
                finally
                {
                    _largeObjectData.Unlock();
                }
            }
        }
Exemplo n.º 8
0
            private Volume LoadCore(VolumeLoadProgressCallback callback)
            {
                // TODO (CR Apr 2013): Same comment as with Fusion - shouldn't actually need to lock for
                // the duration of volume creation. Should be enough to set a _loading flag, exit the lock,
                // then re-enter the lock to reset the _loading flag and set any necessary fields.
                // Locking for the duration means the memory manager could get hung up while trying to unload
                // a big volume that is in the process of being created.

                lock (_syncRoot)
                {
                    if (_volumeReference != null)
                    {
                        return(_volumeReference.Volume);
                    }

                    Progress = 0;

                    using (var volume = Volume.Create(_frames, (n, total) =>
                    {
                        Progress = Math.Min(100f, 100f * n / total);
                        if (callback != null)
                        {
                            callback.Invoke(this, n, total);
                        }
                        _largeObjectContainerData.UpdateLastAccessTime();

#if UNIT_TESTS
                        if (ThrowAsyncVolumeLoadException)
                        {
                            ThrowAsyncVolumeLoadException = false;
                            throw new CreateVolumeException("User manually triggered exception");
                        }
#endif
                    }))
                    {
                        _volumeReference = volume.CreateReference();

                        _largeObjectContainerData.LargeObjectCount = 1;
                        _largeObjectContainerData.BytesHeldCount   = 2 * volume.ArrayLength;
                        _largeObjectContainerData.UpdateLastAccessTime();
                        MemoryManager.Add(this);
                    }

                    Progress = 100f;

                    return(_volumeReference.Volume);
                }
            }
Exemplo n.º 9
0
            private Volume LoadCore(VolumeLoadProgressCallback callback)
            {
                if (_volumeReference != null)
                {
                    return(_volumeReference.Volume);
                }

                lock (_syncRoot)
                {
                    if (_volumeReference != null)
                    {
                        return(_volumeReference.Volume);
                    }

                    Progress = 0;

                    using (var volume = Volume.Create(_frames, (n, total) =>
                    {
                        Progress = Math.Min(100f, 100f * n / total);
                        if (callback != null)
                        {
                            callback.Invoke(this, n, total);
                        }
                    }))
                    {
                        _volumeReference = volume.CreateTransientReference();

                        _largeObjectContainerData.LargeObjectCount = 1;
                        _largeObjectContainerData.BytesHeldCount   = 2 * volume.SizeInVoxels;
                        _largeObjectContainerData.UpdateLastAccessTime();
                        MemoryManager.Add(this);
                    }

                    Progress = 100f;

                    return(_volumeReference.Volume);
                }
            }
Exemplo n.º 10
0
        private VolumeData LoadVolume(IBackgroundTaskContext context)
        {
            // wait for synchronized access
            lock (_syncVolumeDataLock)
            {
                // if the data is now available, return it immediately
                // (i.e. we were blocked because we were already reading the data)
                if (_volume != null)
                {
                    return(_volume);
                }

                // load the volume data
                if (context == null)
                {
                    _volume = VolumeData.Create(_frames);
                }
                else
                {
                    _volume = VolumeData.Create(_frames, (n, count) => context.ReportProgress(new BackgroundTaskProgress(n, count, SR.MessageFusionInProgress)));
                }

                // update our stats
                _largeObjectData.BytesHeldCount   = 2 * _volume.SizeInVoxels;
                _largeObjectData.LargeObjectCount = 1;
                _largeObjectData.UpdateLastAccessTime();

                // regenerating the volume data is easy when the source frames are already in memory!
                _largeObjectData.RegenerationCost = RegenerationCost.Low;

                // register with memory manager
                MemoryManager.Add(this);

                return(_volume);
            }
        }
Exemplo n.º 11
0
            /// <summary>
            /// Gets pixel data in normalized form (8 or 16-bit grayscale, or ARGB).
            /// </summary>
            /// <returns></returns>
            /// <remarks>
            /// <i>Normalized</i> pixel data means that:
            /// <list type="Bullet">
            /// <item>
            /// <description>Grayscale pixel data has embedded overlays removed and each pixel value
            /// is padded so that it can be cast directly to the appropriate type (e.g. byte, sbyte, ushort, short).</description>
            /// </item>
            /// <item>
            /// <description>Colour pixel data is always converted into ARGB format.</description>
            /// </item>
            /// <item>
            /// <description>Pixel data is always uncompressed.</description>
            /// </item>
            /// </list>
            /// <para>
            /// Ensuring that the pixel data always meets the above criteria
            /// allows clients to easily consume pixel data without having
            /// to worry about the the multitude of DICOM photometric interpretations
            /// and transfer syntaxes.
            /// </para>
            /// <para>
            /// Pixel data is reloaded when this method is called after a
            /// call to <see cref="ISopFrameData.Unload"/>.
            /// </para>
            /// </remarks>
            public override byte[] GetNormalizedPixelData()
            {
                _largeObjectContainerData.UpdateLastAccessTime();

                var pixelData = _pixelData;

                if (pixelData == null && !_isLoading)
                {
                    lock (SyncLock)
                    {
                        // if an asynchronous exception was thrown, throw it now and reset the field
                        if (_lastAsyncException != null)
                        {
                            var ex = _lastAsyncException;
                            _lastAsyncException = null;
                            throw new AsyncSopDataSourceException(ex);
                        }

                        pixelData = _pixelData;
                        if (pixelData == null && !_isLoading)
                        {
                            LockSource();
                            try
                            {
                                if (IsReadySynchronously())
                                {
                                    _pixelData = pixelData = SyncCreateNormalizedPixelData();
                                    _largeObjectContainerData.UpdateLastAccessTime();

                                    UpdateLargeObjectInfo();
                                    MemoryManager.Add(this);

                                    Diagnostics.OnLargeObjectAllocated(pixelData.Length);
                                    UpdateProgress(100, true, pixelData, null, false);

                                    return(pixelData);
                                }

                                _isLoading      = true;
                                ProgressPercent = 0;
                                IsLoaded        = false;

                                AsyncCreateNormalizedPixelData((pd, e) =>
                                {
                                    try
                                    {
                                        _largeObjectContainerData.UpdateLastAccessTime();

                                        if (pd != null)
                                        {
                                            lock (SyncLock)
                                            {
                                                Monitor.Pulse(SyncLock);
                                                _pixelData = pd;
                                                UpdateLargeObjectInfo();
                                                MemoryManager.Add(this);
                                            }

                                            Diagnostics.OnLargeObjectAllocated(pd.Length);
                                        }

                                        // we have to update progress no matter how it finished (success/failed)
                                        UpdateProgress(100, true, pd, e, true);
                                    }
                                    catch (Exception ex)
                                    {
                                        UpdateProgress(100, true, pd, ex, true);
                                        Platform.Log(LogLevel.Error, ex, "Encountered error while asynchronously loading SOP frame data.");
                                    }
                                    finally
                                    {
                                        _isLoading = false;
                                    }
                                });
                            }
                            catch (Exception ex)
                            {
                                Platform.Log(LogLevel.Error, ex, "Encountered error while asynchronously loading SOP frame data.");
                            }
                            finally
                            {
                                UnlockSource();
                            }
                            pixelData = _pixelData;
                        }
                    }
                }

                return(pixelData);
            }