valetudo-map-parser 0.1.9b50__py3-none-any.whl → 0.1.9b52__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- valetudo_map_parser/__init__.py +2 -0
- valetudo_map_parser/config/color_utils.py +69 -13
- valetudo_map_parser/config/colors.py +55 -70
- valetudo_map_parser/config/drawable_elements.py +0 -676
- valetudo_map_parser/config/enhanced_drawable.py +75 -193
- valetudo_map_parser/config/shared.py +0 -1
- valetudo_map_parser/config/types.py +19 -33
- valetudo_map_parser/config/utils.py +0 -67
- valetudo_map_parser/hypfer_draw.py +222 -57
- valetudo_map_parser/hypfer_handler.py +48 -155
- valetudo_map_parser/hypfer_rooms_handler.py +406 -0
- valetudo_map_parser/map_data.py +0 -30
- valetudo_map_parser/rand25_handler.py +2 -84
- {valetudo_map_parser-0.1.9b50.dist-info → valetudo_map_parser-0.1.9b52.dist-info}/METADATA +1 -1
- valetudo_map_parser-0.1.9b52.dist-info/RECORD +26 -0
- valetudo_map_parser-0.1.9b50.dist-info/RECORD +0 -25
- {valetudo_map_parser-0.1.9b50.dist-info → valetudo_map_parser-0.1.9b52.dist-info}/LICENSE +0 -0
- {valetudo_map_parser-0.1.9b50.dist-info → valetudo_map_parser-0.1.9b52.dist-info}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.9b50.dist-info → valetudo_map_parser-0.1.9b52.dist-info}/WHEEL +0 -0
valetudo_map_parser/__init__.py
CHANGED
@@ -15,11 +15,13 @@ from .config.types import (
|
|
15
15
|
TrimCropData,
|
16
16
|
UserLanguageStore,
|
17
17
|
)
|
18
|
+
from .hypfer_rooms_handler import HypferRoomsHandler
|
18
19
|
from .hypfer_handler import HypferMapImageHandler
|
19
20
|
from .rand25_handler import ReImageHandler
|
20
21
|
|
21
22
|
|
22
23
|
__all__ = [
|
24
|
+
"HypferRoomsHandler",
|
23
25
|
"HypferMapImageHandler",
|
24
26
|
"ReImageHandler",
|
25
27
|
"RRMapParser",
|
@@ -18,26 +18,82 @@ def get_blended_color(
|
|
18
18
|
Get a blended color for a pixel based on the current element map and the new element to draw.
|
19
19
|
|
20
20
|
This function:
|
21
|
-
1. Gets the
|
22
|
-
2.
|
23
|
-
3.
|
21
|
+
1. Gets the background colors at the start and end points (with offset to avoid sampling already drawn pixels)
|
22
|
+
2. Directly blends the foreground color with the background using straight alpha
|
23
|
+
3. Returns the average of the two blended colors
|
24
24
|
|
25
25
|
Returns:
|
26
26
|
Blended RGBA color to use for drawing
|
27
27
|
"""
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
# Extract foreground color components
|
29
|
+
fg_r, fg_g, fg_b, fg_a = color
|
30
|
+
fg_alpha = fg_a / 255.0 # Convert to 0-1 range
|
31
|
+
|
32
|
+
# Fast path for fully opaque or transparent foreground
|
33
|
+
if fg_a == 255:
|
34
|
+
return color
|
35
|
+
if fg_a == 0:
|
36
|
+
# Sample background at midpoint
|
37
|
+
mid_x, mid_y = (x0 + x1) // 2, (y0 + y1) // 2
|
38
|
+
if 0 <= mid_y < arr.shape[0] and 0 <= mid_x < arr.shape[1]:
|
39
|
+
return tuple(arr[mid_y, mid_x])
|
40
|
+
return (0, 0, 0, 0) # Default if out of bounds
|
41
|
+
|
42
|
+
# Calculate direction vector for offset sampling
|
43
|
+
dx = x1 - x0
|
44
|
+
dy = y1 - y0
|
45
|
+
length = max(1, (dx**2 + dy**2) ** 0.5) # Avoid division by zero
|
46
|
+
offset = 5 # 5-pixel offset to avoid sampling already drawn pixels
|
47
|
+
|
48
|
+
# Calculate offset coordinates for start point (move away from the line)
|
49
|
+
offset_x0 = int(x0 - (offset * dx / length))
|
50
|
+
offset_y0 = int(y0 - (offset * dy / length))
|
51
|
+
|
52
|
+
# Calculate offset coordinates for end point (move away from the line)
|
53
|
+
offset_x1 = int(x1 + (offset * dx / length))
|
54
|
+
offset_y1 = int(y1 + (offset * dy / length))
|
55
|
+
|
56
|
+
# Sample background at offset start point
|
57
|
+
if 0 <= offset_y0 < arr.shape[0] and 0 <= offset_x0 < arr.shape[1]:
|
58
|
+
bg_color_start = arr[offset_y0, offset_x0]
|
59
|
+
# Direct straight alpha blending
|
60
|
+
start_r = int(fg_r * fg_alpha + bg_color_start[0] * (1 - fg_alpha))
|
61
|
+
start_g = int(fg_g * fg_alpha + bg_color_start[1] * (1 - fg_alpha))
|
62
|
+
start_b = int(fg_b * fg_alpha + bg_color_start[2] * (1 - fg_alpha))
|
63
|
+
start_a = int(fg_a + bg_color_start[3] * (1 - fg_alpha))
|
64
|
+
start_blended_color = (start_r, start_g, start_b, start_a)
|
34
65
|
else:
|
35
|
-
|
66
|
+
# If offset point is out of bounds, try original point
|
67
|
+
if 0 <= y0 < arr.shape[0] and 0 <= x0 < arr.shape[1]:
|
68
|
+
bg_color_start = arr[y0, x0]
|
69
|
+
start_r = int(fg_r * fg_alpha + bg_color_start[0] * (1 - fg_alpha))
|
70
|
+
start_g = int(fg_g * fg_alpha + bg_color_start[1] * (1 - fg_alpha))
|
71
|
+
start_b = int(fg_b * fg_alpha + bg_color_start[2] * (1 - fg_alpha))
|
72
|
+
start_a = int(fg_a + bg_color_start[3] * (1 - fg_alpha))
|
73
|
+
start_blended_color = (start_r, start_g, start_b, start_a)
|
74
|
+
else:
|
75
|
+
start_blended_color = color
|
36
76
|
|
37
|
-
|
38
|
-
|
77
|
+
# Sample background at offset end point
|
78
|
+
if 0 <= offset_y1 < arr.shape[0] and 0 <= offset_x1 < arr.shape[1]:
|
79
|
+
bg_color_end = arr[offset_y1, offset_x1]
|
80
|
+
# Direct straight alpha blending
|
81
|
+
end_r = int(fg_r * fg_alpha + bg_color_end[0] * (1 - fg_alpha))
|
82
|
+
end_g = int(fg_g * fg_alpha + bg_color_end[1] * (1 - fg_alpha))
|
83
|
+
end_b = int(fg_b * fg_alpha + bg_color_end[2] * (1 - fg_alpha))
|
84
|
+
end_a = int(fg_a + bg_color_end[3] * (1 - fg_alpha))
|
85
|
+
end_blended_color = (end_r, end_g, end_b, end_a)
|
39
86
|
else:
|
40
|
-
|
87
|
+
# If offset point is out of bounds, try original point
|
88
|
+
if 0 <= y1 < arr.shape[0] and 0 <= x1 < arr.shape[1]:
|
89
|
+
bg_color_end = arr[y1, x1]
|
90
|
+
end_r = int(fg_r * fg_alpha + bg_color_end[0] * (1 - fg_alpha))
|
91
|
+
end_g = int(fg_g * fg_alpha + bg_color_end[1] * (1 - fg_alpha))
|
92
|
+
end_b = int(fg_b * fg_alpha + bg_color_end[2] * (1 - fg_alpha))
|
93
|
+
end_a = int(fg_a + bg_color_end[3] * (1 - fg_alpha))
|
94
|
+
end_blended_color = (end_r, end_g, end_b, end_a)
|
95
|
+
else:
|
96
|
+
end_blended_color = color
|
41
97
|
|
42
98
|
# Use the average of the two blended colors
|
43
99
|
blended_color = (
|
@@ -407,61 +407,56 @@ class ColorsManagement:
|
|
407
407
|
def blend_colors(background: Color, foreground: Color) -> Color:
|
408
408
|
"""
|
409
409
|
Blend foreground color with background color based on alpha values.
|
410
|
-
|
411
|
-
This is used when drawing elements that overlap on the map.
|
412
|
-
The alpha channel determines how much of the foreground color is visible.
|
413
|
-
Uses optimized calculations for better performance.
|
410
|
+
Optimized version with more fast paths and simplified calculations.
|
414
411
|
|
415
412
|
:param background: Background RGBA color (r,g,b,a)
|
416
413
|
:param foreground: Foreground RGBA color (r,g,b,a) to blend on top
|
417
414
|
:return: Blended RGBA color
|
418
415
|
"""
|
419
|
-
#
|
420
|
-
|
421
|
-
fg_r, fg_g, fg_b, fg_a = foreground
|
416
|
+
# Fast paths for common cases
|
417
|
+
fg_a = foreground[3]
|
422
418
|
|
423
|
-
|
424
|
-
if fg_a == 255:
|
419
|
+
if fg_a == 255: # Fully opaque foreground
|
425
420
|
return foreground
|
426
|
-
if fg_a == 0:
|
427
|
-
return background
|
428
421
|
|
429
|
-
#
|
430
|
-
|
431
|
-
fg_alpha = fg_a / 255.0
|
432
|
-
bg_alpha = bg_a / 255.0
|
422
|
+
if fg_a == 0: # Fully transparent foreground
|
423
|
+
return background
|
433
424
|
|
434
|
-
|
435
|
-
|
425
|
+
bg_a = background[3]
|
426
|
+
if bg_a == 0: # Fully transparent background
|
427
|
+
return foreground
|
436
428
|
|
437
|
-
#
|
438
|
-
|
439
|
-
|
429
|
+
# Extract components (only after fast paths)
|
430
|
+
bg_r, bg_g, bg_b = background[:3]
|
431
|
+
fg_r, fg_g, fg_b = foreground[:3]
|
440
432
|
|
441
|
-
#
|
442
|
-
|
443
|
-
|
444
|
-
inv_alpha_ratio = 1.0 - alpha_ratio
|
433
|
+
# Pre-calculate the blend factor once (avoid repeated division)
|
434
|
+
blend = fg_a / 255.0
|
435
|
+
inv_blend = 1.0 - blend
|
445
436
|
|
446
|
-
|
447
|
-
|
448
|
-
|
437
|
+
# Simple linear interpolation for RGB channels
|
438
|
+
# This is faster than the previous implementation
|
439
|
+
out_r = int(fg_r * blend + bg_r * inv_blend)
|
440
|
+
out_g = int(fg_g * blend + bg_g * inv_blend)
|
441
|
+
out_b = int(fg_b * blend + bg_b * inv_blend)
|
449
442
|
|
450
|
-
#
|
451
|
-
out_a = int(
|
443
|
+
# Alpha blending - simplified calculation
|
444
|
+
out_a = int(fg_a + bg_a * inv_blend)
|
452
445
|
|
453
|
-
#
|
454
|
-
|
455
|
-
out_g = max(0, min(255, out_g))
|
456
|
-
out_b = max(0, min(255, out_b))
|
446
|
+
# No need for min/max checks as the blend math keeps values in range
|
447
|
+
# when input values are valid (0-255)
|
457
448
|
|
458
449
|
return [out_r, out_g, out_b, out_a]
|
459
450
|
|
451
|
+
# Cache for recently sampled background colors
|
452
|
+
_bg_color_cache = {}
|
453
|
+
_cache_size = 1024 # Limit cache size to avoid memory issues
|
454
|
+
|
460
455
|
@staticmethod
|
461
456
|
def sample_and_blend_color(array, x: int, y: int, foreground: Color) -> Color:
|
462
457
|
"""
|
463
458
|
Sample the background color from the array at coordinates (x,y) and blend with foreground color.
|
464
|
-
|
459
|
+
Optimized version with caching and faster sampling.
|
465
460
|
|
466
461
|
Args:
|
467
462
|
array: The RGBA numpy array representing the image
|
@@ -472,53 +467,43 @@ class ColorsManagement:
|
|
472
467
|
Returns:
|
473
468
|
Blended RGBA color
|
474
469
|
"""
|
475
|
-
#
|
470
|
+
# Fast path for fully opaque foreground - no need to sample or blend
|
471
|
+
if foreground[3] == 255:
|
472
|
+
return foreground
|
473
|
+
|
474
|
+
# Ensure array exists
|
476
475
|
if array is None:
|
477
476
|
return foreground
|
478
477
|
|
478
|
+
# Check if coordinates are within bounds
|
479
479
|
height, width = array.shape[:2]
|
480
480
|
if not (0 <= y < height and 0 <= x < width):
|
481
|
-
return foreground # Return foreground if coordinates are out of bounds
|
482
|
-
|
483
|
-
# Fast path for fully opaque foreground
|
484
|
-
if foreground[3] == 255:
|
485
481
|
return foreground
|
486
482
|
|
487
|
-
#
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
coordinates = np.array([[y, x]])
|
496
|
-
|
497
|
-
# Sample each channel separately with nearest neighbor interpolation
|
498
|
-
# This is faster than sampling all channels at once for large arrays
|
499
|
-
r = ndimage.map_coordinates(
|
500
|
-
array[..., 0], coordinates.T, order=0, mode="nearest"
|
501
|
-
)[0]
|
502
|
-
g = ndimage.map_coordinates(
|
503
|
-
array[..., 1], coordinates.T, order=0, mode="nearest"
|
504
|
-
)[0]
|
505
|
-
b = ndimage.map_coordinates(
|
506
|
-
array[..., 2], coordinates.T, order=0, mode="nearest"
|
507
|
-
)[0]
|
508
|
-
a = ndimage.map_coordinates(
|
509
|
-
array[..., 3], coordinates.T, order=0, mode="nearest"
|
510
|
-
)[0]
|
511
|
-
background = (int(r), int(g), int(b), int(a))
|
512
|
-
else:
|
513
|
-
# For smaller arrays, direct indexing is faster
|
514
|
-
background = tuple(array[y, x])
|
515
|
-
except (IndexError, ValueError):
|
516
|
-
# Fallback to direct indexing if ndimage fails
|
483
|
+
# Check cache for this coordinate
|
484
|
+
cache_key = (id(array), x, y)
|
485
|
+
cache = ColorsManagement._bg_color_cache
|
486
|
+
|
487
|
+
if cache_key in cache:
|
488
|
+
background = cache[cache_key]
|
489
|
+
else:
|
490
|
+
# Sample the background color using direct indexing (fastest method)
|
517
491
|
try:
|
518
|
-
background = tuple(array[y, x])
|
492
|
+
background = tuple(map(int, array[y, x]))
|
493
|
+
|
494
|
+
# Update cache (with simple LRU-like behavior)
|
495
|
+
if len(cache) >= ColorsManagement._cache_size:
|
496
|
+
# Remove a random entry if cache is full
|
497
|
+
cache.pop(next(iter(cache)))
|
498
|
+
cache[cache_key] = background
|
499
|
+
|
519
500
|
except (IndexError, ValueError):
|
520
501
|
return foreground
|
521
502
|
|
503
|
+
# Fast path for fully transparent foreground
|
504
|
+
if foreground[3] == 0:
|
505
|
+
return background
|
506
|
+
|
522
507
|
# Blend the colors
|
523
508
|
return ColorsManagement.blend_colors(background, foreground)
|
524
509
|
|