Normalize battle unit animation sprites
@@ -18,7 +18,7 @@ UNIT_DIR = ROOT / "src" / "assets" / "images" / "units"
|
||||
SOURCE_ATLAS = ROOT / "src" / "assets" / "images" / "unit-sources" / "three-kingdoms-unit-atlas.png"
|
||||
|
||||
DIRECTIONS = ("south", "east", "north", "west")
|
||||
ACTION_ORDER = ("attack", "strategy", "item", "hurt")
|
||||
ACTION_ORDER = ("attack", "strategy", "item", "hurt", "celebrate")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -39,19 +39,37 @@ class UnitPlan:
|
||||
scale: float = 1.0
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RoleSpec:
|
||||
height: int
|
||||
max_width: int
|
||||
bottom_padding: int
|
||||
idle_scale_x: tuple[float, float, float, float]
|
||||
idle_scale_y: tuple[float, float, float, float]
|
||||
idle_dx: tuple[int, int, int, int]
|
||||
|
||||
|
||||
TEMPLATES: dict[str, Template] = {
|
||||
"shu-lord": Template(0, "infantry", 296, 284),
|
||||
"green-polearm": Template(1, "polearm", 300, 292),
|
||||
"red-spear": Template(2, "polearm", 296, 292),
|
||||
"white-cavalry": Template(3, "cavalry", 304, 302),
|
||||
"wei-lord": Template(4, "infantry", 296, 284),
|
||||
"red-cavalry": Template(5, "cavalry", 304, 302),
|
||||
"strategist": Template(6, "strategist", 288, 270),
|
||||
"rebel-infantry": Template(7, "infantry", 290, 278),
|
||||
"rebel-archer": Template(8, "archer", 286, 284),
|
||||
"rebel-cavalry": Template(9, "cavalry", 304, 302),
|
||||
"wu-officer": Template(10, "infantry", 292, 282),
|
||||
"nanman-officer": Template(11, "polearm", 294, 286),
|
||||
"shu-lord": Template(0, "infantry", 286, 274),
|
||||
"green-polearm": Template(1, "polearm", 292, 282),
|
||||
"red-spear": Template(2, "polearm", 292, 282),
|
||||
"white-cavalry": Template(3, "cavalry", 292, 304),
|
||||
"wei-lord": Template(4, "infantry", 286, 274),
|
||||
"red-cavalry": Template(5, "cavalry", 292, 304),
|
||||
"strategist": Template(6, "strategist", 276, 250),
|
||||
"rebel-infantry": Template(7, "infantry", 286, 274),
|
||||
"rebel-archer": Template(8, "archer", 282, 276),
|
||||
"rebel-cavalry": Template(9, "cavalry", 292, 304),
|
||||
"wu-officer": Template(10, "infantry", 286, 274),
|
||||
"nanman-officer": Template(11, "polearm", 292, 282),
|
||||
}
|
||||
|
||||
ROLE_SPECS: dict[str, RoleSpec] = {
|
||||
"infantry": RoleSpec(286, 274, 4, (1.0, 0.985, 1.015, 1.0), (1.0, 1.018, 0.992, 1.01), (0, 0, 0, 0)),
|
||||
"polearm": RoleSpec(292, 282, 4, (1.0, 0.986, 1.014, 1.0), (1.0, 1.018, 0.992, 1.01), (0, 0, 0, 0)),
|
||||
"cavalry": RoleSpec(292, 304, 3, (1.0, 1.012, 0.988, 1.008), (1.0, 1.014, 0.99, 1.008), (0, 1, 0, -1)),
|
||||
"strategist": RoleSpec(276, 250, 5, (1.0, 0.988, 1.012, 1.0), (1.0, 1.018, 0.994, 1.01), (0, 0, 0, 0)),
|
||||
"archer": RoleSpec(282, 276, 4, (1.0, 0.986, 1.012, 1.0), (1.0, 1.016, 0.992, 1.01), (0, 0, 0, 0)),
|
||||
}
|
||||
|
||||
SIGNATURE_PLANS: dict[str, UnitPlan] = {
|
||||
@@ -62,7 +80,7 @@ SIGNATURE_PLANS: dict[str, UnitPlan] = {
|
||||
"unit-cao-cao": UnitPlan("wei-lord", (52, 58, 122), 0.06, 1.02, 1.01, 1.0),
|
||||
"unit-lu-bu": UnitPlan("red-cavalry", (140, 36, 54), 0.05, 1.05, 1.02, 1.0),
|
||||
"unit-zhuge-liang": UnitPlan("strategist", (42, 126, 118), 0.05, 1.02, 1.03, 1.0),
|
||||
"unit-pang-tong": UnitPlan("strategist", (80, 126, 68), 0.09, 1.02, 1.0, 0.98),
|
||||
"unit-pang-tong": UnitPlan("strategist", (80, 126, 68), 0.09, 1.02, 1.0, 1.0),
|
||||
"unit-sima-yi": UnitPlan("strategist", (58, 62, 132), 0.16, 1.04, 0.96, 1.0),
|
||||
"unit-huang-zhong": UnitPlan("rebel-archer", (54, 124, 64), 0.28, 1.04, 1.02, 1.0),
|
||||
"unit-ma-chao": UnitPlan("white-cavalry", (54, 118, 194), 0.1, 1.04, 1.04, 1.0),
|
||||
@@ -207,18 +225,21 @@ def fit_sprite(source: Image.Image, template: Template, plan: UnitPlan) -> Image
|
||||
return source
|
||||
subject = source.crop(bbox)
|
||||
width, height = subject.size
|
||||
target_height = round(template.target_height * plan.scale)
|
||||
target_width = round(template.target_width * plan.scale)
|
||||
scale = min(target_width / width, target_height / height, 1.35)
|
||||
new_size = (max(1, round(width * scale)), max(1, round(height * scale)))
|
||||
spec = ROLE_SPECS[template.role]
|
||||
target_height = round(spec.height * plan.scale)
|
||||
proportional_width = round(width * (target_height / height))
|
||||
target_width = min(round(spec.max_width * plan.scale), max(1, proportional_width))
|
||||
new_size = (max(1, target_width), max(1, target_height))
|
||||
subject = subject.resize(new_size, Image.Resampling.LANCZOS)
|
||||
subject = subject.filter(ImageFilter.UnsharpMask(radius=0.65, percent=95, threshold=2))
|
||||
return subject
|
||||
|
||||
|
||||
def orient_sprite(sprite: Image.Image, direction: str) -> Image.Image:
|
||||
if direction == "east":
|
||||
return side_variant(sprite)
|
||||
if direction == "west":
|
||||
return ImageOps_mirror(sprite)
|
||||
return ImageOps_mirror(side_variant(sprite))
|
||||
if direction == "north":
|
||||
return back_variant(sprite)
|
||||
return sprite
|
||||
@@ -227,54 +248,68 @@ def orient_sprite(sprite: Image.Image, direction: str) -> Image.Image:
|
||||
def frame_variant(sprite: Image.Image, template: Template, stem: str, direction: str, frame_index: int) -> Image.Image:
|
||||
canvas = Image.new("RGBA", (FRAME_SIZE, FRAME_SIZE), (0, 0, 0, 0))
|
||||
seed = stable_int(f"{stem}:{direction}")
|
||||
if template.role == "cavalry":
|
||||
offsets = [(-6, 0), (0, -5), (6, 0), (0, -3)]
|
||||
else:
|
||||
offsets = [(-4, 0), (0, -4), (4, 0), (0, -2)]
|
||||
dx, dy = offsets[frame_index]
|
||||
if direction == "north":
|
||||
dx = round(dx * 0.55)
|
||||
spec = ROLE_SPECS[template.role]
|
||||
frame = idle_pose(sprite, spec, frame_index)
|
||||
dx = spec.idle_dx[frame_index]
|
||||
if direction == "west":
|
||||
dx = -dx
|
||||
if direction == "north":
|
||||
dx = round(dx * 0.5)
|
||||
dx += seed % 3 - 1
|
||||
bottom = FRAME_SIZE - (4 if template.role == "cavalry" else 3)
|
||||
left = round((FRAME_SIZE - sprite.width) / 2 + dx)
|
||||
top = round(bottom - sprite.height + dy)
|
||||
canvas.alpha_composite(sprite, (left, top))
|
||||
bottom = FRAME_SIZE - spec.bottom_padding
|
||||
left = round((FRAME_SIZE - frame.width) / 2 + dx)
|
||||
top = round(bottom - frame.height)
|
||||
canvas.alpha_composite(frame, (left, top))
|
||||
return finish_frame(canvas)
|
||||
|
||||
|
||||
def idle_pose(sprite: Image.Image, spec: RoleSpec, frame_index: int) -> Image.Image:
|
||||
sx = spec.idle_scale_x[frame_index]
|
||||
sy = spec.idle_scale_y[frame_index]
|
||||
width = max(1, round(sprite.width * sx))
|
||||
height = max(1, round(sprite.height * sy))
|
||||
return sprite.resize((width, height), Image.Resampling.LANCZOS)
|
||||
|
||||
|
||||
def draw_action_sheet(base_sheet: Image.Image, template: Template, stem: str) -> Image.Image:
|
||||
output = Image.new("RGBA", (FRAME_SIZE * len(ACTION_ORDER), FRAME_SIZE * len(DIRECTIONS)), (0, 0, 0, 0))
|
||||
frame_by_action = {"attack": 2, "strategy": 0, "item": 1, "hurt": 0}
|
||||
output = Image.new("RGBA", (FRAME_SIZE * GRID_SIZE * len(ACTION_ORDER), FRAME_SIZE * len(DIRECTIONS)), (0, 0, 0, 0))
|
||||
for row, direction in enumerate(DIRECTIONS):
|
||||
for col, action in enumerate(ACTION_ORDER):
|
||||
frame_index = frame_by_action[action]
|
||||
frame = base_sheet.crop((frame_index * FRAME_SIZE, row * FRAME_SIZE, (frame_index + 1) * FRAME_SIZE, (row + 1) * FRAME_SIZE)).convert("RGBA")
|
||||
output.alpha_composite(action_frame(frame, template, stem, direction, action), (col * FRAME_SIZE, row * FRAME_SIZE))
|
||||
for action_index, action in enumerate(ACTION_ORDER):
|
||||
for frame_index in range(GRID_SIZE):
|
||||
frame = base_sheet.crop((frame_index * FRAME_SIZE, row * FRAME_SIZE, (frame_index + 1) * FRAME_SIZE, (row + 1) * FRAME_SIZE)).convert("RGBA")
|
||||
output.alpha_composite(
|
||||
action_frame(frame, template, stem, direction, action, frame_index),
|
||||
((action_index * GRID_SIZE + frame_index) * FRAME_SIZE, row * FRAME_SIZE)
|
||||
)
|
||||
return output
|
||||
|
||||
|
||||
def action_frame(frame: Image.Image, template: Template, stem: str, direction: str, action: str) -> Image.Image:
|
||||
def action_frame(frame: Image.Image, template: Template, stem: str, direction: str, action: str, frame_index: int) -> Image.Image:
|
||||
if action == "hurt":
|
||||
return hurt_frame(frame, direction)
|
||||
return hurt_frame(frame, direction, frame_index)
|
||||
if action == "celebrate":
|
||||
return celebrate_frame(frame, direction, frame_index)
|
||||
|
||||
effect = Image.new("RGBA", frame.size, (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(effect)
|
||||
if action == "attack":
|
||||
draw_attack_effect(draw, template, direction)
|
||||
body = offset_subject(frame, *direction_offset(direction, 10 if template.role != "cavalry" else 16))
|
||||
if frame_index >= 2:
|
||||
draw_attack_effect(draw, template, direction, frame_index)
|
||||
lunge = [0, 5, 13, 7][frame_index] if template.role != "cavalry" else [0, 8, 18, 10][frame_index]
|
||||
lift = [0, -2, -4, -1][frame_index]
|
||||
dx, dy = direction_offset(direction, lunge)
|
||||
body = offset_subject(frame, dx, dy + lift)
|
||||
result = Image.alpha_composite(effect, body)
|
||||
elif action == "strategy":
|
||||
draw_strategy_effect(draw)
|
||||
result = Image.alpha_composite(effect, frame)
|
||||
draw_strategy_effect(draw, frame_index)
|
||||
result = Image.alpha_composite(effect, offset_subject(frame, 0, [0, -3, -5, -2][frame_index]))
|
||||
else:
|
||||
draw_item_effect(draw, direction)
|
||||
result = Image.alpha_composite(frame, effect)
|
||||
draw_item_effect(draw, direction, frame_index)
|
||||
result = Image.alpha_composite(offset_subject(frame, 0, [0, -2, -3, -1][frame_index]), effect)
|
||||
return finish_frame(result)
|
||||
|
||||
|
||||
def draw_attack_effect(draw: ImageDraw.ImageDraw, template: Template, direction: str) -> None:
|
||||
def draw_attack_effect(draw: ImageDraw.ImageDraw, template: Template, direction: str, frame_index: int = 2) -> None:
|
||||
warm = (239, 177, 68, 160)
|
||||
bright = (255, 237, 184, 205)
|
||||
red = (178, 52, 42, 132)
|
||||
@@ -286,13 +321,13 @@ def draw_attack_effect(draw: ImageDraw.ImageDraw, template: Template, direction:
|
||||
"south": ((143, 112), (180, 283)),
|
||||
}
|
||||
start, end = shafts[direction]
|
||||
line(draw, [start, end], bright, 7)
|
||||
line(draw, [start, end], red, 3)
|
||||
line(draw, [start, end], bright, 6 if frame_index == 2 else 4)
|
||||
line(draw, [start, end], red, 3 if frame_index == 2 else 2)
|
||||
draw.polygon(arrow_tip(end, start, 19), fill=bright, outline=(25, 17, 14, 210))
|
||||
return
|
||||
|
||||
if template.role == "strategist":
|
||||
draw_strategy_effect(draw)
|
||||
draw_strategy_effect(draw, frame_index)
|
||||
return
|
||||
|
||||
arcs = {
|
||||
@@ -302,14 +337,16 @@ def draw_attack_effect(draw: ImageDraw.ImageDraw, template: Template, direction:
|
||||
"south": ((45, 113, 269, 295), 25, 155),
|
||||
}
|
||||
box, start, end = arcs[direction]
|
||||
draw.arc(box, start=start, end=end, fill=warm, width=17)
|
||||
width = 17 if frame_index == 2 else 11
|
||||
draw.arc(box, start=start, end=end, fill=warm, width=width)
|
||||
inset = (box[0] + 15, box[1] + 15, box[2] - 15, box[3] - 15)
|
||||
draw.arc(inset, start=start + 4, end=end - 4, fill=bright, width=7)
|
||||
draw.arc(inset, start=start + 4, end=end - 4, fill=bright, width=max(4, width - 10))
|
||||
|
||||
|
||||
def draw_strategy_effect(draw: ImageDraw.ImageDraw) -> None:
|
||||
def draw_strategy_effect(draw: ImageDraw.ImageDraw, frame_index: int = 0) -> None:
|
||||
center = (156, 151)
|
||||
for radius, color, width in ((88, (39, 94, 156, 66), 4), (58, (46, 142, 174, 106), 4), (28, (236, 184, 74, 134), 5)):
|
||||
pulse = (0, 8, 16, 6)[frame_index]
|
||||
for radius, color, width in ((88 + pulse, (39, 94, 156, 66), 4), (58 + pulse // 2, (46, 142, 174, 106), 4), (28 + pulse // 3, (236, 184, 74, 134), 5)):
|
||||
draw.ellipse((center[0] - radius, center[1] - radius, center[0] + radius, center[1] + radius), outline=color, width=width)
|
||||
for angle in range(0, 360, 60):
|
||||
x = center[0] + math.cos(math.radians(angle)) * 72
|
||||
@@ -317,7 +354,7 @@ def draw_strategy_effect(draw: ImageDraw.ImageDraw) -> None:
|
||||
draw.polygon([(x, y - 7), (x + 5, y), (x, y + 7), (x - 5, y)], fill=(236, 184, 74, 126))
|
||||
|
||||
|
||||
def draw_item_effect(draw: ImageDraw.ImageDraw, direction: str) -> None:
|
||||
def draw_item_effect(draw: ImageDraw.ImageDraw, direction: str, frame_index: int = 0) -> None:
|
||||
positions = {
|
||||
"south": (184, 145),
|
||||
"east": (220, 146),
|
||||
@@ -325,14 +362,16 @@ def draw_item_effect(draw: ImageDraw.ImageDraw, direction: str) -> None:
|
||||
"west": (92, 146),
|
||||
}
|
||||
x, y = positions[direction]
|
||||
y += [0, -8, -12, -6][frame_index]
|
||||
draw.rounded_rectangle((x - 20, y - 16, x + 20, y + 20), radius=7, fill=(126, 79, 39, 235), outline=(25, 18, 14, 235), width=3)
|
||||
line(draw, [(x - 27, y + 1), (x + 27, y + 1)], (226, 178, 72, 196), 4)
|
||||
draw.ellipse((x - 11, y - 31, x + 11, y - 9), fill=(76, 178, 112, 200), outline=(24, 18, 14, 220), width=2)
|
||||
|
||||
|
||||
def hurt_frame(frame: Image.Image, direction: str) -> Image.Image:
|
||||
dx, dy = direction_offset(direction, -12)
|
||||
body = offset_subject(frame, dx, dy)
|
||||
def hurt_frame(frame: Image.Image, direction: str, frame_index: int = 0) -> Image.Image:
|
||||
knockback = [0, -10, -15, -5][frame_index]
|
||||
dx, dy = direction_offset(direction, knockback)
|
||||
body = offset_subject(frame, dx, dy + [0, -2, 2, 0][frame_index])
|
||||
body = ImageEnhance.Color(body).enhance(0.74)
|
||||
alpha = body.getchannel("A")
|
||||
red = Image.new("RGBA", body.size, (188, 42, 36, 0))
|
||||
@@ -340,13 +379,35 @@ def hurt_frame(frame: Image.Image, direction: str) -> Image.Image:
|
||||
body = Image.alpha_composite(body, red)
|
||||
effect = Image.new("RGBA", frame.size, (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(effect)
|
||||
if frame_index == 0:
|
||||
return finish_frame(body)
|
||||
cx, cy = (194, 122) if direction in ("west", "north") else (120, 122)
|
||||
cy += -4 if frame_index == 1 else 4
|
||||
spikes = [(cx, cy - 31), (cx + 9, cy - 9), (cx + 34, cy - 6), (cx + 13, cy + 8), (cx + 23, cy + 31), (cx, cy + 15), (cx - 24, cy + 30), (cx - 14, cy + 7), (cx - 34, cy - 6), (cx - 9, cy - 9)]
|
||||
draw.polygon(spikes, fill=(232, 176, 72, 190), outline=(138, 31, 31, 220))
|
||||
line(draw, [(cx - 38, cy - 34), (cx + 36, cy + 34)], (255, 231, 181, 166), 5)
|
||||
return finish_frame(Image.alpha_composite(body, effect))
|
||||
|
||||
|
||||
def celebrate_frame(frame: Image.Image, direction: str, frame_index: int = 0) -> Image.Image:
|
||||
lift = [0, -8, -3, -11][frame_index]
|
||||
sway = [0, -2, 2, 0][frame_index]
|
||||
if direction == "west":
|
||||
sway = -sway
|
||||
body = offset_subject(frame, sway, lift)
|
||||
effect = Image.new("RGBA", frame.size, (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(effect)
|
||||
cx = 156 + sway
|
||||
cy = 92 + lift
|
||||
if frame_index in (1, 3):
|
||||
draw.ellipse((cx - 42, cy - 26, cx + 42, cy + 58), outline=(255, 220, 114, 118), width=5)
|
||||
for angle in range(20, 360, 72):
|
||||
x = cx + math.cos(math.radians(angle)) * 54
|
||||
y = cy + math.sin(math.radians(angle)) * 40
|
||||
draw.polygon([(x, y - 8), (x + 5, y), (x, y + 8), (x - 5, y)], fill=(255, 226, 132, 148))
|
||||
return finish_frame(Image.alpha_composite(body, effect))
|
||||
|
||||
|
||||
def unit_plan(stem: str) -> UnitPlan:
|
||||
if stem in SIGNATURE_PLANS:
|
||||
return SIGNATURE_PLANS[stem]
|
||||
@@ -369,8 +430,7 @@ def unit_plan(stem: str) -> UnitPlan:
|
||||
template_key = template_for(faction, role, stem)
|
||||
saturation = 1.03 if "veteran" in stem or "elite" in stem or "warlord" in stem else 1.0
|
||||
brightness = 1.03 if "white" in stem else 1.0
|
||||
scale = 1.02 if "guard" in stem or "elite" in stem or "warlord" in stem else 1.0
|
||||
return UnitPlan(template_key, tint, strength, saturation, brightness, scale)
|
||||
return UnitPlan(template_key, tint, strength, saturation, brightness, 1.0)
|
||||
|
||||
|
||||
def template_for(faction: str, role: str, stem: str) -> str:
|
||||
@@ -465,12 +525,20 @@ def tint_sprite(image: Image.Image, plan: UnitPlan) -> Image.Image:
|
||||
|
||||
def back_variant(sprite: Image.Image) -> Image.Image:
|
||||
result = sprite.copy()
|
||||
result = result.resize((max(1, round(result.width * 0.96)), result.height), Image.Resampling.LANCZOS)
|
||||
overlay = Image.new("RGBA", result.size, (18, 20, 26, 0))
|
||||
overlay.putalpha(result.getchannel("A").point(lambda value: min(48, value // 6)))
|
||||
result = Image.alpha_composite(result, overlay)
|
||||
return result
|
||||
|
||||
|
||||
def side_variant(sprite: Image.Image) -> Image.Image:
|
||||
result = sprite.resize((max(1, round(sprite.width * 0.9)), sprite.height), Image.Resampling.LANCZOS)
|
||||
overlay = Image.new("RGBA", result.size, (16, 16, 22, 0))
|
||||
overlay.putalpha(result.getchannel("A").point(lambda value: min(18, value // 18)))
|
||||
return Image.alpha_composite(result, overlay)
|
||||
|
||||
|
||||
def finish_frame(frame: Image.Image) -> Image.Image:
|
||||
frame = clean_alpha(frame)
|
||||
alpha = frame.getchannel("A")
|
||||
|
||||
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 942 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 336 KiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 820 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 286 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 948 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 907 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 319 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 953 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 334 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 400 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 993 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 281 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 442 KiB |
|
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 441 KiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 820 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 286 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 405 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 818 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 285 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 879 KiB |
|
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 879 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 878 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 462 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 462 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 255 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 383 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 383 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 383 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 383 KiB |
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 888 KiB |
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 888 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 888 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 436 KiB |
|
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 438 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 436 KiB |
|
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 945 KiB |
|
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 945 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 231 KiB After Width: | Height: | Size: 946 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 946 KiB |
|
Before Width: | Height: | Size: 231 KiB After Width: | Height: | Size: 946 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 944 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 332 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 820 KiB |