Skip to content

Tool for figure extraction from pdf files #29

Description

@klpanagi
#!/usr/bin/env python3
"""
Extract embedded images from the thesis PDF for use in the paper.
Phase 1: Extract all images with metadata for analysis.
Phase 2: Select key figures and save as PDFs.
"""
import fitz
import os
import json
from collections import defaultdict

PDF_PATH = "ΤΗ-ΜΔ-69.pdf"
OUTPUT_DIR = "paper/figures"
os.makedirs(OUTPUT_DIR, exist_ok=True)

doc = fitz.open(PDF_PATH)
print(f"PDF has {doc.page_count} pages")

# Phase 1: Extract ALL images with metadata
all_images = []

for page_num in range(doc.page_count):
    page = doc[page_num]
    page_images = page.get_images(full=True)
    
    for img_idx, img_info in enumerate(page_images):
        xref = img_info[0]  # xref of the image
        width = img_info[2]  # width in pixels
        height = img_info[3]  # height in pixels
        
        # Get more details
        base_image = doc.extract_image(xref)
        image_bytes = base_image["image"]
        image_ext = base_image["ext"]
        image_w = base_image["width"]
        image_h = base_image["height"]
        
        # Get the image bbox on the page
        # Find the image on the page to get its position
        try:
            img_rects = page.get_image_rects(xref)
            if img_rects:
                rect = img_rects[0]
                bbox = f"{rect.x0:.0f},{rect.y0:.0f},{rect.x1:.0f},{rect.y1:.0f}"
                area = rect.width * rect.height
            else:
                bbox = "no_position"
                area = 0
        except:
            bbox = "error"
            area = 0
        
        info = {
            "xref": xref,
            "page": page_num + 1,  # 1-indexed for readability
            "page_0indexed": page_num,
            "img_idx": img_idx,
            "ext": image_ext,
            "width": image_w,
            "height": image_h,
            "file_size": len(image_bytes),
            "bbox": bbox,
            "area": area,
        }
        all_images.append(info)
        
        # Save raw image for inspection
        raw_dir = os.path.join(OUTPUT_DIR, "_raw")
        os.makedirs(raw_dir, exist_ok=True)
        raw_path = os.path.join(raw_dir, f"p{page_num+1}_xref{xref}.{image_ext}")
        with open(raw_path, "wb") as f:
            f.write(image_bytes)

doc.close()

# Print summary
print(f"\nFound {len(all_images)} embedded images total")
print(f"{'Page':>4} | {'Xref':>4} | {'Ext':>4} | {'Width':>6} | {'Height':>6} | {'SizeKB':>7} | {'Area':>10} | BBox")
print("-" * 80)

# Group by page for easier analysis
by_page = defaultdict(list)
for img in all_images:
    by_page[img["page"]].append(img)

for page in sorted(by_page.keys()):
    for img in by_page[page]:
        print(f"  {img['page']:>4} | {img['xref']:>4} | {img['ext']:>4} | {img['width']:>6} | {img['height']:>6} | {img['file_size']/1024:>7.1f} | {img['area']:>10.0f} | {img['bbox']}")

# Save JSON for analysis
json_path = os.path.join(OUTPUT_DIR, "_image_metadata.json")
with open(json_path, "w") as f:
    json.dump(all_images, f, indent=2)
print(f"\nMetadata saved to {json_path}")
print(f"Raw images saved to {OUTPUT_DIR}/_raw/")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions