pythonicMedia.hpp provides functions to convert standard media files into encrypted Pythonic formats (.pi, .pv). This tutorial explains the format, encryption, compression, and practical workflows.
- What is Pythonic Format?
- File Structure & Encryption
- RLE Compression
- Core Workflow: convert() & revert()
- Integration with Print/Export
- Practical Examples
Pythonic format provides encrypted, optionally compressed media files that can only be read by this library.
| Extension | Type | Description |
|---|---|---|
.pi |
Image | Pythonic Image (encrypted) |
.pv |
Video | Pythonic Video (encrypted) |
| Feature | Benefit |
|---|---|
| Obfuscation | XOR encryption with salt-based key |
| Compression | RLE compression for terminal graphics |
| Round-trip | Lossless conversion back to original |
| Auto-integration | Works seamlessly with print() and export() |
| Metadata | Preserves original format for perfect restoration |
┌─────────────────────────────────────────┐
│ Header (64 bytes) │
│ - Magic bytes (8 bytes) │
│ - Version (1 byte) │
│ - Original extension (16 bytes) │
│ - Salt (4 bytes) │
│ - Compression info (8 bytes) │
│ - Size metadata (16 bytes) │
│ - Reserved (14 bytes) │
├─────────────────────────────────────────┤
│ Encrypted Data (variable size) │
│ - XOR encrypted with rotating key │
│ - Bit-rotated for additional obfusc. │
│ - Optionally RLE compressed │
└─────────────────────────────────────────┘
| Offset | Field | Size | Purpose |
|---|---|---|---|
| 0-7 | Magic bytes | 8 | 'PYTHIMG\x01' or 'PYTHVID\x01' |
| 8 | Version | 1 | Format version (v1 = current) |
| 9 | Ext length | 1 | Length of original extension |
| 10-25 | Original extension | 16 | .jpg, .png, .mp4, etc. |
| 26-29 | Salt | 4 | Random salt for key derivation |
| 30 | Compression type | 1 | 0=none, 1=RLE |
| 34-41 | Original size | 8 | Size before encryption/compression |
| 42-49 | Compressed size | 8 | Size after compression (0 if none) |
Magic Bytes Identification:
// Image file
'P' 'Y' 'T' 'H' 'I' 'M' 'G' 0x01
// Video file
'P' 'Y' 'T' 'H' 'V' 'I' 'D' 0x01Step 1: Key Derivation
// Base key (32 bytes): "Pythonic" + random hex values
ENCRYPT_KEY = {0x50, 0x79, 0x74, 0x68, 0x6F, 0x6E, 0x69, 0x63, ...}
// File-specific key (XOR with salt)
for (size_t i = 0; i < 32; ++i) {
file_key[i] = ENCRYPT_KEY[i] ^ (salt >> (i % 4 * 8));
}Step 2: Byte Transformation
for (size_t i = 0; i < data.size(); ++i) {
// 1. XOR with rotating key
size_t key_idx = (i + (i / 32)) % 32; // Position-dependent
data[i] ^= file_key[key_idx];
// 2. Bit rotation (left 3, right 5)
data[i] = (data[i] << 3) | (data[i] >> 5);
}Decryption:
// Reverse order: bit rotation first, then XOR
data[i] = (data[i] >> 3) | (data[i] << 5); // Reverse rotation
data[i] ^= file_key[key_idx]; // XOR againSecurity Note: This is obfuscation, not cryptographic security. XOR is symmetric and reversible. Use for privacy, not military-grade secrets!
Run-Length Encoding (RLE) compresses runs of identical bytes. Perfect for terminal graphics with many repeated values (e.g., 0x00 for empty braille cells).
For runs of 3+ identical bytes:
[ESCAPE=0xFF] [count] [value]
For other bytes:
[literal byte]
Special case (if byte is 0xFF):
[0xFF] [0x01] [0xFF]
Input:
0x00 0x00 0x00 0x00 0x00 0x41 0x42 0xFF 0xFF 0xFF
Output:
0xFF 0x05 0x00 // 5 zeros
0x41 // literal 'A'
0x42 // literal 'B'
0xFF 0x03 0xFF // 3 escape bytes
Compression Ratio:
Original: 10 bytes
Compressed: 7 bytes
Ratio: 70%
| Content Type | Typical Ratio | Reason |
|---|---|---|
| Terminal graphics | 20-40% | Many repeated 0x00 (empty cells) |
| Already compressed (.png, .jpg, .mp4) | 98-102% | No benefit (already compressed) |
| Raw bitmap data | 60-80% | Some repeated pixels |
| Text files | 50-70% | Repeated spaces, newlines |
Process Flow:
1. Read source file into memory
↓
2. Auto-detect type (image vs video)
↓
3. Apply RLE compression (if enabled)
↓
4. XOR encrypt with file-specific key
↓
5. Create header with metadata
↓
6. Write header + encrypted data to .pi/.pv
Usage:
#include <pythonic/pythonic.hpp>
using namespace pythonic::media;
// Basic usage (auto-detect, with compression)
std::string output = convert("photo.jpg");
// Creates: photo.pi
// Force type
convert("data.bin", MediaType::image);
// Disable compression
convert("video.mp4", MediaType::auto_detect, false);When to disable compression:
- Already compressed media (.jpg, .png, .mp4): No benefit
- Speed-critical conversions: Skip compression step
- Small files (< 100 KB): Overhead not worth it
Process Flow:
1. Read .pi/.pv file
↓
2. Parse header, validate magic bytes
↓
3. Read encrypted data
↓
4. XOR decrypt with salt-derived key
↓
5. Decompress RLE (if compression flag set)
↓
6. Write original file with saved extension
Usage:
// Default naming: basename_reverted.ext
revert("photo.pi"); // Creates: photo_reverted.jpg
// Custom output name
revert("photo.pi", "restored_photo"); // Creates: restored_photo.jpg
// With path
revert("secret.pi", "output/final"); // Creates: output/final.jpgSeamless Decryption: print() and export() automatically decrypt .pi/.pv files!
using namespace Pythonic;
using namespace pythonic::media;
// Encrypt
convert("photo.jpg"); // Creates photo.pi
// Print (auto-decrypts!)
print("photo.pi"); // Displays as if it were photo.jpg
// Works with videos too
convert("movie.mp4"); // Creates movie.pv
print("movie.pv"); // Plays video with audio// Encrypt source
convert("photo.jpg"); // photo.pi
// Export encrypted file (auto-decrypts, then exports)
export("photo.pi", "output", RenderConfig()
.set_format(Format::image)
.set_mode(Mode::colored));
// Creates: output.png (rendered from decrypted photo.pi)// 1. Encrypt source media
std::string encrypted_img = convert("sensitive_photo.jpg");
std::string encrypted_vid = convert("private_video.mp4");
// 2. Use encrypted files everywhere
print(encrypted_img); // Display
export(encrypted_vid, "clip", RenderConfig()
.set_format(Format::video)
.set_start_time(10)
.set_end_time(20));
// 3. Revert when needed
revert(encrypted_img, "final_output");#include <pythonic/pythonic.hpp>
#include <filesystem>
namespace fs = std::filesystem;
using namespace pythonic::media;
void encrypt_directory(const std::string &dir) {
for (const auto &entry : fs::directory_iterator(dir)) {
if (!entry.is_regular_file()) continue;
std::string path = entry.path().string();
std::string ext = get_extension(path);
if (is_image_extension(ext) || is_video_extension(ext)) {
try {
std::string output = convert(path);
std::cout << "✓ " << path << " → " << output << "\n";
} catch (const std::exception &e) {
std::cerr << "✗ " << path << ": " << e.what() << "\n";
}
}
}
}#include <pythonic/pythonic.hpp>
#include <iomanip>
using namespace pythonic::media;
void analyze_pythonic_file(const std::string &filepath) {
auto [is_image, ext, orig_size, comp_size, comp_type] =
get_info_detailed(filepath);
std::cout << "════════════════════════════════════\n";
std::cout << "File: " << filepath << "\n";
std::cout << "────────────────────────────────────\n";
std::cout << "Type: " << (is_image ? "Image" : "Video") << "\n";
std::cout << "Original format: " << ext << "\n";
std::cout << "Original size: " << orig_size << " bytes ("
<< (orig_size / 1024.0) << " KB)\n";
if (comp_type == Compression::rle && comp_size > 0) {
double ratio = 100.0 * comp_size / orig_size;
double savings = orig_size - comp_size;
std::cout << "Compressed: " << comp_size << " bytes ("
<< std::fixed << std::setprecision(1) << ratio << "%)\n";
std::cout << "Saved: " << savings << " bytes ("
<< (savings / 1024.0) << " KB)\n";
} else {
std::cout << "Compression: None\n";
}
std::cout << "════════════════════════════════════\n";
}Output:
════════════════════════════════════
File: terminal_art.pi
────────────────────────────────────
Type: Image
Original format: .txt
Original size: 1024000 bytes (1000.0 KB)
Compressed: 256000 bytes (25.0%)
Saved: 768000 bytes (750.0 KB)
════════════════════════════════════
#include <pythonic/pythonic.hpp>
#include <filesystem>
using namespace pythonic::media;
std::string smart_convert(const std::string &filepath) {
std::string ext = get_extension(filepath);
size_t size = std::filesystem::file_size(filepath);
// Heuristics for compression
bool should_compress = false;
// Text/raw formats: Always compress
if (ext == ".txt" || ext == ".csv" || ext == ".bmp") {
should_compress = true;
}
// Already compressed: Never compress
else if (ext == ".jpg" || ext == ".png" || ext == ".mp4") {
should_compress = false;
}
// Large files: Compress if > 1MB
else {
should_compress = (size > 1024 * 1024);
}
std::string output = convert(filepath, MediaType::auto_detect, should_compress);
std::cout << filepath << " → " << output
<< (should_compress ? " (compressed)" : " (uncompressed)") << "\n";
return output;
}| Function | Purpose | Input | Output |
|---|---|---|---|
convert() |
Encrypt media to .pi/.pv | .jpg, .mp4, etc | .pi or .pv |
revert() |
Decrypt .pi/.pv back to original | .pi or .pv | Original format |
get_info() |
Get metadata (type, ext, size) | .pi or .pv | Tuple (bool, str, uint64) |
get_info_detailed() |
Get detailed info + compression | .pi or .pv | Tuple (5 values) |
is_pythonic_format() |
Check if file is .pi/.pv | Any filename | bool |
extract_to_temp() |
Decrypt to temp file | .pi or .pv | Temp file path |
✅ Enable compression for:
- Terminal graphics (.txt with Braille/ASCII art)
- Raw bitmap data (.bmp)
- Text-based formats (.csv, .log)
❌ Disable compression for:
- Already compressed formats (.jpg, .png, .mp4)
- Real-time conversion scenarios
- Very small files (< 100 KB)
📦 Storage savings:
- Terminal graphics: 60-80% reduction
- Videos/Images: Minimal (already compressed)
🔐 Security level:
- Obfuscation: ✅ (good for privacy)
- Cryptographic security: ❌ (not for sensitive secrets)
- Use case: Protecting media in public repositories, preventing casual viewing