Initial support for _F output file
parent
95e944f983
commit
d7a8e03d2c
|
|
@ -2,6 +2,7 @@ import argparse
|
||||||
import math
|
import math
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
@ -96,6 +97,13 @@ def process_images(base_dir):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error processing image for '{student_name}': {e}")
|
print(f"Error processing image for '{student_name}': {e}")
|
||||||
|
|
||||||
|
for pdf_path in sorted(search_path.glob("*/*.pdf")):
|
||||||
|
student_name = pdf_path.stem # Filename without extension
|
||||||
|
save_path = OUTPUT_DIR / f"{student_name}.pdf"
|
||||||
|
|
||||||
|
shutil.copy(str(pdf_path), str(save_path))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description="Stamp scores on exam copies.")
|
parser = argparse.ArgumentParser(description="Stamp scores on exam copies.")
|
||||||
parser.add_argument("dir", type=Path, help="Root directory containing 'A Rendre' folder")
|
parser.add_argument("dir", type=Path, help="Root directory containing 'A Rendre' folder")
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,20 @@ import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
def compile_to_pdf(text, output_pdf_path):
|
def compile_to_pdf(text, output_pdf_path): # 21 cm + 3.8 (dimension de la marge de gauche)
|
||||||
"""Wraps text in a standalone template and compiles it to PDF."""
|
"""Wraps text in a standalone template and compiles it to PDF."""
|
||||||
latex_template = f"""\\documentclass[varwidth=21cm,margin=0.2cm]{{standalone}}
|
latex_template = f"""\\documentclass[varwidth=24.8cm,margin=0.4cm]{{standalone}}
|
||||||
\\usepackage[utf8]{{inputenc}}
|
\\usepackage[utf8]{{inputenc}}
|
||||||
\\usepackage[T1]{{fontenc}}
|
\\usepackage[T1]{{fontenc}}
|
||||||
\\usepackage{{lmodern}}
|
\\usepackage{{lmodern}}
|
||||||
\\usepackage{{amsmath, amssymb}}
|
\\usepackage{{amsmath, amssymb}}
|
||||||
\\usepackage{{commands}}
|
\\usepackage{{commands}}
|
||||||
|
\\usepackage{{graphicx}}
|
||||||
\\usepackage{{enumitem}}
|
\\usepackage{{enumitem}}
|
||||||
\\begin{{document}}
|
\\begin{{document}}
|
||||||
|
\\begin{{minipage}}{{24.8cm}}
|
||||||
{text}
|
{text}
|
||||||
|
\\end{{minipage}}
|
||||||
\\end{{document}}
|
\\end{{document}}
|
||||||
"""
|
"""
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
|
|
||||||
|
|
@ -73,13 +73,13 @@ def main():
|
||||||
dest_path = os.path.join(target_subdir, dest_folder_name)
|
dest_path = os.path.join(target_subdir, dest_folder_name)
|
||||||
os.makedirs(dest_path, exist_ok=True)
|
os.makedirs(dest_path, exist_ok=True)
|
||||||
|
|
||||||
links = [("Concat.jpg", f"{safe_name}.jpg"), ("score.json", "score.json")]
|
links = [("Concat.jpg", f"{safe_name}.jpg"),("Concat_F.pdf", f"{safe_name}.pdf"), ("score.json", "score.json")]
|
||||||
for src_name, dst_name in links:
|
for src_name, dst_name in links:
|
||||||
src_file = os.path.join(source_folder, src_name)
|
src_file = os.path.join(source_folder, src_name)
|
||||||
dst_link = os.path.join(dest_path, dst_name)
|
dst_link = os.path.join(dest_path, dst_name)
|
||||||
try:
|
try:
|
||||||
if os.path.lexists(dst_link): os.remove(dst_link)
|
if os.path.lexists(dst_link): os.remove(dst_link)
|
||||||
os.symlink(src_file, dst_link)
|
if os.path.exists(src_file): os.symlink(src_file, dst_link)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error linking {src_name} for {dest_folder_name}: {e}")
|
print(f"Error linking {src_name} for {dest_folder_name}: {e}")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import json
|
||||||
import collections
|
import collections
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PIL import Image
|
from PIL import Image, ImageDraw
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import annotating
|
import annotating
|
||||||
|
|
@ -12,6 +12,79 @@ import annotating
|
||||||
from utils import natural_key
|
from utils import natural_key
|
||||||
from reading_annotations import detect_checks_and_notes, has_significant_notes
|
from reading_annotations import detect_checks_and_notes, has_significant_notes
|
||||||
|
|
||||||
|
def get_extra_pdfs_as_images(root_dir, label, annotating_module):
|
||||||
|
"""Fetches Text and Sol pdfs for a given label and converts them to images."""
|
||||||
|
extra_images = []
|
||||||
|
for folder in ["Text", "Sol"]:
|
||||||
|
pdf_path = os.path.join(root_dir, folder, f"{label}.pdf")
|
||||||
|
if os.path.exists(pdf_path):
|
||||||
|
img, _, _ = annotating_module.make_base_image(pdf_path)
|
||||||
|
if img:
|
||||||
|
extra_images.append(img)
|
||||||
|
return extra_images
|
||||||
|
|
||||||
|
def save_paginated_pdf(image_groups, output_path):
|
||||||
|
"""Concatenates groups of images vertically, adding specific inner borders."""
|
||||||
|
if not image_groups:
|
||||||
|
return
|
||||||
|
|
||||||
|
max_w = max(img.width for group in image_groups for img in group)
|
||||||
|
max_page_h = int(max_w * 1.414 * 1.3)
|
||||||
|
|
||||||
|
# Calculate 0.2 cm in pixels at 100 DPI (0.2 / 2.54 inches * 100)
|
||||||
|
border_px = int((0.2 / 2.54) * 100)
|
||||||
|
|
||||||
|
pages = []
|
||||||
|
current_page_imgs = []
|
||||||
|
current_h = 0
|
||||||
|
|
||||||
|
for group in image_groups:
|
||||||
|
if not group:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Process the group to add borders
|
||||||
|
processed_group = []
|
||||||
|
for i, img in enumerate(group):
|
||||||
|
if i in (0, 1):
|
||||||
|
img = img.copy() # Do not modify the original image object in memory
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
color = "black" if i == 0 else "blue"
|
||||||
|
|
||||||
|
# Draw the border inside the image edges
|
||||||
|
draw.rectangle(
|
||||||
|
[0, 0, img.width - 1, img.height - 1],
|
||||||
|
outline=color,
|
||||||
|
width=border_px
|
||||||
|
)
|
||||||
|
processed_group.append(img)
|
||||||
|
|
||||||
|
group_h = sum(img.height for img in processed_group)
|
||||||
|
|
||||||
|
if current_page_imgs and (current_h + group_h > max_page_h):
|
||||||
|
page = Image.new("RGB", (max_w, current_h), "white")
|
||||||
|
y = 0
|
||||||
|
for c_img in current_page_imgs:
|
||||||
|
page.paste(c_img, (0, y))
|
||||||
|
y += c_img.height
|
||||||
|
pages.append(page)
|
||||||
|
|
||||||
|
current_page_imgs = processed_group
|
||||||
|
current_h = group_h
|
||||||
|
else:
|
||||||
|
current_page_imgs.extend(processed_group)
|
||||||
|
current_h += group_h
|
||||||
|
|
||||||
|
if current_page_imgs:
|
||||||
|
page = Image.new("RGB", (max_w, current_h), "white")
|
||||||
|
y = 0
|
||||||
|
for c_img in current_page_imgs:
|
||||||
|
page.paste(c_img, (0, y))
|
||||||
|
y += c_img.height
|
||||||
|
pages.append(page)
|
||||||
|
|
||||||
|
if pages:
|
||||||
|
pages[0].save(output_path, "PDF", resolution=100.0, save_all=True, append_images=pages[1:])
|
||||||
|
|
||||||
def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, label_notes, all_labels):
|
def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, label_notes, all_labels):
|
||||||
"""
|
"""
|
||||||
Modifies data based on actions, pastes label-specific note crops,
|
Modifies data based on actions, pastes label-specific note crops,
|
||||||
|
|
@ -136,8 +209,11 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
||||||
else:
|
else:
|
||||||
if len(result.get('feedback', [])) != 0:
|
if len(result.get('feedback', [])) != 0:
|
||||||
perfect_no_comment = False
|
perfect_no_comment = False
|
||||||
|
|
||||||
if not perfect_no_comment:
|
if not perfect_no_comment:
|
||||||
concat_list_F.append(final_img)
|
extras = get_extra_pdfs_as_images(root_dir, label, annotating)
|
||||||
|
extras.append(final_img)
|
||||||
|
concat_list_F.append(extras)
|
||||||
|
|
||||||
# --- 3. Save Final Outputs ---
|
# --- 3. Save Final Outputs ---
|
||||||
with open(score_path, "w") as f:
|
with open(score_path, "w") as f:
|
||||||
|
|
@ -158,17 +234,21 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
||||||
logs.append(f" Saved regenerated Concat.jpg")
|
logs.append(f" Saved regenerated Concat.jpg")
|
||||||
|
|
||||||
if concat_list_F:
|
if concat_list_F:
|
||||||
max_w = max(i.width for i in concat_list_F)
|
pdf_out_path = os.path.join(output_dir, "Concat_F.pdf")
|
||||||
total_h = sum(i.height for i in concat_list_F)
|
save_paginated_pdf(concat_list_F, pdf_out_path)
|
||||||
full_img = Image.new("RGB", (max_w, total_h), "white")
|
logs.append(f" Saved regenerated Concat_F.pdf")
|
||||||
|
|
||||||
y = 0
|
# max_w = max(i.width for i in concat_list_F)
|
||||||
for img in concat_list_F:
|
# total_h = sum(i.height for i in concat_list_F)
|
||||||
full_img.paste(img, (0, y))
|
# full_img = Image.new("RGB", (max_w, total_h), "white")
|
||||||
y += img.height
|
|
||||||
|
|
||||||
full_img.save(os.path.join(output_dir, "Concat_F.jpg"))
|
# y = 0
|
||||||
logs.append(f" Saved regenerated Concat_F.jpg")
|
# for img in concat_list_F:
|
||||||
|
# full_img.paste(img, (0, y))
|
||||||
|
# y += img.height
|
||||||
|
|
||||||
|
# full_img.save(os.path.join(output_dir, "Concat_F.jpg"))
|
||||||
|
# logs.append(f" Saved regenerated Concat_F.jpg")
|
||||||
|
|
||||||
return "\n".join(logs)
|
return "\n".join(logs)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue