// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
// Moving pixels around without looking at what they are.
//
// A flip, a quarter turn and a crop are the three operations a caller needs to
// fix an image that arrived the wrong way up, and all three are the same kind of
// work: copy a pixel from here to there. Because the format is never consulted,
// a 16-bit image and a grey one go through the same code, and no precision is
// lost on the way.
///|
/// The image reflected left to right.
pub fn Image::flip_horizontal(self : Image) -> Image {
let pixel = self.format.bytes()
let stride = self.width * pixel
let buffer : FixedArray[Byte] = FixedArray::make(
if self.height == 0 {
0
} else {
stride * self.height
},
b'\x00',
)
for y in 0.. Image {
let row_bytes = self.width * self.format.bytes()
let buffer : FixedArray[Byte] = FixedArray::make(
if self.height == 0 {
0
} else {
row_bytes * self.height
},
b'\x00',
)
for y in 0.. Image {
let turns = (quarters.unwrap_or(1) % 4 + 4) % 4
if turns == 0 {
return self
}
let pixel = self.format.bytes()
let width = self.width
let height = self.height
let (out_width, out_height) = if turns == 2 {
(width, height)
} else {
(height, width)
}
let stride = out_width * pixel
let buffer : FixedArray[Byte] = FixedArray::make(
if out_height == 0 {
0
} else {
stride * out_height
},
b'\x00',
)
for y in 0.. (y, height - 1 - x)
2 => (width - 1 - x, height - 1 - y)
_ => (width - 1 - y, x)
}
let from = source_y * self.stride + source_x * pixel
let to = y * stride + x * pixel
for k in 0.. Image raise Refused {
if x < 0 || y < 0 || width < 0 || height < 0 {
raise Unexpected(
at=0,
got="a rectangle outside the image",
want="x, y, width and height at least zero",
)
}
if x + width > self.width {
raise OverLimit(limit=self.width, got=x + width)
}
if y + height > self.height {
raise OverLimit(limit=self.height, got=y + height)
}
let pixel = self.format.bytes()
let stride = width * pixel
let buffer : FixedArray[Byte] = FixedArray::make(
if height == 0 {
0
} else {
stride * height
},
b'\x00',
)
for row in 0..