예제 #1
0
        private static CompressionParameters ToCompressionParameters(DicomJpegParams parameters)
        {
            var compressionParams = new CompressionParameters();

            if (parameters != null)
            {
                compressionParams.Quality         = parameters.Quality;
                compressionParams.SmoothingFactor = parameters.SmoothingFactor;
            }

            return(compressionParams);
        }
예제 #2
0
        internal static void Decode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpegParams parameters)
        {
            var pixelCount = oldPixelData.Height * oldPixelData.Width;

            if (parameters.ConvertColorspaceToRGB)
            {
                if (oldPixelData.PixelRepresentation == PixelRepresentation.Signed)
                {
                    throw new DicomCodecException(
                              "JPEG codec unable to perform colorspace conversion on signed pixel data");
                }

                newPixelData.PhotometricInterpretation = PhotometricInterpretation.Rgb;
                newPixelData.PlanarConfiguration       = PlanarConfiguration.Interleaved;
            }

            for (var frame = 0; frame < oldPixelData.NumberOfFrames; frame++)
            {
                var jpegData = oldPixelData.GetFrame(frame);

                // Destination frame should be of even length
                var frameSize = newPixelData.UncompressedFrameSize;
                if ((frameSize & 1) == 1)
                {
                    ++frameSize;
                }
                var destArray = new byte[frameSize];

                using (var stream = new MemoryStream(jpegData.Data))
                {
                    var decoder = new JpegImage(stream);
                    var w       = decoder.Width;
                    var h       = decoder.Height;

                    for (var c = 0; c < decoder.ComponentsPerSample; c++)
                    {
                        var pos    = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? c * pixelCount : c;
                        var offset = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar
                                         ? 1
                                         : decoder.ComponentsPerSample;

                        if (newPixelData.BytesAllocated == 1)
                        {
                            for (var y = 0; y < h; ++y)
                            {
                                var row = decoder.GetRow(y);
                                for (var x = 0; x < w; ++x)
                                {
                                    destArray[pos] = (byte)row[x][c];
                                    pos           += offset;
                                }
                            }
                        }
#if SUPPORT16BIT
                        else if (newPixelData.BytesAllocated == 2)
                        {
                            var destArray16 = new short[frameSize >> 1];
                            for (var y = 0; y < h; ++y)
                            {
                                var row = decoder.GetRow(y);
                                for (var x = 0; x < w; ++x)
                                {
                                    destArray16[pos] = row[x][c];
                                    pos += offset;
                                }
                            }

                            Buffer.BlockCopy(destArray16, 0, destArray, 0, frameSize);
                        }
#endif
                        else
                        {
                            throw new InvalidOperationException(
                                      $"JPEG module does not support Bits Allocated == {newPixelData.BitsAllocated}!");
                        }
                    }

                    newPixelData.AddFrame(new MemoryByteBuffer(destArray));
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Loads the pixel data for specified frame and set the internal dataset
        /// 
        /// </summary>
        /// <param name="dataset">dataset to load pixeldata from</param>
        /// <param name="frame">The frame number to create pixeldata for</param>
        private void Load(DicomDataset dataset, int frame)
        {
            Dataset = dataset;

            if (PixelData == null) {
                PixelData = DicomPixelData.Create(Dataset);
                PhotometricInterpretation = PixelData.PhotometricInterpretation;
            }

            if (Dataset.InternalTransferSyntax.IsEncapsulated) {
                // decompress single frame from source dataset
                DicomCodecParams cparams = null;
                if (Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess1 || Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess2_4) {
                    cparams = new DicomJpegParams {
                        ConvertColorspaceToRGB = true
                    };
                }

                var transcoder = new DicomTranscoder(Dataset.InternalTransferSyntax, DicomTransferSyntax.ExplicitVRLittleEndian);
                transcoder.InputCodecParams = cparams;
                transcoder.OutputCodecParams = cparams;
                var buffer = transcoder.DecodeFrame(Dataset, frame);

                // clone the dataset because modifying the pixel data modifies the dataset
                var clone = Dataset.Clone();
                clone.InternalTransferSyntax = DicomTransferSyntax.ExplicitVRLittleEndian;

                var pixelData = DicomPixelData.Create(clone, true);
                pixelData.AddFrame(buffer);

                // temporary fix for JPEG compressed YBR images
                if ((Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess1 || Dataset.InternalTransferSyntax == DicomTransferSyntax.JPEGProcess2_4) && pixelData.SamplesPerPixel == 3)
                    pixelData.PhotometricInterpretation = PhotometricInterpretation.Rgb;

                // temporary fix for JPEG 2000 Lossy images
                if (pixelData.PhotometricInterpretation == PhotometricInterpretation.YbrIct || pixelData.PhotometricInterpretation == PhotometricInterpretation.YbrRct)
                    pixelData.PhotometricInterpretation = PhotometricInterpretation.Rgb;

                _pixelData = PixelDataFactory.Create(pixelData, 0);
            } else {
                // pull uncompressed frame from source pixel data
                _pixelData = PixelDataFactory.Create(PixelData, frame);
            }

            _pixelData = _pixelData.Rescale(_scale);

            _overlays = DicomOverlayData.FromDataset(Dataset).Where(x => x.Type == DicomOverlayType.Graphics && x.Data != null).ToArray();

            _currentFrame = frame;

            CreatePipeline();
        }
예제 #4
0
        internal static void Encode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpegParams parameters)
        {
            if ((oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrFull422) ||
                (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial422) ||
                (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial420))
            {
                throw new InvalidOperationException(
                          "Photometric Interpretation '" + oldPixelData.PhotometricInterpretation
                          + "' not supported by JPEG encoder");
            }

            var w = oldPixelData.Width;
            var h = oldPixelData.Height;

            for (var frame = 0; frame < oldPixelData.NumberOfFrames; frame++)
            {
                var frameData = oldPixelData.GetFrame(frame);

                var nc   = oldPixelData.SamplesPerPixel;
                var sgnd = oldPixelData.PixelRepresentation == PixelRepresentation.Signed;

                var rows = Enumerable.Range(0, h).Select(i => new short[w, nc]).ToArray();

                for (var c = 0; c < nc; c++)
                {
                    var pos    = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * w * h) : c;
                    var offset = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? 1 : nc;

                    if (oldPixelData.BytesAllocated == 1)
                    {
                        var data = frameData.Data;
                        if (sgnd)
                        {
                            if (oldPixelData.BitsStored < 8)
                            {
                                var sign = (byte)(1 << oldPixelData.HighBit);
                                var mask = (byte)(0xff >> (oldPixelData.BitsAllocated - oldPixelData.BitsStored));
                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        var pixel = (sbyte)data[pos];
                                        rows[y][x, c] = (short)((pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel);
                                        pos          += offset;
                                    }
                                }
                            }
                            else
                            {
                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        rows[y][x, c] = (sbyte)data[pos];
                                        pos          += offset;
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (var y = 0; y < h; ++y)
                            {
                                for (var x = 0; x < w; ++x)
                                {
                                    rows[y][x, c] = data[pos];
                                    pos          += offset;
                                }
                            }
                        }
                    }
#if SUPPORT16BIT
                    else if (oldPixelData.BytesAllocated == 2)
                    {
                        if (sgnd)
                        {
                            if (oldPixelData.BitsStored < 16)
                            {
                                var frameData16 = new ushort[w * h];
                                Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                                var sign = (ushort)(1 << oldPixelData.HighBit);
                                var mask = (ushort)(0xffff >> (oldPixelData.BitsAllocated - oldPixelData.BitsStored));
                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        var pixel = frameData16[pos];
                                        rows[y][x, c] = (short)((pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel);
                                        pos          += offset;
                                    }
                                }
                            }
                            else
                            {
                                var frameData16 = new short[w * h];
                                Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        rows[y][x, c] = frameData16[pos];
                                        pos          += offset;
                                    }
                                }
                            }
                        }
                        else
                        {
                            var frameData16 = new ushort[w * h];
                            Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                            for (var y = 0; y < h; ++y)
                            {
                                for (var x = 0; x < w; ++x)
                                {
                                    rows[y][x, c] = (short)frameData16[pos];
                                    pos          += offset;
                                }
                            }
                        }
                    }
#endif
                    else
                    {
                        throw new InvalidOperationException(
                                  $"JPEG codec does not support Bits Allocated == {oldPixelData.BitsAllocated}");
                    }
                }

                try
                {
                    using (var stream = new MemoryStream())
                    {
                        var sampleRows =
                            rows.Select(
                                row =>
                                new SampleRow(
                                    ToRawRow(row, oldPixelData.BitsAllocated),
                                    w,
                                    (byte)oldPixelData.BitsStored,
                                    (byte)nc)).ToArray();
                        var colorSpace = GetColorSpace(oldPixelData.PhotometricInterpretation);
                        using (var encoder = new JpegImage(sampleRows, colorSpace))
                        {
                            encoder.WriteJpeg(stream, ToCompressionParameters(parameters));
                        }
                        newPixelData.AddFrame(new MemoryByteBuffer(stream.ToArray()));
                        newPixelData.PhotometricInterpretation =
                            (parameters != null && parameters.SampleFactor == DicomJpegSampleFactor.SF422)
                           ? PhotometricInterpretation.YbrFull422 : PhotometricInterpretation.YbrFull;
                    }
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException("Unable to JPEG encode image", e);
                }
            }

            if (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.Rgb)
            {
                newPixelData.PlanarConfiguration = PlanarConfiguration.Interleaved;
            }
        }
