private static int findStartOfStaffs(Bitmap bitmap) { var x = 0; while (!bitmap.Column(x).Any(pixel => pixel == true)) { x++; } log("Staffs found at {0}.", x); return x; }
private static Rectangle noteBoundsAt(Bitmap bitmap, int x, int staffDistance) { int? minY = null, maxY = null; var endX = x; do { var yMinMax = noteTopBottomAt(bitmap.Column(endX).ToArray(), staffDistance); if (yMinMax == null) break; if (!minY.HasValue || minY > yMinMax.Item1) minY = yMinMax.Item1; if (!maxY.HasValue || maxY < yMinMax.Item2) maxY = yMinMax.Item2; endX++; } while (true); if (!minY.HasValue) return null; return new Rectangle { X1 = x, Y1 = minY.Value, X2 = endX, Y2 = maxY.Value }; }
public static IEnumerable<Note> enumerate(Bitmap bitmap) { //log("Skipping to start of staffs"); var x = findStartOfStaffs(bitmap); var outsideStaffIndexes = staffPositions(bitmap.Column(x).ToArray()); log("Staff indexes: {0}", string.Join(", ", outsideStaffIndexes)); eraseStaffs(bitmap, outsideStaffIndexes); var staffThickness = outsideStaffIndexes[1] - outsideStaffIndexes[0]; var staffDistance = outsideStaffIndexes[2] - outsideStaffIndexes[0]; log("Staff heights: {0}", staffDistance); var notePositions = getNotePositions(outsideStaffIndexes).ToArray(); while (x < bitmap.Width) { //log("x={0}", x); var noteBounds = noteBoundsAt(bitmap, x, staffDistance); if (noteBounds != null) { var centerX = (noteBounds.X1 + noteBounds.X2) / 2; var centerY = (noteBounds.Y1 + noteBounds.Y2) / 2; log("At {2}-{3}; Found note at: ({0}, {1})", centerX, centerY, noteBounds.X1, noteBounds.X2); var duration = durationAt(bitmap, centerX, centerY + staffThickness); var pitch = pitchAt(centerY, notePositions); yield return new Note { Pitch = pitch, Duration = duration }; x = noteBounds.X2; log("Skipping to end of note at {0}", x); } x++; } }