Remove header and footer from the upload pdf without changing the content pages and information form it
cd /home/daytona/workspace && python3 -c " import pdfplumber pdf_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' with pdfplumber.open(pdf_path) as pdf: print(f'Total pages: {len(pdf.pages)}') print() for i, page in enumerate(pdf.pages[:3]): print(f'=== PAGE {i+1} ===') print(f'Page size: {page.width} x {page.height}') words = page.extract_words() if words: # Show top words (potential header) top_words = [w for w in words if w['top'] < 80] print(f'TOP area words (top < 80): {[(w[\"text\"], round(w[\"top\"],1), round(w[\"bottom\"],1)) for w in top_words]}') # Show bottom words (potential footer) bottom_words = [w for w in words if w['bottom'] > page.height - 80] print(f'BOTTOM area words (bottom > {page.height-80:.0f}): {[(w[\"text\"], round(w[\"top\"],1), round(w[\"bottom\"],1)) for w in bottom_words]}') print() "
python3 -c " from pypdf import PdfReader, PdfWriter from pypdf.generic import RectangleObject input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' reader = PdfReader(input_path) writer = PdfWriter() # Header ends around y=57 (top=36.9, bottom=45.9 for header text, bottom=77 for chapter heading) # Footer starts around y=747.6 (top of footer text) # PDF coordinates: origin is bottom-left, y increases upward # Page height = 792 # Header: top area in PDF coords = 792 - 57 = 735 (we want to keep content BELOW y=57 from top) # Footer: bottom area in PDF coords = 792 - 747.6 = 44.4 (we want to keep content ABOVE y=747.6 from top) # In PDF coords (bottom-left origin): # We want to crop: # bottom of visible area (remove footer): y_min = 792 - 747.6 + 10 = 54.4 -> use 60 # top of visible area (remove header): y_max = 792 - 57 + 5 = 740 -> use 735 # But chapter headings at top=57,bottom=77 -- those are CONTENT, not header # Pure header is only at top=36.9,bottom=45.9 (the 'KLE Ayurveda...' line) # So header crop: remove only up to bottom=50 from top -> PDF y_max = 792 - 50 = 742 # Let's be precise: # Header text: top=36.9, bottom=45.9 -> crop above PDF y = 792-36.9=755.1 down to 792-50=742 # Footer text: top=747.6, bottom=757.2 -> crop below PDF y = 792-757.2=34.8 up to 792-747.6+5=49.4 -> use 50 # # New crop box: x0=0, y0=50 (removes footer), x1=612, y1=742 (removes header) # But we should preserve borders - let's check if there's a border/frame # Safe crop margins: HEADER_HEIGHT = 55 # points from top to remove (covers y=36.9 to y=45.9 header line) FOOTER_HEIGHT = 50 # points from bottom to remove (covers footer at y=747.6 to 757.2) # page height=792: keep from y=FOOTER_HEIGHT to y=792-HEADER_HEIGHT # in PDF coords (y=0 at bottom): keep y0=FOOTER_HEIGHT, y1=792-HEADER_HEIGHT for page in reader.pages: page_height = float(page.mediabox.height) page_width = float(page.mediabox.width) # Set cropbox to hide header and footer new_bottom = FOOTER_HEIGHT new_top = page_height - HEADER_HEIGHT page.cropbox = RectangleObject((0, new_bottom, page_width, new_top)) writer.add_page(page) with open(output_path, 'wb') as f: writer.write(f) print(f'Done! Output: {output_path}') print(f'Pages processed: {len(reader.pages)}') "
python3 -c " import pdfplumber output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' with pdfplumber.open(output_path) as pdf: print(f'Total pages: {len(pdf.pages)}') for i in [0, 1, 2, 14, 29]: page = pdf.pages[i] print(f'\\n=== PAGE {i+1} ===') print(f'Visible area: {page.width} x {page.height}') words = page.extract_words() if words: top5 = words[:5] bot5 = words[-5:] print(f'First words: {[w[\"text\"] for w in top5]}') print(f'Last words: {[w[\"text\"] for w in bot5]}') else: print('No words extracted') "
python3 -c " from pypdf import PdfReader, PdfWriter import io # We'll use pypdf's page transformation to truly crop by modifying the content stream # The cleanest approach: use pypdf's add_transformation + page trim # Actually the correct way with pypdf is to set mediabox AND cropbox from pypdf import PdfReader, PdfWriter, Transformation from pypdf.generic import RectangleObject input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' reader = PdfReader(input_path) page0 = reader.pages[0] print('mediabox:', page0.mediabox) print('cropbox:', page0.cropbox) print('trimbox:', page0.trimbox) print('bleedbox:', page0.bleedbox) print('artbox:', page0.artbox) "
python3 << 'EOF' # Use reportlab to create white overlay pages, then merge them with pypdf from reportlab.pdfgen import canvas from reportlab.lib.units import pt from pypdf import PdfReader, PdfWriter import io input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' reader = PdfReader(input_path) writer = PdfWriter() PAGE_W = 612 PAGE_H = 792 # Header region: y from top=36.9, bottom=45.9 -> PDF coords y = 792-45.9=746.1 to 792-36.9=755.1 # But we want to cover the entire header band including a small margin # Header band: PDF y from 735 to 792 (top 57 points) # Footer band: PDF y from 0 to 52 (bottom 52 points) HEADER_TOP_PDF_Y = 792 # top of page HEADER_BOT_PDF_Y = 735 # bottom of header region (keep content below this) FOOTER_TOP_PDF_Y = 52 # top of footer region (keep content above this) FOOTER_BOT_PDF_Y = 0 # bottom of page for page in reader.pages: # Create an overlay with white rectangles covering header and footer packet = io.BytesIO() c = canvas.Canvas(packet, pagesize=(PAGE_W, PAGE_H)) # Draw white rectangle over header c.setFillColorRGB(1, 1, 1) # white c.setStrokeColorRGB(1, 1, 1) c.rect(0, HEADER_BOT_PDF_Y, PAGE_W, HEADER_TOP_PDF_Y - HEADER_BOT_PDF_Y, fill=1, stroke=0) # Draw white rectangle over footer c.rect(0, FOOTER_BOT_PDF_Y, PAGE_W, FOOTER_TOP_PDF_Y - FOOTER_BOT_PDF_Y, fill=1, stroke=0) c.save() packet.seek(0) overlay_reader = PdfReader(packet) overlay_page = overlay_reader.pages[0] # Merge overlay on top of original page page.merge_page(overlay_page) writer.add_page(page) with open(output_path, 'wb') as f: writer.write(f) print(f'Done! Output written to {output_path}') print(f'Total pages: {len(reader.pages)}') EOF
python3 << 'EOF' from reportlab.pdfgen import canvas from pypdf import PdfReader, PdfWriter import io input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' reader = PdfReader(input_path) writer = PdfWriter() PAGE_W = 612 PAGE_H = 792 # Header band: top 57 points (PDF y from 735 to 792) # Footer band: bottom 52 points (PDF y from 0 to 52) HEADER_BOT_PDF_Y = 735 FOOTER_TOP_PDF_Y = 52 for page in reader.pages: packet = io.BytesIO() c = canvas.Canvas(packet, pagesize=(PAGE_W, PAGE_H)) c.setFillColorRGB(1, 1, 1) c.setStrokeColorRGB(1, 1, 1) # Cover header (top strip) c.rect(0, HEADER_BOT_PDF_Y, PAGE_W, PAGE_H - HEADER_BOT_PDF_Y, fill=1, stroke=0) # Cover footer (bottom strip) c.rect(0, 0, PAGE_W, FOOTER_TOP_PDF_Y, fill=1, stroke=0) c.save() packet.seek(0) overlay_reader = PdfReader(packet) overlay_page = overlay_reader.pages[0] page.merge_page(overlay_page) writer.add_page(page) with open(output_path, 'wb') as f: writer.write(f) print(f'Done! Pages: {len(reader.pages)}') print(f'Output: {output_path}') EOF
python3 -c " import pdfplumber output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' with pdfplumber.open(output_path) as pdf: print(f'Total pages: {len(pdf.pages)}') for i in [0, 1, 2, 14, 29]: page = pdf.pages[i] words = page.extract_words() print(f'\\n=== PAGE {i+1} ===') if words: # top 5 print(f'First 5 words: {[w[\"text\"] for w in words[:5]]}') # bottom 5 print(f'Last 5 words: {[w[\"text\"] for w in words[-5:]]}') # Check if header/footer keywords still present all_text = ' '.join(w['text'] for w in words) has_header = 'KLE' in all_text or 'Ayurveda' in all_text has_footer = 'PPaaggee' in all_text or '23A5979' in all_text print(f'Header present: {has_header} | Footer present: {has_footer}') else: print('No words') "
python3 -c "import pikepdf; print('pikepdf available:', pikepdf.__version__)"
python3 << 'EOF' import pikepdf from pikepdf import Pdf, Page, Rectangle from reportlab.pdfgen import canvas from pypdf import PdfReader import io input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' # Strategy: Use pikepdf to wrap each page content stream in a clipping path # that clips out the header and footer regions. This truly prevents those # areas from rendering/existing in the output. PAGE_W = 612 PAGE_H = 792 # Keep content between y=52 (above footer) and y=735 (below header) # i.e., clip rect: x0=0, y0=52, x1=612, y1=735 KEEP_Y0 = 52 # bottom of content area (above footer) KEEP_Y1 = 735 # top of content area (below header) pdf = Pdf.open(input_path) for page in pdf.pages: # Prepend a clip path to the content stream # This uses PDF graphics operators: # q = save graphics state # <x> <y> <w> <h> re = rectangle path # W* = clip path (even-odd) # n = no-op (end path without fill/stroke) # Then all existing content is clipped, and Q restores state clip_stream = ( f"q\n" f"0 {KEEP_Y0} {PAGE_W} {KEEP_Y1 - KEEP_Y0} re\n" f"W* n\n" ).encode() end_stream = b"\nQ\n" # Get existing content stream(s) if "/Contents" not in page: continue contents = page["/Contents"] # Create new stream objects clip_obj = pdf.make_stream(clip_stream) end_obj = pdf.make_stream(end_stream) # Build new contents array: [clip, ...original..., end] if hasattr(contents, 'objgen'): # Single stream reference new_contents = pikepdf.Array([clip_obj, contents, end_obj]) else: # Already an array new_contents = pikepdf.Array([clip_obj] + list(contents) + [end_obj]) page["/Contents"] = new_contents pdf.save(output_path) print(f'Done! Saved to {output_path}') print(f'Pages: {len(pdf.pages)}') EOF
rm -f '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' && echo "removed"
python3 << 'EOF' import pikepdf from pikepdf import Pdf input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' PAGE_W = 612 PAGE_H = 792 KEEP_Y0 = 52 # above footer KEEP_Y1 = 735 # below header pdf = Pdf.open(input_path) for page in pdf.pages: if "/Contents" not in page: continue clip_stream = ( f"q\n" f"0 {KEEP_Y0} {PAGE_W} {KEEP_Y1 - KEEP_Y0} re\n" f"W* n\n" ).encode() end_stream = b"\nQ\n" clip_obj = pdf.make_stream(clip_stream) end_obj = pdf.make_stream(end_stream) contents = page["/Contents"] if hasattr(contents, 'objgen'): new_contents = pikepdf.Array([clip_obj, contents, end_obj]) else: new_contents = pikepdf.Array([clip_obj] + list(contents) + [end_obj]) page["/Contents"] = new_contents pdf.save(output_path) print(f'Done! Saved to {output_path}') print(f'Pages: {len(pdf.pages)}') EOF
python3 -c " import pdfplumber output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' with pdfplumber.open(output_path) as pdf: print(f'Total pages: {len(pdf.pages)}') for i in [0, 1, 14, 29]: page = pdf.pages[i] words = page.extract_words() print(f'\\n=== PAGE {i+1} ===') if words: all_text = ' '.join(w['text'] for w in words) has_header = 'KLE' in all_text or 'Ayurveda' in all_text has_footer = 'PPaaggee' in all_text or '23A5979' in all_text print(f'Header removed: {not has_header} | Footer removed: {not has_footer}') print(f'First 5 words: {[w[\"text\"] for w in words[:5]]}') print(f'Last 5 words: {[w[\"text\"] for w in words[-5:]]}') else: print('No words extracted') "
python3 -c "import fitz; print('pymupdf:', fitz.__version__)"
pip install --user pymupdf --quiet && python3 -c "import fitz; print('pymupdf:', fitz.__version__)"
rm -f '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' && python3 << 'EOF' import fitz # pymupdf input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' doc = fitz.open(input_path) PAGE_W = 612 PAGE_H = 792 # Header region: top 57 points from top -> y from 0 to 57 in fitz coords (top-left origin) # Footer region: bottom 52 points -> y from PAGE_H-52 to PAGE_H = 740 to 792 HEADER_RECT = fitz.Rect(0, 0, PAGE_W, 57) FOOTER_RECT = fitz.Rect(0, PAGE_H - 52, PAGE_W, PAGE_H) for page in doc: # Add redaction annotations for header and footer areas page.add_redact_annot(HEADER_RECT) page.add_redact_annot(FOOTER_RECT) # Apply redactions - this permanently removes content from those areas page.apply_redactions() doc.save(output_path) doc.close() print(f'Done! Saved to: {output_path}') # Verify import pdfplumber with pdfplumber.open(output_path) as pdf: print(f'Total pages: {len(pdf.pages)}') for i in [0, 1, 14, 29]: page = pdf.pages[i] words = page.extract_words() all_text = ' '.join(w['text'] for w in words) has_header = 'KLE' in all_text or 'Ayurveda' in all_text has_footer = 'PPaaggee' in all_text or '23A5979' in all_text print(f'Page {i+1}: Header removed={not has_header}, Footer removed={not has_footer}') if words: print(f' First words: {[w["text"] for w in words[:5]]}') print(f' Last words: {[w["text"] for w in words[-5:]]}') EOF
python3 -c " import fitz input_path = '/home/daytona/workspace/attachments/c274d174-9958-4091-b492-f36f619d9db3/Rutucharya_Assignment_bordered-1 (1).pdf' doc = fitz.open(input_path) for i in [0, 1, 29]: page = doc[i] words = page.get_text('words') # Show words in top 80 points top_words = [(w[4], round(w[1],1), round(w[3],1)) for w in words if w[1] < 80] print(f'Page {i+1} top words (y0<80): {top_words[:15]}') # Show words in bottom 60 points bot_words = [(w[4], round(w[1],1), round(w[3],1)) for w in words if w[3] > 730] print(f'Page {i+1} bottom words (y1>730): {bot_words[:10]}') print() "
python3 << 'EOF' import fitz output_path = '/home/daytona/workspace/Rutucharya_Assignment_no_header_footer.pdf' doc = fitz.open(output_path) print(f'Checking output file: {output_path}') print(f'Total pages: {len(doc)}') for i in [0, 1, 14, 29]: page = doc[i] words = page.get_text('words') all_text = ' '.join(w[4] for w in words) has_header = 'KLE' in all_text or 'Ayurveda' in all_text has_footer = 'PPaaggee' in all_text or '23A5979' in all_text or 'Isha' in all_text print(f'Page {i+1}: Header removed={not has_header}, Footer removed={not has_footer}') top_words = [w[4] for w in words if w[1] < 60] bot_words = [w[4] for w in words if w[3] > 740] print(f' Top area words: {top_words}') print(f' Bottom area words: {bot_words}') EOF
Rutucharya Assignment no header footer
PDF Document · PDF