* @name make_single_row * * Arrange the blobs into a single row... well actually, if there is * only a single blob, it makes 2 rows, in case the top-level blob * is a container of the real blobs to recognize. */
| 162 | * is a container of the real blobs to recognize. |
| 163 | */ |
| 164 | float make_single_row(ICOORD page_tr, bool allow_sub_blobs, |
| 165 | TO_BLOCK* block, TO_BLOCK_LIST* blocks) { |
| 166 | BLOBNBOX_IT blob_it = &block->blobs; |
| 167 | TO_ROW_IT row_it = block->get_rows(); |
| 168 | |
| 169 | // Include all the small blobs and large blobs. |
| 170 | blob_it.add_list_after(&block->small_blobs); |
| 171 | blob_it.add_list_after(&block->noise_blobs); |
| 172 | blob_it.add_list_after(&block->large_blobs); |
| 173 | if (block->blobs.singleton() && allow_sub_blobs) { |
| 174 | blob_it.move_to_first(); |
| 175 | float size = MakeRowFromSubBlobs(block, blob_it.data()->cblob(), &row_it); |
| 176 | if (size > block->line_size) |
| 177 | block->line_size = size; |
| 178 | } else if (block->blobs.empty()) { |
| 179 | // Make a fake blob. |
| 180 | C_BLOB* blob = C_BLOB::FakeBlob(block->block->bounding_box()); |
| 181 | // The blobnbox owns the blob. |
| 182 | BLOBNBOX* bblob = new BLOBNBOX(blob); |
| 183 | blob_it.add_after_then_move(bblob); |
| 184 | } |
| 185 | MakeRowFromBlobs(block->line_size, &blob_it, &row_it); |
| 186 | // Fit an LMS line to the rows. |
| 187 | for (row_it.mark_cycle_pt(); !row_it.cycled_list(); row_it.forward()) |
| 188 | fit_lms_line(row_it.data()); |
| 189 | float gradient; |
| 190 | float fit_error; |
| 191 | // Compute the skew based on the fitted line. |
| 192 | compute_page_skew(blocks, gradient, fit_error); |
| 193 | return gradient; |
| 194 | } |
| 195 | |
| 196 | /** |
| 197 | * @name make_rows |
no test coverage detected