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