예제 #5
0
 protected abstract IJpegNativeCodec GetCodec(int bits, DicomJpegParams jparams);
예제 #6
0
 protected abstract IJpegNativeCodec GetCodec(int bits, DicomJpegParams jparams);
예제 #7
0
        private static CompressionParameters ToCompressionParameters(DicomJpegParams parameters)
        {
            var compressionParams = new CompressionParameters();

            if (parameters != null)
            {
                compressionParams.Quality = parameters.Quality;
                compressionParams.SmoothingFactor = parameters.SmoothingFactor;
            }

            return compressionParams;
        }
예제 #8
0
        internal static void Decode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpegParams parameters)
        {
            var pixelCount = oldPixelData.Height * oldPixelData.Width;

            if (newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrIct
                || newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrRct)
            {
                newPixelData.PhotometricInterpretation = PhotometricInterpretation.Rgb;
            }

            if (newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrFull422
                || newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial422)
            {
                newPixelData.PhotometricInterpretation = PhotometricInterpretation.YbrFull;
            }

            if (newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrFull)
            {
                newPixelData.PlanarConfiguration = PlanarConfiguration.Planar;
            }

            for (var frame = 0; frame < oldPixelData.NumberOfFrames; frame++)
            {
                var jpegData = oldPixelData.GetFrame(frame);

                // Destination frame should be of even length
                var frameSize = newPixelData.UncompressedFrameSize;
                if ((frameSize & 1) == 1) ++frameSize;
                var destArray = new byte[frameSize];

                using (var stream = new MemoryStream(jpegData.Data))
                {
                    var decoder = new JpegImage(stream);
                    var w = decoder.Width;
                    var h = decoder.Height;

                    for (var c = 0; c < decoder.ComponentsPerSample; c++)
                    {
                        var pos = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * pixelCount) : c;
                        var offset = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar
                                         ? 1
                                         : decoder.ComponentsPerSample;

                        if (newPixelData.BytesAllocated == 1)
                        {
                            for (var y = 0; y < h; ++y)
                            {
                                var row = decoder.GetRow(y);
                                for (var x = 0; x < w; ++x)
                                {
                                    destArray[pos] = (byte)row[x][c];
                                    pos += offset;
                                }
                            }
                        }
#if SUPPORT16BIT
                        else if (newPixelData.BytesAllocated == 2)
                        {
                            var destArray16 = new short[frameSize >> 1];
                            for (var y = 0; y < h; ++y)
                            {
                                var row = decoder.GetRow(y);
                                for (var x = 0; x < w; ++x)
                                {
                                    destArray16[pos] = row[x][c];
                                    pos += offset;
                                }
                            }

                            Buffer.BlockCopy(destArray16, 0, destArray, 0, frameSize);
                        }
#endif
                        else
                        {
                            throw new InvalidOperationException(
                                $"JPEG module does not support Bits Allocated == {newPixelData.BitsAllocated}!");
                        }
                    }

                    newPixelData.AddFrame(new MemoryByteBuffer(destArray));
                }
            }
        }
