123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- // Copyright (c) 2012-2020 fo-dicom contributors.
- // Licensed under the Microsoft Public License (MS-PL).
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Threading.Tasks;
- using Dicom;
- using Dicom.Imaging;
- using Dicom.IO;
- using Dicom.Network;
- using Dicom.Printing;
- using DicomClient = Dicom.Network.Client.DicomClient;
- namespace Print_SCU
- {
- internal class PrintJob
- {
- public string CallingAE { get; set; }
- public string CalledAE { get; set; }
- public string RemoteAddress { get; set; }
- public int RemotePort { get; set; }
- public FilmSession FilmSession { get; private set; }
- private FilmBox _currentFilmBox;
- public PrintJob(string jobLabel)
- {
- FilmSession = new FilmSession(DicomUID.BasicFilmSessionSOPClass)
- {
- FilmSessionLabel = jobLabel,
- MediumType = "PAPER",
- NumberOfCopies = 1
- };
- }
- public FilmBox StartFilmBox(string format, string orientation, string filmSize)
- {
- var filmBox = new FilmBox(FilmSession, null, DicomTransferSyntax.ExplicitVRLittleEndian)
- {
- ImageDisplayFormat = format,
- FilmOrientation = orientation,
- FilmSizeID = filmSize,
- MagnificationType = "NONE",
- BorderDensity = "BLACK",
- EmptyImageDensity = "BLACK"
- };
- filmBox.Initialize();
- FilmSession.BasicFilmBoxes.Add(filmBox);
- _currentFilmBox = filmBox;
- return filmBox;
- }
- public void AddImage(Bitmap bitmap, int index)
- {
- if (FilmSession.IsColor)
- {
- AddColorImage(bitmap, index);
- }
- else
- {
- AddGreyscaleImage(bitmap, index);
- }
- }
- private void AddGreyscaleImage(Bitmap bitmap, int index)
- {
- if (_currentFilmBox == null)
- {
- throw new InvalidOperationException("Start film box first!");
- }
- if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count)
- {
- throw new ArgumentOutOfRangeException(nameof(index), "Image box index out of range");
- }
- if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb
- && bitmap.PixelFormat != PixelFormat.Format32bppRgb)
- {
- throw new ArgumentException("Not supported bitmap format", nameof(bitmap));
- }
- var dataset = new DicomDataset();
- dataset.Add<ushort>(DicomTag.Columns, (ushort)bitmap.Width)
- .Add<ushort>(DicomTag.Rows, (ushort)bitmap.Height)
- .Add<ushort>(DicomTag.BitsAllocated, 8)
- .Add<ushort>(DicomTag.BitsStored, 8)
- .Add<ushort>(DicomTag.HighBit, 7)
- .Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned)
- .Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved)
- .Add<ushort>(DicomTag.SamplesPerPixel, 1)
- .Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Monochrome2.Value);
- var pixelData = DicomPixelData.Create(dataset, true);
- var pixels = GetGreyBytes(bitmap);
- var buffer = new Dicom.IO.Buffer.MemoryByteBuffer(pixels.Data);
- pixelData.AddFrame(buffer);
- var imageBox = _currentFilmBox.BasicImageBoxes[index];
- imageBox.ImageSequence = dataset;
- pixels.Dispose();
- }
- private void AddColorImage(Bitmap bitmap, int index)
- {
- if (_currentFilmBox == null)
- {
- throw new InvalidOperationException("Start film box first!");
- }
- if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count)
- {
- throw new ArgumentOutOfRangeException(nameof(index), "Image box index out of range");
- }
- if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb
- && bitmap.PixelFormat != PixelFormat.Format32bppRgb)
- {
- throw new ArgumentException("Not supported bitmap format", nameof(bitmap));
- }
- var dataset = new DicomDataset();
- dataset.Add<ushort>(DicomTag.Columns, (ushort)bitmap.Width)
- .Add<ushort>(DicomTag.Rows, (ushort)bitmap.Height)
- .Add<ushort>(DicomTag.BitsAllocated, 8)
- .Add<ushort>(DicomTag.BitsStored, 8)
- .Add<ushort>(DicomTag.HighBit, 7)
- .Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned)
- .Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved)
- .Add<ushort>(DicomTag.SamplesPerPixel, 3)
- .Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value);
- var pixelData = DicomPixelData.Create(dataset, true);
- var pixels = GetColorbytes(bitmap);
- var buffer = new Dicom.IO.Buffer.MemoryByteBuffer(pixels.Data);
- pixelData.AddFrame(buffer);
- var imageBox = _currentFilmBox.BasicImageBoxes[index];
- imageBox.ImageSequence = dataset;
- pixels.Dispose();
- }
- public void EndFilmBox()
- {
- _currentFilmBox = null;
- }
- public async Task Print()
- {
- var dicomClient = new DicomClient(RemoteAddress, RemotePort, false, CallingAE, CalledAE);
- await dicomClient.AddRequestAsync(
- new DicomNCreateRequest(FilmSession.SOPClassUID, FilmSession.SOPInstanceUID)
- {
- Dataset = FilmSession
- });
- foreach (var filmbox in FilmSession.BasicFilmBoxes)
- {
- var imageBoxRequests = new List<DicomNSetRequest>();
- var filmBoxRequest = new DicomNCreateRequest(FilmBox.SOPClassUID, filmbox.SOPInstanceUID)
- {
- Dataset = filmbox
- };
- filmBoxRequest.OnResponseReceived = (request, response) =>
- {
- if (response.HasDataset)
- {
- var seq = response.Dataset.GetSequence(DicomTag.ReferencedImageBoxSequence);
- for (int i = 0; i < seq.Items.Count; i++)
- {
- var req = imageBoxRequests[i];
- var imageBox = req.Dataset;
- var sopInstanceUid = seq.Items[i].GetSingleValue<string>(DicomTag.ReferencedSOPInstanceUID);
- imageBox.AddOrUpdate(DicomTag.SOPInstanceUID, sopInstanceUid);
- req.Command.AddOrUpdate(DicomTag.RequestedSOPInstanceUID, sopInstanceUid);
- }
- }
- };
- await dicomClient.AddRequestAsync(filmBoxRequest);
- foreach (var image in filmbox.BasicImageBoxes)
- {
- var req = new DicomNSetRequest(image.SOPClassUID, image.SOPInstanceUID) { Dataset = image };
- imageBoxRequests.Add(req);
- await dicomClient.AddRequestAsync(req);
- }
- }
- await dicomClient.AddRequestAsync(new DicomNActionRequest(FilmSession.SOPClassUID, FilmSession.SOPInstanceUID, 0x0001));
- await dicomClient.SendAsync();
- }
- private unsafe PinnedByteArray GetGreyBytes(Bitmap bitmap)
- {
- var pixels = new PinnedByteArray(bitmap.Width * bitmap.Height);
- var data = bitmap.LockBits(
- new Rectangle(0, 0, bitmap.Width, bitmap.Height),
- ImageLockMode.ReadOnly,
- bitmap.PixelFormat);
- var srcComponents = bitmap.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;
- var dstLine = (byte*)pixels.Pointer;
- var srcLine = (byte*)data.Scan0.ToPointer();
- for (int i = 0; i < data.Height; i++)
- {
- for (int j = 0; j < data.Width; j++)
- {
- var pixel = srcLine + j * srcComponents;
- int grey = (int)(pixel[0] * 0.3 + pixel[1] * 0.59 + pixel[2] * 0.11);
- dstLine[j] = (byte)grey;
- }
- srcLine += data.Stride;
- dstLine += data.Width;
- }
- bitmap.UnlockBits(data);
- return pixels;
- }
- private unsafe PinnedByteArray GetColorbytes(Bitmap bitmap)
- {
- var pixels = new PinnedByteArray(bitmap.Width * bitmap.Height * 3);
- var data = bitmap.LockBits(
- new Rectangle(0, 0, bitmap.Width, bitmap.Height),
- ImageLockMode.ReadOnly,
- bitmap.PixelFormat);
- var srcComponents = bitmap.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;
- var dstLine = (byte*)pixels.Pointer;
- var srcLine = (byte*)data.Scan0.ToPointer();
- for (int i = 0; i < data.Height; i++)
- {
- for (int j = 0; j < data.Width; j++)
- {
- var srcPixel = srcLine + j * srcComponents;
- var dstPixel = dstLine + j * 3;
- //convert from bgr to rgb
- dstPixel[0] = srcPixel[2];
- dstPixel[1] = srcPixel[1];
- dstPixel[2] = srcPixel[0];
- }
- srcLine += data.Stride;
- dstLine += data.Width * 3;
- }
- bitmap.UnlockBits(data);
- return pixels;
- }
- }
- }
|