CodeOCR: Vision-Based Code Understanding with Optical Compression
This skill enables Claude to guide users in converting source code into rendered images and feeding them to Vision Language Models (VLMs) instead of raw text tokens. Based on the CodeOCR research, this approach achieves up to 8x token compression by leveraging the inherent compressibility of image representations -- adjusting image resolution reduces token consumption while preserving enough visual structure for code understanding tasks. The technique is particularly effective for clone detection, code QA, and code completion when combined with syntax highlighting.
When to Use
- When a user needs to analyze a large codebase with a VLM and wants to reduce API token costs
- When the user asks about sending code as images to GPT-4o, Gemini, or other multimodal models
- When performing clone detection across many file pairs and text token limits are a bottleneck
- When the user wants to compare image-based vs text-based code representations for efficiency
- When building pipelines that batch-process code files through vision APIs at scale
- When the user asks how to add syntax highlighting to code images for better VLM performance
- When exploring whether a code understanding task (summarization, QA, completion) can tolerate image compression
Key Technique
Optical compression replaces the text-based paradigm (code as token sequences) with an image-based one (code as rendered screenshots). Text tokens scale linearly with code length and are hard to compress without losing semantics. Images, by contrast, can be resized to lower resolutions -- the VLM's vision encoder tiles the image into fixed-size patches (typically 112px tiles, each costing ~170 tokens), so reducing resolution directly reduces token count. A 1024x1024 rendered code image might cost ~1100 tokens regardless of how many lines of code it contains, whereas the same code as text could consume 4000+ tokens.
The critical insight is that not all code tasks degrade equally under compression. Clone detection is highly resilient -- structural similarity is visually apparent even at low resolution, and some compressed ratios slightly outperform raw text. Code completion benefits significantly from syntax highlighting (VS Code-style color themes), which provides visual cues that help VLMs distinguish keywords, strings, functions, and comments even when individual characters blur. Code summarization and QA degrade more, as they require fine-grained character-level reading. The practical recommendation: use 2-4x compression with syntax highlighting for most tasks, reserve 1x (no compression) for tasks requiring exact token recovery.
The rendering pipeline uses Pygments for syntax tokenization and Pillow for image generation. Code is drawn character-by-character onto an RGB canvas with configurable font size (default 32px), DPI (300), and dimensions (1024x1024). The "modern" theme mirrors VS Code Light Modern colors (magenta keywords, teal classes, green comments, red strings). Compression is applied by resizing with LANCZOS resampling to a target resolution calculated from the desired token budget.
Step-by-Step Workflow
Install CodeOCR from the repository:
git clone https://github.com/YerbaPage/CodeOCR.git
cd CodeOCR
pip install -r requirements.txt
Requires Python >= 3.10, Pillow, Pygments, and tiktoken. GPU optional (only needed for embedding models in retrieval tasks).
Render code to images using the Python API with syntax highlighting enabled:
from CodeOCR import render_code_to_images
with open("target.py") as f:
code = f.read()
images = render_code_to_images(
code,
language="python",
enable_syntax_highlight=True,
theme="modern", # VS Code Light Modern colors
auto_optimize=True, # auto-adjust font/layout for content
width=1024,
height=1024,
font_size=32
)
images[0].save("rendered_code.png")
Calculate the baseline token costs to understand your compression ratio:
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4")
text_tokens = len(enc.encode(code))
# Image tokens: ceil(width/112) * ceil(height/112) * 170
image_tokens = (1024 // 112 + 1) ** 2 * 170 # ~13770 for 1024x1024
Apply compression by resizing images to a target token budget:
from CodeOCR import compress_images
compressed = compress_images(
images,
text_tokens=text_tokens,
compression_ratio=4.0 # 4x fewer tokens than text
)
The compressor calculates image_token_limit = text_tokens / ratio, finds the closest resolution from the tile grid, and resizes with LANCZOS.
Choose the compression ratio based on task type:
- Clone detection: 4-8x compression works well (structural similarity survives heavy compression)
- Code completion: 2-4x with syntax highlighting enabled (color cues compensate for resolution loss)
- Code QA / summarization: 1-2x maximum (requires reading specific identifiers and logic)
- Code search/retrieval: 2-4x (semantic gist is preserved)
Send rendered images to the VLM with a task-appropriate prompt:
from CodeOCR import create_client, call_llm_with_images
client = create_client() # reads OPENAI_API_KEY from env
response, token_info = call_llm_with_images(
client,
model_name="gpt-4o",
images=compressed,
system_prompt="You are a code analysis assistant.",
user_prompt="Are these two code snippets functionally equivalent?"
)
print(f"Response: {response}")
print(f"Tokens used: {token_info}")
For batch processing, render and compress in a loop, tracking token savings:
total_text_tokens = 0
total_image_tokens = 0
for filepath in code_files:
with open(filepath) as f:
code = f.read()
text_toks = len(enc.encode(code))
imgs = render_code_to_images(code, language="python", enable_syntax_highlight=True)
compressed = compress_images(imgs, text_tokens=text_toks, compression_ratio=4.0)
total_text_tokens += text_toks
total_image_tokens += sum(calculate_image_tokens(img) for img in compressed)
print(f"Compression: {total_text_tokens / total_image_tokens:.1f}x")
Use the CLI for quick experiments without writing code:
# Render a file to an image
python -m CodeOCR.demo render --file example.py -o output.png
# Query a VLM about rendered code
python -m CodeOCR.demo query --file example.py -i "Explain this function"
# OCR: render then reconstruct text (test round-trip fidelity)
python -m CodeOCR.demo ocr --file example.py
Run downstream task benchmarks to validate on standard datasets:
cd downstream
# Clone detection with image compression
python -u run_pipeline.py --run-tasks --task code_clone_detection \
--models gpt-4o --resize-mode --code-clone-detection-separate-mode
# Code completion with syntax highlighting
python -u run_pipeline.py --run-tasks --task code_completion_rag \
--models gpt-4o --resize-mode --preserve-newlines --enable-syntax-highlight
Evaluate round-trip fidelity with code reconstruction (RQ5) to gauge how much information is lost:
cd reconstruction
python run.py # renders -> OCR -> compares against original
Concrete Examples
Example 1: Reducing token cost for bulk clone detection
User: "I have 500 pairs of code files to check for clones. The text tokens would cost too much with GPT-4o. Can I use images instead?"
Approach:
- Render each code file as a 1024x1024 syntax-highlighted PNG using
render_code_to_images()
- Apply 4x compression via
compress_images() -- clone detection tolerates this well
- Send each pair as two images to GPT-4o with the prompt: "Are these two code snippets functionally equivalent? Answer yes or no and explain."
- Track token savings -- expect ~4x reduction vs sending raw text
Output:
File pair: auth_v1.py vs auth_v2.py
Text tokens (both files): 3,200
Image tokens (4x compressed): 780
Result: "Yes, functionally equivalent. Both implement OAuth2 flow with
identical logic; v2 renames variables and extracts a helper method."
Savings: 4.1x token reduction
Example 2: Code completion with syntax highlighting boost
User: "I want to test whether sending code as a highlighted screenshot helps GPT-4o complete a function better than plain text at the same token budget."
Approach:
- Render the code context with
enable_syntax_highlight=True, theme="modern" and also with enable_syntax_highlight=False
- Compress both versions to 4x the text token cost
- Send each to GPT-4o with the prompt: "Complete the function that starts on the last line"
- Compare exact-match and BLEU scores between highlighted vs plain rendering
Output:
Task: Complete `def merge_sorted_lists(a, b):`
With syntax highlighting (4x compression):
- Exact match: 42% | BLEU: 0.71
Without syntax highlighting (4x compression):
- Exact match: 35% | BLEU: 0.63
Raw text (no compression):
- Exact match: 45% | BLEU: 0.74
Syntax highlighting recovers most of the accuracy lost to compression.
Example 3: Quick code explanation at minimal token cost
User: "Explain this 200-line Python file but minimize API costs."
Approach:
- Render with
render_code_to_images(code, language="python", enable_syntax_highlight=True)
- Apply 2x compression (moderate -- summarization needs some detail)
- Query: "Summarize what this code does, its main classes, and key functions"
- Compare token usage vs sending the raw text
Output:
Text approach: 1,450 tokens input
Image approach (2x): 725 tokens input
Response: "This module implements a rate limiter using the token bucket
algorithm. Class `RateLimiter` manages per-client buckets with
configurable refill rates. Key functions: `acquire()` blocks until
a token is available, `try_acquire()` returns immediately..."
Best Practices
- Do enable syntax highlighting for all tasks -- it consistently improves VLM performance, especially under compression. The "modern" (VS Code) theme provides the strongest visual signal differentiation.
- Do use
auto_optimize=True when rendering -- it adjusts font size and layout to fit the code naturally rather than clipping or leaving empty space.
- Do start with 2x compression for a new task and measure accuracy before increasing to 4x or 8x. Each task has a different compression tolerance curve.
- Do use LANCZOS resampling (the default) for downscaling -- it preserves more high-frequency detail (character edges) than bilinear or nearest-neighbor.
- Avoid compression ratios above 4x for tasks that require reading specific variable names, string literals, or numeric constants -- character-level detail is lost.
- Avoid rendering very long files (500+ lines) as a single image -- split across multiple pages using the multi-page support, or truncate to the relevant section. A single image with tiny text defeats the purpose.
- Avoid using this approach for tasks where exact character recovery is needed (e.g., generating a patch file) -- use raw text for those.
Error Handling
- Pygments import fails: The renderer falls back to plain text (no highlighting). Install Pygments:
pip install Pygments. Without it, you lose the syntax highlighting benefit.
- tiktoken unavailable: Token counting falls back to a ~4 chars/token heuristic. Install tiktoken for accurate compression ratio calculation:
pip install tiktoken.
- Image too small after compression: At extreme ratios (8x+), the image may resize to fewer than 112px, producing only 1 tile (~170 tokens). The code handles ratio 0.0 by returning a 14x14 blank image. Check that your compressed resolution is at least 112px on each side.
- Multi-page overflow: Long code produces multiple images. Each image consumes its own tile budget. Account for total image tokens across all pages, not just one.
- API rate limits: Batch processing hundreds of image-based requests may hit rate limits faster than text -- vision requests are heavier per-call. Implement backoff and batching.
- Font rendering differences: Missing fonts on the system will cause Pillow to use a default bitmap font, producing lower-quality renders. Ensure a monospace TTF font is available.
Limitations
- Character-level precision: VLMs cannot reliably OCR every character from compressed code images. Tasks requiring exact token recovery (code generation, patch creation) should use raw text.
- Language sensitivity: Results are validated primarily on Python and Java. Languages with dense syntax (Haskell, Perl) or non-Latin characters may behave differently.
- Model dependency: Effectiveness varies across VLMs. GPT-4o and Gemini show the strongest vision-code capabilities. Smaller or older vision models may struggle with code images entirely.
- Long code files: The approach works best for code segments under ~200 lines per image. Very long files require multi-page rendering, which increases total token cost and may negate compression benefits.
- No structural encoding: Unlike AST-based representations, images do not explicitly encode syntactic structure. The VLM must infer structure from visual layout and color cues.
- Cost of rendering: There is compute overhead for rendering and compressing images. For single small files, the rendering cost may exceed the token savings. The benefit materializes at scale or with large files.
Reference
Paper: CodeOCR: On the Effectiveness of Vision Language Models in Code Understanding (Shi et al., 2026). Key sections: Section 4 for task-specific compression results, Section 5 for the syntax highlighting ablation, Table 3 for the compression-ratio-vs-accuracy tradeoffs across tasks. Code: github.com/YerbaPage/CodeOCR.
1---2name: codeocr-effectiveness-vision-code3description: Render source code as images for vision LLM processing to reduce token cost while preserving understanding. Use when: 'render code as image for LLM', 'compress code tokens with images', 'use vision model for code understanding', 'reduce token cost for large codebase analysis', 'code image compression for clone detection', 'syntax highlighted code screenshot for VLM'.4---56# CodeOCR: Vision-Based Code Understanding with Optical Compression78This skill enables Claude to guide users in converting source code into rendered images and feeding them to Vision Language Models (VLMs) instead of raw text tokens. Based on the CodeOCR research, this approach achieves up to 8x token compression by leveraging the inherent compressibility of image representations -- adjusting image resolution reduces token consumption while preserving enough visual structure for code understanding tasks. The technique is particularly effective for clone detection, code QA, and code completion when combined with syntax highlighting.910## When to Use1112- When a user needs to analyze a large codebase with a VLM and wants to reduce API token costs13- When the user asks about sending code as images to GPT-4o, Gemini, or other multimodal models14- When performing clone detection across many file pairs and text token limits are a bottleneck15- When the user wants to compare image-based vs text-based code representations for efficiency16- When building pipelines that batch-process code files through vision APIs at scale17- When the user asks how to add syntax highlighting to code images for better VLM performance18- When exploring whether a code understanding task (summarization, QA, completion) can tolerate image compression1920## Key Technique2122**Optical compression** replaces the text-based paradigm (code as token sequences) with an image-based one (code as rendered screenshots). Text tokens scale linearly with code length and are hard to compress without losing semantics. Images, by contrast, can be resized to lower resolutions -- the VLM's vision encoder tiles the image into fixed-size patches (typically 112px tiles, each costing ~170 tokens), so reducing resolution directly reduces token count. A 1024x1024 rendered code image might cost ~1100 tokens regardless of how many lines of code it contains, whereas the same code as text could consume 4000+ tokens.2324The critical insight is that **not all code tasks degrade equally under compression**. Clone detection is highly resilient -- structural similarity is visually apparent even at low resolution, and some compressed ratios slightly outperform raw text. Code completion benefits significantly from **syntax highlighting** (VS Code-style color themes), which provides visual cues that help VLMs distinguish keywords, strings, functions, and comments even when individual characters blur. Code summarization and QA degrade more, as they require fine-grained character-level reading. The practical recommendation: use 2-4x compression with syntax highlighting for most tasks, reserve 1x (no compression) for tasks requiring exact token recovery.2526The rendering pipeline uses **Pygments** for syntax tokenization and **Pillow** for image generation. Code is drawn character-by-character onto an RGB canvas with configurable font size (default 32px), DPI (300), and dimensions (1024x1024). The "modern" theme mirrors VS Code Light Modern colors (magenta keywords, teal classes, green comments, red strings). Compression is applied by resizing with LANCZOS resampling to a target resolution calculated from the desired token budget.2728## Step-by-Step Workflow29301. **Install CodeOCR** from the repository:31 ```bash32 git clone https://github.com/YerbaPage/CodeOCR.git33 cd CodeOCR34 pip install -r requirements.txt35 ```36 Requires Python >= 3.10, Pillow, Pygments, and tiktoken. GPU optional (only needed for embedding models in retrieval tasks).37382. **Render code to images** using the Python API with syntax highlighting enabled:39 ```python40 from CodeOCR import render_code_to_images4142 with open("target.py") as f:43 code = f.read()4445 images = render_code_to_images(46 code,47 language="python",48 enable_syntax_highlight=True,49 theme="modern", # VS Code Light Modern colors50 auto_optimize=True, # auto-adjust font/layout for content51 width=1024,52 height=1024,53 font_size=3254 )55 images[0].save("rendered_code.png")56 ```57583. **Calculate the baseline token costs** to understand your compression ratio:59 ```python60 import tiktoken61 enc = tiktoken.encoding_for_model("gpt-4")62 text_tokens = len(enc.encode(code))63 # Image tokens: ceil(width/112) * ceil(height/112) * 17064 image_tokens = (1024 // 112 + 1) ** 2 * 170 # ~13770 for 1024x102465 ```66674. **Apply compression** by resizing images to a target token budget:68 ```python69 from CodeOCR import compress_images7071 compressed = compress_images(72 images,73 text_tokens=text_tokens,74 compression_ratio=4.0 # 4x fewer tokens than text75 )76 ```77 The compressor calculates `image_token_limit = text_tokens / ratio`, finds the closest resolution from the tile grid, and resizes with LANCZOS.78795. **Choose the compression ratio based on task type**:80 - **Clone detection**: 4-8x compression works well (structural similarity survives heavy compression)81 - **Code completion**: 2-4x with syntax highlighting enabled (color cues compensate for resolution loss)82 - **Code QA / summarization**: 1-2x maximum (requires reading specific identifiers and logic)83 - **Code search/retrieval**: 2-4x (semantic gist is preserved)84856. **Send rendered images to the VLM** with a task-appropriate prompt:86 ```python87 from CodeOCR import create_client, call_llm_with_images8889 client = create_client() # reads OPENAI_API_KEY from env90 response, token_info = call_llm_with_images(91 client,92 model_name="gpt-4o",93 images=compressed,94 system_prompt="You are a code analysis assistant.",95 user_prompt="Are these two code snippets functionally equivalent?"96 )97 print(f"Response: {response}")98 print(f"Tokens used: {token_info}")99 ```1001017. **For batch processing**, render and compress in a loop, tracking token savings:102 ```python103 total_text_tokens = 0104 total_image_tokens = 0105 for filepath in code_files:106 with open(filepath) as f:107 code = f.read()108 text_toks = len(enc.encode(code))109 imgs = render_code_to_images(code, language="python", enable_syntax_highlight=True)110 compressed = compress_images(imgs, text_tokens=text_toks, compression_ratio=4.0)111 total_text_tokens += text_toks112 total_image_tokens += sum(calculate_image_tokens(img) for img in compressed)113 print(f"Compression: {total_text_tokens / total_image_tokens:.1f}x")114 ```1151168. **Use the CLI for quick experiments** without writing code:117 ```bash118 # Render a file to an image119 python -m CodeOCR.demo render --file example.py -o output.png120121 # Query a VLM about rendered code122 python -m CodeOCR.demo query --file example.py -i "Explain this function"123124 # OCR: render then reconstruct text (test round-trip fidelity)125 python -m CodeOCR.demo ocr --file example.py126 ```1271289. **Run downstream task benchmarks** to validate on standard datasets:129 ```bash130 cd downstream131 # Clone detection with image compression132 python -u run_pipeline.py --run-tasks --task code_clone_detection \133 --models gpt-4o --resize-mode --code-clone-detection-separate-mode134135 # Code completion with syntax highlighting136 python -u run_pipeline.py --run-tasks --task code_completion_rag \137 --models gpt-4o --resize-mode --preserve-newlines --enable-syntax-highlight138 ```13914010. **Evaluate round-trip fidelity** with code reconstruction (RQ5) to gauge how much information is lost:141 ```bash142 cd reconstruction143 python run.py # renders -> OCR -> compares against original144 ```145146## Concrete Examples147148**Example 1: Reducing token cost for bulk clone detection**149150User: "I have 500 pairs of code files to check for clones. The text tokens would cost too much with GPT-4o. Can I use images instead?"151152Approach:1531. Render each code file as a 1024x1024 syntax-highlighted PNG using `render_code_to_images()`1542. Apply 4x compression via `compress_images()` -- clone detection tolerates this well1553. Send each pair as two images to GPT-4o with the prompt: "Are these two code snippets functionally equivalent? Answer yes or no and explain."1564. Track token savings -- expect ~4x reduction vs sending raw text157158Output:159```160File pair: auth_v1.py vs auth_v2.py161Text tokens (both files): 3,200162Image tokens (4x compressed): 780163Result: "Yes, functionally equivalent. Both implement OAuth2 flow with164 identical logic; v2 renames variables and extracts a helper method."165Savings: 4.1x token reduction166```167168**Example 2: Code completion with syntax highlighting boost**169170User: "I want to test whether sending code as a highlighted screenshot helps GPT-4o complete a function better than plain text at the same token budget."171172Approach:1731. Render the code context with `enable_syntax_highlight=True, theme="modern"` and also with `enable_syntax_highlight=False`1742. Compress both versions to 4x the text token cost1753. Send each to GPT-4o with the prompt: "Complete the function that starts on the last line"1764. Compare exact-match and BLEU scores between highlighted vs plain rendering177178Output:179```180Task: Complete `def merge_sorted_lists(a, b):`181With syntax highlighting (4x compression):182 - Exact match: 42% | BLEU: 0.71183Without syntax highlighting (4x compression):184 - Exact match: 35% | BLEU: 0.63185Raw text (no compression):186 - Exact match: 45% | BLEU: 0.74187188Syntax highlighting recovers most of the accuracy lost to compression.189```190191**Example 3: Quick code explanation at minimal token cost**192193User: "Explain this 200-line Python file but minimize API costs."194195Approach:1961. Render with `render_code_to_images(code, language="python", enable_syntax_highlight=True)`1972. Apply 2x compression (moderate -- summarization needs some detail)1983. Query: "Summarize what this code does, its main classes, and key functions"1994. Compare token usage vs sending the raw text200201Output:202```203Text approach: 1,450 tokens input204Image approach (2x): 725 tokens input205Response: "This module implements a rate limiter using the token bucket206algorithm. Class `RateLimiter` manages per-client buckets with207configurable refill rates. Key functions: `acquire()` blocks until208a token is available, `try_acquire()` returns immediately..."209```210211## Best Practices212213- **Do** enable syntax highlighting for all tasks -- it consistently improves VLM performance, especially under compression. The "modern" (VS Code) theme provides the strongest visual signal differentiation.214- **Do** use `auto_optimize=True` when rendering -- it adjusts font size and layout to fit the code naturally rather than clipping or leaving empty space.215- **Do** start with 2x compression for a new task and measure accuracy before increasing to 4x or 8x. Each task has a different compression tolerance curve.216- **Do** use LANCZOS resampling (the default) for downscaling -- it preserves more high-frequency detail (character edges) than bilinear or nearest-neighbor.217- **Avoid** compression ratios above 4x for tasks that require reading specific variable names, string literals, or numeric constants -- character-level detail is lost.218- **Avoid** rendering very long files (500+ lines) as a single image -- split across multiple pages using the multi-page support, or truncate to the relevant section. A single image with tiny text defeats the purpose.219- **Avoid** using this approach for tasks where exact character recovery is needed (e.g., generating a patch file) -- use raw text for those.220221## Error Handling222223- **Pygments import fails**: The renderer falls back to plain text (no highlighting). Install Pygments: `pip install Pygments`. Without it, you lose the syntax highlighting benefit.224- **tiktoken unavailable**: Token counting falls back to a ~4 chars/token heuristic. Install tiktoken for accurate compression ratio calculation: `pip install tiktoken`.225- **Image too small after compression**: At extreme ratios (8x+), the image may resize to fewer than 112px, producing only 1 tile (~170 tokens). The code handles ratio 0.0 by returning a 14x14 blank image. Check that your compressed resolution is at least 112px on each side.226- **Multi-page overflow**: Long code produces multiple images. Each image consumes its own tile budget. Account for total image tokens across all pages, not just one.227- **API rate limits**: Batch processing hundreds of image-based requests may hit rate limits faster than text -- vision requests are heavier per-call. Implement backoff and batching.228- **Font rendering differences**: Missing fonts on the system will cause Pillow to use a default bitmap font, producing lower-quality renders. Ensure a monospace TTF font is available.229230## Limitations231232- **Character-level precision**: VLMs cannot reliably OCR every character from compressed code images. Tasks requiring exact token recovery (code generation, patch creation) should use raw text.233- **Language sensitivity**: Results are validated primarily on Python and Java. Languages with dense syntax (Haskell, Perl) or non-Latin characters may behave differently.234- **Model dependency**: Effectiveness varies across VLMs. GPT-4o and Gemini show the strongest vision-code capabilities. Smaller or older vision models may struggle with code images entirely.235- **Long code files**: The approach works best for code segments under ~200 lines per image. Very long files require multi-page rendering, which increases total token cost and may negate compression benefits.236- **No structural encoding**: Unlike AST-based representations, images do not explicitly encode syntactic structure. The VLM must infer structure from visual layout and color cues.237- **Cost of rendering**: There is compute overhead for rendering and compressing images. For single small files, the rendering cost may exceed the token savings. The benefit materializes at scale or with large files.238239## Reference240241**Paper**: [CodeOCR: On the Effectiveness of Vision Language Models in Code Understanding](https://arxiv.org/abs/2602.01785v1) (Shi et al., 2026). Key sections: Section 4 for task-specific compression results, Section 5 for the syntax highlighting ablation, Table 3 for the compression-ratio-vs-accuracy tradeoffs across tasks. Code: [github.com/YerbaPage/CodeOCR](https://github.com/YerbaPage/CodeOCR).