예제 #9
0
        internal static void Encode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpegParams parameters)
        {
            if ((oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrFull422)
                || (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial422)
                || (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial420))
            {
                throw new InvalidOperationException(
                    "Photometric Interpretation '" + oldPixelData.PhotometricInterpretation
                    + "' not supported by JPEG encoder");
            }

            var w = oldPixelData.Width;
            var h = oldPixelData.Height;

            for (var frame = 0; frame < oldPixelData.NumberOfFrames; frame++)
            {
                var frameData = oldPixelData.GetFrame(frame);

                var nc = oldPixelData.SamplesPerPixel;
                var sgnd = oldPixelData.PixelRepresentation == PixelRepresentation.Signed;

                var rows = Enumerable.Range(0, h).Select(i => new short[w, nc]).ToArray();

                for (var c = 0; c < nc; c++)
                {
                    var pos = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * w * h) : c;
                    var offset = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? 1 : nc;

                    if (oldPixelData.BytesAllocated == 1)
                    {
                        var data = frameData.Data;
                        if (sgnd)
                        {
                            if (oldPixelData.BitsStored < 8)
                            {
                                var sign = (byte)(1 << oldPixelData.HighBit);
                                var mask = (byte)(0xff >> (oldPixelData.BitsAllocated - oldPixelData.BitsStored));
                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        var pixel = (sbyte)data[pos];
                                        rows[y][x, c] = (short)((pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel);
                                        pos += offset;
                                    }
                                }
                            }
                            else
                            {
                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        rows[y][x, c] = (sbyte)data[pos];
                                        pos += offset;
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (var y = 0; y < h; ++y)
                            {
                                for (var x = 0; x < w; ++x)
                                {
                                    rows[y][x, c] = data[pos];
                                    pos += offset;
                                }
                            }
                        }
                    }
#if SUPPORT16BIT
                    else if (oldPixelData.BytesAllocated == 2)
                    {
                        if (sgnd)
                        {
                            if (oldPixelData.BitsStored < 16)
                            {
                                var frameData16 = new ushort[w * h];
                                Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                                var sign = (ushort)(1 << oldPixelData.HighBit);
                                var mask = (ushort)(0xffff >> (oldPixelData.BitsAllocated - oldPixelData.BitsStored));
                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        var pixel = frameData16[pos];
                                        rows[y][x, c] = (short)((pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel);
                                        pos += offset;
                                    }
                                }
                            }
                            else
                            {
                                var frameData16 = new short[w * h];
                                Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                                for (var y = 0; y < h; ++y)
                                {
                                    for (var x = 0; x < w; ++x)
                                    {
                                        rows[y][x, c] = frameData16[pos];
                                        pos += offset;
                                    }
                                }
                            }
                        }
                        else
                        {
                            var frameData16 = new ushort[w * h];
                            Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                            for (var y = 0; y < h; ++y)
                            {
                                for (var x = 0; x < w; ++x)
                                {
                                    rows[y][x, c] = (short)frameData16[pos];
                                    pos += offset;
                                }
                            }
                        }
                    }
#endif
                    else
                    {
                        throw new InvalidOperationException(
                            $"JPEG codec does not support Bits Allocated == {oldPixelData.BitsAllocated}");
                    }
                }

                try
                {
                    using (var stream = new MemoryStream())
                    {
                        var sampleRows =
                            rows.Select(
                                row =>
                                new SampleRow(
                                    ToRawRow(row, oldPixelData.BitsAllocated),
                                    w,
                                    (byte)oldPixelData.BitsStored,
                                    (byte)nc)).ToArray();
                        var colorSpace = GetColorSpace(oldPixelData.PhotometricInterpretation);
                        using (var encoder = new JpegImage(sampleRows, colorSpace))
                        {
                            encoder.WriteJpeg(stream, ToCompressionParameters(parameters));
                        }
                        newPixelData.AddFrame(new MemoryByteBuffer(stream.ToArray()));
                    }
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException("Unable to JPEG encode image", e);
                }
            }

            if (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.Rgb)
            {
                newPixelData.PlanarConfiguration = PlanarConfiguration.Interleaved;
            }
        }