Report-Generator / resize.py
Jaimodiji's picture
Upload folder using huggingface_hub
c001f24
import fitz # PyMuPDF
import sys
def expand_pdf_for_notes(input_pdf, output_pdf, bg_color=(1, 1, 1), mode='notes_only', stitch_direction='horizontal', add_space=True, pattern=None, pattern_color=(0.8, 0.8, 0.8)):
"""
Expand or rearrange a PDF for note-taking.
Args:
input_pdf (str): Path to input PDF file.
output_pdf (str): Path to output PDF file.
bg_color (tuple): RGB color for the notes area background.
mode (str): The processing mode: 'notes_only', 'split', or 'stitch'.
stitch_direction (str): For 'stitch' mode, how to rearrange columns ('horizontal' or 'vertical').
add_space (bool): If True, add space for notes.
pattern (str): Name of the pattern to draw ('grid', 'dots').
pattern_color (tuple): RGB color for the pattern.
"""
doc = fitz.open(input_pdf)
new_doc = fitz.open()
for page_num in range(len(doc)):
page = doc[page_num]
orig_rect = page.rect
orig_width = orig_rect.width
orig_height = orig_rect.height
left_half_clip = fitz.Rect(0, 0, orig_width / 2, orig_height)
right_half_clip = fitz.Rect(orig_width / 2, 0, orig_width, orig_height)
if mode == 'split':
# Create a new page for the left half
new_page_width = orig_width / 2 if not add_space else orig_width
left_page = new_doc.new_page(width=new_page_width, height=orig_height)
left_page.show_pdf_page(fitz.Rect(0, 0, orig_width / 2, orig_height), doc, page_num, clip=left_half_clip)
if add_space:
notes_rect = fitz.Rect(orig_width / 2, 0, orig_width, orig_height)
left_page.draw_rect(notes_rect, color=None, fill=bg_color)
if pattern:
_draw_pattern(new_doc, left_page, notes_rect, pattern, pattern_color)
# Create a new page for the right half
right_page = new_doc.new_page(width=new_page_width, height=orig_height)
right_page.show_pdf_page(fitz.Rect(0, 0, orig_width / 2, orig_height), doc, page_num, clip=right_half_clip)
if add_space:
notes_rect = fitz.Rect(orig_width / 2, 0, orig_width, orig_height)
right_page.draw_rect(notes_rect, color=None, fill=bg_color)
if pattern:
_draw_pattern(new_doc, right_page, notes_rect, pattern, pattern_color)
elif mode == 'stitch':
if stitch_direction == 'horizontal':
new_width = orig_width
if add_space:
new_width *= 2
new_page = new_doc.new_page(width=new_width, height=orig_height)
new_page.show_pdf_page(fitz.Rect(0, 0, orig_width / 2, orig_height), doc, page_num, clip=left_half_clip)
new_page.show_pdf_page(fitz.Rect(orig_width / 2, 0, orig_width, orig_height), doc, page_num, clip=right_half_clip)
if add_space:
notes_rect = fitz.Rect(orig_width, 0, new_width, orig_height)
new_page.draw_rect(notes_rect, color=None, fill=bg_color)
if pattern:
_draw_pattern(new_doc, new_page, notes_rect, pattern, pattern_color)
else: # vertical
new_width = orig_width / 2
if add_space:
new_width = orig_width
new_height = orig_height * 2
new_page = new_doc.new_page(width=new_width, height=new_height)
new_page.show_pdf_page(fitz.Rect(0, 0, orig_width / 2, orig_height), doc, page_num, clip=left_half_clip)
new_page.show_pdf_page(fitz.Rect(0, orig_height, orig_width / 2, new_height), doc, page_num, clip=right_half_clip)
if add_space:
notes_rect = fitz.Rect(orig_width / 2, 0, new_width, new_height)
new_page.draw_rect(notes_rect, color=None, fill=bg_color)
if pattern:
_draw_pattern(new_doc, new_page, notes_rect, pattern, pattern_color)
elif mode == 'notes_only':
if add_space:
new_page = new_doc.new_page(width=orig_width * 2, height=orig_height)
right_rect = fitz.Rect(orig_width, 0, orig_width * 2, orig_height)
new_page.draw_rect(right_rect, color=None, fill=bg_color)
if pattern:
_draw_pattern(new_doc, new_page, right_rect, pattern, pattern_color)
new_page.show_pdf_page(fitz.Rect(0, 0, orig_width, orig_height), doc, page_num)
else:
new_doc.insert_pdf(doc, from_page=page_num, to_page=page_num)
else: # Default to copying the page if mode is unknown
new_doc.insert_pdf(doc, from_page=page_num, to_page=page_num)
new_doc.save(output_pdf)
total_pages = len(new_doc)
new_doc.close()
doc.close()
print(f"✓ Successfully created: {output_pdf}")
print(f" Pages processed: {total_pages}")
def _draw_pattern(doc, page, rect, pattern, color):
if pattern == 'grid':
_draw_grid(page, rect, color=color)
elif pattern == 'dots':
_draw_dots(doc, page, rect, color=color)
def _draw_grid(page, rect, spacing=20, color=(0.8, 0.8, 0.8)):
# Draw vertical lines
for x in range(int(rect.x0), int(rect.x1), spacing):
page.draw_line(fitz.Point(x, rect.y0), fitz.Point(x, rect.y1), color=color, width=0.5)
# Draw horizontal lines
for y in range(int(rect.y0), int(rect.y1), spacing):
page.draw_line(fitz.Point(rect.x0, y), fitz.Point(rect.x1, y), color=color, width=0.5)
def _draw_dots(doc, page, rect, spacing=20, radius=1, color=(0.8, 0.8, 0.8)):
"""Creates a tileable dot pattern using a Form XObject for efficiency."""
# Create a small rectangle for one pattern unit
stamp_rect = fitz.Rect(0, 0, spacing, spacing)
# Create a new PDF for the stamp
stamp_doc = fitz.open()
stamp_page = stamp_doc.new_page(width=spacing, height=spacing)
# Draw a single dot in the corner of the stamp page
stamp_page.draw_circle(fitz.Point(radius, radius), radius, color=color, fill=color)
# Convert the stamp page to a stamp (Form XObject) and get its cross-reference number
stamp_xref = doc.get_xref(stamp_doc.convert_to_pdf())
stamp_doc.close()
# Tile the stamp across the target rectangle
for x in range(int(rect.x0), int(rect.x1), spacing):
for y in range(int(rect.y0), int(rect.y1), spacing):
page.show_pdf_page(fitz.Rect(x, y, x + spacing, y + spacing), stamp_xref)
def main():
"""Main function with command-line interface"""
import argparse
parser = argparse.ArgumentParser(description="Expand or rearrange a PDF for note-taking.")
parser.add_argument("input_pdf", help="Path to input PDF file.")
parser.add_argument("output_pdf", nargs='?', help="Path to output PDF file.")
parser.add_argument("--mode", choices=['notes_only', 'split', 'stitch'], default='notes_only', help="Processing mode.")
parser.add_argument("--stitch-direction", choices=['horizontal', 'vertical'], default='horizontal', help="Direction for 'stitch' mode.")
parser.add_argument("--no-space", action='store_true', help="Don't add extra space for notes.")
parser.add_argument("--bg", default='white', help="Background color (white, lightgray, cream)." )
args = parser.parse_args()
output_pdf = args.output_pdf
if not output_pdf:
suffix = f'_{args.mode}'
if args.mode == 'stitch':
suffix += f'_{args.stitch_direction[:4]}'
if not args.no_space:
suffix += '_notes'
suffix += '.pdf'
output_pdf = args.input_pdf.replace('.pdf', suffix)
bg_colors = {
'white': (1, 1, 1),
'lightgray': (0.95, 0.95, 0.95),
'cream': (1, 0.99, 0.94),
}
bg_color = bg_colors.get(args.bg, (1, 1, 1))
try:
expand_pdf_for_notes(
args.input_pdf,
output_pdf,
bg_color=bg_color,
mode=args.mode,
stitch_direction=args.stitch_direction,
add_space=not args.no_space
)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()