Dicom Printer

Created Diff never expires
7 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
334 lines
27 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
354 lines
using System;
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Imaging;
using System.Threading.Tasks;
using System.Threading.Tasks;
using FellowOakDicom;
using FellowOakDicom;
using FellowOakDicom.Imaging;
using FellowOakDicom.Imaging;
using FellowOakDicom.IO;
using FellowOakDicom.IO;
using FellowOakDicom.Network;
using FellowOakDicom.Network;
using FellowOakDicom.Printing;
using FellowOakDicom.Printing;
using FellowOakDicom.Network.Client;
using FellowOakDicom.Network.Client;
using FellowOakDicom.IO.Buffer;
using FellowOakDicom.IO.Buffer;
using System.IO;
using System.IO;
using System.Printing;


namespace libd2print
namespace libd2print
{
{


internal class DicomPrinter
internal class DicomPrinter
{
{
private static DicomPrinter _instance;
private static DicomPrinter _instance;


public static DicomPrinter I
public static DicomPrinter I
{
{
get
get
{
{
if (_instance == null)
if (_instance == null)
{
{
_instance = new DicomPrinter();
_instance = new DicomPrinter();
}
}
return _instance;
return _instance;
}
}


}
}


public async Task Print(string RemoteAddress, int RemotePort, string CallingAE, string CalledAE, string FullPrintJobFolder, int pages)
public async Task Print(string RemoteAddress, int RemotePort, string CallingAE, string CalledAE, string FullPrintJobFolder, int pages)
{
{
var printJob = new PrintJobDicom("DICOM PRINT JOB", "BLUE FILM")
var printJob = new PrintJobDicom("DICOM PRINT JOB", "BLUE FILM")
{
{
RemoteAddress = RemoteAddress,
RemoteAddress = RemoteAddress,
RemotePort = RemotePort,
RemotePort = RemotePort,
CallingAE = CallingAE,// printscu
CallingAE = CallingAE,// print scu
CalledAE = CalledAE //print scp
CalledAE = CalledAE //print scp
};
};


//greyscale
//greyscale


var testPath = Path.Combine(FullPrintJobFolder);
var testPath = Path.Combine(FullPrintJobFolder);
//var greyscaleImg = new DicomImage(testPath + "/I000001.dcm");
//var greyscaleImg = new DicomImage(testPath + "/I000001.dcm");


var i = 0;
var i = 0;
while (i < pages)
while (i < pages)
{
{
Image Dummy = Image.FromFile(testPath + "/" + (i + 1).ToString() + ".png");
Image Dummy = Image.FromFile(testPath + "/" + (i + 1).ToString() + ".png");
using (var dum = Dummy)
using (var dum = Dummy)
{
{
Bitmap bmp = new Bitmap(dum);
Bitmap bmp = new Bitmap(dum);
using (var bitmap = bmp)
using (var bitmap = bmp)
{
{
printJob.FilmSession.IsColor = false; //set to true to print in color
printJob.FilmSession.IsColor = false; //set to true to print in color
printJob.StartFilmBox("STANDARD\\1,1", "PORTRAIT", "10INX14IN", "BILINEAR");
printJob.StartFilmBox("STANDARD\\1,1", "PORTRAIT", "8INX10IN", "CUBIC");
printJob.AddImage(bitmap, 0);
printJob.AddImage(bitmap, 0);
}
}
}
}
i++;
i++;
}
}
printJob.EndFilmBox();
printJob.EndFilmBox();




await printJob.Print();
await printJob.Print();
}
}
}
}


internal class PrintJobDicom
internal class PrintJobDicom
{
{
public string CallingAE { get; set; }
public string CallingAE { get; set; }
public string CalledAE { get; set; }
public string CalledAE { get; set; }
public string RemoteAddress { get; set; }
public string RemoteAddress { get; set; }
public int RemotePort { get; set; }
public int RemotePort { get; set; }


public FilmSession FilmSession { get; private set; }
public FilmSession FilmSession { get; private set; }


private FilmBox _currentFilmBox;
private FilmBox _currentFilmBox;


public PrintJobDicom(string jobLabel, string mediumType = "PAPER")
public PrintJobDicom(string jobLabel, string mediumType = "PAPER")
{
{
FilmSession = new FilmSession(DicomUID.BasicFilmSession)
FilmSession = new FilmSession(DicomUID.BasicFilmSession)
{
{
FilmSessionLabel = jobLabel,
FilmSessionLabel = jobLabel,
MediumType = mediumType,
MediumType = mediumType,
NumberOfCopies = 1
NumberOfCopies = 1,
PrintPriority = "MED",
FilmDestination = "BIN_1",
};
};

FilmSession.FilmSessionLabel = "";
}
}


public FilmBox StartFilmBox(string format, string orientation, string filmSize, string magnificationType = "NONE")
public FilmBox StartFilmBox(string format, string orientation, string filmSize, string magnificationType = "NONE")
{
{
var filmBox = new FilmBox(FilmSession, null, DicomTransferSyntax.ExplicitVRLittleEndian)
var filmBox = new FilmBox(FilmSession, null, DicomTransferSyntax.ExplicitVRLittleEndian)
{
{
ImageDisplayFormat = format,
ImageDisplayFormat = format,
FilmOrientation = orientation,
FilmOrientation = orientation,
FilmSizeID = filmSize,
FilmSizeID = filmSize,
MagnificationType = magnificationType,
MagnificationType = magnificationType,
BorderDensity = "WHITE",
BorderDensity = "WHITE",
EmptyImageDensity = "BLACK",
//EmptyImageDensity = "BLACK",
Trim = "YES"
//Trim = "YES"
};
};


filmBox.AnnotationDisplayFormatID = "0";
filmBox.SmoothingType = "5";
filmBox.Illumination = 2000;
filmBox.ReflectedAmbientLight = 10;
filmBox.Trim = "NO";


filmBox.Initialize();
filmBox.Initialize();
FilmSession.BasicFilmBoxes.Add(filmBox);
FilmSession.BasicFilmBoxes.Add(filmBox);


_currentFilmBox = filmBox;
_currentFilmBox = filmBox;
return filmBox;
return filmBox;
}
}


public void AddImage(Bitmap bitmap, int index)
public void AddImage(Bitmap bitmap, int index)
{
{
if (FilmSession.IsColor)
if (FilmSession.IsColor)
{
{
AddColorImage(bitmap, index);
AddColorImage(bitmap, index);
}
}
else
else
{
{
AddGreyscaleImage(bitmap, index);
AddGreyscaleImage(bitmap, index);
}
}
}
}


private void AddGreyscaleImage(Bitmap bitmap, int index)
private void AddGreyscaleImage(Bitmap bitmap, int index)
{
{
if (_currentFilmBox == null)
if (_currentFilmBox == null)
{
{
throw new InvalidOperationException("Start film box first!");
throw new InvalidOperationException("Start film box first!");
}
}
if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count)
if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count)
{
{
throw new ArgumentOutOfRangeException(nameof(index), "Image box index out of range");
throw new ArgumentOutOfRangeException(nameof(index), "Image box index out of range");
}
}


if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb
if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb
&& bitmap.PixelFormat != PixelFormat.Format32bppRgb)
&& bitmap.PixelFormat != PixelFormat.Format32bppRgb)
{
{
throw new ArgumentException("Not supported bitmap format", nameof(bitmap));
throw new ArgumentException("Not supported bitmap format", nameof(bitmap));
}
}


var dataset = new DicomDataset();
var dataset = new DicomDataset();
dataset.Add<ushort>(DicomTag.Columns, (ushort)bitmap.Width)
dataset.Add<ushort>(DicomTag.Columns, (ushort)bitmap.Width)
.Add<ushort>(DicomTag.Rows, (ushort)bitmap.Height)
.Add<ushort>(DicomTag.Rows, (ushort)bitmap.Height)
.Add<ushort>(DicomTag.BitsAllocated, 8)
.Add<ushort>(DicomTag.BitsAllocated, 8)
.Add<ushort>(DicomTag.BitsStored, 8)
.Add<ushort>(DicomTag.BitsStored, 8)
.Add<ushort>(DicomTag.HighBit, 7)
.Add<ushort>(DicomTag.HighBit, 7)
.Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned)
.Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned)
.Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved)
.Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved)
.Add<ushort>(DicomTag.SamplesPerPixel, 1)
.Add<ushort>(DicomTag.SamplesPerPixel, 1)//OK
.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value);
.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Monochrome2);
dataset.Add(DicomTag.PixelAspectRatio, 1);
dataset.Add(DicomTag.PixelRepresentation, "0000H");
dataset.Add(DicomTag.Polarity, "NORMAL");
dataset.Add(DicomTag.MagnificationType, "CUBIC");
dataset.Add(DicomTag.SmoothingType, 5);
dataset.Add(DicomTag.ConfigurationInformation, "LUT=Ver693c0.w87,6");
dataset.Add(DicomTag.RequestedImageSize, "0.00");
dataset.Add(DicomTag.RequestedDecimateCropBehavior, "DECIMATE");


