├── .gitignore
├── Kernels
├── DeBayerKernels.cu
├── Kernels.vcxproj
├── RobustnessModell.cu
├── ShiftMinimizerKernels.cu
├── kernel.cu
└── opticalFlow.cu
├── LICENSE
├── PEFStudioDX
├── App.config
├── App.xaml
├── App.xaml.cs
├── BasicKernels.cs
├── DeBayerKernels.cs
├── DeBayerKernels.ptx
├── DeBayerKernelsDebug.ptx
├── EnumConverter.cs
├── ExtraCameraProfiles.xml
├── ImagePresenterDX.xaml
├── ImagePresenterDX.xaml.cs
├── ImageStackAlignatorController.cs
├── LUTControl.xaml
├── LUTControl.xaml.cs
├── LUTHost.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Matrix.cs
├── OpticalFlow.cs
├── OpticalFlowKernels.cs
├── PEFStudioDX.csproj
├── PatchTracker.cs
├── PatchTrackingLevel.cs
├── PreAlignment.cs
├── PreAlignmentStore.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── RobustnessModell.ptx
├── RobustnessModellDebug.ptx
├── RobustnessModellKernel.cs
├── ShiftCollection.cs
├── ShiftMinimizerKernels.cs
├── ShiftMinimizerKernels.ptx
├── ShiftMinimizerKernelsDebug.ptx
├── SlimDX.dll
├── TestRawFile.cs
├── kernel.ptx
├── kernelDebug.ptx
├── opticalFlow.ptx
├── opticalFlowDebug.ptx
└── packages.config
├── PefFile
├── DNGColorSpace.cs
├── DNGColorSpec.cs
├── DNGFile.cs
├── DNGMatrix.cs
├── DNGOrientation.cs
├── DNGTemperature.cs
├── DNGUtils.cs
├── DNGVector.cs
├── DNGxyCoord.cs
├── ExifEntry.cs
├── ExtraCameraProfiles.cs
├── FileReader.cs
├── GPSDirectoryEntry.cs
├── ImageFileDirectory.cs
├── ImageFileDirectoryEntry.cs
├── Opcode.cs
├── PEFFile.cs
├── PefFile.csproj
├── PentaxMakerNotes.cs
├── PentaxMakerNotesEntry.cs
├── Properties
│ └── AssemblyInfo.cs
├── RawFile.cs
├── SaveTiffTag.cs
└── TIFFValueTypes.cs
├── README.md
├── TestingGoogleSuperRes.sln
└── pictures
├── AdobeCrop.png
├── SuperResCrop.png
├── alpha.gif
├── app1.png
├── app2.png
├── app21.png
├── app3.png
├── app4.png
├── app5.png
├── beta.gif
├── dmd.gif
├── dms.gif
├── edge.gif
├── fraclam1lam2.gif
├── grandCanyon.png
├── lam1.gif
├── lam2.gif
├── newyorkFrame3.png
├── newyorkFrame3Crop1.png
├── newyorkMerged.png
├── newyorkMergedCrop1.png
├── noiseModel.gif
├── overview.png
├── samsung.png
├── sigmamd.gif
├── sigmamdsqrt2.gif
├── sigmams.gif
├── sigmamssqrt2.gif
├── sqrt2.gif
├── superRes.png
└── x.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Microsoft Azure ApplicationInsights config file
170 | ApplicationInsights.config
171 |
172 | # Windows Store app package directory
173 | AppPackages/
174 | BundleArtifacts/
175 |
176 | # Visual Studio cache files
177 | # files ending in .cache can be ignored
178 | *.[Cc]ache
179 | # but keep track of directories ending in .cache
180 | !*.[Cc]ache/
181 |
182 | # Others
183 | ClientBin/
184 | [Ss]tyle[Cc]op.*
185 | ~$*
186 | *~
187 | *.dbmdl
188 | *.dbproj.schemaview
189 | *.pfx
190 | *.publishsettings
191 | node_modules/
192 | orleans.codegen.cs
193 |
194 | # RIA/Silverlight projects
195 | Generated_Code/
196 |
197 | # Backup & report files from converting an old project file
198 | # to a newer Visual Studio version. Backup files are not needed,
199 | # because we have git ;-)
200 | _UpgradeReport_Files/
201 | Backup*/
202 | UpgradeLog*.XML
203 | UpgradeLog*.htm
204 |
205 | # SQL Server files
206 | *.mdf
207 | *.ldf
208 |
209 | # Business Intelligence projects
210 | *.rdl.data
211 | *.bim.layout
212 | *.bim_*.settings
213 |
214 | # Microsoft Fakes
215 | FakesAssemblies/
216 |
217 | # GhostDoc plugin setting file
218 | *.GhostDoc.xml
219 |
220 | # Node.js Tools for Visual Studio
221 | .ntvs_analysis.dat
222 |
223 | # Visual Studio 6 build log
224 | *.plg
225 |
226 | # Visual Studio 6 workspace options file
227 | *.opt
228 |
229 | # Visual Studio LightSwitch build output
230 | **/*.HTMLClient/GeneratedArtifacts
231 | **/*.DesktopClient/GeneratedArtifacts
232 | **/*.DesktopClient/ModelManifest.xml
233 | **/*.Server/GeneratedArtifacts
234 | **/*.Server/ModelManifest.xml
235 | _Pvt_Extensions
236 |
237 | # LightSwitch generated files
238 | GeneratedArtifacts/
239 | ModelManifest.xml
240 |
241 | # Paket dependency manager
242 | .paket/paket.exe
243 |
244 | # FAKE - F# Make
245 | .fake/
--------------------------------------------------------------------------------
/Kernels/Kernels.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 |
14 | {80B85EE4-5AE5-4FD5-80ED-274F7E913606}
15 | Kernels
16 | 10.0
17 |
18 |
19 |
20 | Utility
21 | true
22 | MultiByte
23 | v142
24 |
25 |
26 | Utility
27 | false
28 | true
29 | MultiByte
30 | v142
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | true
45 | $(SolutionDir)PEFStudioDX\
46 |
47 |
48 | $(SolutionDir)PEFStudioDX\
49 |
50 |
51 |
52 | Level3
53 | Disabled
54 | WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
55 |
56 |
57 | true
58 | Console
59 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
60 |
61 |
62 | 64
63 | $(OutDir)%(Filename)Debug.ptx
64 | ptx
65 |
66 |
67 |
68 |
69 | Level3
70 | MaxSpeed
71 | true
72 | true
73 | WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
74 |
75 |
76 | true
77 | true
78 | true
79 | Console
80 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
81 |
82 |
83 | 64
84 | $(OutDir)%(Filename).ptx
85 | ptx
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/Kernels/RobustnessModell.cu:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 |
20 | #include "cuda_runtime.h"
21 | #include "device_launch_parameters.h"
22 |
23 | #include
24 | #include
25 |
26 | #include
27 |
28 | extern "C"
29 | __global__ void ComputeRobustnessMask(
30 | const float3* __restrict__ rawImgRef,
31 | const float3* __restrict__ rawImgMoved,
32 | float4* __restrict__ robustnessMask,
33 | cudaTextureObject_t texUV,
34 | int imgWidth,
35 | int imgHeight,
36 | int imgPitch,
37 | int maskPitch,
38 | float alpha,
39 | float beta,
40 | float thresholdM)
41 | {
42 | int pxX = blockIdx.x * blockDim.x + threadIdx.x;
43 | int pxY = blockIdx.y * blockDim.y + threadIdx.y;
44 |
45 | extern __shared__ float3 pixelsRef[];
46 | int sharedOffset = 3 * 3 * (threadIdx.y * blockDim.x + threadIdx.x);
47 |
48 | if (pxX >= imgWidth - 1|| pxY >= imgHeight - 1 || pxX < 1 || pxY < 1)
49 | return;
50 |
51 | float3 meanRef = make_float3(0, 0, 0);
52 | float3 meanMoved = make_float3(0, 0, 0);
53 | float3 stdRef = make_float3(0, 0, 0);
54 | float3 stdMoved = make_float3(0, 0, 0);
55 | float3 dist = make_float3(0, 0, 0);
56 | float3 sigma = make_float3(0, 0, 0);
57 |
58 | float2 shiftf = tex2D(texUV, ((float)pxX + 0.5f) / (float)imgWidth, ((float)pxY + 0.5f) / (float)imgHeight);
59 | float2 maxShift = shiftf;
60 | float2 minShift = shiftf;
61 |
62 | for (int y = -2; y <= 2; y++)
63 | {
64 | for (int x = -2; x <= 2; x++)
65 | {
66 | float2 s = tex2D(texUV, ((float)pxX + x + 0.5f) / (float)imgWidth, ((float)pxY + y + 0.5f) / (float)imgHeight);
67 | maxShift.x = fmaxf(s.x, shiftf.x);
68 | maxShift.y = fmaxf(s.y, shiftf.y);
69 | minShift.x = fminf(s.x, shiftf.x);
70 | minShift.y = fminf(s.y, shiftf.y);
71 | }
72 | }
73 |
74 | int2 shift;
75 | //half resolution image:
76 | shift.x = roundf(shiftf.x * 0.5f);
77 | shift.y = roundf(shiftf.y * 0.5f);
78 |
79 | for (int y = -1; y <= 1; y++)
80 | {
81 | for (int x = -1; x <= 1; x++)
82 | {
83 | float3 p = *(((float3*)((char*)rawImgRef + imgPitch * (pxY + y))) + pxX + x);
84 | pixelsRef[sharedOffset + (y + 1) * 3 + (x + 1)] = p;
85 |
86 | meanRef.x += p.x;
87 | meanRef.y += p.y;
88 | meanRef.z += p.z;
89 |
90 | int ppy = min(max(pxY + shift.y + y, 0), imgHeight - 1);
91 | int ppx = min(max(pxX + shift.x + x, 0), imgWidth - 1);
92 | p = *(((float3*)((char*)rawImgMoved + imgPitch * (ppy))) + ppx);
93 | meanMoved.x += p.x;
94 | meanMoved.y += p.y;
95 | meanMoved.z += p.z;
96 | }
97 | }
98 | meanRef.x /= 9.0f;
99 | meanRef.y /= 9.0f;
100 | meanRef.z /= 9.0f;
101 | meanMoved.x /= 9.0f;
102 | meanMoved.y /= 9.0f;
103 | meanMoved.z /= 9.0f;
104 |
105 | float meandist = fabs(meanRef.x - meanMoved.x) + fabs(meanRef.y - meanMoved.y) + fabs(meanRef.z - meanMoved.z);
106 | meandist /= 3.0f;
107 | maxShift.x *= 0.5f * meandist;
108 | maxShift.y *= 0.5f * meandist;
109 | minShift.x *= 0.5f * meandist;
110 | minShift.y *= 0.5f * meandist;
111 |
112 | float M = sqrtf((maxShift.x - minShift.x) * (maxShift.x - minShift.x) + (maxShift.y - minShift.y) * (maxShift.y - minShift.y));
113 |
114 | for (int y = -1; y <= 1; y++)
115 | {
116 | for (int x = -1; x <= 1; x++)
117 | {
118 | int p = sharedOffset + (y + 1) * 3 + (x + 1);
119 | stdRef.x += (pixelsRef[p].x - meanRef.x) * (pixelsRef[p].x - meanRef.x);
120 | stdRef.y += (pixelsRef[p].y - meanRef.y) * (pixelsRef[p].y - meanRef.y);
121 | stdRef.z += (pixelsRef[p].z - meanRef.z) * (pixelsRef[p].z - meanRef.z);
122 | }
123 | }
124 |
125 | stdRef.x = sqrtf(stdRef.x / 9.0f);
126 | stdRef.y = sqrtf(stdRef.y / 9.0f);
127 | stdRef.z = sqrtf(stdRef.z / 9.0f);
128 |
129 | float3 sigmaMD;
130 | sigmaMD.x = sqrtf(alpha * meanRef.x + beta);
131 | sigmaMD.y = sqrtf(alpha * meanRef.y + beta) / sqrtf(2.0f); //we have two green pixels averaged --> devide by sqrtf(2);
132 | sigmaMD.z = sqrtf(alpha * meanRef.z + beta);
133 |
134 | dist.x = fabs(meanRef.x - meanMoved.x);
135 | dist.y = fabs(meanRef.y - meanMoved.y);
136 | dist.z = fabs(meanRef.z - meanMoved.z);
137 |
138 | sigma.x = fmaxf(sigmaMD.x, stdRef.x);
139 | sigma.y = fmaxf(sigmaMD.y, stdRef.y);
140 | sigma.z = fmaxf(sigmaMD.z, stdRef.z);
141 |
142 | dist.x = dist.x * (stdRef.x * stdRef.x / (stdRef.x * stdRef.x + sigmaMD.x * sigmaMD.x));
143 | dist.y = dist.y * (stdRef.y * stdRef.y / (stdRef.y * stdRef.y + sigmaMD.y * sigmaMD.y));
144 | dist.z = dist.z * (stdRef.z * stdRef.z / (stdRef.z * stdRef.z + sigmaMD.z * sigmaMD.z));/**/
145 |
146 | float4 mask;
147 | float s = 1.5f;
148 | if (M > thresholdM)
149 | s = 0;
150 |
151 | const float t = 0.12f;
152 | mask.x = fmaxf(fminf(s * exp(-dist.x * dist.x / (sigma.x * sigma.x)) - t, 1.0f), 0.0f);
153 | mask.y = fmaxf(fminf(s * exp(-dist.y * dist.y / (sigma.y * sigma.y)) - t, 1.0f), 0.0f);
154 | mask.z = fmaxf(fminf(s * exp(-dist.z * dist.z / (sigma.z * sigma.z)) - t, 1.0f), 0.0f);
155 | mask.w = M;
156 |
157 | *(((float4*)((char*)robustnessMask + maskPitch * pxY)) + pxX) = mask;
158 | }
--------------------------------------------------------------------------------
/Kernels/ShiftMinimizerKernels.cu:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 |
20 | #include "cuda_runtime.h"
21 | #include "device_launch_parameters.h"
22 |
23 | #include
24 | #include
25 | #include
26 |
27 |
28 | extern "C"
29 | __global__ void copyShiftMatrix(float* __restrict__ matrices, int tileCount, int imageCount, int shiftCount)
30 | {
31 | int tile = blockIdx.x * blockDim.x + threadIdx.x;
32 |
33 | if (tile >= tileCount)
34 | return;
35 |
36 | //we copy the matrix of first tile to all other tiles...
37 | if (tile == 0)
38 | return;
39 |
40 | int matrixSize = (imageCount - 1) * shiftCount;
41 |
42 | int offset = (matrixSize) * tile;
43 |
44 | for (int elem = 0; elem < matrixSize; elem++)
45 | {
46 | matrices[offset + elem] = matrices[elem];
47 | }
48 | }
49 |
50 | extern "C"
51 | __global__ void setPointers(float** __restrict__ shiftMatrixArray, float** __restrict__ shiftMatrixSafeArray, float** __restrict__ matrixSquareArray,
52 | float** __restrict__ matrixInvertedArray, float** __restrict__ solvedMatrixArray,
53 | float2**__restrict__ shiftOneToOneArray, float2** __restrict__ shiftMeasuredArray, float2** __restrict__ shiftOptimArray,
54 | float* shiftMatrices, float* shiftSafeMatrices, float* matricesSquared, float* matricesInverted, float* solvedMatrices,
55 | float2* shiftsOneToOne, float2* shiftsMeasured, float2* shiftsOptim, int tileCount, int imageCount, int shiftCount)
56 | {
57 | int tile = blockIdx.x * blockDim.x + threadIdx.x;
58 |
59 | if (tile >= tileCount)
60 | return;
61 |
62 | int n1 = imageCount - 1;
63 | int m = shiftCount;
64 |
65 | int sizeShiftMatrix = n1 * m;
66 | int sizeSquared = n1 * n1;
67 |
68 | shiftMatrixArray[tile] = shiftMatrices + tile * sizeShiftMatrix;
69 | shiftMatrixSafeArray[tile] = shiftSafeMatrices + tile * sizeShiftMatrix;
70 | matrixSquareArray[tile] = matricesSquared + tile * sizeSquared;
71 | matrixInvertedArray[tile] = matricesInverted + tile * sizeSquared;
72 | solvedMatrixArray[tile] = solvedMatrices + tile * sizeShiftMatrix;
73 | shiftOneToOneArray[tile] = shiftsOneToOne + tile * n1;
74 | shiftOptimArray[tile] = shiftsOptim + tile * m;
75 | shiftMeasuredArray[tile] = shiftsMeasured + tile * m;
76 | }
77 |
78 |
79 |
80 | extern "C"
81 | __global__ void checkForOutliers(
82 | float2* __restrict__ measuredShifts,
83 | const float* __restrict__ optimShiftsT,
84 | float* __restrict__ shiftMatrix,
85 | int* __restrict__ status,
86 | int* __restrict__ inversionInfo,
87 | int tileCount, int imageCount, int shiftCount)
88 | {
89 | int tile = blockIdx.x * blockDim.x + threadIdx.x;
90 |
91 | if (tile >= tileCount)
92 | return;
93 |
94 | if (status[tile] < 0)
95 | return;
96 |
97 | if (inversionInfo[tile] != 0)
98 | {
99 | status[tile] = -1;
100 | return;
101 | }
102 |
103 | int n1 = imageCount - 1;
104 | int m = shiftCount;
105 | int offsetMatrix = (n1 * m) * tile;
106 | int offsetAllVec = m * tile;
107 |
108 |
109 | float max = 1;
110 | int idxMax = -1;
111 |
112 | for (int i = 0; i < m; i++)
113 | {
114 | float distx = measuredShifts[offsetAllVec + i].x - optimShiftsT[2*offsetAllVec + i];
115 | float disty = measuredShifts[offsetAllVec + i].y - optimShiftsT[2*offsetAllVec + i + m];
116 |
117 | float dist = distx * distx + disty * disty;
118 | if (dist > max)
119 | {
120 | idxMax = i;
121 | max = dist;
122 | }
123 | }
124 |
125 | status[tile] = idxMax;
126 | //success: we found a meaningful minimum
127 | if (idxMax == -1)
128 | {
129 | return;
130 | }
131 |
132 | //remove the largest outlier
133 | measuredShifts[offsetAllVec + idxMax].x = 0;
134 | measuredShifts[offsetAllVec + idxMax].y = 0;
135 | for (int col = 0; col < n1; col++)
136 | {
137 | shiftMatrix[offsetMatrix + idxMax + col * m] = 0;
138 | }
139 | }
140 |
141 |
142 | extern "C"
143 | __global__ void transposeShifts(
144 | float2 * __restrict__ measuredShifts,
145 | const float* __restrict__ measuredShiftsT,
146 | const float* __restrict__ shiftsOneToOneT,
147 | float2* __restrict__ shiftsOneToOne,
148 | int tileCount, int imageCount, int shiftCount)
149 | {
150 | int tile = blockIdx.x * blockDim.x + threadIdx.x;
151 | int i = blockIdx.y * blockDim.y + threadIdx.y;
152 |
153 | if (tile >= tileCount)
154 | return;
155 |
156 | int n1 = imageCount - 1;
157 | int m = shiftCount;
158 |
159 | if (i >= m)
160 | return;
161 |
162 | int offsetAllVec = m * tile;
163 |
164 | float2 shift;
165 | shift.x = measuredShiftsT[2 * offsetAllVec + i];
166 | shift.y = measuredShiftsT[2 * offsetAllVec + i + m];
167 | measuredShifts[offsetAllVec + i] = shift;
168 |
169 | if (i >= n1)
170 | return;
171 | int offsetOneToOne = n1 * tile;
172 | float2 temp;
173 | temp.x = shiftsOneToOneT[2 * offsetOneToOne + i];
174 | temp.y = shiftsOneToOneT[2 * offsetOneToOne + i + n1];
175 | shiftsOneToOne[offsetOneToOne + i] = temp;
176 | }
177 |
178 | extern "C"
179 | __global__ void getOptimalShifts(
180 | float2 * __restrict__ optimalShifts,
181 | const float2 * __restrict__ bestShifts,
182 | int imageCount,
183 | int tileCountX,
184 | int tileCountY,
185 | int optimalShiftsPitch,
186 | int referenceImage,
187 | int imageToTrack)
188 | {
189 | int tileIdxX = blockIdx.x * blockDim.x + threadIdx.x;
190 | int tileIdxY = blockIdx.y * blockDim.y + threadIdx.y;
191 |
192 | if (tileIdxX >= tileCountX || tileIdxY >= tileCountY)
193 | return;
194 |
195 | int n1 = imageCount - 1;
196 |
197 | const float2* r = &bestShifts[(tileIdxX + tileIdxY * tileCountX) * n1];
198 |
199 | float2 totalShift = make_float2(0, 0);
200 | if (referenceImage < imageToTrack)
201 | {
202 | for (int i = referenceImage; i < imageToTrack; i++)
203 | {
204 | totalShift.x += r[i].x;
205 | totalShift.y += r[i].y;
206 | }
207 | }
208 | else if(imageToTrack < referenceImage)
209 | {
210 | for (int i = imageToTrack; i < referenceImage; i++)
211 | {
212 | totalShift.x -= r[i].x;
213 | totalShift.y -= r[i].y;
214 | }
215 | }
216 |
217 | *(((float2*)((char*)(optimalShifts) +optimalShiftsPitch * tileIdxY)) + tileIdxX) = totalShift;
218 | }
219 |
220 |
221 |
222 | extern "C"
223 | __global__ void concatenateShifts(
224 | const float2* __restrict__ const* __restrict__ shiftIn,
225 | int* __restrict__ shiftInPitch,
226 | float2* __restrict__ shiftOut,
227 | int shiftCount,
228 | int tileCountX, int tileCountY)
229 | {
230 | int shift = blockIdx.x * blockDim.x + threadIdx.x;
231 | int tileX = blockIdx.y * blockDim.y + threadIdx.y;
232 | int tileY = blockIdx.z * blockDim.z + threadIdx.z;
233 |
234 | if (tileX >= tileCountX || tileY >= tileCountY || shift >= shiftCount)
235 | return;
236 |
237 | const float2* line = (const float2*)((const char*)(shiftIn[shift]) + shiftInPitch[shift] * tileY);
238 | shiftOut[(tileX + tileY * tileCountX) * shiftCount + shift] = line[tileX];
239 | }
240 |
241 | extern "C"
242 | __global__ void separateShifts(
243 | const float2* __restrict__ shiftIn,
244 | float2* __restrict__ const * __restrict__ shiftOut,
245 | int* __restrict__ shiftOutPitch,
246 | int shiftCount,
247 | int tileCountX, int tileCountY)
248 | {
249 | int shift = blockIdx.x * blockDim.x + threadIdx.x;
250 | int tileX = blockIdx.y * blockDim.y + threadIdx.y;
251 | int tileY = blockIdx.z * blockDim.z + threadIdx.z;
252 |
253 | if (tileX >= tileCountX || tileY >= tileCountY|| shift >= shiftCount)
254 | return;
255 |
256 | float2* line = (float2*)((char*)(shiftOut[shift]) + shiftOutPitch[shift] * tileY);
257 | line[tileX] = shiftIn[(tileX + tileY * tileCountX) * shiftCount + shift];
258 | }
--------------------------------------------------------------------------------
/Kernels/opticalFlow.cu:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 |
20 | #include "cuda_runtime.h"
21 | #include "device_launch_parameters.h"
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | extern "C"
28 | __global__ void WarpingKernel(int width, int height, int stride,
29 | cudaTextureObject_t texUV, float* __restrict__ out, cudaTextureObject_t texToWarp)
30 | {
31 | const int ix = threadIdx.x + blockIdx.x * blockDim.x;
32 | const int iy = threadIdx.y + blockIdx.y * blockDim.y;
33 |
34 | if (ix >= width || iy >= height) return;
35 |
36 | float2 shift = tex2D(texUV, ((float)ix + 0.5f) / (float)width, ((float)iy + 0.5f) / (float)height);
37 |
38 | float x = ((float)ix + 0.5f + shift.x) / (float)width;
39 | float y = ((float)iy + 0.5f + shift.y) / (float)height;
40 |
41 | float pixel = tex2D(texToWarp, x, y);
42 |
43 | *(((float*)((char*)out + stride * (iy))) + (ix)) = pixel;
44 | }
45 |
46 |
47 | extern "C"
48 | __global__ void CreateFlowFieldFromTiles(
49 | float2* __restrict__ outImg,
50 | cudaTextureObject_t texObjShiftXY,
51 | int tileSize,
52 | int tileCountX,
53 | int tileCountY,
54 | int imgWidth,
55 | int imgHeight,
56 | int imgPitch,
57 | float2 baseShift,
58 | float baseRotation)
59 | {
60 | int pxX = blockIdx.x * blockDim.x + threadIdx.x;
61 | int pxY = blockIdx.y * blockDim.y + threadIdx.y;
62 |
63 | if (pxX >= imgWidth || pxY >= imgHeight)
64 | return;
65 |
66 | int tileX = pxX / tileSize;
67 | int tileY = pxY / tileSize;
68 |
69 | tileX = min(tileX, tileCountX - 1);
70 | tileY = min(tileY, tileCountY - 1);
71 |
72 | int tileIdx = tileX + tileY * tileCountX;
73 | float2 shift;
74 | shift.x = 0;
75 | shift.y = 0;
76 |
77 | //add base shift and rotation
78 | shift.x = cosf(baseRotation) * -baseShift.x - sinf(baseRotation) * -baseShift.y;
79 | shift.y = sinf(baseRotation) * -baseShift.x + cosf(baseRotation) * -baseShift.y;
80 |
81 | float patchCenterX = pxX - imgWidth / 2; //in pixels
82 | float patchCenterY = pxY - imgHeight / 2;
83 |
84 | shift.x += cosf(baseRotation) * patchCenterX - sinf(baseRotation) * patchCenterY - patchCenterX;
85 | shift.y += sinf(baseRotation) * patchCenterX + cosf(baseRotation) * patchCenterY - patchCenterY;
86 |
87 |
88 | float2 shiftPatch = tex2D(texObjShiftXY, (pxX + 0.5f) / (float)imgWidth, (pxY + 0.5f) / (float)imgHeight);
89 | shift.x += shiftPatch.x;
90 | shift.y += shiftPatch.y;
91 |
92 | *(((float2*)((char*)outImg + imgPitch * pxY)) + pxX) = shift;
93 | }
94 |
95 |
96 | extern "C"
97 | __global__ void ComputeDerivativesKernel(int width, int height, int stride,
98 | float* Ix, float* Iy, float* Iz,
99 | cudaTextureObject_t texSource,
100 | cudaTextureObject_t texTarget)
101 | {
102 | const int ix = threadIdx.x + blockIdx.x * blockDim.x;
103 | const int iy = threadIdx.y + blockIdx.y * blockDim.y;
104 |
105 |
106 | if (ix >= width || iy >= height) return;
107 |
108 | float dx = 1.0f / (float)width;
109 | float dy = 1.0f / (float)height;
110 |
111 | float x = ((float)ix + 0.5f) * dx;
112 | float y = ((float)iy + 0.5f) * dy;
113 |
114 | float t0, t1;
115 | // x derivative
116 | t0 = tex2D(texSource, x + 2.0f * dx, y);
117 | t0 -= tex2D(texSource, x + 1.0f * dx, y) * 8.0f;
118 | t0 += tex2D(texSource, x - 1.0f * dx, y) * 8.0f;
119 | t0 -= tex2D(texSource, x - 2.0f * dx, y);
120 | t0 /= 12.0f;
121 |
122 | t1 = tex2D(texTarget, x + 2.0f * dx, y);
123 | t1 -= tex2D(texTarget, x + 1.0f * dx, y) * 8.0f;
124 | t1 += tex2D(texTarget, x - 1.0f * dx, y) * 8.0f;
125 | t1 -= tex2D(texTarget, x - 2.0f * dx, y);
126 | t1 /= 12.0f;
127 |
128 | *(((float*)((char*)Ix + stride * iy)) + ix) = (t0 + t1) * 0.5f;
129 |
130 | // t derivative
131 | *(((float*)((char*)Iz + stride * iy)) + ix) = tex2D(texSource, x, y) - tex2D(texTarget, x, y);
132 |
133 | // y derivative
134 | t0 = tex2D(texSource, x, y + 2.0f * dy);
135 | t0 -= tex2D(texSource, x, y + 1.0f * dy) * 8.0f;
136 | t0 += tex2D(texSource, x, y - 1.0f * dy) * 8.0f;
137 | t0 -= tex2D(texSource, x, y - 2.0f * dy);
138 | t0 /= 12.0f;
139 |
140 | t1 = tex2D(texTarget, x, y + 2.0f * dy);
141 | t1 -= tex2D(texTarget, x, y + 1.0f * dy) * 8.0f;
142 | t1 += tex2D(texTarget, x, y - 1.0f * dy) * 8.0f;
143 | t1 -= tex2D(texTarget, x, y - 2.0f * dy);
144 | t1 /= 12.0f;
145 |
146 | *(((float*)((char*)Iy + stride * iy)) + ix) = (t0 + t1) * 0.5f;
147 | }
148 |
149 |
150 | extern "C"
151 | __global__ void ComputeDerivatives2Kernel(int width, int height, int stride,
152 | float* Ix, float* Iy,
153 | cudaTextureObject_t tex)
154 | {
155 | const int ix = threadIdx.x + blockIdx.x * blockDim.x;
156 | const int iy = threadIdx.y + blockIdx.y * blockDim.y;
157 |
158 | if (ix >= width || iy >= height) return;
159 |
160 | float dx = 1.0f / (float)width;
161 | float dy = 1.0f / (float)height;
162 |
163 | float x = ((float)ix + 0.5f) * dx;
164 | float y = ((float)iy + 0.5f) * dy;
165 |
166 | float t0, t1;
167 | // x derivative
168 | t0 = tex2D(tex, x + 2.0f * dx, y);
169 | t0 -= tex2D(tex, x + 1.0f * dx, y) * 8.0f;
170 | t0 += tex2D(tex, x - 1.0f * dx, y) * 8.0f;
171 | t0 -= tex2D(tex, x - 2.0f * dx, y);
172 | t0 /= 12.0f;
173 |
174 | *(((float*)((char*)Ix + stride * iy)) + ix) = t0;
175 |
176 |
177 | // y derivative
178 | t0 = tex2D(tex, x, y + 2.0f * dy);
179 | t0 -= tex2D(tex, x, y + 1.0f * dy) * 8.0f;
180 | t0 += tex2D(tex, x, y - 1.0f * dy) * 8.0f;
181 | t0 -= tex2D(tex, x, y - 2.0f * dy);
182 | t0 /= 12.0f;
183 |
184 | *(((float*)((char*)Iy + stride * iy)) + ix) = t0;
185 | }
186 |
187 |
188 |
189 | extern "C"
190 | __global__ void lucasKanadeOptim(
191 | float2 * __restrict__ shifts,
192 | const float* __restrict__ imFx,
193 | const float* __restrict__ imFy,
194 | const float* __restrict__ imFt,
195 | int pitchShift,
196 | int pitchImg,
197 | int width,
198 | int height,
199 | int halfWindowSize,
200 | float minDet)
201 | {
202 | int pxX = blockIdx.x * blockDim.x + threadIdx.x;
203 | int pxY = blockIdx.y * blockDim.y + threadIdx.y;
204 |
205 | if (pxX < halfWindowSize || pxX >= width - halfWindowSize ||
206 | pxY < halfWindowSize || pxY >= height - halfWindowSize)
207 | return;
208 |
209 | int windowSize = halfWindowSize * 2 + 1;
210 | float matMul[4];
211 | float matMulInv[4];
212 | float UT[4];
213 | float S[4];
214 | float V[4];
215 |
216 | float UV[2];
217 |
218 | matMul[0] = matMul[1] = matMul[2] = matMul[3] = 0;
219 | for (int y = -halfWindowSize; y <= halfWindowSize; y++)
220 | {
221 | for (int x = -halfWindowSize; x <= halfWindowSize; x++)
222 | {
223 | int globalX = pxX + x;
224 | int globalY = pxY + y;
225 |
226 | float dx = *(((float*)(((char*)imFx) + globalY * pitchImg)) + globalX);
227 | float dy = *(((float*)(((char*)imFy) + globalY * pitchImg)) + globalX);
228 |
229 | matMul[0] += dx * dx;
230 | matMul[1] += dx * dy;
231 | matMul[3] += dy * dy;
232 | }
233 | }
234 | matMul[2] = matMul[1];
235 |
236 | //matrix pseudo inversion:
237 | float a = matMul[0];
238 | float b = matMul[1];
239 | float c = matMul[2];
240 | float d = matMul[3];
241 |
242 | float theta = 0.5f * atan2(2.0f * a * c + 2.0f * b * d, a * a + b * b - c * c - d * d);
243 | float ct = cos(theta);
244 | float st = sin(theta);
245 | UT[0] = ct;
246 | UT[2] = -st; //transposed
247 | UT[1] = st; //transposed
248 | UT[3] = ct;
249 |
250 | float S1 = a * a + b * b + c * c + d * d;
251 | float S2 = sqrtf((a * a + b * b - c * c - d * d) * (a * a + b * b - c * c - d * d) + 4 * (a * c + b * d) * (a * c + b * d));
252 | float sigma1 = sqrt((S1 + S2) / 2);
253 | float sigma2 = sqrt((S1 - S2) / 2);
254 |
255 | float smin = fminf(sigma1, sigma1);
256 | if (smin < minDet)
257 | return;
258 |
259 |
260 | sigma1 = sigma1 != 0 ? 1.0f / sigma1 : 0;
261 | sigma2 = sigma2 != 0 ? 1.0f / sigma2 : 0;
262 |
263 | S[0] = sigma1;
264 | S[1] = 0;
265 | S[2] = 0;
266 | S[3] = sigma2;
267 |
268 | float epsilon = 0.5f * atan2(2.0f * a * b + 2.0f * c * d, a * a - b * b + c * c - d * d);
269 |
270 | float ce = cos(epsilon);
271 | float se = sin(epsilon);
272 |
273 | float s11 = (a * ct + c * st) * ce + (b * ct + d * st) * se;
274 | float s22 = (a * st - c * ct) * se + (-b * st + d * ct) * ce;
275 |
276 | s11 = s11 > 0.0f ? 1.0f : s11 < 0 ? -1.0f : 0.0f;
277 | s22 = s22 > 0.0f ? 1.0f : s22 < 0 ? -1.0f : 0.0f;
278 |
279 | V[0] = s11 * ce;
280 | V[1] = -s22 * se;
281 | V[2] = s11 * se;
282 | V[3] = s22 * ce;
283 |
284 | matMul[0] = S[0] * UT[0] + S[1] * UT[2];
285 | matMul[1] = S[0] * UT[1] + S[1] * UT[3];
286 | matMul[2] = S[2] * UT[0] + S[3] * UT[2];
287 | matMul[3] = S[2] * UT[1] + S[3] * UT[3];
288 |
289 | matMulInv[0] = V[0] * matMul[0] + V[1] * matMul[2];
290 | matMulInv[1] = V[0] * matMul[1] + V[1] * matMul[3];
291 | matMulInv[2] = V[2] * matMul[0] + V[3] * matMul[2];
292 | matMulInv[3] = V[2] * matMul[1] + V[3] * matMul[3];
293 |
294 | int ws2 = windowSize * windowSize;
295 | UV[0] = 0;
296 | UV[1] = 0;
297 |
298 | for (int i = 0; i < ws2; i++)
299 | {
300 | int y = i / windowSize;
301 | int x = i - (y * windowSize);
302 |
303 | int globalX = pxX + x - halfWindowSize;
304 | int globalY = pxY + y - halfWindowSize;
305 |
306 | float dx = *(((float*)(((char*)imFx) + globalY * pitchImg)) + globalX);
307 | float dy = *(((float*)(((char*)imFy) + globalY * pitchImg)) + globalX);
308 |
309 | float dt = *(((float*)(((char*)imFt) + globalY * pitchImg)) + globalX);
310 |
311 | UV[0] += (matMulInv[0] * dx + matMulInv[1] * dy) * dt;
312 | UV[1] += (matMulInv[2] * dx + matMulInv[3] * dy) * dt;
313 | }
314 |
315 | UV[0] = isnan(UV[0]) ? 0 : UV[0];
316 | UV[1] = isnan(UV[1]) ? 0 : UV[1];
317 |
318 | /*UV[0] = fmaxf(fminf(2.0f, UV[0]), -2.0f);
319 | UV[1] = fmaxf(fminf(2.0f, UV[1]), -2.0f);*/
320 |
321 | float2 shift = *(((float2*)(((char*)shifts) + pxY * pitchShift)) + pxX);
322 | shift.x += UV[0];
323 | shift.y += UV[1];
324 | *(((float2*)((char*)shifts + pxY * pitchShift)) + pxX) = shift;
325 | }
326 |
--------------------------------------------------------------------------------
/PEFStudioDX/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/PEFStudioDX/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/PEFStudioDX/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace PEFStudioDX
10 | {
11 | ///
12 | /// Interaktionslogik für "App.xaml"
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/PEFStudioDX/DeBayerKernels.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using ManagedCuda;
25 | using ManagedCuda.BasicTypes;
26 | using ManagedCuda.VectorTypes;
27 | using ManagedCuda.NPP;
28 |
29 | namespace PEFStudioDX
30 | {
31 | public class DeBayerGreenKernel : CudaKernel
32 | {
33 | public DeBayerGreenKernel(CUmodule module, CudaContext ctx)
34 | : base("deBayerGreenKernel", module, ctx)
35 | {
36 | BlockDimensions = new dim3(32, 16, 1);
37 | GridDimensions = new dim3(1, 1, 1);
38 | }
39 |
40 | public float RunSafe(NPPImage_32fC1 imgIn, NPPImage_32fC3 imgOut, float3 blackPoint, float3 scale)
41 | {
42 | //const int width, const int height, const float* __restrict__ imgIn, int strideIn, float3 *outImage, int strideOut, float3 blackPoint, float3 scale
43 | SetComputeSize((uint)imgIn.Width, (uint)imgIn.Height, 1);
44 | return base.Run(imgIn.Width, imgIn.Height, imgIn.DevicePointer, imgIn.Pitch, imgOut.DevicePointer, imgOut.Pitch, blackPoint, scale);
45 | }
46 |
47 | public float RunSafe(CudaDeviceVariable imgIn, CudaDeviceVariable imgOut, int patchSize, float3 blackPoint, float3 scale)
48 | {
49 | SetComputeSize((uint)patchSize, (uint)patchSize, 1);
50 | return base.Run(patchSize, patchSize, imgIn.DevicePointer, patchSize * 4, imgOut.DevicePointer, patchSize * 12, blackPoint, scale);
51 | }
52 |
53 | public PentaxPefFile.RawFile.BayerColor[] BayerPattern
54 | {
55 | set
56 | {
57 | int[] temp = new int[value.Length];
58 | for (int i = 0; i < value.Length; i++)
59 | {
60 | temp[i] = (int)value[i];
61 | }
62 | base.SetConstantVariable("c_cfaPattern", temp);
63 | }
64 | }
65 | }
66 |
67 | public class DeBayerRedBlueKernel : CudaKernel
68 | {
69 | public DeBayerRedBlueKernel(CUmodule module, CudaContext ctx)
70 | : base("deBayerRedBlueKernel", module, ctx)
71 | {
72 | BlockDimensions = new dim3(32, 16, 1);
73 | GridDimensions = new dim3(1, 1, 1);
74 | }
75 |
76 | public float RunSafe(NPPImage_32fC1 imgIn, NPPImage_32fC3 imgOut, float3 blackPoint, float3 scale)
77 | {
78 | //const int width, const int height, const float* __restrict__ imgIn, int strideIn, float3 *outImage, int strideOut, float3 blackPoint, float3 scale
79 | SetComputeSize((uint)imgIn.Width, (uint)imgIn.Height, 1);
80 | return base.Run(imgIn.Width, imgIn.Height, imgIn.DevicePointer, imgIn.Pitch, imgOut.DevicePointer, imgOut.Pitch, blackPoint, scale);
81 | }
82 |
83 | public float RunSafe(CudaDeviceVariable imgIn, CudaDeviceVariable imgOut, int patchSize, float3 blackPoint, float3 scale)
84 | {
85 | SetComputeSize((uint)patchSize, (uint)patchSize, 1);
86 | return base.Run(patchSize, patchSize, imgIn.DevicePointer, patchSize * 4, imgOut.DevicePointer, patchSize * 12, blackPoint, scale);
87 | }
88 |
89 | public PentaxPefFile.RawFile.BayerColor[] BayerPattern
90 | {
91 | set
92 | {
93 | int[] temp = new int[value.Length];
94 | for (int i = 0; i < value.Length; i++)
95 | {
96 | temp[i] = (int)value[i];
97 | }
98 | base.SetConstantVariable("c_cfaPattern", temp);
99 | }
100 | }
101 | }
102 |
103 | public class DeBayersSubSampleKernel : CudaKernel
104 | {
105 | private const uint BlockSizeX = 16;
106 | private const uint BlockSizeY = 16;
107 |
108 | public DeBayersSubSampleKernel(CudaContext ctx, CUmodule module)
109 | : base("deBayersSubSample3", module, ctx, BlockSizeX, BlockSizeY)
110 | {
111 | //deBayersSubSample(unsigned short* dataIn, float3* imgOut, int bitDepth, int dimX, int dimY, int strideOut)
112 | }
113 |
114 | public float RunSafe(CudaDeviceVariable imgIn, NPPImage_32fC3 imgOut, float maxVal)
115 | {
116 | SetComputeSize((uint)imgOut.WidthRoi, (uint)imgOut.HeightRoi);
117 | return base.Run(imgIn.DevicePointer, imgOut.DevicePointer, maxVal, imgOut.WidthRoi, imgOut.HeightRoi, imgOut.Pitch);
118 | }
119 |
120 | public PentaxPefFile.RawFile.BayerColor[] BayerPattern
121 | {
122 | set
123 | {
124 | int[] temp = new int[value.Length];
125 | for (int i = 0; i < value.Length; i++)
126 | {
127 | temp[i] = (int)value[i];
128 | }
129 | base.SetConstantVariable("c_cfaPattern", temp);
130 | }
131 | }
132 | }
133 |
134 | public class AccumulateImagesKernel : CudaKernel
135 | {
136 | private const uint BlockSizeX = 16;
137 | private const uint BlockSizeY = 16;
138 |
139 | public AccumulateImagesKernel(CudaContext ctx, CUmodule module)
140 | : base("accumulateImages", module, ctx, BlockSizeX, BlockSizeY)
141 | {
142 | /*
143 | * accumulateImages(
144 | unsigned short* __restrict__ dataIn,
145 | float3 * __restrict__ imgOut,
146 | float3 * __restrict__ totalWeights,
147 | const float3 * __restrict__ certaintyMask,
148 | const float3* __restrict__ kernelParam,
149 | const float2* __restrict__ shifts,
150 | float maxVal, int dimX, int dimY, int strideOut)
151 | */
152 | }
153 |
154 | public float RunSafe(CudaDeviceVariable dataIn, NPPImage_32fC3 imgOut, NPPImage_32fC3 totalWeights, NPPImage_32fC4 certaintyMask, NPPImage_32fC3 kernelParam, NPPImage_32fC2 shifts, float3 whiteLevel, float3 blackLevel)
155 | {
156 | SetComputeSize((uint)imgOut.WidthRoi, (uint)imgOut.HeightRoi);
157 |
158 | return base.Run(dataIn.DevicePointer, imgOut.DevicePointerRoi, totalWeights.DevicePointerRoi,
159 | certaintyMask.DevicePointerRoi, kernelParam.DevicePointerRoi, shifts.DevicePointerRoi,
160 | whiteLevel, blackLevel, imgOut.WidthRoi, imgOut.HeightRoi, imgOut.Pitch, certaintyMask.Pitch, shifts.Pitch);
161 | }
162 |
163 | public PentaxPefFile.RawFile.BayerColor[] BayerPattern
164 | {
165 | set
166 | {
167 | int[] temp = new int[value.Length];
168 | for (int i = 0; i < value.Length; i++)
169 | {
170 | temp[i] = (int)value[i];
171 | }
172 | base.SetConstantVariable("c_cfaPattern", temp);
173 | }
174 | }
175 | }
176 |
177 | public class AccumulateImagesSuperResKernel : CudaKernel
178 | {
179 | private const uint BlockSizeX = 16;
180 | private const uint BlockSizeY = 16;
181 |
182 | public AccumulateImagesSuperResKernel(CudaContext ctx, CUmodule module)
183 | : base("accumulateImagesSuperRes", module, ctx, BlockSizeX, BlockSizeY)
184 | {
185 | /*
186 | * accumulateImages(
187 | unsigned short* __restrict__ dataIn,
188 | float3 * __restrict__ imgOut,
189 | float3 * __restrict__ totalWeights,
190 | const float3 * __restrict__ certaintyMask,
191 | const float3* __restrict__ kernelParam,
192 | const float2* __restrict__ shifts,
193 | float maxVal, int dimX, int dimY, int strideOut)
194 | */
195 | }
196 |
197 | public float RunSafe(CudaDeviceVariable dataIn, NPPImage_32fC3 imgOut, NPPImage_32fC3 totalWeights, NPPImage_32fC4 certaintyMask, NPPImage_32fC4 kernelParam, NPPImage_32fC2 shifts, float3 whiteLevel, float3 blackLevel)
198 | {
199 | SetComputeSize((uint)imgOut.WidthRoi, (uint)imgOut.HeightRoi);
200 |
201 | CudaResourceDesc descKernel = new CudaResourceDesc(kernelParam);
202 | CudaTextureDescriptor texDescKernel = new CudaTextureDescriptor(CUAddressMode.Clamp, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
203 | CudaTexObject texKernel = new CudaTexObject(descKernel, texDescKernel);
204 |
205 | CudaResourceDesc descShift = new CudaResourceDesc(shifts);
206 | CudaTextureDescriptor texDescShift = new CudaTextureDescriptor(CUAddressMode.Mirror, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
207 | CudaTexObject texShift = new CudaTexObject(descShift, texDescShift);
208 |
209 | float t = base.Run(dataIn.DevicePointer, imgOut.DevicePointerRoi, totalWeights.DevicePointerRoi,
210 | certaintyMask.DevicePointerRoi, texKernel.TexObject, texShift.TexObject,
211 | whiteLevel, blackLevel, imgOut.WidthRoi, imgOut.HeightRoi, imgOut.Pitch, certaintyMask.Pitch, kernelParam.Pitch, shifts.Pitch);
212 |
213 | texShift.Dispose();
214 | texKernel.Dispose();
215 | return t;
216 | }
217 |
218 | public PentaxPefFile.RawFile.BayerColor[] BayerPattern
219 | {
220 | set
221 | {
222 | int[] temp = new int[value.Length];
223 | for (int i = 0; i < value.Length; i++)
224 | {
225 | temp[i] = (int)value[i];
226 | }
227 | base.SetConstantVariable("c_cfaPattern", temp);
228 | }
229 | }
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/PEFStudioDX/EnumConverter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using System.Windows.Data;
25 | using System.ComponentModel;
26 | using System.Reflection;
27 | using System.Windows.Markup;
28 |
29 | namespace PEFStudioDX
30 | {
31 | public class EnumDescriptionTypeConverter : EnumConverter
32 | {
33 | public EnumDescriptionTypeConverter(Type type)
34 | : base(type)
35 | {
36 | }
37 |
38 | public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
39 | {
40 | if (destinationType == typeof(string))
41 | {
42 | if (value != null)
43 | {
44 | FieldInfo fi = value.GetType().GetField(value.ToString());
45 | if (fi != null)
46 | {
47 | var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
48 | return ((attributes.Length > 0) && (!String.IsNullOrEmpty(attributes[0].Description))) ? attributes[0].Description : value.ToString();
49 | }
50 | }
51 | return string.Empty;
52 | }
53 | return base.ConvertTo(context, culture, value, destinationType);
54 | }
55 | }
56 | public class EnumBindingSourceExtension : MarkupExtension
57 | {
58 | private Type _enumType;
59 | public Type EnumType
60 | {
61 | get { return this._enumType; }
62 | set
63 | {
64 | if (value != this._enumType)
65 | {
66 | if (null != value)
67 | {
68 | Type enumType = Nullable.GetUnderlyingType(value) ?? value;
69 |
70 | if (!enumType.IsEnum)
71 | throw new ArgumentException("Type must be for an Enum.");
72 | }
73 | this._enumType = value;
74 | }
75 | }
76 | }
77 | public EnumBindingSourceExtension() { }
78 | public EnumBindingSourceExtension(Type enumType)
79 | {
80 | this.EnumType = enumType;
81 | }
82 | public override object ProvideValue(IServiceProvider serviceProvider)
83 | {
84 | if (null == this._enumType)
85 | throw new InvalidOperationException("The EnumType must be specified.");
86 | Type actualEnumType = Nullable.GetUnderlyingType(this._enumType) ?? this._enumType;
87 | Array enumValues = Enum.GetValues(actualEnumType);
88 | if (actualEnumType == this._enumType)
89 | return enumValues;
90 | Array tempArray = Array.CreateInstance(actualEnumType, enumValues.Length + 1);
91 | enumValues.CopyTo(tempArray, 1);
92 | return tempArray;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/PEFStudioDX/ExtraCameraProfiles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | RICOH IMAGING COMPANY, LTD.
6 | PENTAX K-3
7 |
8 | 0.9281921387
9 | -0.4597167969
10 | -0.07611083984
11 | -0.3495941162
12 | 0.9834136963
13 | 0.4286651611
14 | -0.02061462402
15 | 0.0431060791
16 | 0.788482666
17 |
18 |
19 | 0.8190460205
20 | -0.2475128174
21 | -0.1096954346
22 | -0.3995361328
23 | 1.230117798
24 | 0.1880645752
25 | -0.1049804688
26 | 0.1840820313
27 | 0.6998596191
28 |
29 | StandardLightA
30 | D65
31 |
32 |
33 | 100
34 | 200
35 | 400
36 | 800
37 | 1600
38 | 3200
39 | 6400
40 |
41 |
42 | 6.66667E-05
43 | 0.0001
44 | 0.000192308
45 | 0.000357143
46 | 0.000714286
47 | 0.001388889
48 | 0.025
49 |
50 |
51 | 0.0
52 | 0.0
53 | 0.0
54 | 0.0
55 | 0.0
56 | 0.0
57 | 0.0
58 |
59 |
60 |
61 | 16
62 | 16
63 | 6016
64 | 4000
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/PEFStudioDX/ImagePresenterDX.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/PEFStudioDX/LUTControl.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/PEFStudioDX/LUTHost.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using System.Windows;
25 | using System.Windows.Input;
26 | using System.Windows.Media;
27 |
28 | namespace PEFStudioDX
29 | {
30 | public class LUTHost : FrameworkElement
31 | {
32 | private readonly VisualCollection _children;
33 | Nullable dragStart = null;
34 |
35 | public LUTHost()
36 | {
37 | _children = new VisualCollection(this);
38 | MouseLeftButtonUp += LUTHost_MouseLeftButtonUp;
39 | MouseLeftButtonDown += LUTHost_MouseLeftButtonDown;
40 | MouseDown += LUTHost_MouseDown;
41 | MouseLeave += LUTHost_MouseLeave;
42 | MouseMove += LUTHost_MouseMove;
43 | }
44 |
45 | private void LUTHost_MouseDown(object sender, MouseButtonEventArgs e)
46 | {
47 | if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Pressed)
48 | {
49 | // Retreive the coordinates of the mouse button event.
50 | Point pt = e.GetPosition((UIElement)sender);
51 |
52 | PointCreateOrDeleteEvent?.Invoke(pt.X / ActualWidth, (ActualHeight - pt.Y) / ActualHeight);
53 | }
54 | }
55 |
56 | public delegate void PointSelectedEventHandler(double x, double y);
57 | public event PointSelectedEventHandler PointSelectedEvent;
58 |
59 | public delegate void PointMovedEventHandler(double x, double y);
60 | public event PointMovedEventHandler PointMovedEvent;
61 |
62 | public delegate void PointCreateOrDeleteEventHandler(double x, double y);
63 | public event PointCreateOrDeleteEventHandler PointCreateOrDeleteEvent;
64 |
65 | public delegate void PointReleasedEventHandler();
66 | public event PointReleasedEventHandler PointReleasedEvent;
67 |
68 | private void LUTHost_MouseMove(object sender, MouseEventArgs e)
69 | {
70 | if (dragStart != null && e.LeftButton == MouseButtonState.Pressed)
71 | {
72 | var element = (UIElement)sender;
73 | var p2 = e.GetPosition(this);
74 | PointMovedEvent?.Invoke(p2.X / ActualWidth, (ActualHeight - p2.Y) / ActualHeight);
75 | }
76 | }
77 |
78 | private void LUTHost_MouseLeave(object sender, MouseEventArgs e)
79 | {
80 | PointReleasedEvent?.Invoke();
81 | dragStart = null;
82 | this.ReleaseMouseCapture();
83 | }
84 |
85 | private void LUTHost_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
86 | {
87 | // Retreive the coordinates of the mouse button event.
88 | Point pt = e.GetPosition((UIElement)sender);
89 |
90 | dragStart = pt;
91 | PointSelectedEvent?.Invoke(pt.X / ActualWidth, (ActualHeight - pt.Y) / ActualHeight);
92 | this.CaptureMouse();
93 | }
94 |
95 | private void LUTHost_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
96 | {
97 | dragStart = null;
98 | PointReleasedEvent?.Invoke();
99 | this.ReleaseMouseCapture();
100 | }
101 |
102 | public HitTestResultBehavior MyCallback(HitTestResult result)
103 | {
104 | PointHitTestResult pointHit = result as PointHitTestResult;
105 | if (pointHit != null)
106 | {
107 | Console.WriteLine("Hit: " + pointHit.PointHit.X / ActualWidth + "; " + (ActualHeight - pointHit.PointHit.Y) / ActualHeight);
108 | }
109 | if (result.VisualHit.GetType() == typeof(System.Windows.Media.DrawingVisual))
110 | {
111 | if (pointHit != null)
112 | {
113 | dragStart = pointHit.PointHit;
114 | }
115 | this.CaptureMouse();
116 | }
117 |
118 | return HitTestResultBehavior.Stop;
119 | }
120 |
121 | // Provide a required override for the VisualChildrenCount property.
122 | protected override int VisualChildrenCount => _children.Count;
123 |
124 | // Provide a required override for the GetVisualChild method.
125 | protected override Visual GetVisualChild(int index)
126 | {
127 | if (index < 0 || index >= _children.Count)
128 | {
129 | throw new ArgumentOutOfRangeException();
130 | }
131 | return _children[index];
132 | }
133 |
134 | public void DrawPoints(SortedList points, Point[] line)
135 | {
136 | _children.Clear();
137 |
138 | double width = ActualWidth;
139 | double height = ActualHeight;
140 |
141 |
142 | foreach (var point in line)
143 | {
144 | System.Windows.Media.DrawingVisual drawingVisual = new System.Windows.Media.DrawingVisual();
145 | DrawingContext drawingContext = drawingVisual.RenderOpen();
146 | double x = point.X * width;
147 | double y = height - point.Y * height;
148 |
149 | drawingContext.DrawEllipse(Brushes.Blue, null, new Point(x, y), 1, 1);
150 | drawingContext.Close();
151 | _children.Add(drawingVisual);
152 | }
153 |
154 |
155 | foreach (var point in points)
156 | {
157 | System.Windows.Media.DrawingVisual drawingVisual = new System.Windows.Media.DrawingVisual();
158 | DrawingContext drawingContext = drawingVisual.RenderOpen();
159 | Pen pen = new Pen(Brushes.AntiqueWhite, 3);
160 | drawingContext.DrawEllipse(Brushes.Transparent, pen, new Point(point.Key * width, height - point.Value * height), 3, 3);
161 | drawingContext.Close();
162 | _children.Add(drawingVisual);
163 | }
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/PEFStudioDX/Matrix.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PEFStudioDX
26 | {
27 | class Matrix3x3
28 | {
29 | private double[] data;
30 | private int cols = 3;
31 | private int rows = 3;
32 |
33 | public Matrix3x3()
34 | {
35 | data = new double[9];
36 | }
37 |
38 | public double this[int row, int col]
39 | {
40 | get { return data[col + row * cols]; }
41 | set { data[col + row * cols] = value; }
42 | }
43 |
44 | public static Matrix3x3 Mul(Matrix3x3 src, Matrix3x3 value)
45 | {
46 | Matrix3x3 res = new Matrix3x3();
47 | for (int retx = 0; retx < src.rows; retx++)
48 | for (int rety = 0; rety < value.cols; rety++)
49 | {
50 | double val = 0;
51 | for (int i = 0; i < src.cols; i++)
52 | {
53 | val += src[retx, i] * value[i, rety];
54 | }
55 | res[retx, rety] = val;
56 | }
57 | return res;
58 | }
59 |
60 | public static Matrix3x3 operator *(Matrix3x3 src, Matrix3x3 value)
61 | {
62 | return Matrix3x3.Mul(src, value);
63 | }
64 | public static Matrix3x3 Unit()
65 | {
66 | Matrix3x3 res = new Matrix3x3();
67 | res[0, 0] = 1;
68 | res[1, 1] = 1;
69 | res[2, 2] = 1;
70 | return res;
71 | }
72 |
73 | public static Matrix3x3 ShiftAffine(double x, double y)
74 | {
75 | Matrix3x3 res = Unit();
76 | res[0, 2] = x;
77 | res[1, 2] = y;
78 | return res;
79 | }
80 |
81 | public static Matrix3x3 Rotation(double angInDeg)
82 | {
83 | Matrix3x3 res = Unit();
84 | double s = Math.Sin(angInDeg / 180.0 * Math.PI);
85 | double c = Math.Cos(angInDeg / 180.0 * Math.PI);
86 | res[0, 0] = c;
87 | res[1, 0] = -s;
88 | res[0, 1] = s;
89 | res[1, 1] = c;
90 | return res;
91 | }
92 |
93 | public static Matrix3x3 RotAroundCenter(double angle, double width, double height)
94 | {
95 | Matrix3x3 res = Matrix3x3.ShiftAffine(width / 2.0, height / 2.0);
96 | res = res * Matrix3x3.Rotation(angle);
97 | res = res * Matrix3x3.ShiftAffine(-width / 2.0, -height / 2.0);
98 | return res;
99 | }
100 |
101 | public override string ToString()
102 | {
103 | string res = "{";
104 | for (int c = 0; c < cols; c++)
105 | {
106 | for (int r = 0; r < rows; r++)
107 | {
108 | res += this[r, c].ToString("0.000");
109 | if (r < rows - 1)
110 | res += " ";
111 | else
112 | res += "; ";
113 | }
114 | }
115 | res += "}";
116 | return res;
117 | }
118 |
119 | public double[,] ToAffine()
120 | {
121 | double[,] res = new double[2, 3];
122 | for (int c = 0; c < cols; c++)
123 | {
124 | for (int r = 0; r < 2; r++)
125 | {
126 | res[r, c] = this[r, c];
127 | }
128 | }
129 | return res;
130 | }
131 |
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/PEFStudioDX/OpticalFlow.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.IO;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using ManagedCuda;
25 | using ManagedCuda.BasicTypes;
26 | using ManagedCuda.VectorTypes;
27 | using ManagedCuda.NPP;
28 |
29 | namespace PEFStudioDX
30 | {
31 | public class OpticalFlow
32 | {
33 | NPPImage_32fC1 d_tmp;
34 | NPPImage_32fC1 d_Ix;
35 | NPPImage_32fC1 d_Iy;
36 | NPPImage_32fC1 d_Iz;
37 |
38 | NPPImage_32fC2 d_flow;
39 | CudaDeviceVariable buffer;
40 | CudaDeviceVariable mean;
41 | CudaDeviceVariable std;
42 | CudaDeviceVariable d_filterX;
43 | CudaDeviceVariable d_filterY;
44 | CudaDeviceVariable d_filterT;
45 |
46 | CreateFlowFieldFromTiles createFlowFieldFromTiles;
47 | WarpingKernel warpingKernel;
48 | ComputeDerivativesKernel computeDerivativesKernel;
49 | LukasKanadeKernel lukasKanade;
50 |
51 | public void FreeDeviceMemory()
52 | {
53 | d_tmp.Dispose();
54 | d_Ix.Dispose();
55 | d_Iy.Dispose();
56 | d_Iz.Dispose();
57 | //d_imageHalf.Dispose();
58 |
59 | d_flow.Dispose();
60 | buffer.Dispose();
61 | mean.Dispose();
62 | std.Dispose();
63 | d_filterX.Dispose();
64 | d_filterY.Dispose();
65 | d_filterT.Dispose();
66 | }
67 |
68 | private void DumpFlowField(NPPImage_32fC2 flow, string filename)
69 | {
70 | float2[] f = new float2[flow.Width * flow.Height];
71 |
72 | flow.CopyToHost(f);
73 |
74 | FileStream fs = File.OpenWrite(filename);
75 | BinaryWriter bw = new BinaryWriter(fs);
76 |
77 | bw.Write(flow.Width);
78 | bw.Write(flow.Height);
79 |
80 | for (int i = 0; i < f.Length; i++)
81 | {
82 | bw.Write(f[i].x);
83 | bw.Write(f[i].y);
84 | }
85 |
86 | bw.Close();
87 | fs.Close();
88 | bw.Dispose();
89 | fs.Dispose();
90 | }
91 |
92 | private void DumpImage(NPPImage_32fC1 img, string filename)
93 | {
94 | float[] f = new float[img.Width * img.Height];
95 |
96 | img.CopyToHost(f);
97 |
98 | FileStream fs = File.OpenWrite(filename);
99 | BinaryWriter bw = new BinaryWriter(fs);
100 |
101 | bw.Write(img.Width);
102 | bw.Write(img.Height);
103 |
104 | for (int i = 0; i < f.Length; i++)
105 | {
106 | bw.Write(f[i]);
107 | }
108 |
109 | bw.Close();
110 | fs.Close();
111 | bw.Dispose();
112 | fs.Dispose();
113 | }
114 |
115 | public OpticalFlow(int width, int height, CudaContext ctx)
116 | {
117 | CUmodule mod = ctx.LoadModulePTX("opticalFlow.ptx");
118 |
119 | warpingKernel = new WarpingKernel(ctx, mod);
120 | createFlowFieldFromTiles = new CreateFlowFieldFromTiles(ctx, mod);
121 | computeDerivativesKernel = new ComputeDerivativesKernel(ctx, mod);
122 | lukasKanade = new LukasKanadeKernel(ctx, mod);
123 |
124 | d_tmp = new NPPImage_32fC1(width, height);
125 | d_Ix = new NPPImage_32fC1(width, height);
126 | d_Iy = new NPPImage_32fC1(width, height);
127 | d_Iz = new NPPImage_32fC1(width, height);
128 | d_flow = new NPPImage_32fC2(width, height);
129 |
130 | buffer = new CudaDeviceVariable(d_tmp.MeanStdDevGetBufferHostSize() * 3);
131 | mean = new CudaDeviceVariable(1);
132 | std = new CudaDeviceVariable(1);
133 |
134 |
135 | d_filterX = new float[] { -0.25f, 0.25f, -0.25f, 0.25f };
136 | d_filterY = new float[] { -0.25f, -0.25f, 0.25f, 0.25f };
137 | d_filterT = new float[] { 0.25f, 0.25f, 0.25f, 0.25f };
138 | }
139 |
140 | private void Swap(ref NPPImage_32fC2 a, ref NPPImage_32fC2 b)
141 | {
142 | NPPImage_32fC2 temp = a;
143 | a = b;
144 | b = temp;
145 | }
146 |
147 | public void LucasKanade(NPPImage_32fC1 sourceImg, NPPImage_32fC1 targetImg, NPPImage_32fC2 tiledFlow, int tileSize, int tileCountX, int tileCountY, int iterations, float2 baseShift, float baseRotation, float minDet, int windowSize)
148 | {
149 | createFlowFieldFromTiles.RunSafe(tiledFlow, d_flow, baseShift, baseRotation, tileSize, tileCountX, tileCountY);
150 |
151 | for (int iter = 0; iter < iterations; iter++)
152 | {
153 | warpingKernel.RunSafe(sourceImg, d_tmp, d_flow);
154 | NppiPoint p = new NppiPoint(0,0);
155 | d_Ix.Set(0);
156 | d_Iy.Set(0);
157 | d_Iz.Set(0);
158 |
159 | computeDerivativesKernel.RunSafe(d_tmp, targetImg, d_Ix, d_Iy, d_Iz);
160 | lukasKanade.RunSafe(d_flow, d_Ix, d_Iy, d_Iz, minDet, windowSize);
161 | }
162 | warpingKernel.RunSafe(sourceImg, d_tmp, d_flow);
163 | d_tmp.Copy(sourceImg);
164 | }
165 |
166 | public NPPImage_32fC2 LastFlow
167 | {
168 | get { return d_flow; }
169 | }
170 |
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/PEFStudioDX/OpticalFlowKernels.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using ManagedCuda;
25 | using ManagedCuda.BasicTypes;
26 | using ManagedCuda.VectorTypes;
27 | using ManagedCuda.NPP;
28 |
29 | namespace PEFStudioDX
30 | {
31 |
32 | public class WarpingKernel : CudaKernel
33 | {
34 | const string kernelName = "WarpingKernel";
35 | public WarpingKernel(CudaContext ctx, CUmodule module)
36 | : base(kernelName, module, ctx)
37 | {
38 | }
39 |
40 | //int width, int height, int stride,
41 | //cudaTextureObject_t texUV, float* __restrict__ out, cudaTextureObject_t texToWarp
42 | public float RunSafe(NPPImage_32fC1 inImg, NPPImage_32fC1 outImg, NPPImage_32fC2 flow)
43 | {
44 | this.BlockDimensions = new dim3(32, 6, 1);
45 | this.SetComputeSize((uint)(outImg.WidthRoi), (uint)(outImg.HeightRoi), 1);
46 |
47 | CudaResourceDesc descImg = new CudaResourceDesc(inImg);
48 | CudaTextureDescriptor texDescImg = new CudaTextureDescriptor(CUAddressMode.Mirror, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
49 | CudaTexObject texImg = new CudaTexObject(descImg, texDescImg);
50 |
51 | CudaResourceDesc descFlow = new CudaResourceDesc(flow);
52 | CudaTextureDescriptor texDescFlow = new CudaTextureDescriptor(CUAddressMode.Clamp, CUFilterMode.Point, CUTexRefSetFlags.NormalizedCoordinates);
53 | CudaTexObject texFlow = new CudaTexObject(descFlow, texDescFlow);
54 |
55 | return this.Run(outImg.WidthRoi, outImg.HeightRoi, outImg.Pitch, texFlow.TexObject, outImg.DevicePointerRoi, texImg.TexObject);
56 | }
57 | }
58 | public class CreateFlowFieldFromTiles : CudaKernel
59 | {
60 | const string kernelName = "CreateFlowFieldFromTiles";
61 | public CreateFlowFieldFromTiles(CudaContext ctx, CUmodule module)
62 | : base(kernelName, module, ctx)
63 | {
64 | }
65 |
66 | //float2* __restrict__ outImg,
67 | //cudaTextureObject_t texObjShiftXY,
68 | //int imgWidth,
69 | //int imgHeight,
70 | //int imgPitch
71 | public float RunSafe(NPPImage_32fC2 inFlow, NPPImage_32fC2 outFlow, float2 baseShift, float baseRotation, int tileSize, int tileCountX, int tileCountY)
72 | {
73 | this.BlockDimensions = new dim3(32, 6, 1);
74 | this.SetComputeSize((uint)(outFlow.WidthRoi), (uint)(outFlow.HeightRoi), 1);
75 |
76 | CudaResourceDesc descImg = new CudaResourceDesc(inFlow);
77 | CudaTextureDescriptor texDescImg = new CudaTextureDescriptor(CUAddressMode.Clamp, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
78 | CudaTexObject texImg = new CudaTexObject(descImg, texDescImg);
79 |
80 |
81 | float t = this.Run(outFlow.DevicePointerRoi, texImg.TexObject, tileSize, tileCountX, tileCountY, outFlow.WidthRoi, outFlow.HeightRoi, outFlow.Pitch, baseShift, baseRotation);
82 | texImg.Dispose();
83 | return t;
84 | }
85 | }
86 | public class ComputeDerivativesKernel : CudaKernel
87 | {
88 | const string kernelName = "ComputeDerivativesKernel";
89 | public ComputeDerivativesKernel(CudaContext ctx, CUmodule module)
90 | : base(kernelName, module, ctx)
91 | {
92 | }
93 |
94 | //int width, int height, int stride,
95 | //float* Ix, float* Iy, float* Iz,
96 | //cudaTextureObject_t texSource,
97 | //cudaTextureObject_t texTarget
98 | public float RunSafe(NPPImage_32fC1 imgSource, NPPImage_32fC1 imgTarget, NPPImage_32fC1 Ix, NPPImage_32fC1 Iy, NPPImage_32fC1 Iz)
99 | {
100 | this.BlockDimensions = new dim3(32, 6, 1);
101 | this.SetComputeSize((uint)(imgSource.WidthRoi), (uint)(imgSource.HeightRoi), 1);
102 |
103 | CudaResourceDesc descImgSource = new CudaResourceDesc(imgSource);
104 | CudaTextureDescriptor texDescImgSource = new CudaTextureDescriptor(CUAddressMode.Mirror, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
105 | CudaTexObject texImgSource = new CudaTexObject(descImgSource, texDescImgSource);
106 |
107 | CudaResourceDesc descImgTarget = new CudaResourceDesc(imgTarget);
108 | CudaTextureDescriptor texDescImgTarget = new CudaTextureDescriptor(CUAddressMode.Mirror, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
109 | CudaTexObject texImgTarget = new CudaTexObject(descImgTarget, texDescImgTarget);
110 |
111 |
112 | float t = this.Run(Ix.WidthRoi, Ix.HeightRoi, Ix.Pitch, Ix.DevicePointerRoi, Iy.DevicePointerRoi, Iz.DevicePointerRoi, texImgSource.TexObject, texImgTarget.TexObject);
113 |
114 | texImgTarget.Dispose();
115 | texImgSource.Dispose();
116 |
117 | return t;
118 | }
119 | }
120 | public class ComputeDerivatives2Kernel : CudaKernel
121 | {
122 | const string kernelName = "ComputeDerivatives2Kernel";
123 | public ComputeDerivatives2Kernel(CudaContext ctx, CUmodule module)
124 | : base(kernelName, module, ctx)
125 | {
126 | }
127 |
128 | public float RunSafe(NPPImage_32fC1 imgSource, NPPImage_32fC1 Ix, NPPImage_32fC1 Iy)
129 | {
130 | this.BlockDimensions = new dim3(32, 6, 1);
131 | this.SetComputeSize((uint)(imgSource.WidthRoi), (uint)(imgSource.HeightRoi), 1);
132 |
133 | CudaResourceDesc descImgSource = new CudaResourceDesc(imgSource);
134 | CudaTextureDescriptor texDescImgSource = new CudaTextureDescriptor(CUAddressMode.Mirror, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
135 | CudaTexObject texImgSource = new CudaTexObject(descImgSource, texDescImgSource);
136 |
137 |
138 | float t = this.Run(Ix.WidthRoi, Ix.HeightRoi, Ix.Pitch, Ix.DevicePointerRoi, Iy.DevicePointerRoi, texImgSource.TexObject);
139 |
140 | texImgSource.Dispose();
141 |
142 | return t;
143 | }
144 | }
145 |
146 | public class LukasKanadeKernel : CudaKernel
147 | {
148 | /*const float4 * __restrict__ temp,
149 | float2 * __restrict__ shifts,
150 | const float* __restrict__ imFx,
151 | const float* __restrict__ imFy,
152 | const float* __restrict__ imFt,
153 | int pitchShift,
154 | int pitchImg,
155 | int pitchTemp,
156 | int width,
157 | int height,
158 | int halfWindowSize
159 | */
160 | const string kernelName = "lucasKanadeOptim";
161 | public LukasKanadeKernel(CudaContext ctx, CUmodule module)
162 | : base(kernelName, module, ctx)
163 | {
164 | }
165 | public float RunSafe(NPPImage_32fC2 shifts, NPPImage_32fC1 imFx, NPPImage_32fC1 imFy, NPPImage_32fC1 imFt, float minDet, int windowSize)
166 | {
167 | this.BlockDimensions = new dim3(32, 16, 1);
168 | this.SetComputeSize((uint)(shifts.WidthRoi), (uint)(shifts.HeightRoi), 1);
169 | //this.DynamicSharedMemory = (uint)(5 * windowSize * windowSize) * BlockDimensions.x * BlockDimensions.y * sizeof(float);
170 |
171 | int windowSizeHalf = windowSize / 2;
172 | return this.Run(shifts.DevicePointerRoi, imFx.DevicePointerRoi, imFy.DevicePointerRoi, imFt.DevicePointerRoi, shifts.Pitch, imFx.Pitch, shifts.WidthRoi, shifts.HeightRoi, windowSizeHalf, minDet);
173 |
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/PEFStudioDX/PEFStudioDX.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}
8 | WinExe
9 | PEFStudioDX
10 | PEFStudioDX
11 | v4.7.2
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 | false
28 |
29 |
30 | AnyCPU
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 | false
38 |
39 |
40 |
41 | ..\packages\ManagedCuda-CUBLAS.10.2.41\lib\net40\CudaBlas.dll
42 |
43 |
44 | ..\packages\ManagedCuda-CUFFT.10.2.41\lib\net40\CudaFFT.dll
45 |
46 |
47 | ..\packages\ManagedCuda-102.10.2.41\lib\net40\ManagedCuda.dll
48 |
49 |
50 | ..\packages\ManagedCuda-NPP.10.2.41\lib\net40\NPP.dll
51 |
52 |
53 | .\SlimDX.dll
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 4.0
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | MSBuild:Compile
74 | Designer
75 |
76 |
77 |
78 | LUTControl.xaml
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | Designer
92 | MSBuild:Compile
93 |
94 |
95 | Designer
96 | MSBuild:Compile
97 |
98 |
99 | MSBuild:Compile
100 | Designer
101 |
102 |
103 | App.xaml
104 | Code
105 |
106 |
107 |
108 |
109 | ImagePresenterDX.xaml
110 |
111 |
112 |
113 | MainWindow.xaml
114 | Code
115 |
116 |
117 |
118 |
119 |
120 |
121 | Code
122 |
123 |
124 | True
125 | True
126 | Resources.resx
127 |
128 |
129 | True
130 | Settings.settings
131 | True
132 |
133 |
134 | ResXFileCodeGenerator
135 | Resources.Designer.cs
136 |
137 |
138 |
139 | SettingsSingleFileGenerator
140 | Settings.Designer.cs
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | {ceb1ffe5-2ba8-48aa-ac87-7c5fb5cc01b4}
149 | PefFile
150 |
151 |
152 |
153 |
154 | Always
155 |
156 |
157 | Always
158 |
159 |
160 | Always
161 |
162 |
163 | Always
164 |
165 |
166 | Always
167 |
168 |
169 | Always
170 |
171 |
172 | Always
173 |
174 |
175 | Always
176 |
177 |
178 | Always
179 |
180 |
181 | Always
182 |
183 |
184 | Always
185 |
186 |
187 |
188 |
--------------------------------------------------------------------------------
/PEFStudioDX/PatchTrackingLevel.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PEFStudioDX
26 | {
27 | public class PatchTrackingLevel
28 | {
29 | int _resizeLevel;
30 | int _tileSize;
31 | int _maxShift;
32 |
33 | public PatchTrackingLevel()
34 | {
35 | _resizeLevel = 1;
36 | _tileSize = 32;
37 | _maxShift = 2;
38 | }
39 | public PatchTrackingLevel(int aResizeLevel, int aTileSize, int aMaxShift)
40 | {
41 | _resizeLevel = aResizeLevel;
42 | _tileSize = aTileSize;
43 | _maxShift = aMaxShift;
44 | }
45 |
46 | public int ResizeLevel
47 | {
48 | get { return _resizeLevel; }
49 | set { _resizeLevel = value; }
50 | }
51 |
52 | public int TileSize
53 | {
54 | get { return _tileSize; }
55 | set { _tileSize = value; }
56 | }
57 |
58 | public int MaxShift
59 | {
60 | get { return _maxShift; }
61 | set { _maxShift = value; }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/PEFStudioDX/PreAlignmentStore.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using ManagedCuda.VectorTypes;
25 |
26 | namespace PEFStudioDX
27 | {
28 | public class PreAlignmentStore
29 | {
30 | float2[] _shifts;
31 | float[] _rotations;
32 | int _referenceIndex = -1;
33 |
34 |
35 |
36 | public PreAlignmentStore(double4[] initialShifts)
37 | {
38 | int imageCount = initialShifts.Length;
39 | _shifts = new float2[imageCount];
40 | _rotations = new float[imageCount];
41 |
42 | double4[] basicShifts = new double4[initialShifts.Length];
43 |
44 | for (int i = 1; i < imageCount; i++)
45 | {
46 | double4 shiftToI = initialShifts[i];
47 | double4 shiftToIMinus1 = initialShifts[i - 1];
48 |
49 | basicShifts[i - 1] = new double4(shiftToI.x - shiftToIMinus1.x, shiftToI.y - shiftToIMinus1.y, shiftToI.z - shiftToIMinus1.z, 0);
50 | }
51 | int minIndex = -1;
52 |
53 | //Reduce total shift:
54 | double2[] shiftLengthMin = new double2[imageCount - 1];
55 |
56 | for (int i = 0; i < imageCount - 1; i++)
57 | {
58 | double2 a = new double2();
59 | for (int j = 0; j < i; j++)
60 | {
61 | a.x -= basicShifts[j].x;
62 | a.y -= basicShifts[j].y;
63 | }
64 |
65 | double2 b = new double2();
66 | for (int j = i; j < imageCount - 1; j++)
67 | {
68 | b.x += basicShifts[j].x;
69 | b.y += basicShifts[j].y;
70 | }
71 |
72 | shiftLengthMin[i].x = a.x + b.x;
73 | shiftLengthMin[i].y = a.y + b.y;
74 | }
75 |
76 | minIndex = -1;
77 | double minShift = double.MaxValue;
78 | for (int i = 0; i < imageCount - 1; i++)
79 | {
80 | double2 a = shiftLengthMin[i];
81 | double d = System.Math.Sqrt(a.x * a.x + a.y * a.y);
82 | if (d < minShift)
83 | {
84 | minShift = d;
85 | minIndex = i;
86 | }
87 | }
88 |
89 | for (int i = 0; i < imageCount; i++)
90 | {
91 | double4 a = new double4();
92 | for (int j = i; j < minIndex; j++)
93 | {
94 | a.x -= basicShifts[j].x;
95 | a.y -= basicShifts[j].y;
96 | a.z -= basicShifts[j].z;
97 | }
98 |
99 | for (int j = minIndex; j < i; j++)
100 | {
101 | a.x += basicShifts[j].x;
102 | a.y += basicShifts[j].y;
103 | a.z += basicShifts[j].z;
104 | }
105 | float2 shift = new float2((float)a.x, (float)a.y);
106 | _shifts[i] = shift;
107 | _rotations[i] = (float)a.z;
108 | }
109 | _referenceIndex = minIndex;
110 | }
111 |
112 | public int ReferenceIndex
113 | {
114 | get { return _referenceIndex; }
115 | set { _referenceIndex = value; }
116 | }
117 |
118 |
119 | public float2 GetShift(int from, int to)
120 | {
121 | return _shifts[to] - _shifts[from];
122 | }
123 |
124 | public float2 GetShift(int to)
125 | {
126 | if (_referenceIndex < 0)
127 | return new float2(0, 0);
128 | return GetShift(_referenceIndex, to);
129 | }
130 |
131 | public float GetRotation(int from, int to)
132 | {
133 | float angle = _rotations[to] - _rotations[from];
134 | angle = angle / 180.0f * (float)System.Math.PI;
135 | return angle;
136 | }
137 |
138 | public float GetRotation(int to)
139 | {
140 | if (_referenceIndex < 0)
141 | return 0.0f;
142 | return GetRotation(_referenceIndex, to);
143 | }
144 |
145 | public void Reset()
146 | {
147 | for (int i = 0; i < _rotations.Length; i++)
148 | {
149 | _rotations[i] = 0;
150 | }
151 | for (int i = 0; i < _shifts.Length; i++)
152 | {
153 | _shifts[i] = new float2(0,0);
154 | }
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/PEFStudioDX/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // Allgemeine Informationen über eine Assembly werden über die folgenden
8 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
9 | // die einer Assembly zugeordnet sind.
10 | [assembly: AssemblyTitle("PEFStudioDX")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("PEFStudioDX")]
15 | [assembly: AssemblyCopyright("Copyright © 2019")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
20 | // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
21 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
22 | [assembly: ComVisible(false)]
23 |
24 | //Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
25 | //ImCodeVerwendeteKultur in der .csproj-Datei
26 | //in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
27 | //(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
28 | //des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
29 | //sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
36 | //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
37 | // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
38 | ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
39 | //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
40 | // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
41 | )]
42 |
43 |
44 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
45 | //
46 | // Hauptversion
47 | // Nebenversion
48 | // Buildnummer
49 | // Revision
50 | //
51 | // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
52 | // indem Sie "*" wie unten gezeigt eingeben:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/PEFStudioDX/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Dieser Code wurde von einem Tool generiert.
4 | // Laufzeitversion: 4.0.30319.42000
5 | //
6 | // Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn
7 | // der Code erneut generiert wird.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PEFStudioDX.Properties
12 | {
13 |
14 |
15 | ///
16 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
17 | ///
18 | // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse
19 | // über ein Tool wie ResGen oder Visual Studio automatisch generiert.
20 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
21 | // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PEFStudioDX.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
56 | /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/PEFStudioDX/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/PEFStudioDX/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PEFStudioDX.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/PEFStudioDX/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/PEFStudioDX/RobustnessModellKernel.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System.Collections.Generic;
20 | using System.Linq;
21 | using System.Text;
22 | using System.Threading.Tasks;
23 | using ManagedCuda;
24 | using ManagedCuda.BasicTypes;
25 | using ManagedCuda.VectorTypes;
26 | using ManagedCuda.NPP;
27 |
28 | namespace PEFStudioDX
29 | {
30 | public class RobustnessModellKernel : CudaKernel
31 | {
32 | const string kernelName = "ComputeRobustnessMask";
33 | public RobustnessModellKernel(CudaContext ctx, CUmodule module)
34 | : base(kernelName, module, ctx)
35 | {
36 | }
37 | /*
38 |
39 | const float3* __restrict__ rawImgRef,
40 | const float3* __restrict__ rawImgMoved,
41 | float3* __restrict__ robustnessMask,
42 | cudaTextureObject_t texUV,
43 | int imgWidth,
44 | int imgHeight,
45 | int imgPitch,
46 | float alpha,
47 | float beta)
48 | */
49 | public float RunSafe(NPPImage_32fC3 rawImgRef, NPPImage_32fC3 rawImgMoved, NPPImage_32fC4 robustnessMask, NPPImage_32fC2 shift, float alpha, float beta, float thresholdM)
50 | {
51 | this.BlockDimensions = new dim3(8, 8, 1);
52 | this.SetComputeSize((uint)(rawImgRef.WidthRoi), (uint)(rawImgRef.HeightRoi), 1);
53 | this.DynamicSharedMemory = BlockDimensions.x * BlockDimensions.y * float3.SizeOf * 3 * 3;
54 |
55 | CudaResourceDesc descShift = new CudaResourceDesc(shift);
56 | CudaTextureDescriptor texDescShift = new CudaTextureDescriptor(CUAddressMode.Mirror, CUFilterMode.Linear, CUTexRefSetFlags.NormalizedCoordinates);
57 | CudaTexObject texShift = new CudaTexObject(descShift, texDescShift);
58 |
59 |
60 | float t = this.Run(rawImgRef.DevicePointerRoi, rawImgMoved.DevicePointerRoi, robustnessMask.DevicePointerRoi, texShift.TexObject, rawImgRef.WidthRoi,
61 | rawImgRef.HeightRoi, rawImgRef.Pitch, robustnessMask.Pitch, alpha, beta, thresholdM);
62 |
63 | texShift.Dispose();
64 |
65 | return t;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/PEFStudioDX/ShiftMinimizerKernels.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using ManagedCuda;
25 | using ManagedCuda.BasicTypes;
26 | using ManagedCuda.VectorTypes;
27 | using ManagedCuda.NPP;
28 |
29 | namespace PEFStudioDX
30 | {
31 | public class concatenateShiftsKernel : CudaKernel
32 | {
33 | const string kernelName = "concatenateShifts";
34 | public concatenateShiftsKernel(CudaContext ctx, CUmodule module)
35 | : base(kernelName, module, ctx)
36 | {
37 | }
38 |
39 | /*shiftIn,
40 | float2* __restrict__ shiftOut,
41 | int shiftCount,
42 | int tileCount
43 | */
44 |
45 | public float RunSafe(CudaDeviceVariable measuredShifts, CudaDeviceVariable shiftPitch, CudaDeviceVariable shiftOut, int shiftCount, int tileCountX, int tileCountY)
46 | {
47 | this.BlockDimensions = new dim3(8, 8, 4);
48 | this.SetComputeSize((uint)(shiftCount), (uint)(tileCountX), (uint)(tileCountY));
49 |
50 | return this.Run(measuredShifts.DevicePointer, shiftPitch.DevicePointer, shiftOut.DevicePointer, shiftCount, tileCountX, tileCountY);
51 | }
52 | }
53 | public class separateShiftsKernel : CudaKernel
54 | {
55 | const string kernelName = "separateShifts";
56 | public separateShiftsKernel(CudaContext ctx, CUmodule module)
57 | : base(kernelName, module, ctx)
58 | {
59 | }
60 |
61 | public float RunSafe(CudaDeviceVariable shiftIn, CudaDeviceVariable measuredShifts, CudaDeviceVariable shiftPitch, int shiftCount, int tileCountX, int tileCountY)
62 | {
63 | this.BlockDimensions = new dim3(8, 8, 4);
64 | this.SetComputeSize((uint)(shiftCount), (uint)(tileCountX), (uint)(tileCountY));
65 |
66 | return this.Run(shiftIn.DevicePointer, measuredShifts.DevicePointer, shiftPitch.DevicePointer, shiftCount, tileCountX, tileCountY);
67 | }
68 | }
69 | public class getOptimalShiftsKernel : CudaKernel
70 | {
71 | /*
72 | getOptimalShifts(
73 | float2 * __restrict__ optimalShifts,
74 | const float2 * __restrict__ bestShifts,
75 | int imageCount,
76 | int tileCountX,
77 | int tileCountY,
78 | int optimalShiftsPitch,
79 | int referenceImage,
80 | int imageToTrack
81 | */
82 |
83 | const string kernelName = "getOptimalShifts";
84 | public getOptimalShiftsKernel(CudaContext ctx, CUmodule module)
85 | : base(kernelName, module, ctx)
86 | {
87 | }
88 |
89 | public float RunSafe(NPPImage_32fC2 optimalShifts, CudaDeviceVariable bestShifts, int imageCount, int referenceImage, int imageToTrack)
90 | {
91 | this.BlockDimensions = new dim3(32, 8, 1);
92 | this.SetComputeSize((uint)(optimalShifts.WidthRoi), (uint)(optimalShifts.HeightRoi), 1);
93 |
94 | return this.Run(optimalShifts.DevicePointer, bestShifts.DevicePointer, imageCount, optimalShifts.WidthRoi, optimalShifts.HeightRoi, optimalShifts.Pitch, referenceImage, imageToTrack);
95 | }
96 | }
97 |
98 | public class copyShiftMatrixKernel : CudaKernel
99 | {
100 | const string kernelName = "copyShiftMatrix";
101 | public copyShiftMatrixKernel(CudaContext ctx, CUmodule module)
102 | : base(kernelName, module, ctx)
103 | {
104 | }
105 |
106 | //copyShiftMatrix(float* __restrict__ matrices, int tileCount, int imageCount, int shiftCount)
107 | public float RunSafe(CudaDeviceVariable matrices, int tileCount, int imageCount, int shiftCount)
108 | {
109 | this.BlockDimensions = new dim3(128, 1, 1);
110 | this.SetComputeSize((uint)tileCount, 1, 1);
111 |
112 | return this.Run(matrices.DevicePointer, tileCount, imageCount, shiftCount);
113 | }
114 | }
115 |
116 | public class setPointersKernel : CudaKernel
117 | {
118 | const string kernelName = "setPointers";
119 | public setPointersKernel(CudaContext ctx, CUmodule module)
120 | : base(kernelName, module, ctx)
121 | {
122 | }
123 |
124 | /*
125 | * setPointers(float** __restrict__ shiftMatrixArray, float** __restrict__ matrixSquareArray,
126 | float** __restrict__ matrixInvertedArray, float** __restrict__ solvedMatrixArray,
127 | float2**__restrict__ shiftOneToOneArray, float2** __restrict__ shiftMeasuredArray, float2** __restrict__ shiftOptimArray,
128 | float* shiftMatrices, float* matricesSquared, float* matricesInverted, float* solvedMatrices,
129 | float2* shiftsOneToOne, float2* shiftsMeasured, float2* shiftsOptim, int tileCount, int imageCount)
130 | */
131 | public float RunSafe(CudaDeviceVariable shiftMatrixArray, CudaDeviceVariable shiftMatrixSafeArray, CudaDeviceVariable matrixSquareArray,
132 | CudaDeviceVariable matrixInvertedArray, CudaDeviceVariable solvedMatrixArray,
133 | CudaDeviceVariable shiftOneToOneArray, CudaDeviceVariable shiftMeasuredArray, CudaDeviceVariable shiftOptimArray,
134 | CudaDeviceVariable shiftMatrices, CudaDeviceVariable shiftSafeMatrices, CudaDeviceVariable matricesSquared, CudaDeviceVariable matricesInverted, CudaDeviceVariable solvedMatrices,
135 | CudaDeviceVariable shiftsOneToOne, CudaDeviceVariable shiftsMeasured, CudaDeviceVariable shiftsOptim, int tileCount, int imageCount, int shiftCount)
136 | {
137 | this.BlockDimensions = new dim3(128, 1, 1);
138 | this.SetComputeSize((uint)tileCount, 1, 1);
139 |
140 | return this.Run(shiftMatrixArray.DevicePointer, shiftMatrixSafeArray.DevicePointer, matrixSquareArray.DevicePointer,
141 | matrixInvertedArray.DevicePointer, solvedMatrixArray.DevicePointer,
142 | shiftOneToOneArray.DevicePointer, shiftMeasuredArray.DevicePointer, shiftOptimArray.DevicePointer,
143 | shiftMatrices.DevicePointer, shiftSafeMatrices.DevicePointer, matricesSquared.DevicePointer, matricesInverted.DevicePointer, solvedMatrices.DevicePointer,
144 | shiftsOneToOne.DevicePointer, shiftsMeasured.DevicePointer, shiftsOptim.DevicePointer, tileCount, imageCount, shiftCount);
145 | }
146 | }
147 |
148 |
149 | public class checkForOutliersKernel : CudaKernel
150 | {
151 | const string kernelName = "checkForOutliers";
152 | public checkForOutliersKernel(CudaContext ctx, CUmodule module)
153 | : base(kernelName, module, ctx)
154 | {
155 | }
156 |
157 | /*
158 | * checkForOutliers(
159 | float2* __restrict__ measuredShifts,
160 | const float2* __restrict__ optimShifts,
161 | const float* __restrict__ shiftsOneToOneT,
162 | float2* __restrict__ shiftsOneToOne,
163 | float* __restrict__ shiftMatrix,
164 | int* __restrict__ status,
165 | int* __restrict__ inversionInfo,
166 | int tileCount, int imageCount)
167 | */
168 | public float RunSafe(CudaDeviceVariable measuredShifts, CudaDeviceVariable optimShifts,
169 | CudaDeviceVariable shiftMatrix, CudaDeviceVariable status,
170 | CudaDeviceVariable inversionInfo, int tileCount, int imageCount, int shiftCount)
171 | {
172 | this.BlockDimensions = new dim3(128, 1, 1);
173 | this.SetComputeSize((uint)tileCount, 1, 1);
174 |
175 | return this.Run(measuredShifts.DevicePointer, optimShifts.DevicePointer,
176 | shiftMatrix.DevicePointer, status.DevicePointer,
177 | inversionInfo.DevicePointer, tileCount, imageCount, shiftCount);
178 | }
179 | }
180 |
181 |
182 | public class transposeShiftsKernel : CudaKernel
183 | {
184 | const string kernelName = "transposeShifts";
185 | public transposeShiftsKernel(CudaContext ctx, CUmodule module)
186 | : base(kernelName, module, ctx)
187 | {
188 | }
189 |
190 | /*
191 | * transposeShifts(
192 | float2 * __restrict__ measuredShifts,
193 | const float* __restrict__ measuredShiftsT,
194 | int tileCount, int imageCount)
195 | */
196 | public float RunSafe(CudaDeviceVariable measuredShifts, CudaDeviceVariable measuredShiftsT,
197 | CudaDeviceVariable shiftsOneToOneT, CudaDeviceVariable shiftsOneToOne,
198 | int tileCount, int imageCount, int shiftCount)
199 | {
200 | uint m = (uint)((imageCount - 1) * ((float)imageCount / 2.0f));
201 | this.BlockDimensions = new dim3(32, 8, 1);
202 | this.SetComputeSize((uint)tileCount, m, 1);
203 |
204 | return this.Run(measuredShifts.DevicePointer, measuredShiftsT.DevicePointer,
205 | shiftsOneToOneT.DevicePointer, shiftsOneToOne.DevicePointer,
206 | tileCount, imageCount, shiftCount);
207 | }
208 | }
209 |
210 | }
211 |
--------------------------------------------------------------------------------
/PEFStudioDX/SlimDX.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/PEFStudioDX/SlimDX.dll
--------------------------------------------------------------------------------
/PEFStudioDX/TestRawFile.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using ManagedCuda;
25 | using ManagedCuda.BasicTypes;
26 | using ManagedCuda.VectorTypes;
27 | using ManagedCuda.NPP;
28 |
29 |
30 | namespace PEFStudioDX
31 | {
32 | public class TestRawFile : PentaxPefFile.RawFile
33 | {
34 | public TestRawFile(string dummyFile, int size, float preShiftX, float preShiftY, float preRotDeg, float shiftX, float shiftY)
35 | : base(dummyFile)
36 | {
37 | //close the file
38 | Close();
39 | Random rand = new Random(0);
40 |
41 | mRawImage = new ushort[size, size];
42 |
43 | float[] temp = new float[size * size];
44 | NPPImage_32fC1 img1 = new NPPImage_32fC1(size, size);
45 | NPPImage_32fC1 img2 = new NPPImage_32fC1(size, size);
46 | NPPImage_16uC1 img16u = new NPPImage_16uC1(size, size);
47 |
48 | for (int i = 0; i < temp.Length; i++)
49 | {
50 | temp[i] = (float)rand.NextDouble();
51 | }
52 |
53 | img1.CopyToDevice(temp);
54 | img1.FilterGaussBorder(img2, MaskSize.Size_5_X_5, NppiBorderType.Replicate);
55 | img1.Set(0);
56 | img2.WarpAffine(img1, Matrix3x3.ShiftAffine(-preShiftX, -preShiftY).ToAffine(), InterpolationMode.Cubic);
57 | img2.Set(0);
58 | img1.WarpAffine(img2, Matrix3x3.RotAroundCenter(-preRotDeg, size, size).ToAffine(), InterpolationMode.Cubic);
59 | img1.Set(0);
60 | img2.WarpAffine(img1, Matrix3x3.ShiftAffine(-shiftX, -shiftY).ToAffine(), InterpolationMode.Cubic);
61 | img1.Mul(65535);
62 | img1.Convert(img16u, NppRoundMode.Near);
63 |
64 | img16u.CopyToHost(mRawImage, size * sizeof(ushort));
65 |
66 | double[] colorMatrix = new double[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
67 | mColorSpec = new PentaxPefFile.DNGColorSpec(colorMatrix, colorMatrix, PentaxPefFile.IFDDNGCalibrationIlluminant.Illuminant.D50,
68 | PentaxPefFile.IFDDNGCalibrationIlluminant.Illuminant.D65, new float[] {1f, 1,1f });
69 | mOrientation = new PentaxPefFile.DNGOrientation(PentaxPefFile.DNGOrientation.Orientation.Normal);
70 |
71 | mWidth = size;
72 | mHeight = size;
73 | mCropLeft = 0;
74 | mCropTop = 0;
75 | mCroppedWidth = size;
76 | mCroppedHeight = size;
77 | mBitDepth = 16;
78 | mISO = 100;
79 | mBayerPattern = new BayerColor[] { BayerColor.Red, BayerColor.Cyan, BayerColor.Blue };
80 | mWhiteLevel = new float[] { 65535, 65535, 65535 };
81 | mBlackLevel = new float[] { 0, 0, 0 };
82 | mWhiteBalance = new float[] { 1, 1, 1 }; ;
83 | mRollAngle = 0;
84 | mRollAnglePresent = false;
85 | mNoiseModelAlpha = float.Epsilon;
86 | mNoiseModelBeta = 0;
87 | mExposureTime = new PentaxPefFile.Rational(1, 1);
88 | mRecordingDate = DateTime.Now;
89 | mMake = "None";
90 | mUniqueModelName = "Test file";
91 |
92 | img1.Dispose();
93 | img2.Dispose();
94 | img16u.Dispose();
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/PEFStudioDX/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/PefFile/DNGColorSpace.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PentaxPefFile
26 | {
27 | //More or less a 1:1 copy of the DNGColorSpace class in Adobe DNG SDK
28 | //https://www.adobe.com/support/downloads/dng/dng_sdk.html
29 |
30 | public class DNGColorSpace
31 | {
32 | DNGMatrix mToPCS;
33 | DNGMatrix mFromPCS;
34 |
35 | //XYZ with D50 to sRGB with D65
36 | public static DNGColorSpace sRGB50 = new DNGColorSpace(new DNGMatrix3x3(0.4360747, 0.3850649, 0.1430804,
37 | 0.2225045, 0.7168786, 0.0606169,
38 | 0.0139322, 0.0971045, 0.7141733));
39 | //XYZ and ProPhoto D50
40 | public static DNGColorSpace ProPhoto = new DNGColorSpace(new DNGMatrix3x3(0.7976749, 0.1351917, 0.0313534,
41 | 0.2880402, 0.7118741, 0.0000857,
42 | 0.0000000, 0.0000000, 0.8252100));
43 |
44 | public DNGColorSpace(DNGMatrix3x3 toPCS)
45 | {
46 | // The matrix values are often rounded, so adjust to
47 | // get them to convert device white exactly to the PCS.
48 | DNGVector W1 = toPCS * new DNGVector3(1.0, 1.0, 1.0);
49 | DNGVector W2 = DNGxyCoord.PCStoXYZ;
50 |
51 | double s0 = W2[0] / W1[0];
52 | double s1 = W2[1] / W1[1];
53 | double s2 = W2[2] / W1[2];
54 |
55 | DNGMatrix3x3 S = new DNGMatrix3x3(s0, 0, 0,
56 | 0, s1, 0,
57 | 0, 0, s2);
58 |
59 | mToPCS = S * toPCS;
60 |
61 | // Find reverse matrix.
62 | mFromPCS = mToPCS.Invert();
63 | }
64 |
65 | public DNGMatrix ToPCS
66 | {
67 | get { return mToPCS; }
68 | }
69 |
70 | public DNGMatrix FromPCS
71 | {
72 | get { return mFromPCS; }
73 | }
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/PefFile/DNGOrientation.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PentaxPefFile
26 | {
27 | ///
28 | /// Same as DNG SDK, this is more human readable than TIFF spec.
29 | /// https://www.adobe.com/support/downloads/dng/dng_sdk.html
30 | ///
31 | public class DNGOrientation
32 | {
33 | public enum Orientation
34 | {
35 | Normal = 0,
36 | Rotate90CW = 1,
37 | Rotate180 = 2,
38 | Rotate90CCW = 3,
39 | Mirror = 4,
40 | Mirror90CW = 5,
41 | Mirror180 = 6,
42 | Mirror90CCW = 7,
43 | Unknown = 8
44 | }
45 |
46 | private Orientation _value;
47 |
48 | public DNGOrientation(Orientation aValue)
49 | {
50 | _value = aValue;
51 | }
52 |
53 | public DNGOrientation(ushort tiffOrientation)
54 | {
55 | switch (tiffOrientation)
56 | {
57 | case 1:
58 | _value = Orientation.Normal;
59 | break;
60 | case 2:
61 | _value = Orientation.Mirror;
62 | break;
63 | case 3:
64 | _value = Orientation.Rotate180;
65 | break;
66 | case 4:
67 | _value = Orientation.Mirror180;
68 | break;
69 | case 5:
70 | _value = Orientation.Mirror90CCW;
71 | break;
72 | case 6:
73 | _value = Orientation.Rotate90CW;
74 | break;
75 | case 7:
76 | _value = Orientation.Mirror90CW;
77 | break;
78 | case 8:
79 | _value = Orientation.Rotate90CCW;
80 | break;
81 | case 9:
82 | _value = Orientation.Unknown;
83 | break;
84 | default:
85 | _value = Orientation.Normal;
86 | break;
87 | }
88 | }
89 |
90 | public Orientation Value
91 | {
92 | get { return _value; }
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/PefFile/DNGTemperature.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PentaxPefFile
26 | {
27 | //More or less a 1:1 copy of the dng_temperature class in Adobe DNG SDK
28 | //https://www.adobe.com/support/downloads/dng/dng_sdk.html
29 |
30 | public class DNGTemperature
31 | {
32 | const double kTintScale = -3000.0;
33 | struct ruvt
34 | {
35 | public double r;
36 | public double u;
37 | public double v;
38 | public double t;
39 |
40 | public ruvt(double aR, double aU, double aV, double aT)
41 | {
42 | r = aR;
43 | u = aU;
44 | v = aV;
45 | t = aT;
46 | }
47 | };
48 |
49 | static ruvt[] kTempTable = new ruvt[]
50 | {
51 | new ruvt( 0, 0.18006, 0.26352, -0.24341 ),
52 | new ruvt( 10, 0.18066, 0.26589, -0.25479 ),
53 | new ruvt( 20, 0.18133, 0.26846, -0.26876 ),
54 | new ruvt( 30, 0.18208, 0.27119, -0.28539 ),
55 | new ruvt( 40, 0.18293, 0.27407, -0.30470 ),
56 | new ruvt( 50, 0.18388, 0.27709, -0.32675 ),
57 | new ruvt( 60, 0.18494, 0.28021, -0.35156 ),
58 | new ruvt( 70, 0.18611, 0.28342, -0.37915 ),
59 | new ruvt( 80, 0.18740, 0.28668, -0.40955 ),
60 | new ruvt( 90, 0.18880, 0.28997, -0.44278 ),
61 | new ruvt( 100, 0.19032, 0.29326, -0.47888 ),
62 | new ruvt( 125, 0.19462, 0.30141, -0.58204 ),
63 | new ruvt( 150, 0.19962, 0.30921, -0.70471 ),
64 | new ruvt( 175, 0.20525, 0.31647, -0.84901 ),
65 | new ruvt( 200, 0.21142, 0.32312, -1.0182 ),
66 | new ruvt( 225, 0.21807, 0.32909, -1.2168 ),
67 | new ruvt( 250, 0.22511, 0.33439, -1.4512 ),
68 | new ruvt( 275, 0.23247, 0.33904, -1.7298 ),
69 | new ruvt( 300, 0.24010, 0.34308, -2.0637 ),
70 | new ruvt( 325, 0.24702, 0.34655, -2.4681 ),
71 | new ruvt( 350, 0.25591, 0.34951, -2.9641 ),
72 | new ruvt( 375, 0.26400, 0.35200, -3.5814 ),
73 | new ruvt( 400, 0.27218, 0.35407, -4.3633 ),
74 | new ruvt( 425, 0.28039, 0.35577, -5.3762 ),
75 | new ruvt( 450, 0.28863, 0.35714, -6.7262 ),
76 | new ruvt( 475, 0.29685, 0.35823, -8.5955 ),
77 | new ruvt( 500, 0.30505, 0.35907, -11.324 ),
78 | new ruvt( 525, 0.31320, 0.35968, -15.628 ),
79 | new ruvt( 550, 0.32129, 0.36011, -23.325 ),
80 | new ruvt( 575, 0.32931, 0.36038, -40.770 ),
81 | new ruvt( 600, 0.33724, 0.36051, -116.45 )
82 | };
83 |
84 | double _temperature;
85 | double _tint;
86 |
87 | public DNGTemperature()
88 | {
89 | }
90 |
91 | public DNGTemperature(double aTemperature, double aTint)
92 | {
93 | _temperature = aTemperature;
94 | _tint = aTint;
95 | }
96 |
97 | public DNGTemperature(DNGxyCoord xy)
98 | {
99 | xyCoord = xy;
100 | }
101 |
102 | public double Temperature
103 | {
104 | get { return _temperature; }
105 | set { _temperature = value; }
106 | }
107 |
108 | public double Tint
109 | {
110 | get { return _tint; }
111 | set { _tint = value; }
112 | }
113 |
114 | public DNGxyCoord xyCoord
115 | {
116 | get
117 | {
118 | DNGxyCoord result = new DNGxyCoord();
119 |
120 | // Find inverse temperature to use as index.
121 | double r = 1.0E6 / _temperature;
122 |
123 | // Convert tint to offset is uv space.
124 | double offset = _tint * (1.0 / kTintScale);
125 |
126 | // Search for line pair containing coordinate.
127 | for (uint index = 0; index <= 29; index++)
128 | {
129 | if (r < kTempTable[index + 1].r || index == 29)
130 | {
131 | // Find relative weight of first line.
132 | double f = (kTempTable[index + 1].r - r) /
133 | (kTempTable[index + 1].r - kTempTable[index].r);
134 |
135 | // Interpolate the black body coordinates.
136 | double u = kTempTable[index].u * f +
137 | kTempTable[index + 1].u * (1.0 - f);
138 |
139 | double v = kTempTable[index].v * f +
140 | kTempTable[index + 1].v * (1.0 - f);
141 |
142 | // Find vectors along slope for each line.
143 | double uu1 = 1.0;
144 | double vv1 = kTempTable[index].t;
145 |
146 | double uu2 = 1.0;
147 | double vv2 = kTempTable[index + 1].t;
148 |
149 | double len1 = Math.Sqrt(1.0 + vv1 * vv1);
150 | double len2 = Math.Sqrt(1.0 + vv2 * vv2);
151 |
152 | uu1 /= len1;
153 | vv1 /= len1;
154 |
155 | uu2 /= len2;
156 | vv2 /= len2;
157 |
158 | // Find vector from black body point.
159 | double uu3 = uu1 * f + uu2 * (1.0 - f);
160 | double vv3 = vv1 * f + vv2 * (1.0 - f);
161 |
162 | double len3 = Math.Sqrt(uu3 * uu3 + vv3 * vv3);
163 |
164 | uu3 /= len3;
165 | vv3 /= len3;
166 |
167 | // Adjust coordinate along this vector.
168 | u += uu3 * offset;
169 | v += vv3 * offset;
170 |
171 | // Convert to xy coordinates.
172 | result.X = 1.5 * u / (u - 4.0 * v + 2.0);
173 | result.Y = v / (u - 4.0 * v + 2.0);
174 |
175 | break;
176 | }
177 | }
178 |
179 | return result;
180 | }
181 |
182 | set
183 | {
184 | // Convert to uv space.
185 | double u = 2.0 * value.X / (1.5 - value.X + 6.0 * value.Y);
186 | double v = 3.0 * value.Y / (1.5 - value.X + 6.0 * value.Y);
187 |
188 | // Search for line pair coordinate is between.
189 | double last_dt = 0.0;
190 | double last_dv = 0.0;
191 | double last_du = 0.0;
192 |
193 | for (uint index = 1; index <= 30; index++)
194 | {
195 | // Convert slope to delta-u and delta-v, with length 1.
196 | double du = 1.0;
197 | double dv = kTempTable[index].t;
198 |
199 | double len = Math.Sqrt(1.0 + dv * dv);
200 | du /= len;
201 | dv /= len;
202 |
203 | // Find delta from black body point to test coordinate.
204 | double uu = u - kTempTable[index].u;
205 | double vv = v - kTempTable[index].v;
206 |
207 | // Find distance above or below line.
208 | double dt = -uu * dv + vv * du;
209 |
210 | // If below line, we have found line pair.
211 | if (dt <= 0.0 || index == 30)
212 | {
213 | // Find fractional weight of two lines.
214 | if (dt > 0.0)
215 | dt = 0.0;
216 |
217 | dt = -dt;
218 |
219 | double f;
220 |
221 | if (index == 1)
222 | {
223 | f = 0.0;
224 | }
225 | else
226 | {
227 | f = dt / (last_dt + dt);
228 | }
229 |
230 | // Interpolate the temperature.
231 | _temperature = 1.0E6 / (kTempTable[index - 1].r * f +
232 | kTempTable[index].r * (1.0 - f));
233 |
234 | // Find delta from black body point to test coordinate.
235 | uu = u - (kTempTable[index - 1].u * f +
236 | kTempTable[index].u * (1.0 - f));
237 |
238 | vv = v - (kTempTable[index - 1].v * f +
239 | kTempTable[index].v * (1.0 - f));
240 |
241 | // Interpolate vectors along slope.
242 | du = du * (1.0 - f) + last_du * f;
243 | dv = dv * (1.0 - f) + last_dv * f;
244 |
245 | len = Math.Sqrt(du * du + dv * dv);
246 |
247 | du /= len;
248 | dv /= len;
249 |
250 | // Find distance along slope.
251 | _tint = (uu * du + vv * dv) * kTintScale;
252 | break;
253 | }
254 |
255 | // Try next line pair.
256 | last_dt = dt;
257 | last_du = du;
258 | last_dv = dv;
259 | }
260 | }
261 | }
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/PefFile/DNGUtils.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PentaxPefFile
26 | {
27 | public static class DNGUtils
28 | {
29 | public static double Pin(double min, double x, double max)
30 | {
31 | return Math.Max(min, Math.Min(x, max));
32 | }
33 |
34 | public static double Pin(double x)
35 | {
36 | return Pin(0.0, x, 1.0);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/PefFile/DNGxyCoord.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PentaxPefFile
26 | {
27 | //More or less a 1:1 copy of the DNGxyCoord class in Adobe DNG SDK
28 | //https://www.adobe.com/support/downloads/dng/dng_sdk.html
29 |
30 | public class DNGxyCoord
31 | {
32 | double x;
33 | double y;
34 |
35 | public DNGxyCoord()
36 | {
37 | }
38 |
39 | public DNGxyCoord(double xx, double yy)
40 | {
41 | x = xx;
42 | y = yy;
43 | }
44 |
45 | public DNGxyCoord(DNGxyCoord a)
46 | {
47 | x = a.x;
48 | y = a.y;
49 | }
50 |
51 | public double X
52 | {
53 | get { return x; }
54 | set { x = value; }
55 | }
56 |
57 | public double Y
58 | {
59 | get { return y; }
60 | set { y = value; }
61 | }
62 |
63 | public void Clear()
64 | {
65 | x = 0.0;
66 | y = 0.0;
67 | }
68 |
69 | public bool IsValid()
70 | {
71 | return x > 0.0 && y > 0.0;
72 | }
73 |
74 | public bool NotValid()
75 | {
76 | return !IsValid();
77 | }
78 |
79 | public DNGVector3 XYtoXYZ()
80 | {
81 | DNGxyCoord temp = new DNGxyCoord(this);
82 |
83 | // Restrict xy coord to someplace inside the range of real xy coordinates.
84 | // This prevents math from doing strange things when users specify
85 | // extreme temperature/tint coordinates.
86 | temp.x = DNGUtils.Pin(0.000001, temp.x, 0.999999);
87 | temp.y = DNGUtils.Pin(0.000001, temp.y, 0.999999);
88 |
89 | if (temp.x + temp.y > 0.999999)
90 | {
91 | double scale = 0.999999 / (temp.x + temp.y);
92 | temp.x *= scale;
93 | temp.y *= scale;
94 | }
95 |
96 | return new DNGVector3(temp.x / temp.y,
97 | 1.0,
98 | (1.0 - temp.x - temp.y) / temp.y);
99 | }
100 |
101 | public static DNGxyCoord XYZtoXY(DNGVector3 coord)
102 | {
103 | double X = coord[0];
104 | double Y = coord[1];
105 | double Z = coord[2];
106 |
107 | double total = X + Y + Z;
108 |
109 | if (total > 0.0)
110 | {
111 | return new DNGxyCoord(X / total, Y / total);
112 | }
113 |
114 | return DNGxyCoord.D50;
115 | }
116 |
117 | public override bool Equals(object obj)
118 | {
119 | if (!(obj is DNGxyCoord))
120 | {
121 | return false;
122 | }
123 |
124 | DNGxyCoord t = (DNGxyCoord)obj;
125 | return this.x == t.x && this.y == t.y;
126 | }
127 |
128 | public override int GetHashCode()
129 | {
130 | return x.GetHashCode() | y.GetHashCode();
131 | }
132 |
133 | public static bool operator ==(DNGxyCoord a, DNGxyCoord b)
134 | {
135 | return a.x == b.x && a.y == b.y;
136 | }
137 |
138 | public static bool operator !=(DNGxyCoord a, DNGxyCoord b)
139 | {
140 | return a.x != b.x && a.y != b.y;
141 | }
142 |
143 | public static DNGxyCoord operator +(DNGxyCoord a, DNGxyCoord b)
144 | {
145 | return new DNGxyCoord(a.x + b.x, a.y + b.y);
146 | }
147 |
148 | public static DNGxyCoord operator -(DNGxyCoord a, DNGxyCoord b)
149 | {
150 | return new DNGxyCoord(a.x - b.x, a.y - b.y);
151 | }
152 |
153 | public static DNGxyCoord operator *(double scale, DNGxyCoord b)
154 | {
155 | return new DNGxyCoord(scale * b.x, scale * b.y);
156 | }
157 |
158 | public static DNGxyCoord operator *(DNGxyCoord a, double scale)
159 | {
160 | return new DNGxyCoord(a.x * scale, a.y * scale);
161 | }
162 |
163 | public static double operator *(DNGxyCoord a, DNGxyCoord b)
164 | {
165 | return a.x * b.x + a.y * a.y;
166 | }
167 |
168 | public static DNGxyCoord StdA
169 | {
170 | get
171 | {
172 | return new DNGxyCoord(0.4476, 0.4074);
173 | }
174 | }
175 | public static DNGxyCoord D50
176 | {
177 | get
178 | {
179 | return new DNGxyCoord(0.3457, 0.3585);
180 | }
181 | }
182 |
183 | public static DNGxyCoord D55
184 | {
185 | get
186 | {
187 | return new DNGxyCoord(0.3324, 0.3474);
188 | }
189 | }
190 |
191 | public static DNGxyCoord D65
192 | {
193 | get
194 | {
195 | return new DNGxyCoord(0.3127, 0.3290);
196 | }
197 | }
198 |
199 | public static DNGxyCoord D75
200 | {
201 | get
202 | {
203 | return new DNGxyCoord(0.2990, 0.3149);
204 | }
205 | }
206 |
207 | public static DNGxyCoord PCStoXY
208 | {
209 | get { return D50; } //using ProPhoto as intermediate RGB space
210 | }
211 | public static DNGVector3 PCStoXYZ
212 | {
213 | get { return D50.XYtoXYZ(); }
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/PefFile/ExtraCameraProfiles.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using System.Xml.Serialization;
25 |
26 | namespace PentaxPefFile
27 | {
28 | public class ExtraCameraProfiles
29 | {
30 | #region Seralization
31 | ///
32 | /// Saves to an xml file
33 | ///
34 | /// File path of the new xml file
35 | public void Save(string FileName)
36 | {
37 | using (var writer = new System.IO.StreamWriter(FileName))
38 | {
39 | var serializer = new XmlSerializer(this.GetType());
40 | serializer.Serialize(writer, this);
41 | writer.Flush();
42 | }
43 | }
44 |
45 | ///
46 | /// Load an object from an xml file
47 | ///
48 | /// Xml file name
49 | /// The object created from the xml file
50 | public static ExtraCameraProfiles Load(string FileName)
51 | {
52 | using (var stream = System.IO.File.OpenRead(FileName))
53 | {
54 | var serializer = new XmlSerializer(typeof(ExtraCameraProfiles));
55 | return serializer.Deserialize(stream) as ExtraCameraProfiles;
56 | }
57 | }
58 | #endregion
59 |
60 | List extraCameraProfiles;
61 |
62 | public List Profiles
63 | {
64 | get { return extraCameraProfiles; }
65 | set { extraCameraProfiles = value; }
66 | }
67 |
68 | public ExtraCameraProfile GetProfile(string aMake, string aUniqueModel)
69 | {
70 | if (extraCameraProfiles == null)
71 | return null;
72 |
73 | for (int i = 0; i < extraCameraProfiles.Count; i++)
74 | {
75 | if (extraCameraProfiles[i].Make == aMake)
76 | {
77 | if (extraCameraProfiles[i].UniqueModel == aUniqueModel)
78 | {
79 | return extraCameraProfiles[i];
80 | }
81 | }
82 | }
83 | return null;
84 | }
85 | }
86 |
87 | public class ExtraCameraProfile
88 | {
89 | string make;
90 | string uniqueModel;
91 |
92 | double[] colorMatrix1;
93 | double[] colorMatrix2;
94 | IFDDNGCalibrationIlluminant.Illuminant illuminant1;
95 | IFDDNGCalibrationIlluminant.Illuminant illuminant2;
96 |
97 | NoiseModel noiseModel;
98 | CropInfo cropInfo;
99 |
100 | public string Make
101 | {
102 | get { return make; }
103 | set { make = value; }
104 | }
105 | public string UniqueModel
106 | {
107 | get { return uniqueModel; }
108 | set { uniqueModel = value; }
109 | }
110 | public double[] ColorMatrix1
111 | {
112 | get { return colorMatrix1; }
113 | set { colorMatrix1 = value; }
114 | }
115 | public double[] ColorMatrix2
116 | {
117 | get { return colorMatrix2; }
118 | set { colorMatrix2 = value; }
119 | }
120 | public IFDDNGCalibrationIlluminant.Illuminant Illuminant1
121 | {
122 | get { return illuminant1; }
123 | set { illuminant1 = value; }
124 | }
125 | public IFDDNGCalibrationIlluminant.Illuminant Illuminant2
126 | {
127 | get { return illuminant2; }
128 | set { illuminant2 = value; }
129 | }
130 | public NoiseModel NoiseModel
131 | {
132 | get { return noiseModel; }
133 | set { noiseModel = value; }
134 | }
135 | public CropInfo CropInfo
136 | {
137 | get { return cropInfo; }
138 | set { cropInfo = value; }
139 | }
140 | }
141 |
142 | public class NoiseModel
143 | {
144 | int[] iso;
145 | double[] alpha;
146 | double[] beta;
147 |
148 | public int[] Iso
149 | {
150 | get { return iso; }
151 | set { iso = value; }
152 | }
153 | public double[] Alpha
154 | {
155 | get { return alpha; }
156 | set { alpha = value; }
157 | }
158 | public double[] Beta
159 | {
160 | get { return beta; }
161 | set { beta = value; }
162 | }
163 |
164 | public (double, double) GetValue(int aIso)
165 | {
166 | if (iso.Length == 0)
167 | {
168 | return (0, 0);
169 | }
170 |
171 | int index = -1;
172 | for (int i = iso.Length - 1; i >= 0; i--)
173 | {
174 | if (iso[i] <= aIso)
175 | {
176 | index = i;
177 | break;
178 | }
179 | }
180 |
181 | //found at last index
182 | if (index == iso.Length - 1)
183 | {
184 | return (alpha[iso.Length - 1], beta[iso.Length - 1]);
185 | }
186 | //or asked ISO is smaller than our model
187 | if (index < 0)
188 | {
189 | return (alpha[0], beta[0]);
190 | }
191 |
192 | //linear interpolate between two values
193 | double weight = ((double)aIso - (double)iso[index + 1]) / ((double)iso[index] - (double)iso[index + 1]);
194 | double a = weight * alpha[index] + (1.0 - weight) * alpha[index + 1];
195 | double b = weight * beta[index] + (1.0 - weight) * beta[index + 1];
196 |
197 | return (a, b);
198 | }
199 | }
200 |
201 | public class CropInfo
202 | {
203 | int top;
204 | int left;
205 | int width;
206 | int height;
207 |
208 | public int Top
209 | {
210 | get { return top; }
211 | set { top = value; }
212 | }
213 | public int Left
214 | {
215 | get { return left; }
216 | set { left = value; }
217 | }
218 | public int Width
219 | {
220 | get { return width; }
221 | set { width = value; }
222 | }
223 | public int Height
224 | {
225 | get { return height; }
226 | set { height = value; }
227 | }
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/PefFile/FileReader.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Text;
22 | using System.IO;
23 | using System.Runtime.InteropServices;
24 |
25 | namespace PentaxPefFile
26 | {
27 | public class FileReader
28 | {
29 | protected Stream mFile;
30 | protected BinaryReader mFileReader;
31 | protected string mFileName;
32 | protected bool mEndianSwap;
33 |
34 | public FileReader(string aFileName)
35 | {
36 | mFileName = aFileName;
37 | mFile = new FileStream(aFileName, FileMode.Open, FileAccess.Read);
38 | mFileReader = new BinaryReader(mFile);
39 | mEndianSwap = false;
40 | }
41 |
42 | public FileReader(Stream aFileStream)
43 | {
44 | mFile = aFileStream;
45 | mFileReader = new BinaryReader(mFile);
46 | mEndianSwap = false;
47 | }
48 |
49 | protected ushort Endian_swap(ushort x)
50 | {
51 | return (ushort)((x >> 8) | (x << 8));
52 | }
53 |
54 | protected uint Endian_swap(uint x)
55 | {
56 | return (uint)((x >> 24) |
57 | ((x << 8) & 0x00FF0000) |
58 | ((x >> 8) & 0x0000FF00) |
59 | (x << 24));
60 | }
61 |
62 | protected ulong Endian_swap(ulong x)
63 | {
64 | return (ulong)((x >> 56) |
65 | ((x << 40) & 0x00FF000000000000) |
66 | ((x << 24) & 0x0000FF0000000000) |
67 | ((x << 8) & 0x000000FF00000000) |
68 | ((x >> 8) & 0x00000000FF000000) |
69 | ((x >> 24) & 0x0000000000FF0000) |
70 | ((x >> 40) & 0x000000000000FF00) |
71 | (x << 56));
72 | }
73 |
74 | protected unsafe short Endian_swap(short x)
75 | {
76 | ushort i = *(ushort*)&x;
77 | return (short)((i >> 8) | (i << 8));
78 | }
79 |
80 | protected unsafe int Endian_swap(int x)
81 | {
82 | uint i = *(uint*)&x;
83 | return (int)((i >> 24) |
84 | ((i << 8) & 0x00FF0000) |
85 | ((i >> 8) & 0x0000FF00) |
86 | (i << 24));
87 | }
88 |
89 | protected unsafe long Endian_swap(long x)
90 | {
91 | ulong i = *(ulong*)&x;
92 | return (long)((i >> 56) |
93 | ((i << 40) & 0x00FF000000000000) |
94 | ((i << 24) & 0x0000FF0000000000) |
95 | ((i << 8) & 0x000000FF00000000) |
96 | ((i >> 8) & 0x00000000FF000000) |
97 | ((i >> 24) & 0x0000000000FF0000) |
98 | ((i >> 40) & 0x000000000000FF00) |
99 | (i << 56));
100 | }
101 |
102 | protected unsafe double Endian_swap(double x)
103 | {
104 | ulong i = *(ulong*)&x;
105 | i = (i >> 56) |
106 | ((i << 40) & 0x00FF000000000000) |
107 | ((i << 24) & 0x0000FF0000000000) |
108 | ((i << 8) & 0x000000FF00000000) |
109 | ((i >> 8) & 0x00000000FF000000) |
110 | ((i >> 24) & 0x0000000000FF0000) |
111 | ((i >> 40) & 0x000000000000FF00) |
112 | (i << 56);
113 | return *(double*)&i;
114 | }
115 |
116 | protected unsafe float Endian_swap(float x)
117 | {
118 | uint i = *(uint*)&x;
119 | i = (i >> 24) |
120 | ((i << 8) & 0x00FF0000) |
121 | ((i >> 8) & 0x0000FF00) |
122 | (i << 24);
123 | return *(float*)&i;
124 | }
125 |
126 | public long ReadI8()
127 | {
128 | long temp = mFileReader.ReadInt64();
129 | if (mEndianSwap) temp = Endian_swap(temp);
130 | return temp;
131 | }
132 |
133 | public long ReadI8BE()
134 | {
135 | long temp = mFileReader.ReadInt64();
136 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
137 | return temp;
138 | }
139 |
140 | public int ReadI4()
141 | {
142 | int temp = mFileReader.ReadInt32();
143 | if (mEndianSwap) temp = Endian_swap(temp);
144 | return temp;
145 | }
146 |
147 | public int ReadI4BE()
148 | {
149 | int temp = mFileReader.ReadInt32();
150 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
151 | return temp;
152 | }
153 |
154 | public short ReadI2()
155 | {
156 | short temp = mFileReader.ReadInt16();
157 | if (mEndianSwap) temp = Endian_swap(temp);
158 | return temp;
159 | }
160 |
161 | public short ReadI2BE()
162 | {
163 | short temp = mFileReader.ReadInt16();
164 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
165 | return temp;
166 | }
167 |
168 | public sbyte ReadI1()
169 | {
170 | sbyte temp = mFileReader.ReadSByte();
171 | return temp;
172 | }
173 |
174 | public ulong ReadUI8()
175 | {
176 | ulong temp = mFileReader.ReadUInt64();
177 | if (mEndianSwap) temp = Endian_swap(temp);
178 | return temp;
179 | }
180 |
181 | public ulong ReadUI8BE()
182 | {
183 | ulong temp = mFileReader.ReadUInt64();
184 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
185 | return temp;
186 | }
187 |
188 | public uint ReadUI4()
189 | {
190 | uint temp = mFileReader.ReadUInt32();
191 | if (mEndianSwap) temp = Endian_swap(temp);
192 | return temp;
193 | }
194 |
195 | public uint ReadUI4BE()
196 | {
197 | uint temp = mFileReader.ReadUInt32();
198 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
199 | return temp;
200 | }
201 |
202 | public ushort ReadUI2()
203 | {
204 | ushort temp = mFileReader.ReadUInt16();
205 | if (mEndianSwap) temp = Endian_swap(temp);
206 | return temp;
207 | }
208 |
209 | public ushort ReadUI2BE()
210 | {
211 | ushort temp = mFileReader.ReadUInt16();
212 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
213 | return temp;
214 | }
215 |
216 | public byte ReadUI1()
217 | {
218 | byte temp = mFileReader.ReadByte();
219 | return temp;
220 | }
221 |
222 | public float ReadF4()
223 | {
224 | float temp = mFileReader.ReadSingle();
225 | if (mEndianSwap) temp = Endian_swap(temp);
226 | return temp;
227 | }
228 |
229 | public float ReadF4BE()
230 | {
231 | float temp = mFileReader.ReadSingle();
232 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
233 | return temp;
234 | }
235 |
236 | public double ReadF8()
237 | {
238 | double temp = mFileReader.ReadDouble();
239 | if (mEndianSwap) temp = Endian_swap(temp);
240 | return temp;
241 | }
242 |
243 | public double ReadF8BE()
244 | {
245 | double temp = mFileReader.ReadDouble();
246 | if (BitConverter.IsLittleEndian) temp = Endian_swap(temp);
247 | return temp;
248 | }
249 |
250 | public string ReadStr(int aCountBytes)
251 | {
252 | byte[] arr = mFileReader.ReadBytes(aCountBytes);
253 | System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
254 | return enc.GetString(arr);
255 | }
256 |
257 | public void Close()
258 | {
259 | mFileReader.Close();
260 | mFile.Close();
261 | }
262 |
263 | public void Seek(uint aPosition, SeekOrigin aOrigin)
264 | {
265 | mFile.Seek(aPosition, aOrigin);
266 | }
267 |
268 | public uint Position()
269 | {
270 | return (uint)mFile.Position;
271 | }
272 |
273 | public bool EndianSwap
274 | {
275 | get { return mEndianSwap; }
276 | }
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/PefFile/ImageFileDirectory.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 | using System.IO;
25 |
26 | namespace PentaxPefFile
27 | {
28 | public class ImageFileDirectory
29 | {
30 | private FileReader mPefFile;
31 | private ushort mEntryCount;
32 | public List mEntries;
33 |
34 | public ImageFileDirectory(FileReader aPefFile)
35 | {
36 | mPefFile = aPefFile;
37 | mEntries = new List();
38 | mEntryCount = mPefFile.ReadUI2();
39 | for (ushort i = 0; i < mEntryCount; i++)
40 | {
41 | ImageFileDirectoryEntry entry = ImageFileDirectoryEntry.CreateImageFileDirectoryEntry(mPefFile);
42 | mEntries.Add(entry);
43 | }
44 | }
45 |
46 | public T GetEntry() where T : ImageFileDirectoryEntry
47 | {
48 | Type t = typeof(T);
49 | foreach (var item in mEntries)
50 | {
51 | if (item is T)
52 | return (T)item;
53 | }
54 | return null;
55 | }
56 |
57 | internal void SavePass1(Stream stream)
58 | {
59 | stream.Write(BitConverter.GetBytes((ushort)mEntries.Count), 0, 2);
60 | for (int i = 0; i < mEntries.Count; i++)
61 | {
62 | mEntries[i].SavePass1(stream);
63 | }
64 | }
65 |
66 | internal void SavePass2(Stream stream)
67 | {
68 | //end of IFDs marker
69 | //stream.Write(new byte[] { 0, 0, 0, 0 }, 0, 4);
70 | for (int i = 0; i < mEntries.Count; i++)
71 | {
72 | mEntries[i].SavePass2(stream);
73 | }
74 | }
75 |
76 | public ImageFileDirectory(uint width, uint height)
77 | {
78 | mEntries = new List();
79 |
80 | mEntries.Add(new IFDImageWidth(width));
81 | mEntries.Add(new IFDImageLength(height));
82 | mEntries.Add(new IFDBitsPerSample(new ushort[] { 16, 16, 16}));
83 | mEntries.Add(new IFDCompression(IFDCompression.Compression.NoCompression));
84 | mEntries.Add(new IFDPhotometricInterpretation(IFDPhotometricInterpretation.PhotometricInterpretation.RGB));
85 | mEntries.Add(new IFDStripOffsets(new uint[] { 0 }));
86 | mEntries.Add(new IFDSamplesPerPixel(3));
87 | mEntries.Add(new IFDRowsPerStrip(height));
88 | mEntries.Add(new IFDStripByteCounts(new uint[] { width * height * 3 * 2 }));
89 | mEntries.Add(new IFDXResolution(new Rational(720, 10)));
90 | mEntries.Add(new IFDYResolution(new Rational(720, 10)));
91 | mEntries.Add(new IFDResolutionUnit(IFDResolutionUnit.ResolutionUnit.None));
92 | mEntries.Add(new IFDMake("MK TIFF"));
93 | mEntryCount = (ushort)mEntries.Count;
94 | }
95 |
96 | public void SaveAsTiff(string aFilename, ushort[] data)
97 | {
98 | FileStream fs = new FileStream(aFilename, FileMode.Create, FileAccess.Write);
99 | fs.Write(new byte[] { 0x49, 0x49, 0x2A, 00, 8, 0, 0, 0 }, 0, 8); //Tiff header with offset to first IFD=8
100 | fs.Write(BitConverter.GetBytes(mEntryCount), 0, 2);
101 | foreach (var item in mEntries)
102 | {
103 | fs.Flush();
104 | item.SavePass1(fs);
105 | }
106 | fs.Write(new byte[] { 0, 0, 0, 0 }, 0, 4);
107 | foreach (var item in mEntries)
108 | {
109 | item.SavePass2(fs);
110 | }
111 | fs.Seek(0, SeekOrigin.End);
112 | uint finalImageOffset = (uint)fs.Position;
113 | GetEntry().SaveFinalOffsets(fs, new uint[] { finalImageOffset });
114 | fs.Seek(finalImageOffset, SeekOrigin.Begin);
115 | BinaryWriter br = new BinaryWriter(fs);
116 | for (int i = 0; i < data.Length; i++)
117 | {
118 | br.Write(data[i]);
119 | }
120 | br.Close();
121 | br.Dispose();
122 | fs.Close();
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/PefFile/PefFile.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}
8 | Library
9 | Properties
10 | PentaxPefFile
11 | PefFile
12 | v4.7.2
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | true
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | true
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/PefFile/PentaxMakerNotes.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.IO;
22 | using System.Linq;
23 | using System.Text;
24 | using System.Threading.Tasks;
25 |
26 | namespace PentaxPefFile
27 | {
28 | public class PentaxMakerNotes : FileReader
29 | {
30 | List mEntries;
31 | ushort mEntryCount;
32 | public bool K3Specific = false;
33 | //the "AOC" makenotes uses absolute offsets to file beginning, not in makernote.
34 | //hence subtract that offset...
35 | int mAdditionalOffset;
36 |
37 | public void SeekWithOffset(uint aPosition, SeekOrigin aOrigin)
38 | {
39 | base.Seek((uint)((int)aPosition - mAdditionalOffset), aOrigin);
40 | }
41 |
42 | public PentaxMakerNotes(byte[] aData, uint offset)
43 | : base(new MemoryStream(aData))
44 | {
45 | //FileStream fs = new FileStream("dumpMakerNote.bin", FileMode.Create, FileAccess.Write);
46 | //fs.Write(aData, 0, aData.Length);
47 | //fs.Close();
48 |
49 |
50 | mAdditionalOffset = 0;
51 | mEntries = new List();
52 |
53 | string testVersion = ReadStr(4);
54 | if (testVersion == "AOC\0")
55 | {
56 | byte a = mFileReader.ReadByte();
57 | byte b = mFileReader.ReadByte();
58 |
59 | bool fileIsLittleEndian;
60 | if (a == b && b == 'I')
61 | fileIsLittleEndian = true;
62 | else
63 | if (a == b && b == 'M')
64 | fileIsLittleEndian = false;
65 | else
66 | throw new FileLoadException("Could not determine file endianess for maker notes");
67 |
68 | mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;
69 | mAdditionalOffset = (int)offset;
70 | }
71 | else
72 | {
73 | Seek(0, SeekOrigin.Begin);
74 | testVersion = ReadStr(8);
75 | if (testVersion == "PENTAX \0")
76 | {
77 | byte a = mFileReader.ReadByte();
78 | byte b = mFileReader.ReadByte();
79 |
80 | bool fileIsLittleEndian;
81 | if (a == b && b == 'I')
82 | fileIsLittleEndian = true;
83 | else
84 | if (a == b && b == 'M')
85 | fileIsLittleEndian = false;
86 | else
87 | throw new FileLoadException("Could not determine file endianess for maker notes");
88 |
89 | mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;
90 | }
91 | else
92 | {
93 | Seek(0, SeekOrigin.Begin);
94 | testVersion = ReadStr(10);
95 | const int SizeAdobeHeader = 20;
96 | if (testVersion == "Adobe\0MakN")
97 | {
98 | uint byteCount = mFileReader.ReadUInt32();
99 | if (BitConverter.IsLittleEndian)
100 | {
101 | byteCount = ((byteCount >> 24) |
102 | ((byteCount << 8) & 0x00FF0000) |
103 | ((byteCount >> 8) & 0x0000FF00) |
104 | (byteCount << 24));
105 | }
106 |
107 | byte a = mFileReader.ReadByte();
108 | byte b = mFileReader.ReadByte();
109 |
110 | bool fileIsLittleEndian;
111 | if (a == b && b == 'I')
112 | fileIsLittleEndian = true;
113 | else
114 | if (a == b && b == 'M')
115 | fileIsLittleEndian = false;
116 | else
117 | throw new FileLoadException("Could not determine file endianess for maker notes");
118 |
119 | mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;
120 |
121 | uint temp = mFileReader.ReadUInt32();
122 | if (mEndianSwap)
123 | {
124 | temp = ((temp >> 24) |
125 | ((temp << 8) & 0x00FF0000) |
126 | ((temp >> 8) & 0x0000FF00) |
127 | (temp << 24));
128 | }
129 | mAdditionalOffset = (int)temp;
130 |
131 |
132 |
133 |
134 |
135 | testVersion = ReadStr(4);
136 | if (testVersion == "AOC\0")
137 | {
138 | a = mFileReader.ReadByte();
139 | b = mFileReader.ReadByte();
140 |
141 |
142 | if (a == b && b == 'I')
143 | fileIsLittleEndian = true;
144 | else
145 | if (a == b && b == 'M')
146 | fileIsLittleEndian = false;
147 | else
148 | throw new FileLoadException("Could not determine file endianess for maker notes");
149 |
150 | mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;
151 | mAdditionalOffset -= SizeAdobeHeader;
152 | }
153 | else
154 | {
155 | Seek(Position() - 4, SeekOrigin.Begin);
156 | testVersion = ReadStr(8);
157 | if (testVersion == "PENTAX \0")
158 | {
159 | a = mFileReader.ReadByte();
160 | b = mFileReader.ReadByte();
161 |
162 |
163 | if (a == b && b == 'I')
164 | fileIsLittleEndian = true;
165 | else
166 | if (a == b && b == 'M')
167 | fileIsLittleEndian = false;
168 | else
169 | throw new FileLoadException("Could not determine file endianess for maker notes");
170 |
171 | mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;
172 | mAdditionalOffset = -SizeAdobeHeader;
173 | }
174 | }
175 | /* Following Exiftool:
176 | 1. Six bytes containing the zero-terminated string "Adobe". (The DNG specification calls for the DNGPrivateData tag to start with an ASCII string identifying the creator/format).
177 | 2. 4 bytes: an ASCII string ("MakN" for a Makernote), indicating what sort of data is being stored here. Note that this is not zero-terminated.
178 | 3. A four-byte count (number of data bytes following); this is the length of the original MakerNote data. (This is always in "most significant byte first" format).
179 | 4. 2 bytes: the byte-order indicator from the original file (the usual 'MM'/4D4D or 'II'/4949).
180 | 5. 4 bytes: the original file offset for the MakerNote tag data (stored according to the byte order given above).
181 | 6. The contents of the MakerNote tag. This is a simple byte-for-byte copy, with no modification.
182 | */
183 | }
184 | else
185 | {
186 | return; //Not a Pentax make note, can't handle it...
187 | }
188 | }
189 | }
190 |
191 | mEntryCount = ReadUI2();
192 | for (ushort i = 0; i < mEntryCount; i++)
193 | {
194 | PentaxMakerNotesEntry entry = PentaxMakerNotesEntry.CreatePentaxMakerNotesEntry(this);
195 | mEntries.Add(entry);
196 | }
197 |
198 | //MNPreviewImageSize imagesize = GetEntry();
199 | //MNPreviewImageLength imagelength = GetEntry();
200 | //MNPreviewImageStart imagestart = GetEntry();
201 | //MNPreviewImageBorders imageborder = GetEntry();
202 |
203 | //uint curPos = Position();
204 | //Seek(imagestart.Value, SeekOrigin.Begin);
205 | //byte[] data = mFileReader.ReadBytes((int)imagelength.Value);
206 | //Seek(curPos, SeekOrigin.Begin);
207 |
208 | }
209 |
210 | public T GetEntry() where T : PentaxMakerNotesEntry
211 | {
212 | Type t = typeof(T);
213 | foreach (var item in mEntries)
214 | {
215 | if (item is T)
216 | return (T)item;
217 | }
218 | return null;
219 | }
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/PefFile/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // Allgemeine Informationen über eine Assembly werden über die folgenden
6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
7 | // die einer Assembly zugeordnet sind.
8 | [assembly: AssemblyTitle("PefFile")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("PefFile")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
18 | // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
19 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
20 | [assembly: ComVisible(false)]
21 |
22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
23 | [assembly: Guid("ceb1ffe5-2ba8-48aa-ac87-7c5fb5cc01b4")]
24 |
25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
26 | //
27 | // Hauptversion
28 | // Nebenversion
29 | // Buildnummer
30 | // Revision
31 | //
32 | // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
33 | // indem Sie "*" wie unten gezeigt eingeben:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/PefFile/RawFile.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.IO;
22 | using System.Linq;
23 | using System.Text;
24 | using System.Threading.Tasks;
25 |
26 | namespace PentaxPefFile
27 | {
28 | public abstract class RawFile : FileReader
29 | {
30 | public enum BayerColor : int
31 | {
32 | Red = 0,
33 | Green = 1,
34 | Blue = 2,
35 | Cyan = 3,
36 | Magenta = 4,
37 | Yellow = 5,
38 | White = 6
39 | }
40 |
41 | public RawFile(string aFileName)
42 | : base(aFileName)
43 | {
44 | //set some default values:
45 |
46 | //color channels are assumed in order RGB if no tag present
47 | mColorTwist = new float[3,4];
48 | mColorTwist[0, 0] = 1.0f;
49 | mColorTwist[1, 1] = 1.0f;
50 | mColorTwist[2, 2] = 1.0f;
51 | mColorTwistIsIdentity = true;
52 |
53 | //it seems as if only Pentax is capable of giving us that info
54 | mRollAnglePresent = false;
55 | mRecordingDate = new DateTime();
56 |
57 | //read all IFDs/Tags:
58 | byte a = mFileReader.ReadByte();
59 | byte b = mFileReader.ReadByte();
60 |
61 | bool fileIsLittleEndian;
62 | if (a == b && b == 'I')
63 | fileIsLittleEndian = true;
64 | else
65 | if (a == b && b == 'M')
66 | fileIsLittleEndian = false;
67 | else
68 | throw new FileLoadException("Could not determine file endianess. Is this a proper TIFF/PEF/DNG file?", aFileName);
69 |
70 | mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;
71 |
72 | ushort magicNumber = ReadUI2();
73 |
74 | if (magicNumber != 42)
75 | throw new FileLoadException("This is not a valid TIFF/PEF/DNG file: Magic number is not 42.", aFileName);
76 |
77 | uint offsetToFirstIFD = ReadUI4();
78 |
79 | mFile.Seek(offsetToFirstIFD, SeekOrigin.Begin);
80 | mIfds = new List();
81 | while (true)
82 | {
83 | ImageFileDirectory ifd = new ImageFileDirectory(this);
84 | mIfds.Add(ifd);
85 | uint offsetToNext = ReadUI4();
86 | if (offsetToNext == 0)
87 | break;
88 | Seek(offsetToNext, System.IO.SeekOrigin.Begin);
89 | }
90 |
91 | //until here PEF and DNG are the same. They diverge on how to read the tags
92 | }
93 |
94 | protected List mIfds;
95 | protected DNGColorSpec mColorSpec;
96 | protected DNGOrientation mOrientation;
97 | protected ushort[,] mRawImage;
98 | protected int mWidth;
99 | protected int mHeight;
100 | protected int mCropLeft;
101 | protected int mCropTop;
102 | protected int mCroppedWidth;
103 | protected int mCroppedHeight;
104 | protected int mBitDepth;
105 | protected int mISO;
106 | protected BayerColor[] mBayerPattern;
107 | protected float[,] mColorTwist;
108 | protected bool mColorTwistIsIdentity;
109 | protected float[] mWhiteLevel;
110 | protected float[] mBlackLevel;
111 | protected float[] mWhiteBalance;
112 | protected float mRollAngle;
113 | protected bool mRollAnglePresent;
114 | protected float mNoiseModelAlpha;
115 | protected float mNoiseModelBeta;
116 | protected Rational mExposureTime;
117 | protected DateTime mRecordingDate;
118 | protected string mMake;
119 | protected string mUniqueModelName;
120 |
121 |
122 |
123 |
124 | public ushort[,] RawImage
125 | {
126 | get { return mRawImage; }
127 | }
128 | public int RawWidth
129 | {
130 | get { return mWidth; }
131 | }
132 | public int RawHeight
133 | {
134 | get { return mHeight; }
135 | }
136 | public int CropLeft
137 | {
138 | get { return mCropLeft; }
139 | }
140 | public int CropTop
141 | {
142 | get { return mCropTop; }
143 | }
144 | public int CroppedWidth
145 | {
146 | get { return mCroppedWidth; }
147 | }
148 | public int CroppedHeight
149 | {
150 | get { return mCroppedHeight; }
151 | }
152 | public DNGOrientation Orientation
153 | {
154 | get { return mOrientation; }
155 | }
156 | public float[,] ColorTwist
157 | {
158 | get { return mColorTwist; }
159 | }
160 | public bool ColorTwistIsIdentity
161 | {
162 | get { return mColorTwistIsIdentity; }
163 | }
164 | public BayerColor[] BayerPattern
165 | {
166 | get { return mBayerPattern; }
167 | }
168 | public float RollAngle
169 | {
170 | get { return mRollAngle; }
171 | }
172 | public bool RollAnglePresent
173 | {
174 | get { return mRollAnglePresent; }
175 | }
176 | public Rational ExposureTime
177 | {
178 | get { return mExposureTime; }
179 | }
180 | public DateTime RecordingDate
181 | {
182 | get { return mRecordingDate; }
183 | }
184 |
185 | ///
186 | /// In R G B order
187 | ///
188 | public float[] WhiteLevel
189 | {
190 | get { return mWhiteLevel; }
191 | }
192 | ///
193 | /// In R G B order
194 | ///
195 | public float[] BlackLevel
196 | {
197 | get { return mBlackLevel; }
198 | }
199 | ///
200 | /// In R G B order
201 | ///
202 | public float[] WhiteBalance
203 | {
204 | get { return mWhiteBalance; }
205 | }
206 | public int ISO
207 | {
208 | get { return mISO; }
209 | }
210 |
211 | public float NoiseModelAlpha
212 | {
213 | get { return mNoiseModelAlpha; }
214 | }
215 |
216 | public float NoiseModelBeta
217 | {
218 | get { return mNoiseModelBeta; }
219 | }
220 |
221 | public string Make
222 | {
223 | get { return mMake; }
224 | }
225 |
226 | public string UniqueModelName
227 | {
228 | get { return mUniqueModelName; }
229 | }
230 |
231 | public DNGColorSpec ColorSpec
232 | {
233 | get { return mColorSpec; }
234 | }
235 |
236 | public bool LoadExtraCameraProfile(string xmlFileName)
237 | {
238 | PentaxPefFile.ExtraCameraProfiles extraCameraProfiles = PentaxPefFile.ExtraCameraProfiles.Load(xmlFileName);
239 | PentaxPefFile.ExtraCameraProfile p = extraCameraProfiles.GetProfile(mMake, mUniqueModelName);
240 |
241 | bool setAnything = false;
242 | if (p == null)
243 | {
244 | return false;
245 | }
246 |
247 | if (p.CropInfo != null)
248 | {
249 | int cropLeft = p.CropInfo.Left;
250 | int cropTop = p.CropInfo.Top;
251 |
252 | int croppedWidth = p.CropInfo.Width;
253 | int croppedHeight = p.CropInfo.Height;
254 |
255 | //we always crop at least two pixels because of our algos...
256 | mCropLeft = Math.Max(2, cropLeft);
257 | mCropTop = Math.Max(2, cropTop);
258 |
259 | mCroppedWidth = croppedWidth - Math.Max(0, (cropLeft + croppedWidth) - (mWidth - 2));
260 | mCroppedHeight = croppedHeight - Math.Max(0, (cropTop + croppedHeight) - (mHeight - 2));
261 | setAnything = true;
262 | }
263 |
264 | if (p.ColorMatrix1 != null)
265 | {
266 | mColorSpec = new DNGColorSpec(p.ColorMatrix1, p.ColorMatrix2, p.Illuminant1, p.Illuminant2, mWhiteBalance);
267 | setAnything = true;
268 | }
269 |
270 | if (p.NoiseModel != null)
271 | {
272 | double a, b;
273 | (a, b) = p.NoiseModel.GetValue(mISO);
274 | mNoiseModelAlpha = (float)a;
275 | mNoiseModelBeta = (float)b;
276 | setAnything = true;
277 | }
278 | return setAnything;
279 | }
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/PefFile/SaveTiffTag.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.IO;
23 | using System.Text;
24 | using System.Threading.Tasks;
25 |
26 | namespace PentaxPefFile
27 | {
28 | public abstract class SaveTiffTag
29 | {
30 | protected uint mOffsetInStream;
31 |
32 | public virtual void SavePass1(Stream stream)
33 | {
34 | //do nothing
35 | }
36 | public virtual void SavePass2(Stream stream)
37 | {
38 | //do nothing
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/PefFile/TIFFValueTypes.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020, Michael Kunz. All rights reserved.
2 | // https://github.com/kunzmi/ImageStackAlignator
3 | //
4 | // This file is part of ImageStackAlignator.
5 | //
6 | // ImageStackAlignator is free software: you can redistribute it and/or modify
7 | // it under the terms of the GNU Lesser General Public License as
8 | // published by the Free Software Foundation, version 3.
9 | //
10 | // ImageStackAlignator is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | // MA 02110-1301 USA, http://www.gnu.org/licenses/.
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Linq;
22 | using System.Text;
23 | using System.Threading.Tasks;
24 |
25 | namespace PentaxPefFile
26 | {
27 | public enum TIFFValueTypes : ushort
28 | {
29 | Byte = 1,
30 | Ascii = 2,
31 | UnsignedShort = 3,
32 | UnsignedLong = 4,
33 | Rational = 5,
34 | SignedByte = 6,
35 | Undefined = 7,
36 | SignedShort = 8,
37 | SignedLong = 9,
38 | SignedRational = 10,
39 | Float = 11,
40 | Double = 12
41 | }
42 |
43 | public struct Rational
44 | {
45 | public uint numerator;
46 | public uint denominator;
47 |
48 | public Rational(uint[] aValues)
49 | {
50 | if (aValues.Length < 2)
51 | throw new ArgumentException("aValues must contain at least two values.");
52 |
53 | numerator = aValues[0];
54 | denominator = aValues[1];
55 | }
56 |
57 | public Rational(uint aNominator, uint aDenominator)
58 | {
59 | numerator = aNominator;
60 | denominator = aDenominator;
61 | }
62 |
63 | public override string ToString()
64 | {
65 | return numerator.ToString() + " / " + denominator.ToString();
66 | }
67 |
68 | public double Value
69 | {
70 | get { return (double)numerator / (double)denominator; }
71 | }
72 | }
73 |
74 | public struct SRational
75 | {
76 | public int numerator;
77 | public int denominator;
78 |
79 | public SRational(int[] aValues)
80 | {
81 | if (aValues.Length < 2)
82 | throw new ArgumentException("aValues must contain at least two values.");
83 |
84 | numerator = aValues[0];
85 | denominator = aValues[1];
86 | }
87 |
88 | public SRational(int aNominator, int aDenominator)
89 | {
90 | numerator = aNominator;
91 | denominator = aDenominator;
92 | }
93 |
94 | public override string ToString()
95 | {
96 | return numerator.ToString() + " / " + denominator.ToString();
97 | }
98 |
99 | public double Value
100 | {
101 | get { return (double)numerator / (double)denominator; }
102 | }
103 | }
104 |
105 | public struct TIFFValueType
106 | {
107 | TIFFValueTypes mType;
108 | public TIFFValueType(TIFFValueTypes aType)
109 | {
110 | mType = aType;
111 | }
112 |
113 | public int SizeInBytes
114 | {
115 | get
116 | {
117 | switch (mType)
118 | {
119 | case TIFFValueTypes.Byte:
120 | return 1;
121 | case TIFFValueTypes.Ascii:
122 | return 1;
123 | case TIFFValueTypes.UnsignedShort:
124 | return 2;
125 | case TIFFValueTypes.UnsignedLong:
126 | return 4;
127 | case TIFFValueTypes.Rational:
128 | return 8;
129 | case TIFFValueTypes.SignedByte:
130 | return 1;
131 | case TIFFValueTypes.Undefined:
132 | return 1;
133 | case TIFFValueTypes.SignedShort:
134 | return 2;
135 | case TIFFValueTypes.SignedLong:
136 | return 4;
137 | case TIFFValueTypes.SignedRational:
138 | return 8;
139 | case TIFFValueTypes.Float:
140 | return 4;
141 | case TIFFValueTypes.Double:
142 | return 8;
143 | default:
144 | throw new ArgumentException(mType.ToString() + " is not a valid type."); //Never happens...
145 | }
146 | }
147 | }
148 |
149 | public ushort GetValue()
150 | {
151 | return (ushort)mType;
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/TestingGoogleSuperRes.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29230.47
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kernels", "Kernels\Kernels.vcxproj", "{80B85EE4-5AE5-4FD5-80ED-274F7E913606}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PefFile", "PefFile\PefFile.csproj", "{CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PEFStudioDX", "PEFStudioDX\PEFStudioDX.csproj", "{DB59DD92-0B30-4A14-B494-29E0FF37E48C}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug|x64 = Debug|x64
16 | Release|Any CPU = Release|Any CPU
17 | Release|x64 = Release|x64
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {80B85EE4-5AE5-4FD5-80ED-274F7E913606}.Debug|Any CPU.ActiveCfg = Debug|x64
21 | {80B85EE4-5AE5-4FD5-80ED-274F7E913606}.Debug|x64.ActiveCfg = Debug|x64
22 | {80B85EE4-5AE5-4FD5-80ED-274F7E913606}.Debug|x64.Build.0 = Debug|x64
23 | {80B85EE4-5AE5-4FD5-80ED-274F7E913606}.Release|Any CPU.ActiveCfg = Release|x64
24 | {80B85EE4-5AE5-4FD5-80ED-274F7E913606}.Release|x64.ActiveCfg = Release|x64
25 | {80B85EE4-5AE5-4FD5-80ED-274F7E913606}.Release|x64.Build.0 = Release|x64
26 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Debug|x64.ActiveCfg = Debug|Any CPU
29 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Debug|x64.Build.0 = Debug|Any CPU
30 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Release|x64.ActiveCfg = Release|Any CPU
33 | {CEB1FFE5-2BA8-48AA-AC87-7C5FB5CC01B4}.Release|x64.Build.0 = Release|Any CPU
34 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Debug|x64.ActiveCfg = Debug|Any CPU
37 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Debug|x64.Build.0 = Debug|Any CPU
38 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Release|x64.ActiveCfg = Release|Any CPU
41 | {DB59DD92-0B30-4A14-B494-29E0FF37E48C}.Release|x64.Build.0 = Release|Any CPU
42 | EndGlobalSection
43 | GlobalSection(SolutionProperties) = preSolution
44 | HideSolutionNode = FALSE
45 | EndGlobalSection
46 | GlobalSection(ExtensibilityGlobals) = postSolution
47 | SolutionGuid = {170BAA05-5076-43F3-9F33-8D415A843B34}
48 | EndGlobalSection
49 | EndGlobal
50 |
--------------------------------------------------------------------------------
/pictures/AdobeCrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/AdobeCrop.png
--------------------------------------------------------------------------------
/pictures/SuperResCrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/SuperResCrop.png
--------------------------------------------------------------------------------
/pictures/alpha.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/alpha.gif
--------------------------------------------------------------------------------
/pictures/app1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/app1.png
--------------------------------------------------------------------------------
/pictures/app2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/app2.png
--------------------------------------------------------------------------------
/pictures/app21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/app21.png
--------------------------------------------------------------------------------
/pictures/app3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/app3.png
--------------------------------------------------------------------------------
/pictures/app4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/app4.png
--------------------------------------------------------------------------------
/pictures/app5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/app5.png
--------------------------------------------------------------------------------
/pictures/beta.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/beta.gif
--------------------------------------------------------------------------------
/pictures/dmd.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/dmd.gif
--------------------------------------------------------------------------------
/pictures/dms.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/dms.gif
--------------------------------------------------------------------------------
/pictures/edge.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/edge.gif
--------------------------------------------------------------------------------
/pictures/fraclam1lam2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/fraclam1lam2.gif
--------------------------------------------------------------------------------
/pictures/grandCanyon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/grandCanyon.png
--------------------------------------------------------------------------------
/pictures/lam1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/lam1.gif
--------------------------------------------------------------------------------
/pictures/lam2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/lam2.gif
--------------------------------------------------------------------------------
/pictures/newyorkFrame3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/newyorkFrame3.png
--------------------------------------------------------------------------------
/pictures/newyorkFrame3Crop1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/newyorkFrame3Crop1.png
--------------------------------------------------------------------------------
/pictures/newyorkMerged.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/newyorkMerged.png
--------------------------------------------------------------------------------
/pictures/newyorkMergedCrop1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/newyorkMergedCrop1.png
--------------------------------------------------------------------------------
/pictures/noiseModel.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/noiseModel.gif
--------------------------------------------------------------------------------
/pictures/overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/overview.png
--------------------------------------------------------------------------------
/pictures/samsung.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/samsung.png
--------------------------------------------------------------------------------
/pictures/sigmamd.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/sigmamd.gif
--------------------------------------------------------------------------------
/pictures/sigmamdsqrt2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/sigmamdsqrt2.gif
--------------------------------------------------------------------------------
/pictures/sigmams.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/sigmams.gif
--------------------------------------------------------------------------------
/pictures/sigmamssqrt2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/sigmamssqrt2.gif
--------------------------------------------------------------------------------
/pictures/sqrt2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/sqrt2.gif
--------------------------------------------------------------------------------
/pictures/superRes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/superRes.png
--------------------------------------------------------------------------------
/pictures/x.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunzmi/ImageStackAlignator/b12e86e835742a99fbe8929d4b3692ba9bb537c0/pictures/x.gif
--------------------------------------------------------------------------------