j2k/adapter/
device_plan.rs1use crate::error::J2kError;
5use j2k_core::{Downscale, Rect};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum DeviceDecodeRequest {
10 Full,
12 Region {
14 roi: Rect,
16 },
17 Scaled {
19 scale: Downscale,
21 },
22 RegionScaled {
24 roi: Rect,
26 scale: Downscale,
28 },
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct DeviceDecodePlan {
34 source_dims: (u32, u32),
35 source_rect: Rect,
36 scale: Downscale,
37 output_rect: Rect,
38}
39
40impl DeviceDecodePlan {
41 pub fn for_image(
43 source_dims: (u32, u32),
44 request: DeviceDecodeRequest,
45 ) -> Result<Self, J2kError> {
46 let (source_rect, scale) = match request {
47 DeviceDecodeRequest::Full => (Rect::full(source_dims), Downscale::None),
48 DeviceDecodeRequest::Region { roi } => (roi, Downscale::None),
49 DeviceDecodeRequest::Scaled { scale } => (Rect::full(source_dims), scale),
50 DeviceDecodeRequest::RegionScaled { roi, scale } => (roi, scale),
51 };
52
53 if source_rect.w == 0 || source_rect.h == 0 || !source_rect.is_within(source_dims) {
54 return Err(J2kError::InvalidRegion {
55 x: source_rect.x,
56 y: source_rect.y,
57 w: source_rect.w,
58 h: source_rect.h,
59 image_w: source_dims.0,
60 image_h: source_dims.1,
61 });
62 }
63
64 Ok(Self {
65 source_dims,
66 source_rect,
67 scale,
68 output_rect: source_rect.scaled_covering(scale),
69 })
70 }
71
72 pub fn source_dims(self) -> (u32, u32) {
74 self.source_dims
75 }
76
77 pub fn source_rect(self) -> Rect {
79 self.source_rect
80 }
81
82 pub fn scale(self) -> Downscale {
84 self.scale
85 }
86
87 pub fn output_rect(self) -> Rect {
89 self.output_rect
90 }
91
92 pub fn output_dims(self) -> (u32, u32) {
94 (self.output_rect.w, self.output_rect.h)
95 }
96
97 pub fn target_resolution(self) -> Option<(u32, u32)> {
99 (self.scale != Downscale::None).then_some(self.output_dims())
100 }
101
102 pub fn is_full_frame(self) -> bool {
104 self.source_rect == Rect::full(self.source_dims) && self.scale == Downscale::None
105 }
106}