Change background to white
Change background to white
python3 - << 'EOF' import subprocess result = subprocess.run(['python3', '-c', 'import pikepdf; print("pikepdf ok"); import pypdf; print("pypdf ok"); import fitz; print("fitz ok")'], capture_output=True, text=True) print(result.stdout) print(result.stderr) EOF
python3 -c "import fitz; print('fitz/pymupdf ok, version:', fitz.version)"
python3 -c "import pypdf; print('pypdf ok')" && python3 -c "from PIL import Image; print('PIL ok')" && which gs && gs --version
python3 -c " import pypdf reader = pypdf.PdfReader('/home/daytona/workspace/attachments/c8268bae-aeff-410a-ac9c-3e807354df20/New Doc 05-26-2026 16.47.pdf') print('Pages:', len(reader.pages)) page = reader.pages[0] print('MediaBox:', page.mediabox) print('Resources keys:', list(page.get('/Resources', {}).keys()) if page.get('/Resources') else 'None') # Check if there are images (XObjects) res = page.get('/Resources') if res: xobj = res.get('/XObject') if xobj: print('XObjects:', list(xobj.keys())) "
python3 << 'EOF' import pypdf import io from PIL import Image src = '/home/daytona/workspace/attachments/c8268bae-aeff-410a-ac9c-3e807354df20/New Doc 05-26-2026 16.47.pdf' reader = pypdf.PdfReader(src) for i, page in enumerate(reader.pages): res = page.get('/Resources') if res: xobj = res.get('/XObject') if xobj: for key in xobj.keys(): obj = xobj[key].get_object() subtype = obj.get('/Subtype') print(f"Page {i+1}, {key}: Subtype={subtype}, Filter={obj.get('/Filter')}, Width={obj.get('/Width')}, Height={obj.get('/Height')}, CS={obj.get('/ColorSpace')}") EOF
python3 << 'EOF' import pypdf import io from PIL import Image import numpy as np src = '/home/daytona/workspace/attachments/c8268bae-aeff-410a-ac9c-3e807354df20/New Doc 05-26-2026 16.47.pdf' reader = pypdf.PdfReader(src) # Extract the main image from page 1 to preview what it looks like page = reader.pages[0] res = page.get('/Resources') xobj = res.get('/XObject') obj = xobj['/X2'].get_object() data = obj.get_data() img = Image.open(io.BytesIO(data)) arr = np.array(img) print("Image shape:", arr.shape) print("Min pixel:", arr.min(), "Max pixel:", arr.max()) print("Mean pixel:", arr.mean()) # Sample corners to see background color print("Top-left 5x5 mean:", arr[:5, :5].mean()) print("Top-right 5x5 mean:", arr[:5, -5:].mean()) print("Bottom-left 5x5 mean:", arr[-5:, :5].mean()) EOF
python3 << 'EOF' # Let's look at the pixel value distribution to understand the background import pypdf import io from PIL import Image import numpy as np src = '/home/daytona/workspace/attachments/c8268bae-aeff-410a-ac9c-3e807354df20/New Doc 05-26-2026 16.47.pdf' reader = pypdf.PdfReader(src) page = reader.pages[0] res = page.get('/Resources') xobj = res.get('/XObject') obj = xobj['/X2'].get_object() data = obj.get_data() img = Image.open(io.BytesIO(data)) arr = np.array(img) gray = arr.mean(axis=2) # Histogram of brightness bins = [0,50,100,150,180,200,220,240,255] hist, edges = np.histogram(gray, bins=bins) for i in range(len(hist)): print(f"{edges[i]:.0f}-{edges[i+1]:.0f}: {hist[i]} pixels ({hist[i]/gray.size*100:.1f}%)") EOF
python3 << 'PYEOF' import pypdf from pypdf import PdfWriter, PdfReader from pypdf.generic import ( ArrayObject, DecodedStreamObject, DictionaryObject, NameObject, NumberObject, RectangleObject ) import io from PIL import Image import numpy as np src = '/home/daytona/workspace/attachments/c8268bae-aeff-410a-ac9c-3e807354df20/New Doc 05-26-2026 16.47.pdf' out_path = '/home/daytona/workspace/attachments/c8268bae-aeff-410a-ac9c-3e807354df20/New Doc 05-26-2026 16.47 white bg.pdf' reader = PdfReader(src) writer = PdfWriter() def whiten_image(jpeg_bytes, threshold=150): """Replace pixels brighter than threshold with pure white.""" img = Image.open(io.BytesIO(jpeg_bytes)).convert('RGB') arr = np.array(img, dtype=np.uint8) # Compute grayscale brightness gray = arr.mean(axis=2) # Mask: background pixels (bright gray) -> white mask = gray > threshold arr[mask] = [255, 255, 255] # Save back to JPEG bytes out = io.BytesIO() Image.fromarray(arr).save(out, format='JPEG', quality=92) return out.getvalue() for page_num, page in enumerate(reader.pages): print(f"Processing page {page_num+1}...") res = page.get('/Resources') if res: xobj = res.get('/XObject') if xobj: for key in list(xobj.keys()): obj = xobj[key].get_object() subtype = obj.get('/Subtype') if subtype == '/Image': width = int(obj.get('/Width')) height = int(obj.get('/Height')) # Only process the main large page image (X2), skip small header (X1) if width > 500 and height > 500: jpeg_data = obj.get_data() new_jpeg = whiten_image(jpeg_data) # Replace stream data obj._data = new_jpeg obj[NameObject('/Length')] = NumberObject(len(new_jpeg)) print(f" Whitened {key}: {width}x{height}, {len(jpeg_data)} -> {len(new_jpeg)} bytes") writer.add_page(page) with open(out_path, 'wb') as f: writer.write(f) print(f"\nDone! Saved to: {out_path}") PYEOF