pub enum PageOrientationHandling {
SelfCorrecting,
RecognisesRotatedText,
RequiresUpright,
}Expand description
How a backend copes with a page raster whose text is not upright.
Rotated-page handling is a backend capability, not a universal guarantee. An A/B run this
session against /Rotate 270 scanned pages showed the three handled cases genuinely differ:
Tesseract reconstructs correct reading order on a sideways raster outright; PaddleOCR
recognises the rotated text correctly (it warps each detected quad upright before running
recognition) but leaves its block list in raw raster (y, x) order, so the caller must
reorder; sceptre produces character garbage on the same sideways raster and only reads
correctly once the page is rendered upright first. A caller that skips an upright-render step
for a backend that actually needs one gets silent garbage, not an error.
§Only one variant is discriminated (#657)
Read this before “simplifying” the type. There is exactly one decision point in the
codebase that inspects this value: upright_raster_for_backend
(crate::extractors::pdf::ocr), which tests orientation_handling != RequiresUpright and
otherwise does nothing. Every other mention forwards the value to that test. So, to that
codepath, SelfCorrecting and RecognisesRotatedText are behaviourally identical — the
enum is a boolean at the point of use, and the three variants describe measured backend
behaviour rather than three dispatch paths.
RecognisesRotatedText’s actual remedy is not this enum. The block-order fix is the
backend_options["page_rotation_degrees"] hint injected by
ocr_config_with_page_rotation_hint (crate::extractors::pdf::ocr) unconditionally, for
every backend, which PaddleOcrBackend::process_image reads back
(page_rotation_degrees_from_backend_options -> residual_rotation_for_reorder ->
reorder_blocks_for_page_rotation, crate::paddle_ocr::backend) and applies internally.
Declaring RecognisesRotatedText therefore changes nothing on its own; a backend in that
class must also read the hint. Conversely, gating that hint on this enum would remove a
field from Tesseract’s OcrConfig and hence from the OCR cache key
(hash(image + language + config)), invalidating every cached page — do not do it without
its own A/B.
§PDF-route-only
Only the PDF OCR routes call OcrBackend::page_orientation_handling (the --force-ocr
route via extract_with_ocr and the scanned-pages route via extract_mixed_ocr_native).
The raw-image route (crate::extractors::image) never calls it: there is no /Rotate to
consult, and orientation there is handled by the PP-LCNet document-orientation classifier
(crate::doc_orientation) gated on OcrConfig::auto_rotate.
§Cost of the default
The trait default is RequiresUpright (deliberately the least capable option, see
OcrBackend::page_orientation_handling). A backend that does not declare therefore pays,
on every page with /Rotate != 0, a re-encode plus rotation of the raster in
upright_raster_for_backend and a bounding-box round-trip back through
undo_upright_raster_correction. That is the safe direction to be wrong in, but it is not
free, and for a backend that never got measured it is not known to be necessary either.
Variants§
SelfCorrecting
Reconstructs reading order regardless of page rotation — safe to hand a raster in any orientation.
RecognisesRotatedText
Recognises rotated text correctly but emits blocks in raw raster order, so the caller must reorder.
RequiresUpright
Requires an upright raster; rotated text produces garbage.
Trait Implementations§
Source§impl Clone for PageOrientationHandling
impl Clone for PageOrientationHandling
Source§fn clone(&self) -> PageOrientationHandling
fn clone(&self) -> PageOrientationHandling
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for PageOrientationHandling
Source§impl Debug for PageOrientationHandling
impl Debug for PageOrientationHandling
Source§impl Default for PageOrientationHandling
impl Default for PageOrientationHandling
Source§fn default() -> PageOrientationHandling
fn default() -> PageOrientationHandling
Source§impl<'de> Deserialize<'de> for PageOrientationHandling
impl<'de> Deserialize<'de> for PageOrientationHandling
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for PageOrientationHandling
Source§impl PartialEq for PageOrientationHandling
impl PartialEq for PageOrientationHandling
Source§impl Serialize for PageOrientationHandling
impl Serialize for PageOrientationHandling
impl StructuralPartialEq for PageOrientationHandling
Auto Trait Implementations§
impl Freeze for PageOrientationHandling
impl RefUnwindSafe for PageOrientationHandling
impl Send for PageOrientationHandling
impl Sync for PageOrientationHandling
impl Unpin for PageOrientationHandling
impl UnsafeUnpin for PageOrientationHandling
impl UnwindSafe for PageOrientationHandling
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more