1 /*
2     Scan Tailor - Interactive post-processing tool for scanned pages.
3     Copyright (C)  Joseph Artsimovich <joseph.artsimovich@gmail.com>
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program 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 General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "Settings.h"
20 #include "../../Utils.h"
21 #include "AbstractRelinker.h"
22 #include "FillColorProperty.h"
23 #include "RelinkablePath.h"
24 
25 namespace output {
Settings()26 Settings::Settings()
27     : m_defaultPictureZoneProps(initialPictureZoneProps()), m_defaultFillZoneProps(initialFillZoneProps()) {}
28 
29 Settings::~Settings() = default;
30 
clear()31 void Settings::clear() {
32   const QMutexLocker locker(&m_mutex);
33 
34   initialPictureZoneProps().swap(m_defaultPictureZoneProps);
35   initialFillZoneProps().swap(m_defaultFillZoneProps);
36   m_perPageParams.clear();
37   m_perPageOutputParams.clear();
38   m_perPagePictureZones.clear();
39   m_perPageFillZones.clear();
40   m_perPageOutputProcessingParams.clear();
41 }
42 
performRelinking(const AbstractRelinker & relinker)43 void Settings::performRelinking(const AbstractRelinker& relinker) {
44   const QMutexLocker locker(&m_mutex);
45 
46   PerPageParams new_params;
47   PerPageOutputParams new_output_params;
48   PerPageZones new_picture_zones;
49   PerPageZones new_fill_zones;
50   PerPageOutputProcessingParams new_output_processing_params;
51 
52   for (const PerPageParams::value_type& kv : m_perPageParams) {
53     const RelinkablePath old_path(kv.first.imageId().filePath(), RelinkablePath::File);
54     PageId new_page_id(kv.first);
55     new_page_id.imageId().setFilePath(relinker.substitutionPathFor(old_path));
56     new_params.insert(PerPageParams::value_type(new_page_id, kv.second));
57   }
58 
59   for (const PerPageOutputParams::value_type& kv : m_perPageOutputParams) {
60     const RelinkablePath old_path(kv.first.imageId().filePath(), RelinkablePath::File);
61     PageId new_page_id(kv.first);
62     new_page_id.imageId().setFilePath(relinker.substitutionPathFor(old_path));
63     new_output_params.insert(PerPageOutputParams::value_type(new_page_id, kv.second));
64   }
65 
66   for (const PerPageZones::value_type& kv : m_perPagePictureZones) {
67     const RelinkablePath old_path(kv.first.imageId().filePath(), RelinkablePath::File);
68     PageId new_page_id(kv.first);
69     new_page_id.imageId().setFilePath(relinker.substitutionPathFor(old_path));
70     new_picture_zones.insert(PerPageZones::value_type(new_page_id, kv.second));
71   }
72 
73   for (const PerPageZones::value_type& kv : m_perPageFillZones) {
74     const RelinkablePath old_path(kv.first.imageId().filePath(), RelinkablePath::File);
75     PageId new_page_id(kv.first);
76     new_page_id.imageId().setFilePath(relinker.substitutionPathFor(old_path));
77     new_fill_zones.insert(PerPageZones::value_type(new_page_id, kv.second));
78   }
79 
80   for (const PerPageOutputProcessingParams::value_type& kv : m_perPageOutputProcessingParams) {
81     const RelinkablePath old_path(kv.first.imageId().filePath(), RelinkablePath::File);
82     PageId new_page_id(kv.first);
83     new_page_id.imageId().setFilePath(relinker.substitutionPathFor(old_path));
84     new_output_processing_params.insert(PerPageOutputProcessingParams::value_type(new_page_id, kv.second));
85   }
86 
87   m_perPageParams.swap(new_params);
88   m_perPageOutputParams.swap(new_output_params);
89   m_perPagePictureZones.swap(new_picture_zones);
90   m_perPageFillZones.swap(new_fill_zones);
91   m_perPageOutputProcessingParams.swap(new_output_processing_params);
92 }  // Settings::performRelinking
93 
getParams(const PageId & page_id) const94 Params Settings::getParams(const PageId& page_id) const {
95   const QMutexLocker locker(&m_mutex);
96 
97   const auto it(m_perPageParams.find(page_id));
98   if (it != m_perPageParams.end()) {
99     return it->second;
100   } else {
101     return Params();
102   }
103 }
104 
setParams(const PageId & page_id,const Params & params)105 void Settings::setParams(const PageId& page_id, const Params& params) {
106   const QMutexLocker locker(&m_mutex);
107   Utils::mapSetValue(m_perPageParams, page_id, params);
108 }
109 
setColorParams(const PageId & page_id,const ColorParams & prms)110 void Settings::setColorParams(const PageId& page_id, const ColorParams& prms) {
111   const QMutexLocker locker(&m_mutex);
112 
113   const auto it(m_perPageParams.find(page_id));
114   if (it == m_perPageParams.end()) {
115     Params params;
116     params.setColorParams(prms);
117     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
118   } else {
119     it->second.setColorParams(prms);
120   }
121 }
122 
setPictureShapeOptions(const PageId & page_id,PictureShapeOptions picture_shape_options)123 void Settings::setPictureShapeOptions(const PageId& page_id, PictureShapeOptions picture_shape_options) {
124   const QMutexLocker locker(&m_mutex);
125 
126   const auto it(m_perPageParams.find(page_id));
127   if (it == m_perPageParams.end()) {
128     Params params;
129     params.setPictureShapeOptions(picture_shape_options);
130     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
131   } else {
132     it->second.setPictureShapeOptions(picture_shape_options);
133   }
134 }
135 
setDpi(const PageId & page_id,const Dpi & dpi)136 void Settings::setDpi(const PageId& page_id, const Dpi& dpi) {
137   const QMutexLocker locker(&m_mutex);
138 
139   const auto it(m_perPageParams.find(page_id));
140   if (it == m_perPageParams.end()) {
141     Params params;
142     params.setOutputDpi(dpi);
143     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
144   } else {
145     it->second.setOutputDpi(dpi);
146   }
147 }
148 
setDewarpingOptions(const PageId & page_id,const DewarpingOptions & opt)149 void Settings::setDewarpingOptions(const PageId& page_id, const DewarpingOptions& opt) {
150   const QMutexLocker locker(&m_mutex);
151 
152   const auto it(m_perPageParams.find(page_id));
153   if (it == m_perPageParams.end()) {
154     Params params;
155     params.setDewarpingOptions(opt);
156     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
157   } else {
158     it->second.setDewarpingOptions(opt);
159   }
160 }
161 
setSplittingOptions(const PageId & page_id,const SplittingOptions & opt)162 void Settings::setSplittingOptions(const PageId& page_id, const SplittingOptions& opt) {
163   const QMutexLocker locker(&m_mutex);
164 
165   const auto it(m_perPageParams.find(page_id));
166   if (it == m_perPageParams.end()) {
167     Params params;
168     params.setSplittingOptions(opt);
169     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
170   } else {
171     it->second.setSplittingOptions(opt);
172   }
173 }
174 
setDistortionModel(const PageId & page_id,const dewarping::DistortionModel & model)175 void Settings::setDistortionModel(const PageId& page_id, const dewarping::DistortionModel& model) {
176   const QMutexLocker locker(&m_mutex);
177 
178   const auto it(m_perPageParams.find(page_id));
179   if (it == m_perPageParams.end()) {
180     Params params;
181     params.setDistortionModel(model);
182     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
183   } else {
184     it->second.setDistortionModel(model);
185   }
186 }
187 
setDepthPerception(const PageId & page_id,const DepthPerception & depth_perception)188 void Settings::setDepthPerception(const PageId& page_id, const DepthPerception& depth_perception) {
189   const QMutexLocker locker(&m_mutex);
190 
191   const auto it(m_perPageParams.find(page_id));
192   if (it == m_perPageParams.end()) {
193     Params params;
194     params.setDepthPerception(depth_perception);
195     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
196   } else {
197     it->second.setDepthPerception(depth_perception);
198   }
199 }
200 
setDespeckleLevel(const PageId & page_id,double level)201 void Settings::setDespeckleLevel(const PageId& page_id, double level) {
202   const QMutexLocker locker(&m_mutex);
203 
204   const auto it(m_perPageParams.find(page_id));
205   if (it == m_perPageParams.end()) {
206     Params params;
207     params.setDespeckleLevel(level);
208     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
209   } else {
210     it->second.setDespeckleLevel(level);
211   }
212 }
213 
getOutputParams(const PageId & page_id) const214 std::unique_ptr<OutputParams> Settings::getOutputParams(const PageId& page_id) const {
215   const QMutexLocker locker(&m_mutex);
216 
217   const auto it(m_perPageOutputParams.find(page_id));
218   if (it != m_perPageOutputParams.end()) {
219     return std::make_unique<OutputParams>(it->second);
220   } else {
221     return nullptr;
222   }
223 }
224 
removeOutputParams(const PageId & page_id)225 void Settings::removeOutputParams(const PageId& page_id) {
226   const QMutexLocker locker(&m_mutex);
227   m_perPageOutputParams.erase(page_id);
228 }
229 
setOutputParams(const PageId & page_id,const OutputParams & params)230 void Settings::setOutputParams(const PageId& page_id, const OutputParams& params) {
231   const QMutexLocker locker(&m_mutex);
232   Utils::mapSetValue(m_perPageOutputParams, page_id, params);
233 }
234 
pictureZonesForPage(const PageId & page_id) const235 ZoneSet Settings::pictureZonesForPage(const PageId& page_id) const {
236   const QMutexLocker locker(&m_mutex);
237 
238   const auto it(m_perPagePictureZones.find(page_id));
239   if (it != m_perPagePictureZones.end()) {
240     return it->second;
241   } else {
242     return ZoneSet();
243   }
244 }
245 
fillZonesForPage(const PageId & page_id) const246 ZoneSet Settings::fillZonesForPage(const PageId& page_id) const {
247   const QMutexLocker locker(&m_mutex);
248 
249   const auto it(m_perPageFillZones.find(page_id));
250   if (it != m_perPageFillZones.end()) {
251     return it->second;
252   } else {
253     return ZoneSet();
254   }
255 }
256 
setPictureZones(const PageId & page_id,const ZoneSet & zones)257 void Settings::setPictureZones(const PageId& page_id, const ZoneSet& zones) {
258   const QMutexLocker locker(&m_mutex);
259   Utils::mapSetValue(m_perPagePictureZones, page_id, zones);
260 }
261 
setFillZones(const PageId & page_id,const ZoneSet & zones)262 void Settings::setFillZones(const PageId& page_id, const ZoneSet& zones) {
263   const QMutexLocker locker(&m_mutex);
264   Utils::mapSetValue(m_perPageFillZones, page_id, zones);
265 }
266 
defaultPictureZoneProperties() const267 PropertySet Settings::defaultPictureZoneProperties() const {
268   const QMutexLocker locker(&m_mutex);
269 
270   return m_defaultPictureZoneProps;
271 }
272 
defaultFillZoneProperties() const273 PropertySet Settings::defaultFillZoneProperties() const {
274   const QMutexLocker locker(&m_mutex);
275 
276   return m_defaultFillZoneProps;
277 }
278 
setDefaultPictureZoneProperties(const PropertySet & props)279 void Settings::setDefaultPictureZoneProperties(const PropertySet& props) {
280   const QMutexLocker locker(&m_mutex);
281   m_defaultPictureZoneProps = props;
282 }
283 
setDefaultFillZoneProperties(const PropertySet & props)284 void Settings::setDefaultFillZoneProperties(const PropertySet& props) {
285   const QMutexLocker locker(&m_mutex);
286   m_defaultFillZoneProps = props;
287 }
288 
initialPictureZoneProps()289 PropertySet Settings::initialPictureZoneProps() {
290   PropertySet props;
291   props.locateOrCreate<PictureLayerProperty>()->setLayer(PictureLayerProperty::PAINTER2);
292 
293   return props;
294 }
295 
initialFillZoneProps()296 PropertySet Settings::initialFillZoneProps() {
297   PropertySet props;
298   props.locateOrCreate<FillColorProperty>()->setColor(Qt::white);
299 
300   return props;
301 }
302 
getOutputProcessingParams(const PageId & page_id) const303 OutputProcessingParams Settings::getOutputProcessingParams(const PageId& page_id) const {
304   const QMutexLocker locker(&m_mutex);
305 
306   const auto it(m_perPageOutputProcessingParams.find(page_id));
307   if (it != m_perPageOutputProcessingParams.end()) {
308     return it->second;
309   } else {
310     return OutputProcessingParams();
311   }
312 }
313 
setOutputProcessingParams(const PageId & page_id,const OutputProcessingParams & output_processing_params)314 void Settings::setOutputProcessingParams(const PageId& page_id,
315                                          const OutputProcessingParams& output_processing_params) {
316   const QMutexLocker locker(&m_mutex);
317   Utils::mapSetValue(m_perPageOutputProcessingParams, page_id, output_processing_params);
318 }
319 
isParamsNull(const PageId & page_id) const320 bool Settings::isParamsNull(const PageId& page_id) const {
321   const QMutexLocker locker(&m_mutex);
322 
323   return m_perPageParams.find(page_id) == m_perPageParams.end();
324 }
325 
setBlackOnWhite(const PageId & page_id,const bool black_on_white)326 void Settings::setBlackOnWhite(const PageId& page_id, const bool black_on_white) {
327   const QMutexLocker locker(&m_mutex);
328 
329   const auto it(m_perPageParams.find(page_id));
330   if (it == m_perPageParams.end()) {
331     Params params;
332     params.setBlackOnWhite(black_on_white);
333     m_perPageParams.insert(it, PerPageParams::value_type(page_id, params));
334   } else {
335     it->second.setBlackOnWhite(black_on_white);
336   }
337 }
338 }  // namespace output