mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-08-07 02:32:32 -04:00
fix: fall back to pixel parsing when zone Units=Percent but coords exceed 100
When zones have Units='Percent' in the database but their Coords contain pixel values (>100), ParsePercentagePolygon treats them as percentages, causing wild scaling (e.g., 639% * 1920 / 100 = 12269) followed by clamping to monitor bounds, producing degenerate full-frame zones. Add a pre-check in Zone::Load that scans coordinate values before calling ParsePercentagePolygon. If any value exceeds 100, log a warning and use ParsePolygonString (pixel path) instead. Also add unit tests for both ParsePolygonString and ParsePercentagePolygon. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
d4c91b80ed
commit
47edcca6ab
3 files changed
+162
-3
No files matched your search
+38
-2
@@ -994,8 +994,44 @@ std::vector<Zone> Zone::Load(const std::shared_ptr<Monitor> &monitor) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Percentage-based coordinates (default): convert to pixels using monitor dimensions
|
||||
if (!ParsePercentagePolygon(Coords, monitor->Width(), monitor->Height(), polygon)) {
|
||||
// Percentage-based coordinates (default): convert to pixels using monitor dimensions.
|
||||
// However, if any coordinate value exceeds 100, these are actually pixel values
|
||||
// stored with incorrect Units — fall back to pixel parsing with a warning.
|
||||
bool has_pixel_values = false;
|
||||
{
|
||||
const char *s = Coords;
|
||||
while (*s != '\0') {
|
||||
double val = strtod(s, nullptr);
|
||||
if (val > 100.0) {
|
||||
has_pixel_values = true;
|
||||
break;
|
||||
}
|
||||
// Skip to next number: find comma then space (x,y pairs separated by spaces)
|
||||
const char *comma = strchr(s, ',');
|
||||
if (!comma) break;
|
||||
val = strtod(comma + 1, nullptr);
|
||||
if (val > 100.0) {
|
||||
has_pixel_values = true;
|
||||
break;
|
||||
}
|
||||
const char *space = strchr(comma + 1, ' ');
|
||||
if (space) {
|
||||
s = space + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_pixel_values) {
|
||||
Warning("Zone %d/%s has Units=Percent but Coords contain pixel values (>100), "
|
||||
"parsing as pixels instead", Id, Name);
|
||||
if (!ParsePolygonString(Coords, polygon)) {
|
||||
Error("Unable to parse polygon string '%s' for zone %d/%s for monitor %s, ignoring",
|
||||
Coords, Id, Name, monitor->Name());
|
||||
continue;
|
||||
}
|
||||
} else if (!ParsePercentagePolygon(Coords, monitor->Width(), monitor->Height(), polygon)) {
|
||||
Error("Unable to parse polygon string '%s' for zone %d/%s for monitor %s, ignoring",
|
||||
Coords, Id, Name, monitor->Name());
|
||||
continue;
|
||||
|
||||
Reference in new issue
Block a user