var pixelData = DicomPixelData.Create(dataset, true);
var pixelData = DicomPixelData.Create(dataset, true);


var pixels = GetGreyBytes(bitmap);
var pixels = GetGreyBytes(bitmap);
var buffer = new MemoryByteBuffer(pixels.Data);
var buffer = new MemoryByteBuffer(pixels.Data);


pixelData.AddFrame(buffer);
pixelData.AddFrame(buffer);


var imageBox = _currentFilmBox.BasicImageBoxes[index];
var imageBox = _currentFilmBox.BasicImageBoxes[index];
imageBox.ImageSequence = dataset;
imageBox.ImageSequence = dataset;


pixels.Dispose();
pixels.Dispose();
}
}


private void AddColorImage(Bitmap bitmap, int index)
private void AddColorImage(Bitmap bitmap, int index)
{
{
if (_currentFilmBox == null)
if (_currentFilmBox == null)
{
{
throw new InvalidOperationException("Start film box first!");
throw new InvalidOperationException("Start film box first!");
}
}
if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count)
if (index < 0 || index > _currentFilmBox.BasicImageBoxes.Count)
{
{
throw new ArgumentOutOfRangeException(nameof(index), "Image box index out of range");
throw new ArgumentOutOfRangeException(nameof(index), "Image box index out of range");
}
}


if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb
if (bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb
&& bitmap.PixelFormat != PixelFormat.Format32bppRgb)
&& bitmap.PixelFormat != PixelFormat.Format32bppRgb)
{
{
throw new ArgumentException("Not supported bitmap format", nameof(bitmap));
throw new ArgumentException("Not supported bitmap format", nameof(bitmap));
}
}


