32k pixel as hard group limit, better manual resolution support
This commit is contained in:
1 parent
a9c0703f03
commit
5009831c7c
9 files changed
+322
-58
No files matched your search
@@ -27,7 +27,7 @@ from copienator.commands import annotating, annotating_with_checks
|
||||
from copienator.filesystem import staged_directory
|
||||
from copienator.utils import natural_key
|
||||
|
||||
MAX_HEIGHT_PX = 25000
|
||||
MAX_HEIGHT_PX = 32000
|
||||
|
||||
|
||||
def render_item(item):
|
||||
@@ -63,6 +63,11 @@ def save_batch(batch, prefix, group_id, output_root: Path) -> None:
|
||||
print(f"Generating group PDF: {prefix} G{group_id} ({len(batch)} elements)")
|
||||
max_width = max(item[2].width for item in batch)
|
||||
total_height = sum(item[2].height for item in batch)
|
||||
if total_height > MAX_HEIGHT_PX:
|
||||
raise CliError(
|
||||
f"{prefix} G{group_id} would be {total_height} px high; "
|
||||
f"the maximum is {MAX_HEIGHT_PX} px."
|
||||
)
|
||||
concatenated = Image.new("RGB", (max_width, total_height), "white")
|
||||
draw = ImageDraw.Draw(concatenated)
|
||||
checkbox_map: list[dict[str, Any]] = []
|
||||
@@ -268,32 +273,44 @@ def _existing_group_state(
|
||||
|
||||
|
||||
def split_batches(rendered):
|
||||
def split(maximum_height: float):
|
||||
batches = []
|
||||
current = []
|
||||
current_height = 0
|
||||
previous_student = None
|
||||
for item in rendered:
|
||||
student_id = item[0]
|
||||
image_height = item[2].height
|
||||
if (
|
||||
current
|
||||
and current_height + image_height > maximum_height
|
||||
and student_id != previous_student
|
||||
):
|
||||
batches.append(current)
|
||||
current = []
|
||||
current_height = 0
|
||||
current.append(item)
|
||||
current_height += image_height
|
||||
previous_student = student_id
|
||||
batches = []
|
||||
current = []
|
||||
current_height = 0
|
||||
|
||||
def flush() -> None:
|
||||
nonlocal current, current_height
|
||||
if current:
|
||||
batches.append(current)
|
||||
return batches
|
||||
current = []
|
||||
current_height = 0
|
||||
|
||||
strict = split(MAX_HEIGHT_PX)
|
||||
relaxed = split(1.1 * MAX_HEIGHT_PX)
|
||||
return relaxed if len(relaxed) < len(strict) else strict
|
||||
index = 0
|
||||
while index < len(rendered):
|
||||
student_id = rendered[index][0]
|
||||
end = index + 1
|
||||
while end < len(rendered) and rendered[end][0] == student_id:
|
||||
end += 1
|
||||
student_items = rendered[index:end]
|
||||
student_height = sum(item[2].height for item in student_items)
|
||||
|
||||
if student_height > MAX_HEIGHT_PX:
|
||||
labels = ", ".join(item[1] for item in student_items)
|
||||
raise CliError(
|
||||
f"Copie{student_id} ({labels}) is {student_height} px high; "
|
||||
f"one student's labels cannot be split across groups and the "
|
||||
f"maximum group height is {MAX_HEIGHT_PX} px."
|
||||
)
|
||||
|
||||
# Consider the student's complete block before adding its first image.
|
||||
# Otherwise later images from that same student could overflow the batch.
|
||||
if current and current_height + student_height > MAX_HEIGHT_PX:
|
||||
flush()
|
||||
current.extend(student_items)
|
||||
current_height += student_height
|
||||
index = end
|
||||
|
||||
flush()
|
||||
return batches
|
||||
|
||||
|
||||
def _generate_groups(
|
||||
|
||||
Reference in new issue
Block a user