예제 #1
0
        private static ParameterList ToParameterList(DicomJpeg2000Params parameters, bool decoder)
        {
            // These JPEG2000 codec parameters are not translated: EncodeSignedPixelValuesAsUnsigned, RateLevels,
            // UpdatePhotometricInterpretation
            var list =
                new ParameterList(
                    decoder
                        ? J2kImage.GetDefaultDecoderParameterList(null)
                        : J2kImage.GetDefaultEncoderParameterList(null));

            var param = parameters ?? new DicomJpeg2000Params();

            list["Mct"]      = param.AllowMCT ? "on" : "off";
            list["lossless"] = param.Irreversible ? "off" : "on";
            list["verbose"]  = param.IsVerbose ? "on" : "off";

            if (param.Irreversible)
            {
                list["rate"] = param.Rate.ToString();
            }

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

            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];

                var image = J2kImage.FromBytes(jpegData.Data, ToParameterList(parameters, true));
                if (image == null)
                {
                    throw new InvalidOperationException("Error in JPEG 2000 code stream!");
                }

                for (var c = 0; c < image.NumberOfComponents; c++)
                {
                    // convert RGB BGR colorspace
                    var comp = image.GetComponent(image.NumberOfComponents - c - 1);

                    var pos    = bytesAllocated * (newPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? c * pixelCount : c);
                    var offset = bytesAllocated * (newPixelData.PlanarConfiguration == PlanarConfiguration.Planar
                                     ? 1
                                     : image.NumberOfComponents);

                    if (bytesAllocated == 1)
                    {
                        if (newPixelData.PixelRepresentation == PixelRepresentation.Signed)
                        {
                            var sign = 1 << newPixelData.HighBit;
                            var mask = 0xff ^ sign;

                            for (var p = 0; p < pixelCount; p++)
                            {
                                int i = (i = comp[p] - sign) < 0 ? (i & mask) | sign : i & mask;
                                destArray[pos] = (byte)i;
                                pos           += offset;
                            }
                        }
                        else
                        {
                            for (var p = 0; p < pixelCount; p++)
                            {
                                destArray[pos] = (byte)comp[p];
                                pos           += offset;
                            }
                        }
                    }
                    else if (bytesAllocated == 2)
                    {
                        if (newPixelData.PixelRepresentation == PixelRepresentation.Signed)
                        {
                            var sign = 1 << newPixelData.HighBit;
                            var mask = 0xffff ^ sign;

                            for (var p = 0; p < pixelCount; p++)
                            {
                                int i = (i = comp[p] - sign) < 0 ? (i & mask) | sign : i & mask;
                                destArray[pos]     = (byte)(i & 0xff);
                                destArray[pos + 1] = (byte)((i >> 8) & 0xff);
                                pos += offset;
                            }
                        }
                        else
                        {
                            for (var p = 0; p < pixelCount; p++)
                            {
                                var i = comp[p];
                                destArray[pos]     = (byte)(i & 0xff);
                                destArray[pos + 1] = (byte)((i >> 8) & 0xff);
                                pos += offset;
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  $"JPEG 2000 codec does not support Bits Allocated == {newPixelData.BitsAllocated}!");
                    }
                }

                newPixelData.AddFrame(new MemoryByteBuffer(destArray));
            }
        }