var dataset = new DicomDataset();
var dataset = new DicomDataset();
dataset.Add<ushort>(DicomTag.Columns, (ushort)bitmap.Width)
dataset.Add<ushort>(DicomTag.Columns, (ushort)bitmap.Width)
.Add<ushort>(DicomTag.Rows, (ushort)bitmap.Height)
.Add<ushort>(DicomTag.Rows, (ushort)bitmap.Height)
.Add<ushort>(DicomTag.BitsAllocated, 8)
.Add<ushort>(DicomTag.BitsAllocated, 8)
.Add<ushort>(DicomTag.BitsStored, 8)
.Add<ushort>(DicomTag.BitsStored, 8)
.Add<ushort>(DicomTag.HighBit, 7)
.Add<ushort>(DicomTag.HighBit, 7)
.Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned)
.Add(DicomTag.PixelRepresentation, (ushort)PixelRepresentation.Unsigned)
.Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved)
.Add(DicomTag.PlanarConfiguration, (ushort)PlanarConfiguration.Interleaved)
.Add<ushort>(DicomTag.SamplesPerPixel, 3)
.Add<ushort>(DicomTag.SamplesPerPixel, 3)
.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value);
.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value);


var pixelData = DicomPixelData.Create(dataset, true);
var pixelData = DicomPixelData.Create(dataset, true);


