Для начала - заполнил матрицу вручную сверху вниз слева направо - чтобы с ректами не путаться (потом вернусь к GetDIBits - непривычное заполнение матрицы на принцип все равно не влияет, просто код будет чуть менее понятный).
Мой алгоритм такой:
1. Перебираю слева направо. Если встречаю цвет контура, то это левый верхний угол, left и top. Запускаю процедуру обхода по контуру. Двигаясь по контуру, одновременно его затираю.
2. Продолжаю движение слева направо, пока не кончится цвет контура. Получили правый верхний угол. Это right.
3. Поворачиваю вниз. Двигаюсь, пока не кончится цвет контура. Это нижний правый угол. Bottom.
4. Поворачиваю налево. Если там нет контура, то это либо ошибка в картинке, либо контур пошел снова вправо. Второй вариант пока не рассматриваю, чтобы не запутаться (благо, таких кнопок все равно не бывает).
5. Двигаюсь справа налево, пока не найду угол. Это нижний левый угол. Снова left.
6. Если первый left и второй совпали, кнопка прямоугольная. Затираю последнюю сторону, становлюсь на правый верхний угол, увеличиваю счётчик ректов, выхожу из процедуры обхода контура. Готу 1
7. Если left-ы не совпали, поворачиваю вверх. Увеличиваю счётчик ректов, копирую второй полученный left, right и bottom в новый рект. В предыдущем ректе теперь bottom не корректно.
8. Двигаюсь вверх до угла. Это top текущего ректа и bottom предыдущего ректа (с разницей в единицу, смотря в какую сторону загнута кнопка). Кстати, если бы кнопки на картинке были не контуром, а спрошные, то этот угол было бы труднее найти при ноутной форме энтера.
9. Поворачиваю влево или вправо (в зависимости от того, какой из двух лефтов был больше) и двигаясь до первого left-a, затирая горизонтальную линию. Затем поворачиваю вверх и затираю последнюю линию. Становлюсь в правый верхний угол предыдущего ректа, выхожу из процедуры обхода контура, готу 1.
Вроде, всё