예제 #3
0
        internal static void Encode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpeg2000Params 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 2000 encoder");
            }

            var jparams = parameters ?? new DicomJpeg2000Params();

            jparams.Irreversible = newPixelData.IsLossy;
            jparams.AllowMCT     = oldPixelData.PhotometricInterpretation == PhotometricInterpretation.Rgb;

            var pixelCount = oldPixelData.Height * oldPixelData.Width;

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

                var nc   = oldPixelData.SamplesPerPixel;
                var sgnd = oldPixelData.PixelRepresentation == PixelRepresentation.Signed &&
                           !jparams.EncodeSignedPixelValuesAsUnsigned;
                var comps = new int[nc][];

                for (var c = 0; c < nc; c++)
                {
                    var comp = new int[pixelCount];

                    var pos    = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * pixelCount) : 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 p = 0; p < pixelCount; p++)
                                {
                                    var pixel = (sbyte)data[pos];
                                    comp[p] = (pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel;
                                    pos    += offset;
                                }
                            }
                            else
                            {
                                for (var p = 0; p < pixelCount; p++)
                                {
                                    comp[p] = (sbyte)data[pos];
                                    pos    += offset;
                                }
                            }
                        }
                        else
                        {
                            for (var p = 0; p < pixelCount; p++)
                            {
                                comp[p] = data[pos];
                                pos    += offset;
                            }
                        }
                    }
                    else if (oldPixelData.BytesAllocated == 2)
                    {
                        if (sgnd)
                        {
                            if (oldPixelData.BitsStored < 16)
                            {
                                var frameData16 = new ushort[pixelCount];
                                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 p = 0; p < pixelCount; p++)
                                {
                                    var pixel = frameData16[pos];
                                    comp[p] = (pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel;
                                    pos    += offset;
                                }
                            }
                            else
                            {
                                var frameData16 = new short[pixelCount];
                                Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                                for (var p = 0; p < pixelCount; p++)
                                {
                                    comp[p] = frameData16[pos];
                                    pos    += offset;
                                }
                            }
                        }
                        else
                        {
                            var frameData16 = new ushort[pixelCount];
                            Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                            for (var p = 0; p < pixelCount; p++)
                            {
                                comp[p] = frameData16[pos];
                                pos    += offset;
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  $"JPEG 2000 codec does not support Bits Allocated == {oldPixelData.BitsAllocated}");
                    }

                    comps[c] = comp;
                }

                var image = new PortableImageSource(
                    oldPixelData.Width,
                    oldPixelData.Height,
                    nc,
                    oldPixelData.BitsAllocated,
                    Enumerable.Repeat(sgnd, nc).ToArray(),
                    comps);

                try
                {
                    var cbuf = J2kImage.ToBytes(image, ToParameterList(jparams, false));
                    newPixelData.AddFrame(new MemoryByteBuffer(cbuf));
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException("Unable to JPEG 2000 encode image", e);
                }
            }

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

                if (jparams.AllowMCT && jparams.UpdatePhotometricInterpretation)
                {
                    if (newPixelData.IsLossy && jparams.Irreversible)
                    {
                        newPixelData.PhotometricInterpretation = PhotometricInterpretation.YbrIct;
                    }
                    else
                    {
                        newPixelData.PhotometricInterpretation = PhotometricInterpretation.YbrRct;
                    }
                }
            }
        }
예제 #4
0
        private static ParameterList ToParameterList(DicomJpeg2000Params parameters, bool decoder = true)
        {
            // These JPEG2000 codec parameters are not translated: EncodeSignedPixelValuesAsUnsigned, RateLevels, 
            // UpdatePhotometricInterpretation
            var list =
                new ParameterList(
                    decoder
                        ? J2kImage.GetDefaultDecoderParameterList(null)
                        : J2kImage.GetDefaultEncoderParameterList(null));

            var param = parameters ?? new DicomJpeg2000Params();

            list["Mct"] = param.AllowMCT ? "on" : "off";
            list["lossless"] = param.Irreversible ? "off" : "on";
            list["verbose"] = param.IsVerbose ? "on" : "off";

            if (param.Irreversible)
            {
                list["rate"] = param.Rate.ToString();
            }

            return list;
        }
예제 #5
0
        internal static void Encode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpeg2000Params 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 2000 encoder");
            }

            var jparams = parameters ?? new DicomJpeg2000Params();

            jparams.Irreversible = newPixelData.IsLossy;
            jparams.AllowMCT = oldPixelData.PhotometricInterpretation == PhotometricInterpretation.Rgb;

            var pixelCount = oldPixelData.Height * oldPixelData.Width;

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

                var nc = oldPixelData.SamplesPerPixel;
                var sgnd = oldPixelData.PixelRepresentation == PixelRepresentation.Signed
                           && !jparams.EncodeSignedPixelValuesAsUnsigned;
                var comps = new int[nc][];

                var colorSpace = GetJpegColorSpace(oldPixelData.PhotometricInterpretation);

                for (var c = 0; c < nc; c++)
                {
                    var comp = new int[pixelCount];

                    var pos = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * pixelCount) : 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 p = 0; p < pixelCount; p++)
                                {
                                    var pixel = (sbyte)data[pos];
                                    comp[p] = (pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel;
                                    pos += offset;
                                }
                            }
                            else
                            {
                                for (var p = 0; p < pixelCount; p++)
                                {
                                    comp[p] = (sbyte)data[pos];
                                    pos += offset;
                                }
                            }
                        }
                        else
                        {
                            for (var p = 0; p < pixelCount; p++)
                            {
                                comp[p] = data[pos];
                                pos += offset;
                            }
                        }
                    }
