1 //=============================================================================
2 // MusE Reader
3 // Music Score Reader
4 //
5 // Copyright (C) 2010 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
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, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "omr.h"
21 #include "omrview.h"
22 #include "libmscore/xml.h"
23 #include "libmscore/sym.h"
24 #include "omrpage.h"
25 #include "pdf.h"
26 #ifdef OCR
27 #include "ocr.h"
28 #endif
29 #include "utils.h"
30 #include "pattern.h"
31
32 namespace Ms {
33
34 #ifdef OMR
35
36 class ScoreView;
37
38 Pattern* Omr::quartheadPattern;
39 Pattern* Omr::halfheadPattern;
40 Pattern* Omr::sharpPattern;
41 Pattern* Omr::flatPattern;
42 Pattern* Omr::naturalPattern;
43 Pattern* Omr::trebleclefPattern;
44 Pattern* Omr::bassclefPattern;
45 Pattern* Omr::timesigPattern[10];
46
47 //---------------------------------------------------------
48 // Omr
49 //---------------------------------------------------------
50
Omr(Score * s)51 Omr::Omr(Score* s)
52 {
53 _score = s;
54 #ifdef OCR
55 _ocr = 0;
56 #endif
57 ActionNames = QList<QString>() << QWidget::tr("Loading PDF") << QWidget::tr("Initializing Staves") << QWidget::tr("Identifying Systems");
58 initUtils();
59 }
60
Omr(const QString & p,Score * s)61 Omr::Omr(const QString& p, Score* s)
62 {
63 _score = s;
64 _path = p;
65 _ocr = 0;
66 ActionNames = QList<QString>()<< QWidget::tr("Loading PDF") << QWidget::tr("Initializing Staves") << QWidget::tr("Load Parameters") << QWidget::tr("Identifying Systems");
67 initUtils();
68 }
69
70 //---------------------------------------------------------
71 // newOmrView
72 //---------------------------------------------------------
73
newOmrView(ScoreView * sv)74 OmrView* Omr::newOmrView(ScoreView* sv)
75 {
76 OmrView* ov = new OmrView(sv);
77 ov->setOmr(this);
78 return ov;
79 }
80
81 //---------------------------------------------------------
82 // write
83 //---------------------------------------------------------
84
write(XmlWriter & xml) const85 void Omr::write(XmlWriter& xml) const
86 {
87 xml.stag("Omr");
88 xml.tag("path", _path);
89 xml.tag("spatium", _spatium);
90 xml.tag("dpmm", _dpmm);
91 for(OmrPage* page : _pages) {
92 page->write(xml);
93 }
94 xml.etag();
95 }
96
97 //---------------------------------------------------------
98 // read
99 //---------------------------------------------------------
100
read(XmlReader & e)101 void Omr::read(XmlReader& e)
102 {
103 _doc = 0;
104 #ifdef OCR
105 if (_ocr == 0)
106 _ocr = new Ocr;
107 _ocr->init();
108 #endif
109 while (e.readNextStartElement()) {
110 const QStringRef& tag(e.name());
111
112 if (tag == "path")
113 _path = e.readElementText();
114 else if (tag == "OmrPage") {
115 OmrPage* page = new OmrPage(this);
116 page->read(e);
117 _pages.append(page);
118 }
119 else if (tag == "spatium")
120 _spatium = e.readDouble();
121 else if (tag == "dpmm")
122 _dpmm = e.readDouble();
123 else
124 e.unknown();
125 }
126 }
127
128 //---------------------------------------------------------
129 // pagesInDocument
130 //---------------------------------------------------------
131
pagesInDocument() const132 int Omr::pagesInDocument() const
133 {
134 return _doc ? _doc->numPages() : 0;
135 }
136
137 //---------------------------------------------------------
138 // readPdf
139 // return true on success
140 //---------------------------------------------------------
141
readPdf()142 bool Omr::readPdf()
143 {
144 QProgressDialog *progress = new QProgressDialog(QWidget::tr("Reading PDF…"), QWidget::tr("Cancel"), 0, 100, 0, Qt::FramelessWindowHint);
145 progress->setWindowModality(Qt::ApplicationModal);
146 progress->show();
147 progress->setRange(0, ACTION_NUM);
148
149 #ifdef OCR
150 if (_ocr == 0)
151 _ocr = new Ocr;
152 _ocr->init();
153 #endif
154 int ID = READ_PDF;
155 int page = 0;
156 bool val;
157 while (ID < ACTION_NUM) {
158 if(ID != INIT_PAGE && ID != SYSTEM_IDENTIFICATION) {
159 page = 0;
160 progress->setLabelText(QWidget::tr("%1 at Page %2").arg(ActionNames.at(ID+1)).arg(1));
161 val = omrActions(ID, page);
162 }
163 else {
164 progress->setLabelText(QWidget::tr("%1 at Page %2").arg(ActionNames.at(ID)).arg(page+1));
165 val = omrActions(ID, page);
166 page++;
167 }
168
169 if (!val || progress->wasCanceled()) {
170 progress->close();
171 return false;
172 }
173 else {
174 if (ID < ACTION_NUM)
175 progress->setValue(ID);
176 else
177 progress->setValue(ACTION_NUM - 1);
178 qApp->processEvents();
179 }
180 }
181 progress->close();
182 delete progress;
183 return true;
184 }
185
186 //---------------------------------------------------------
187 // actions
188 //---------------------------------------------------------
189
omrActions(int & ID,int page)190 bool Omr::omrActions(int &ID, int page)
191 {
192 if(ID == READ_PDF) {
193 _doc = new Pdf();
194 if (!_doc->open(_path)) {
195 delete _doc;
196 _doc = 0;
197 return false;
198 }
199 int n = _doc->numPages();
200 //printf("readPdf: %d pages\n", n);
201 for (int i = 0; i < n; ++i) {
202 OmrPage* page1 = new OmrPage(this);
203 QImage image = _doc->page(i);
204 if (image.isNull())
205 return false;
206 page1->setImage(image);
207 _pages.append(page1);
208 }
209
210 _spatium = 15.0; //constant spatium, image will be rescaled according to this parameter
211 ID++;
212 return true;
213 }
214 else if(ID == INIT_PAGE) {
215 //load one page and rescale
216 _pages[page]->read();
217
218 //do the rescaling here
219 int new_w = _pages[page]->image().width() * _spatium/_pages[page]->spatium();
220 int new_h = _pages[page]->image().height() * _spatium/_pages[page]->spatium();
221 QImage image = _pages[page]->image().scaled(new_w,new_h, Qt::KeepAspectRatio);
222 _pages[page]->setImage(image);
223 _pages[page]->read();
224
225 if(page == _pages.size()-1)
226 ID++;
227 return true;
228 }
229 else if(ID == FINALIZE_PARMS) {
230 int n = _pages.size();
231 double w = 0;
232 for (int i = 0; i < n; ++i) {
233 w += _pages[i]->width();
234 }
235 w /= n;
236 _dpmm = w / 210.0; // PaperSize A4
237
238 quartheadPattern = new Pattern(_score, "solid_note_head");
239 halfheadPattern = new Pattern(_score, SymId::noteheadHalf, _spatium);
240 sharpPattern = new Pattern(_score, SymId::accidentalSharp, _spatium);
241 flatPattern = new Pattern(_score, SymId::accidentalFlat, _spatium);
242 naturalPattern = new Pattern(_score, SymId::accidentalNatural,_spatium);
243 trebleclefPattern = new Pattern(_score, SymId::gClef,_spatium);
244 bassclefPattern = new Pattern(_score, SymId::fClef,_spatium);
245 timesigPattern[0] = new Pattern(_score, SymId::timeSig0, _spatium);
246 timesigPattern[1] = new Pattern(_score, SymId::timeSig1, _spatium);
247 timesigPattern[2] = new Pattern(_score, SymId::timeSig2, _spatium);
248 timesigPattern[3] = new Pattern(_score, SymId::timeSig3, _spatium);
249 timesigPattern[4] = new Pattern(_score, SymId::timeSig4, _spatium);
250 timesigPattern[5] = new Pattern(_score, SymId::timeSig5, _spatium);
251 timesigPattern[6] = new Pattern(_score, SymId::timeSig6, _spatium);
252 timesigPattern[7] = new Pattern(_score, SymId::timeSig7, _spatium);
253 timesigPattern[8] = new Pattern(_score, SymId::timeSig8, _spatium);
254 timesigPattern[9] = new Pattern(_score, SymId::timeSig9, _spatium);
255
256 ID++;
257 return true;
258
259 }
260 else if(ID == SYSTEM_IDENTIFICATION) {
261 _pages[page]->identifySystems();
262 if(page == _pages.size()-1) ID++;
263 return true;
264 }
265 return false;
266 }
267
268 //---------------------------------------------------------
269 // spatiumMM
270 //---------------------------------------------------------
271
spatiumMM() const272 double Omr::spatiumMM() const
273 {
274 return _spatium / _dpmm;
275 }
276
277 //---------------------------------------------------------
278 // staffDistance
279 //---------------------------------------------------------
280
staffDistance() const281 double Omr::staffDistance() const
282 {
283 return _pages[0]->staffDistance();
284 }
285
286 //---------------------------------------------------------
287 // systemDistance
288 //---------------------------------------------------------
289
systemDistance() const290 double Omr::systemDistance() const
291 {
292 return _pages[0]->systemDistance();
293 }
294 #endif
295 }
296
297