AstRawDark
Manage your astrophoto dark frames
 All Classes Functions Variables Enumerations Enumerator Pages
darkMatcher.cpp
1 /*
2  * AstRawDark
3  *
4  * Copyright (C) 2015 - Frédéric CORNU
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "darkMatcher.h"
21 #include "data/helpers/imageStackHelper.h"
22 #include "processing/exceptions/noDarkForShootSettingsExcpetion.h"
23 #include "processing/exceptions/noDarkForTempException.h"
24 
25 #ifndef QT_NO_DEBUG
26 #include <QDebug>
27 #endif
28 
29 DarkMatcher::DarkMatcher() {
30 
31 
32 }
33 
34 DarkMatcher::~DarkMatcher() {
35 
36 }
37 
38 void DarkMatcher::match(QList<ImageInfo> lights, QList<ImageInfo> darks, int desiredDarkCount) {
39 
40  _results.clear();
41 
42  /*
43  * Here we know that all lights have been checked for consistancy
44  * so we can get camera body serial number, exposure time and ISO settings
45  * from whichever light
46  */
47  ImageInfo referenceLight = lights.at(0);
48 
49  QString serial = referenceLight.getCameraSerial();
50  int exposureTime = referenceLight.getExposure();
51  int isoSpeed = referenceLight.getIso();
52 
53  /*
54  * We filter darks based on these shooting conditions.
55  * Keeping only darks shot with :
56  *
57  * - same camera body, based on serial #
58  * - same exposure time
59  * - same ISO settings
60  */
61  QList<ImageInfo> filteredDarks;
62 
63  foreach (ImageInfo dark, darks) {
64 
65  if ( dark.getCameraSerial() == serial &&
66  dark.getExposure() == exposureTime &&
67  dark.getIso() == isoSpeed ) {
68 
69  filteredDarks.append(dark);
70  }
71  }
72 
73  if ( ! filteredDarks.isEmpty() ) {
74 
75  #ifndef QT_NO_DEBUG
76  qDebug() << desiredDarkCount << " darks wanted. We found "
77  << filteredDarks.size() << " darks that match shooting settings";
78  #endif
79 
80  if ( desiredDarkCount > filteredDarks.size() ) {
81 
82  throw NoDarkForTempException("Not enough darks", 0, desiredDarkCount, filteredDarks.size());
83  }
84 
85  #ifndef QT_NO_DEBUG
86  qDebug() << " T° : needed\t| available";
87  qDebug() << "=================================";
88  #endif
89 
90  /*
91  * Create temperature stacks for lights & filtered darks
92  */
93  QList<ImageStack*> lightStacks = ImageStackHelper::createStackListFromImageInfos(lights);
94  QList<ImageStack*> darkStacks = ImageStackHelper::createStackListFromImageInfos(filteredDarks);
95 
96  /*
97  * For each light stack
98  */
99  foreach( ImageStack* pLightStack, lightStacks ) {
100 
101  int lightStackSize = pLightStack->getSize();
102 
103  bool foundDarkStack = false;
104 
105  /*
106  * compute how many darks we need for this temperature
107  *
108  *
109  * total number of darks wanted
110  * needed darks = size of lights stack x ---------------------------------
111  * total number of lights
112  *
113  * FIXME: rounding leads to matched dark count beeing slightly off by +- 1
114  */
115  int neededDarks = qRound(lightStackSize * desiredDarkCount / static_cast<double> (lights.size()));
116 
117  /*
118  * we look for a dark stack with same temperature
119  */
120  int lightStackTemp = pLightStack->getTemperature();
121 
122  foreach ( ImageStack* pDarkStack, darkStacks ) {
123 
124  if ( pDarkStack->getTemperature() == lightStackTemp ) {
125 
126  /*
127  * Found the right dark stack !!!
128  */
129  foundDarkStack = true;
130 
131  int darkStackSize = pDarkStack->getSize();
132 
133  #ifndef QT_NO_DEBUG
134  qDebug() << lightStackTemp << "°C : "
135  << neededDarks
136  << "\t| "
137  << darkStackSize;
138  #endif
139 
140  if ( neededDarks <= darkStackSize ) {
141 
142  /*
143  * Darks stack has enough images, we feed the monkey
144  */
145  for ( int i=0; i<neededDarks; i++ ) {
146 
147  _results << pDarkStack->getImages().at(i);
148  }
149 
150  } else {
151 
152  #ifndef QT_NO_DEBUG
153  qDebug() << "Not enough darks for T = " << lightStackTemp << " °C";
154  #endif
155  throw NoDarkForTempException("Not enough darks", lightStackTemp, neededDarks, darkStackSize);
156  }
157  }
158  }
159 
160  if ( ! foundDarkStack ) {
161 
162  #ifndef QT_NO_DEBUG
163  qDebug() << "No darks for T = " << lightStackTemp << " °C";
164  #endif
165  throw NoDarkForTempException("Not enough darks", lightStackTemp, neededDarks, 0);
166  }
167  }
168 
169  #ifndef QT_NO_DEBUG
170  qDebug() << "Matched " << _results.size() << " darks";
171  #endif
172 
173 
174  } else {
175 
176  throw NoDarkForShootSettingsExcpetion("No darks match your lights shooting conditions");
177  }
178 }