@@ -47,7 +47,7 @@ class UploadFileManager {
47
47
}
48
48
}
49
49
50
- public createMeiFile ( filename : string , lrx : number , lry : number ) : File {
50
+ public createMeiFile ( filename : string , width : number , height : number , staffSpace : number ) : File {
51
51
try {
52
52
if ( ! this . meiTemplate ) {
53
53
throw new Error ( 'Cannot find MEI template' ) ;
@@ -73,11 +73,20 @@ class UploadFileManager {
73
73
const surface = mei . querySelector ( 'surface' ) ;
74
74
const surfaceId = 'm-' + uuidv4 ( ) ;
75
75
surface . setAttribute ( 'xml:id' , surfaceId ) ;
76
- surface . setAttribute ( 'lrx' , lrx . toString ( ) ) ;
77
- surface . setAttribute ( 'lry' , lry . toString ( ) ) ;
76
+ surface . setAttribute ( 'lrx' , width . toString ( ) ) ;
77
+ surface . setAttribute ( 'lry' , height . toString ( ) ) ;
78
+
78
79
const zone = mei . querySelector ( 'zone' ) ;
79
80
const zoneId = 'm-' + uuidv4 ( ) ;
80
81
zone . setAttribute ( 'xml:id' , zoneId ) ;
82
+ const marginRateV = 0.1 ;
83
+ const marginRateH = 0.15 ;
84
+ const marginV = Math . round ( marginRateV * width ) ;
85
+ const marginH = Math . round ( marginRateH * width ) ;
86
+ zone . setAttribute ( 'ulx' , marginH . toString ( ) ) ;
87
+ zone . setAttribute ( 'uly' , marginV . toString ( ) ) ;
88
+ zone . setAttribute ( 'lrx' , ( width - marginH ) . toString ( ) ) ;
89
+ zone . setAttribute ( 'lry' , ( marginV + 3 * staffSpace ) . toString ( ) ) ;
81
90
82
91
const mdiv = mei . querySelector ( 'mdiv' ) ;
83
92
mdiv . setAttribute ( 'xml:id' , 'm-' + uuidv4 ( ) ) ;
@@ -107,7 +116,7 @@ class UploadFileManager {
107
116
}
108
117
}
109
118
110
- public getImgDimension ( filename : string ) : Promise < { width : number ; height : number } > {
119
+ public getImgDimension ( filename : string ) : Promise < { width : number ; height : number , staffSpace : number } > {
111
120
return new Promise ( ( resolve , reject ) => {
112
121
const imgFile = this . getFile ( filename ) ;
113
122
@@ -121,7 +130,51 @@ class UploadFileManager {
121
130
reader . onload = ( event ) => {
122
131
const img = new Image ( ) ;
123
132
img . onload = ( ) => {
124
- resolve ( { width : img . width , height : img . height } ) ;
133
+ const canvas = document . createElement ( 'canvas' ) ;
134
+ const ctx = canvas . getContext ( '2d' , { willReadFrequently : true } ) ;
135
+ if ( ! ctx ) {
136
+ reject ( new Error ( 'Could not get 2D context' ) ) ;
137
+ return ;
138
+ }
139
+
140
+ canvas . width = img . width ;
141
+ canvas . height = img . height ;
142
+ ctx . drawImage ( img , 0 , 0 ) ;
143
+
144
+ // Binarization
145
+ const imageData = ctx . getImageData ( 0 , 0 , canvas . width , canvas . height ) ;
146
+ const binaryThreshold = 127 ;
147
+ const data = imageData . data ;
148
+ for ( let i = 0 ; i < data . length ; i += 4 ) {
149
+ const grayscale = ( data [ i ] + data [ i + 1 ] + data [ i + 2 ] ) / 3 ;
150
+ const binaryValue = grayscale < binaryThreshold ? 0 : 255 ;
151
+ data [ i ] = binaryValue ;
152
+ data [ i + 1 ] = binaryValue ;
153
+ data [ i + 2 ] = binaryValue ;
154
+ }
155
+ ctx . putImageData ( imageData , 0 , 0 ) ;
156
+
157
+ // Finding staff space
158
+ const whiteRunLengths : number [ ] = [ ] ;
159
+ let currSpaceCount = 0 ;
160
+ for ( let x = 0 ; x < canvas . width ; x ++ ) {
161
+ // new currSpaceCount for every column
162
+ const column = ctx . getImageData ( x , 0 , 1 , canvas . height ) . data ;
163
+ for ( let p = 0 ; p < column . length ; p += 4 ) {
164
+ // Check if the pixel is black (0) or white (255)
165
+ if ( column [ p ] === 0 && currSpaceCount > 0 ) {
166
+ whiteRunLengths . push ( currSpaceCount ) ;
167
+ currSpaceCount = 0 ;
168
+ } else {
169
+ currSpaceCount ++ ;
170
+ }
171
+ }
172
+ }
173
+
174
+ // Get the second most common value as staff space
175
+ const staffSpace = whiteRunLengths . length > 0 ? this . findSecondMode ( whiteRunLengths ) : 0 ;
176
+
177
+ resolve ( { width : img . width , height : img . height , staffSpace : staffSpace } ) ;
125
178
} ;
126
179
img . onerror = ( ) => {
127
180
reject ( new Error ( `Failed to load image: ${ filename } ` ) ) ;
@@ -133,6 +186,20 @@ class UploadFileManager {
133
186
} ) ;
134
187
}
135
188
189
+ private findSecondMode ( arr : number [ ] ) : number {
190
+ const countMap : Map < number , number > = new Map ( ) ;
191
+
192
+ // Count occurrences of each element
193
+ arr . forEach ( element => {
194
+ const count = ( countMap . get ( element ) || 0 ) + 1 ;
195
+ countMap . set ( element , count ) ;
196
+ } ) ;
197
+
198
+ const sortedMap = Array . from ( countMap . entries ( ) ) . sort ( ( a , b ) => b [ 1 ] - a [ 1 ] ) ;
199
+
200
+ return sortedMap [ 1 ] [ 0 ] ;
201
+ }
202
+
136
203
137
204
public getFile ( key : string ) : File {
138
205
if ( this . allFiles . has ( key ) ) {
0 commit comments