var pixels = GetColorbytes(bitmap);
var pixels = GetColorbytes(bitmap);
var buffer = new MemoryByteBuffer(pixels.Data);
var buffer = new MemoryByteBuffer(pixels.Data);


pixelData.AddFrame(buffer);
pixelData.AddFrame(buffer);


var imageBox = _currentFilmBox.BasicImageBoxes[index];
var imageBox = _currentFilmBox.BasicImageBoxes[index];
imageBox.ImageSequence = dataset;
imageBox.ImageSequence = dataset;


pixels.Dispose();
pixels.Dispose();
}
}


public void EndFilmBox()
public void EndFilmBox()
{
{
_currentFilmBox = null;
_currentFilmBox = null;
}
}


public async Task Print()
public async Task Print()
{
{
var dicomClient = DicomClientFactory.Create(RemoteAddress, RemotePort, false, CallingAE, CalledAE);
var dicomClient = DicomClientFactory.Create(RemoteAddress, RemotePort, false, CallingAE, CalledAE);


await dicomClient.AddRequestAsync(
await dicomClient.AddRequestAsync(
new DicomNCreateRequest(FilmSession.SOPClassUID, FilmSession.SOPInstanceUID)
new DicomNCreateRequest(FilmSession.SOPClassUID, FilmSession.SOPInstanceUID)
{
{
Dataset = FilmSession
Dataset = FilmSession
});
});




foreach (var filmbox in FilmSession.BasicFilmBoxes)
foreach (var filmbox in FilmSession.BasicFilmBoxes)
{
{


var imageBoxRequests = new List<DicomNSetRequest>();
var imageBoxRequests = new List<DicomNSetRequest>();


var filmBoxRequest = new DicomNCreateRequest(FilmBox.SOPClassUID, filmbox.SOPInstanceUID)
var filmBoxRequest = new DicomNCreateRequest(FilmBox.SOPClassUID, filmbox.SOPInstanceUID)
{
{
Dataset = filmbox
Dataset = filmbox
};
};
filmBoxRequest.OnResponseReceived = (request, response) =>
filmBoxRequest.OnResponseReceived = (request, response) =>
{
{
if (response.HasDataset)
if (response.HasDataset)
{
{
var seq = response.Dataset.GetSequence(DicomTag.ReferencedImageBoxSequence);
var seq = response.Dataset.GetSequence(DicomTag.ReferencedImageBoxSequence);
for (int i = 0; i < seq.Items.Count; i++)
for (int i = 0; i < seq.Items.Count; i++)
{
{
var req = imageBoxRequests[i];
var req = imageBoxRequests[i];
var imageBox = req.Dataset;
var imageBox = req.Dataset;
var sopInstanceUid = seq.Items[i].GetSingleValue<string>(DicomTag.ReferencedSOPInstanceUID);
var sopInstanceUid = seq.Items[i].GetSingleValue<string>(DicomTag.ReferencedSOPInstanceUID);
imageBox.AddOrUpdate(DicomTag.SOPInstanceUID, sopInstanceUid);
imageBox.AddOrUpdate(DicomTag.SOPInstanceUID, sopInstanceUid);
req.Command.AddOrUpdate(DicomTag.RequestedSOPInstanceUID, sopInstanceUid);
req.Command.AddOrUpdate(DicomTag.RequestedSOPInstanceUID, sopInstanceUid);
}
}
}
}
};
};
await dicomClient.AddRequestAsync(filmBoxRequest);
await dicomClient.AddRequestAsync(filmBoxRequest);


foreach (var image in filmbox.BasicImageBoxes)
foreach (var image in filmbox.BasicImageBoxes)
{
{
var req = new DicomNSetRequest(image.SOPClassUID, image.SOPInstanceUID) { Dataset = image };
var req = new DicomNSetRequest(image.SOPClassUID, image.SOPInstanceUID) { Dataset = image };


imageBoxRequests.Add(req);
imageBoxRequests.Add(req);
await dicomClient.AddRequestAsync(req);
await dicomClient.AddRequestAsync(req);
}
}
}
}


await dicomClient.AddRequestAsync(new DicomNActionRequest(FilmSession.SOPClassUID, FilmSession.SOPInstanceUID, 0x0001));
await dicomClient.AddRequestAsync(new DicomNActionRequest(FilmSession.SOPClassUID, FilmSession.SOPInstanceUID, 0x0001));


await dicomClient.SendAsync();
await dicomClient.SendAsync();
}
}




