+ break
+
+
+def rotozoom(
+ dest_bitmap,
+ source_bitmap,
+ *,
+ ox: int,
+ oy: int,
+ dest_clip0: Tuple[int, int],
+ dest_clip1: Tuple[int, int],
+ px: int,
+ py: int,
+ source_clip0: Tuple[int, int],
+ source_clip1: Tuple[int, int],
+ angle: float,
+ scale: float,
+ skip_index: int,
+):
+ dest_clip0_x, dest_clip0_y = dest_clip0
+ dest_clip1_x, dest_clip1_y = dest_clip1
+ source_clip0_x, source_clip0_y = source_clip0
+ source_clip1_x, source_clip1_y = source_clip1
+
+ minx = dest_clip1_x
+ miny = dest_clip1_y
+ maxx = dest_clip0_x
+ maxy = dest_clip0_y
+
+ sin_angle = math.sin(angle)
+ cos_angle = math.cos(angle)
+
+ def update_bounds(dx, dy):
+ nonlocal minx, maxx, miny, maxy
+ if dx < minx:
+ minx = int(dx)
+ if dx > maxx:
+ maxx = int(dx)
+ if dy < miny:
+ miny = int(dy)
+ if dy > maxy:
+ maxy = int(dy)
+
+ w = source_bitmap.width
+ h = source_bitmap.height
+
+ dx = -cos_angle * px * scale + sin_angle * py * scale + ox
+ dy = -sin_angle * px * scale - cos_angle * py * scale + oy
+ update_bounds(dx, dy)
+
+ dx = cos_angle * (w - px) * scale + sin_angle * py * scale + ox
+ dy = sin_angle * (w - px) * scale - cos_angle * py * scale + oy
+ update_bounds(dx, dy)
+
+ dx = cos_angle * (w - px) * scale - sin_angle * (h - py) * scale + ox
+ dy = sin_angle * (w - px) * scale + cos_angle * (h - py) * scale + oy
+ update_bounds(dx, dy)
+
+ dx = -cos_angle * px * scale - sin_angle * (h - py) * scale + ox
+ dy = -sin_angle * px * scale + cos_angle * (h - py) * scale + oy
+ update_bounds(dx, dy)
+
+ # Clip to destination area
+ minx = max(minx, dest_clip0_x)
+ maxx = min(maxx, dest_clip1_x - 1)
+ miny = max(miny, dest_clip0_y)
+ maxy = min(maxy, dest_clip1_y - 1)
+
+ dv_col = cos_angle / scale
+ du_col = sin_angle / scale
+ du_row = dv_col
+ dv_row = -du_col
+
+ startu = px - (ox * dv_col + oy * du_col)
+ startv = py - (ox * dv_row + oy * du_row)
+
+ rowu = startu + miny * du_col
+ rowv = startv + miny * dv_col
+
+ for y in range(miny, maxy + 1):
+ u = rowu + minx * du_row
+ v = rowv + minx * dv_row
+ for x in range(minx, maxx + 1):
+ if (source_clip0_x <= u < source_clip1_x) and (source_clip0_y <= v < source_clip1_y):
+ c = source_bitmap[int(u), int(v)]
+ if skip_index is None or c != skip_index:
+ dest_bitmap[x, y] = c
+ u += du_row
+ v += dv_row
+ rowu += du_col
+ rowv += dv_col