#if SUPPORT16BIT
                    else if (oldPixelData.BytesAllocated == 2)
                    {
                        if (sgnd)
                        {
                            if (oldPixelData.BitsStored < 16)
                            {
                                var frameData16 = new ushort[pixelCount];
                                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 p = 0; p < pixelCount; p++)
                                {
                                    var pixel = frameData16[pos];
                                    comp[p] = (pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel;
                                    pos += offset;
                                }
                            }
                            else
                            {
                                var frameData16 = new short[pixelCount];
                                Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                                for (var p = 0; p < pixelCount; p++)
                                {
                                    comp[p] = frameData16[pos];
                                    pos += offset;
                                }
                            }
                        }
                        else
                        {
                            var frameData16 = new ushort[pixelCount];
                            Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size);

                            for (var p = 0; p < pixelCount; p++)
                            {
                                comp[p] = frameData16[pos];
                                pos += offset;
                            }
                        }
                    }
#endif
                    else
                    {
                        throw new InvalidOperationException(
                            $"JPEG 2000 codec does not support Bits Allocated == {oldPixelData.BitsAllocated}");
                    }

                    comps[c] = comp;
                }

                var image = new PortableImageSource(
                    oldPixelData.Width,
                    oldPixelData.Height,
                    nc,
                    oldPixelData.BitsAllocated,
                    Enumerable.Repeat(sgnd, nc).ToArray(),
                    comps);

                try
                {
                    var cbuf = J2kImage.ToBytes(image, ToParameterList(jparams, false));
                    newPixelData.AddFrame(new MemoryByteBuffer(cbuf));
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException("Unable to JPEG 2000 encode image", e);
                }
            }

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

                if (jparams.AllowMCT && jparams.UpdatePhotometricInterpretation)
                {
                    if (newPixelData.IsLossy && jparams.Irreversible) newPixelData.PhotometricInterpretation = PhotometricInterpretation.YbrIct;
                    else newPixelData.PhotometricInterpretation = PhotometricInterpretation.YbrRct;
                }
            }
        }
예제 #6
0
        internal static void Decode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpeg2000Params 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];

                var image = J2kImage.FromBytes(jpegData.Data, ToParameterList(parameters, true));

                if (image == null) throw new InvalidOperationException("Error in JPEG 2000 code stream!");

                for (var c = 0; c < image.NumberOfComponents; c++)
                {
                    var comp = image.GetComponent(c);

                    var pos = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * pixelCount) : c;
                    var offset = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar
                                     ? 1
                                     : image.NumberOfComponents;

                    if (newPixelData.BytesAllocated == 1)
                    {
                        for (var p = 0; p < pixelCount; p++)
                        {
                            destArray[pos] = comp[p];
                            pos += offset;
                        }
                    }
#if SUPPORT16BIT
                    else if (newPixelData.BytesAllocated == 2)
                    {
                        for (var p = 0; p < pixelCount; p++)
                        {
                            destArray[2 * pos] = comp[p];
                            pos += offset;
                        }
                    }
#endif
                    else
                    {
                        throw new InvalidOperationException(
                            $"JPEG 2000 codec does not support Bits Allocated == {newPixelData.BitsAllocated}!");
                    }
                }

                newPixelData.AddFrame(new MemoryByteBuffer(destArray));
            }
        }
예제 #7
0
        internal static void Decode(
            DicomPixelData oldPixelData,
            DicomPixelData newPixelData,
            DicomJpeg2000Params 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];

                var image = J2kImage.FromBytes(jpegData.Data, ToParameterList(parameters, true));

                if (image == null)
                {
                    throw new InvalidOperationException("Error in JPEG 2000 code stream!");
                }

                for (var c = 0; c < image.NumberOfComponents; c++)
                {
                    var comp = image.GetComponent(c);

                    var pos    = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * pixelCount) : c;
                    var offset = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar
                                     ? 1
                                     : image.NumberOfComponents;

                    if (newPixelData.BytesAllocated == 1)
                    {
                        for (var p = 0; p < pixelCount; p++)
                        {
                            destArray[pos] = comp[p];
                            pos           += offset;
                        }
                    }
#if SUPPORT16BIT
                    else if (newPixelData.BytesAllocated == 2)
                    {
                        for (var p = 0; p < pixelCount; p++)
                        {
                            destArray[2 * pos] = comp[p];
                            pos += offset;
                        }
                    }
#endif
                    else
                    {
                        throw new InvalidOperationException(
                                  $"JPEG 2000 codec does not support Bits Allocated == {newPixelData.BitsAllocated}!");
                    }
                }

                newPixelData.AddFrame(new MemoryByteBuffer(destArray));
            }
        }