private unsafe PinnedByteArray GetGreyBytes(Bitmap bitmap)
private unsafe PinnedByteArray GetGreyBytes(Bitmap bitmap)
{
{
var pixels = new PinnedByteArray(bitmap.Width * bitmap.Height);
var pixels = new PinnedByteArray(bitmap.Width * bitmap.Height);


var data = bitmap.LockBits(
var data = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly,
ImageLockMode.ReadOnly,
bitmap.PixelFormat);
bitmap.PixelFormat);


var srcComponents = bitmap.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;
var srcComponents = bitmap.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;


var dstLine = (byte*)pixels.Pointer;
var dstLine = (byte*)pixels.Pointer;
var srcLine = (byte*)data.Scan0.ToPointer();
var srcLine = (byte*)data.Scan0.ToPointer();


for (int i = 0; i < data.Height; i++)
for (int i = 0; i < data.Height; i++)
{
{
for (int j = 0; j < data.Width; j++)
for (int j = 0; j < data.Width; j++)
{
{
var pixel = srcLine + j * srcComponents;
var pixel = srcLine + j * srcComponents;
int grey = (int)(pixel[0] * 0.3 + pixel[1] * 0.59 + pixel[2] * 0.11);
int grey = (int)(pixel[0] * 0.3 + pixel[1] * 0.59 + pixel[2] * 0.11);
dstLine[j] = (byte)grey;
dstLine[j] = (byte)grey;
}
}


srcLine += data.Stride;
srcLine += data.Stride;
dstLine += data.Width;
dstLine += data.Width;
}
}
bitmap.UnlockBits(data);
bitmap.UnlockBits(data);


return pixels;
return pixels;
}
}


private unsafe PinnedByteArray GetColorbytes(Bitmap bitmap)
private unsafe PinnedByteArray GetColorbytes(Bitmap bitmap)
{
{
var pixels = new PinnedByteArray(bitmap.Width * bitmap.Height * 3);
var pixels = new PinnedByteArray(bitmap.Width * bitmap.Height * 3);


var data = bitmap.LockBits(
var data = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly,
ImageLockMode.ReadOnly,
bitmap.PixelFormat);
bitmap.PixelFormat);


var srcComponents = bitmap.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;
var srcComponents = bitmap.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;


var dstLine = (byte*)pixels.Pointer;
var dstLine = (byte*)pixels.Pointer;
var srcLine = (byte*)data.Scan0.ToPointer();
var srcLine = (byte*)data.Scan0.ToPointer();


for (int i = 0; i < data.Height; i++)
for (int i = 0; i < data.Height; i++)
{
{
for (int j = 0; j < data.Width; j++)
for (int j = 0; j < data.Width; j++)
{
{
var srcPixel = srcLine + j * srcComponents;
var srcPixel = srcLine + j * srcComponents;
var dstPixel = dstLine + j * 3;
var dstPixel = dstLine + j * 3;


//convert from bgr to rgb
//convert from bgr to rgb
dstPixel[0] = srcPixel[2];
dstPixel[0] = srcPixel[2];
dstPixel[1] = srcPixel[1];
dstPixel[1] = srcPixel[1];
dstPixel[2] = srcPixel[0];
dstPixel[2] = srcPixel[0];
}
}


srcLine += data.Stride;
srcLine += data.Stride;
dstLine += data.Width * 3;
dstLine += data.Width * 3;
}
}
bitmap.UnlockBits(data);
bitmap.UnlockBits(data);


return pixels;
return pixels;
}
}


}
}
}
}