Add PDF to fax conversion support
- pdf.rs: Ghostscript-based PDF to TIFF-F conversion - tiff_to_fax_document: Parse TIFF and convert to 1-bit fax format - CLI: Add 'convert' subcommand for dry testing - CLI: Add resolution option for send command - Test files for PDF/TIFF conversion validation
This commit is contained in:
BIN
test/output.tif
Normal file
BIN
test/output.tif
Normal file
Binary file not shown.
BIN
test/output_fax.tif
Normal file
BIN
test/output_fax.tif
Normal file
Binary file not shown.
76
test/test_conversion.py
Normal file
76
test/test_conversion.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
# Test PDF to TIFF-F conversion
|
||||
pdf_path = "/Users/accusys/telfax/test/testfax.pdf"
|
||||
tiff_path = "/Users/accusys/telfax/test/testfax_converted.tif"
|
||||
|
||||
print("=== Testing PDF → TIFF-F Conversion ===")
|
||||
|
||||
# Run ghostscript
|
||||
result = subprocess.run([
|
||||
"gs", "-dBATCH", "-dNOPAUSE", "-q",
|
||||
"-sDEVICE=tiffg3",
|
||||
"-r204x196", # Fine resolution
|
||||
"-sOutputFile", tiff_path,
|
||||
pdf_path
|
||||
], capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(f"Ghostscript failed: {result.stderr}")
|
||||
exit(1)
|
||||
|
||||
# Check output
|
||||
if os.path.exists(tiff_path):
|
||||
size = os.path.getsize(tiff_path)
|
||||
print(f"✓ TIFF-F created: {tiff_path}")
|
||||
print(f" Size: {size} bytes")
|
||||
|
||||
# Get TIFF info
|
||||
import struct
|
||||
|
||||
with open(tiff_path, 'rb') as f:
|
||||
header = f.read(8)
|
||||
if header[:2] == b'II':
|
||||
print(" Byte order: Little-endian")
|
||||
elif header[:2] == b'MM':
|
||||
print(" Byte order: Big-endian")
|
||||
|
||||
# Read IFD offset
|
||||
if header[:2] == b'II':
|
||||
ifd_offset = struct.unpack('<I', header[4:8])[0]
|
||||
else:
|
||||
ifd_offset = struct.unpack('>I', header[4:8])[0]
|
||||
|
||||
f.seek(ifd_offset)
|
||||
num_entries = struct.unpack('<H' if header[:2] == b'II' else '>H', f.read(2))[0]
|
||||
print(f" IFD entries: {num_entries}")
|
||||
|
||||
# Read key tags
|
||||
for i in range(num_entries):
|
||||
tag = struct.unpack('<H' if header[:2] == b'II' else '>H', f.read(2))[0]
|
||||
type_ = struct.unpack('<H' if header[:2] == b'II' else '>H', f.read(2))[0]
|
||||
count = struct.unpack('<I' if header[:2] == b'II' else '>I', f.read(4))[0]
|
||||
value_offset = f.read(4)
|
||||
|
||||
# Tags of interest: 256=width, 257=height, 259=compression, 262=photometric
|
||||
if tag == 256: # Width
|
||||
val = struct.unpack('<I' if header[:2] == b'II' else '>I', value_offset)[0]
|
||||
print(f" Width: {val} pixels")
|
||||
elif tag == 257: # Height
|
||||
val = struct.unpack('<I' if header[:2] == b'II' else '>I', value_offset)[0]
|
||||
print(f" Height: {val} lines")
|
||||
elif tag == 259: # Compression
|
||||
val = struct.unpack('<H' if header[:2] == b'II' else '>H', value_offset[:2])[0]
|
||||
comp_names = {1: "None", 3: "Group 3 MH", 4: "Group 4 MMR"}
|
||||
print(f" Compression: {comp_names.get(val, val)}")
|
||||
elif tag == 262: # PhotometricInterpretation
|
||||
val = struct.unpack('<H' if header[:2] == b'II' else '>H', value_offset[:2])[0]
|
||||
photo_names = {0: "WhiteIsZero", 1: "BlackIsZero"}
|
||||
print(f" Photometric: {photo_names.get(val, val)}")
|
||||
else:
|
||||
print("✗ TIFF-F not created")
|
||||
exit(1)
|
||||
|
||||
print("\n=== Conversion Test Passed ===")
|
||||
33
test/test_tiff_convert.rs
Normal file
33
test/test_tiff_convert.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use telfax::document::pdf::{pdf_to_fax_document, tiff_to_fax_document};
|
||||
use telfax::config::FaxResolution;
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
let tiff_path = "/Users/accusys/telfax/test/testfax.tif";
|
||||
let tiff_data = std::fs::read(tiff_path).expect("Failed to read TIFF");
|
||||
|
||||
println!("=== Testing TIFF → FaxDocument conversion ===");
|
||||
println!("Input TIFF: {} bytes", tiff_data.len());
|
||||
|
||||
let doc = tiff_to_fax_document(&tiff_data).expect("Conversion failed");
|
||||
|
||||
println!("Converted successfully:");
|
||||
println!(" Pages: {}", doc.pages.len());
|
||||
for (i, page) in doc.pages.iter().enumerate() {
|
||||
println!(" Page {}: {}x{} pixels, {} bytes",
|
||||
i + 1, page.width_pels, page.rows, page.pixels.len());
|
||||
}
|
||||
|
||||
// Verify pixel data - check some sample values
|
||||
let page = &doc.pages[0];
|
||||
let bytes_per_row = ((page.width_pels + 7) / 8) as usize;
|
||||
|
||||
println!(" Bytes per row: {}", bytes_per_row);
|
||||
println!(" Expected rows: {}", page.rows);
|
||||
println!(" Actual data rows: {}", page.pixels.len() / bytes_per_row);
|
||||
|
||||
// Sample first few bytes of first row
|
||||
println!(" First row bytes (hex): {:02x?}", &page.pixels[0..8.min(bytes_per_row)]);
|
||||
|
||||
println!("\n=== Test Passed ===");
|
||||
}
|
||||
BIN
test/testfax.pdf
Normal file
BIN
test/testfax.pdf
Normal file
Binary file not shown.
41
test/testfax.ps
Normal file
41
test/testfax.ps
Normal file
@@ -0,0 +1,41 @@
|
||||
%!PS-Adobe-3.0
|
||||
%%Pages: 1
|
||||
%%PageOrder: Ascend
|
||||
%%BoundingBox: 0 0 612 792
|
||||
%%EndComments
|
||||
|
||||
%%BeginProlog
|
||||
/Dict 2 dict def
|
||||
Dict begin
|
||||
/PageSize [612 792] def
|
||||
end
|
||||
|
||||
%%EndProlog
|
||||
|
||||
%%Page: 1 1
|
||||
10 750 moveto
|
||||
/Fnt1 12/Times-Roman findfont definefont pop
|
||||
/Fnt1 12 selectfont
|
||||
(Telfax Test Document - Page 1) show
|
||||
|
||||
10 730 moveto
|
||||
(This is a test fax transmission from telfax Rust server.) show
|
||||
|
||||
10 700 moveto
|
||||
(Testing US Robotics 56K FAX USB Modem) show
|
||||
|
||||
10 680 moveto
|
||||
(Date: 2026-07-01) show
|
||||
|
||||
10 600 moveto
|
||||
/BoxTimes-Roman 14 selectfont
|
||||
(TEST FAX CONTENT) show
|
||||
|
||||
10 550 moveto
|
||||
(This document tests the Class 1 fax protocol implementation.) show
|
||||
|
||||
showpage
|
||||
%%PageTrailer
|
||||
|
||||
%%Trailer
|
||||
%%EOF
|
||||
BIN
test/testfax.tif
Normal file
BIN
test/testfax.tif
Normal file
Binary file not shown.
BIN
test/testfax_gray.tif
Normal file
BIN
test/testfax_gray.tif
Normal file
Binary file not shown.
Reference in New Issue
Block a user