public static float[][] ReadMapFloat(string path, int2 headerlessSliceDims, long headerlessOffset, Type headerlessType, int layer = -1) { MapHeader Header = null; Type ValueType = null; FileInfo Info = new FileInfo(path); float[][] Data; using (BinaryReader Reader = new BinaryReader(OpenWithBigBuffer(path))) { Header = MapHeader.ReadFromFile(Reader, Info, headerlessSliceDims, headerlessOffset, headerlessType); ValueType = Header.GetValueType(); Data = new float[layer < 0 ? Header.Dimensions.Z : 1][]; if (Header.GetType() != typeof(HeaderTiff)) { for (int z = 0; z < Data.Length; z++) { if (layer >= 0) { Reader.BaseStream.Seek((int)Header.Dimensions.ElementsSlice() * (int)ImageFormatsHelper.SizeOf(ValueType) * layer, SeekOrigin.Current); } byte[] Bytes = Reader.ReadBytes((int)Header.Dimensions.ElementsSlice() * (int)ImageFormatsHelper.SizeOf(ValueType)); Data[z] = new float[(int)Header.Dimensions.ElementsSlice()]; unsafe { int Elements = (int)Header.Dimensions.ElementsSlice(); fixed(byte *BytesPtr = Bytes) fixed(float *DataPtr = Data[z]) { float *DataP = DataPtr; if (ValueType == typeof(byte)) { byte *BytesP = BytesPtr; for (int i = 0; i < Elements; i++) { *DataP++ = (float)*BytesP++; } } else if (ValueType == typeof(short)) { short *BytesP = (short *)BytesPtr; for (int i = 0; i < Elements; i++) { *DataP++ = (float)*BytesP++; } } else if (ValueType == typeof(ushort)) { ushort *BytesP = (ushort *)BytesPtr; for (int i = 0; i < Elements; i++) { *DataP++ = (float)*BytesP++; } } else if (ValueType == typeof(int)) { int *BytesP = (int *)BytesPtr; for (int i = 0; i < Elements; i++) { *DataP++ = (float)*BytesP++; } } else if (ValueType == typeof(float)) { float *BytesP = (float *)BytesPtr; for (int i = 0; i < Elements; i++) { *DataP++ = *BytesP++; } } else if (ValueType == typeof(double)) { double *BytesP = (double *)BytesPtr; for (int i = 0; i < Elements; i++) { *DataP++ = (float)*BytesP++; } } } } } } else { Data = ((HeaderTiff)Header).ReadData(layer); } } return(Data); }
static Image LoadAndPrepareStack(string path, decimal scaleFactor, int maxThreads = 8) { Image stack = null; MapHeader header = MapHeader.ReadFromFilePatient(50, 500, path, HeaderlessDims, (int)HeaderlessOffset, ImageFormatsHelper.StringToType(HeaderlessType)); string Extension = Helper.PathToExtension(path).ToLower(); bool IsTiff = header.GetType() == typeof(HeaderTiff); bool IsEER = header.GetType() == typeof(HeaderEER); if (GainRef != null) { if (!IsEER) { if (header.Dimensions.X != GainRef.Dims.X || header.Dimensions.Y != GainRef.Dims.Y) { throw new Exception("Gain reference dimensions do not match image."); } } } int EERSupersample = 1; if (GainRef != null && IsEER) { if (header.Dimensions.X == GainRef.Dims.X) { EERSupersample = 1; } else if (header.Dimensions.X * 2 == GainRef.Dims.X) { EERSupersample = 2; } else if (header.Dimensions.X * 4 == GainRef.Dims.X) { EERSupersample = 3; } else { throw new Exception("Invalid supersampling factor requested for EER based on gain reference dimensions"); } } HeaderEER.SuperResolution = EERSupersample; if (IsEER && GainRef != null) { header.Dimensions.X = GainRef.Dims.X; header.Dimensions.Y = GainRef.Dims.Y; } int NThreads = (IsTiff || IsEER) ? 6 : 2; int GPUThreads = 2; int CurrentDevice = GPU.GetDevice(); if (RawLayers == null || RawLayers.Length != NThreads || RawLayers[0].Length != header.Dimensions.ElementsSlice()) { RawLayers = Helper.ArrayOfFunction(i => new float[header.Dimensions.ElementsSlice()], NThreads); } Image[] GPULayers = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, header.Dimensions.Slice()), GPUThreads); Image[] GPULayers2 = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, header.Dimensions.Slice()), GPUThreads); if (scaleFactor == 1M) { stack = new Image(header.Dimensions); float[][] OriginalStackData = stack.GetHost(Intent.Write); object[] Locks = Helper.ArrayOfFunction(i => new object(), GPUThreads); Helper.ForCPU(0, header.Dimensions.Z, NThreads, threadID => GPU.SetDevice(DeviceID), (z, threadID) => { if (IsTiff) { TiffNative.ReadTIFFPatient(50, 500, path, z, true, RawLayers[threadID]); } else if (IsEER) { EERNative.ReadEERPatient(50, 500, path, z * 10, (z + 1) * 10, EERSupersample, RawLayers[threadID]); } else { IOHelper.ReadMapFloatPatient(50, 500, path, HeaderlessDims, (int)HeaderlessOffset, ImageFormatsHelper.StringToType(HeaderlessType), new[] { z }, null, new[] { RawLayers[threadID] }); } int GPUThreadID = threadID % GPUThreads; lock (Locks[GPUThreadID]) { GPU.CopyHostToDevice(RawLayers[threadID], GPULayers[GPUThreadID].GetDevice(Intent.Write), RawLayers[threadID].Length); if (GainRef != null) { if (IsEER) { GPULayers[GPUThreadID].DivideSlices(GainRef); } else { GPULayers[GPUThreadID].MultiplySlices(GainRef); } } if (DefectMap != null) { GPU.CopyDeviceToDevice(GPULayers[GPUThreadID].GetDevice(Intent.Read), GPULayers2[GPUThreadID].GetDevice(Intent.Write), header.Dimensions.Elements()); DefectMap.Correct(GPULayers2[GPUThreadID], GPULayers[GPUThreadID]); } GPU.Xray(GPULayers[GPUThreadID].GetDevice(Intent.Read), GPULayers2[GPUThreadID].GetDevice(Intent.Write), 20f, new int2(header.Dimensions), 1); GPU.CopyDeviceToHost(GPULayers2[GPUThreadID].GetDevice(Intent.Read), OriginalStackData[z], header.Dimensions.ElementsSlice()); } }, null); } else { int3 ScaledDims = new int3((int)Math.Round(header.Dimensions.X * scaleFactor) / 2 * 2, (int)Math.Round(header.Dimensions.Y * scaleFactor) / 2 * 2, header.Dimensions.Z); stack = new Image(ScaledDims); float[][] OriginalStackData = stack.GetHost(Intent.Write); int[] PlanForw = Helper.ArrayOfFunction(i => GPU.CreateFFTPlan(header.Dimensions.Slice(), 1), GPUThreads); int[] PlanBack = Helper.ArrayOfFunction(i => GPU.CreateIFFTPlan(ScaledDims.Slice(), 1), GPUThreads); Image[] GPULayersInputFT = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, header.Dimensions.Slice(), true, true), GPUThreads); Image[] GPULayersOutputFT = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, ScaledDims.Slice(), true, true), GPUThreads); Image[] GPULayersScaled = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, ScaledDims.Slice()), GPUThreads); object[] Locks = Helper.ArrayOfFunction(i => new object(), GPUThreads); Helper.ForCPU(0, ScaledDims.Z, NThreads, threadID => GPU.SetDevice(DeviceID), (z, threadID) => { if (IsTiff) { TiffNative.ReadTIFFPatient(50, 500, path, z, true, RawLayers[threadID]); } else if (IsEER) { EERNative.ReadEERPatient(50, 500, path, z * 10, (z + 1) * 10, EERSupersample, RawLayers[threadID]); } else { IOHelper.ReadMapFloatPatient(50, 500, path, HeaderlessDims, (int)HeaderlessOffset, ImageFormatsHelper.StringToType(HeaderlessType), new[] { z }, null, new[] { RawLayers[threadID] }); } int GPUThreadID = threadID % GPUThreads; lock (Locks[GPUThreadID]) { GPU.CopyHostToDevice(RawLayers[threadID], GPULayers[GPUThreadID].GetDevice(Intent.Write), RawLayers[threadID].Length); if (GainRef != null) { if (IsEER) { GPULayers[GPUThreadID].DivideSlices(GainRef); } else { GPULayers[GPUThreadID].MultiplySlices(GainRef); } } if (DefectMap != null) { GPU.CopyDeviceToDevice(GPULayers[GPUThreadID].GetDevice(Intent.Read), GPULayers2[GPUThreadID].GetDevice(Intent.Write), header.Dimensions.Elements()); DefectMap.Correct(GPULayers2[GPUThreadID], GPULayers[GPUThreadID]); } GPU.Xray(GPULayers[GPUThreadID].GetDevice(Intent.Read), GPULayers2[GPUThreadID].GetDevice(Intent.Write), 20f, new int2(header.Dimensions), 1); GPU.Scale(GPULayers2[GPUThreadID].GetDevice(Intent.Read), GPULayersScaled[GPUThreadID].GetDevice(Intent.Write), header.Dimensions.Slice(), ScaledDims.Slice(), 1, PlanForw[GPUThreadID], PlanBack[GPUThreadID], GPULayersInputFT[GPUThreadID].GetDevice(Intent.Write), GPULayersOutputFT[GPUThreadID].GetDevice(Intent.Write)); GPU.CopyDeviceToHost(GPULayersScaled[GPUThreadID].GetDevice(Intent.Read), OriginalStackData[z], ScaledDims.ElementsSlice()); } }, null); for (int i = 0; i < GPUThreads; i++) { GPU.DestroyFFTPlan(PlanForw[i]); GPU.DestroyFFTPlan(PlanBack[i]); GPULayersInputFT[i].Dispose(); GPULayersOutputFT[i].Dispose(); GPULayersScaled[i].Dispose(); } } foreach (var layer in GPULayers) { layer.Dispose(); } foreach (var layer in GPULayers2) { layer.Dispose(); } return(stack); }
static Image LoadAndPrepareStack(string path, Image imageGain, decimal scaleFactor, int maxThreads = 8) { Image stack = null; MapHeader header = MapHeader.ReadFromFilePatient(50, 500, path, HeaderlessDims, (int)HeaderlessOffset, ImageFormatsHelper.StringToType(HeaderlessType)); if (imageGain != null) { if (header.Dimensions.X != imageGain.Dims.X || header.Dimensions.Y != imageGain.Dims.Y) { throw new Exception("Gain reference dimensions do not match image."); } } bool IsTiff = header.GetType() == typeof(HeaderTiff); int NThreads = IsTiff ? 6 : 2; int GPUThreads = 2; int CurrentDevice = GPU.GetDevice(); if (RawLayers == null || RawLayers.Length != NThreads || RawLayers[0].Length != header.Dimensions.ElementsSlice()) { RawLayers = Helper.ArrayOfFunction(i => new float[header.Dimensions.ElementsSlice()], NThreads); } Image[] GPULayers = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, header.Dimensions.Slice()), GPUThreads); Image[] GPULayers2 = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, header.Dimensions.Slice()), GPUThreads); if (scaleFactor == 1M) { stack = new Image(header.Dimensions); float[][] OriginalStackData = stack.GetHost(Intent.Write); object[] Locks = Helper.ArrayOfFunction(i => new object(), GPUThreads); Helper.ForCPU(0, header.Dimensions.Z, NThreads, threadID => GPU.SetDevice(DeviceID), (z, threadID) => { if (IsTiff) { TiffNative.ReadTIFFPatient(50, 500, path, z, true, RawLayers[threadID]); } else { IOHelper.ReadMapFloatPatient(50, 500, path, HeaderlessDims, (int)HeaderlessOffset, ImageFormatsHelper.StringToType(HeaderlessType), z, null, new[] { RawLayers[threadID] }); } int GPUThreadID = threadID % GPUThreads; lock (Locks[GPUThreadID]) { GPU.CopyHostToDevice(RawLayers[threadID], GPULayers[GPUThreadID].GetDevice(Intent.Write), RawLayers[threadID].Length); if (imageGain != null) { GPULayers[GPUThreadID].MultiplySlices(imageGain); } GPU.Xray(GPULayers[GPUThreadID].GetDevice(Intent.Read), GPULayers2[GPUThreadID].GetDevice(Intent.Write), 20f, new int2(header.Dimensions), 1); GPU.CopyDeviceToHost(GPULayers2[GPUThreadID].GetDevice(Intent.Read), OriginalStackData[z], header.Dimensions.ElementsSlice()); } }, null); } else { int3 ScaledDims = new int3((int)Math.Round(header.Dimensions.X * scaleFactor) / 2 * 2, (int)Math.Round(header.Dimensions.Y * scaleFactor) / 2 * 2, header.Dimensions.Z); stack = new Image(ScaledDims); float[][] OriginalStackData = stack.GetHost(Intent.Write); int[] PlanForw = Helper.ArrayOfFunction(i => GPU.CreateFFTPlan(header.Dimensions.Slice(), 1), GPUThreads); int[] PlanBack = Helper.ArrayOfFunction(i => GPU.CreateIFFTPlan(ScaledDims.Slice(), 1), GPUThreads); Image[] GPULayersInputFT = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, header.Dimensions.Slice(), true, true), GPUThreads); Image[] GPULayersOutputFT = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, ScaledDims.Slice(), true, true), GPUThreads); Image[] GPULayersScaled = Helper.ArrayOfFunction(i => new Image(IntPtr.Zero, ScaledDims.Slice()), GPUThreads); object[] Locks = Helper.ArrayOfFunction(i => new object(), GPUThreads); Helper.ForCPU(0, ScaledDims.Z, NThreads, threadID => GPU.SetDevice(DeviceID), (z, threadID) => { if (IsTiff) { TiffNative.ReadTIFFPatient(50, 500, path, z, true, RawLayers[threadID]); } else { IOHelper.ReadMapFloatPatient(50, 500, path, HeaderlessDims, (int)HeaderlessOffset, ImageFormatsHelper.StringToType(HeaderlessType), z, null, new[] { RawLayers[threadID] }); } int GPUThreadID = threadID % GPUThreads; lock (Locks[GPUThreadID]) { GPU.CopyHostToDevice(RawLayers[threadID], GPULayers[GPUThreadID].GetDevice(Intent.Write), RawLayers[threadID].Length); if (imageGain != null) { GPULayers[GPUThreadID].MultiplySlices(imageGain); } GPU.Xray(GPULayers[GPUThreadID].GetDevice(Intent.Read), GPULayers2[GPUThreadID].GetDevice(Intent.Write), 20f, new int2(header.Dimensions), 1); GPU.Scale(GPULayers2[GPUThreadID].GetDevice(Intent.Read), GPULayersScaled[GPUThreadID].GetDevice(Intent.Write), header.Dimensions.Slice(), ScaledDims.Slice(), 1, PlanForw[GPUThreadID], PlanBack[GPUThreadID], GPULayersInputFT[GPUThreadID].GetDevice(Intent.Write), GPULayersOutputFT[GPUThreadID].GetDevice(Intent.Write)); GPU.CopyDeviceToHost(GPULayersScaled[GPUThreadID].GetDevice(Intent.Read), OriginalStackData[z], ScaledDims.ElementsSlice()); } }, null); for (int i = 0; i < GPUThreads; i++) { GPU.DestroyFFTPlan(PlanForw[i]); GPU.DestroyFFTPlan(PlanBack[i]); GPULayersInputFT[i].Dispose(); GPULayersOutputFT[i].Dispose(); GPULayersScaled[i].Dispose(); } } foreach (var layer in GPULayers) { layer.Dispose(); } foreach (var layer in GPULayers2) { layer.Dispose(); } return(stack); }