use oxidize_pdf::graphics::state::{TransferFunctionData, TransferFunctionParams};
use oxidize_pdf::graphics::{Color, ExtGState, TransferFunction};
use oxidize_pdf::{Document, Font, Page, Result};
fn main() -> Result<()> {
println!("=== Transfer Functions Example ===\n");
let mut doc = Document::new();
let mut page = Page::a4();
page.text()
.set_font(Font::HelveticaBold, 16.0)
.at(50.0, 750.0)
.write("Transfer Functions Examples")?;
page.text()
.set_font(Font::Helvetica, 10.0)
.at(50.0, 730.0)
.write("ISO 32000-1 Section 10.4 - Transfer Functions")?;
page.text()
.set_font(Font::HelveticaBold, 12.0)
.at(50.0, 690.0)
.write("1. Gamma Correction (2.2)")?;
let gamma_state = ExtGState::new().with_gamma_correction(2.2);
println!("Created gamma correction ExtGState: gamma = 2.2");
page.text()
.set_font(Font::HelveticaBold, 12.0)
.at(50.0, 650.0)
.write("2. Linear Transfer (slope=0.8, intercept=0.1)")?;
let linear_state = ExtGState::new().with_linear_transfer(0.8, 0.1);
println!("Created linear transfer ExtGState: y = 0.8x + 0.1");
page.text()
.set_font(Font::HelveticaBold, 12.0)
.at(50.0, 610.0)
.write("3. Identity Transfer (no transformation)")?;
let identity_state = ExtGState::new().with_transfer_function(TransferFunction::Identity);
println!("Created identity transfer ExtGState");
page.text()
.set_font(Font::HelveticaBold, 12.0)
.at(50.0, 570.0)
.write("4. Custom Exponential Function")?;
let exponential_data = TransferFunctionData {
function_type: 2, domain: vec![0.0, 1.0],
range: vec![0.0, 1.0],
params: TransferFunctionParams::Exponential {
c0: vec![0.0],
c1: vec![1.0],
n: 1.8, },
};
let custom_state =
ExtGState::new().with_transfer_function(TransferFunction::Single(exponential_data));
println!("Created custom exponential transfer: n = 1.8");
page.text()
.set_font(Font::HelveticaBold, 12.0)
.at(50.0, 530.0)
.write("5. Separate CMYK Transfer Functions")?;
let cmyk_functions = TransferFunction::Separate {
c_or_r: TransferFunctionData {
function_type: 2,
domain: vec![0.0, 1.0],
range: vec![0.0, 1.0],
params: TransferFunctionParams::Exponential {
c0: vec![0.0],
c1: vec![1.0],
n: 1.8, },
},
m_or_g: TransferFunctionData {
function_type: 2,
domain: vec![0.0, 1.0],
range: vec![0.0, 1.0],
params: TransferFunctionParams::Exponential {
c0: vec![0.0],
c1: vec![1.0],
n: 2.0, },
},
y_or_b: TransferFunctionData {
function_type: 2,
domain: vec![0.0, 1.0],
range: vec![0.0, 1.0],
params: TransferFunctionParams::Exponential {
c0: vec![0.0],
c1: vec![1.0],
n: 2.2, },
},
k: Some(TransferFunctionData {
function_type: 2,
domain: vec![0.0, 1.0],
range: vec![0.0, 1.0],
params: TransferFunctionParams::Exponential {
c0: vec![0.0],
c1: vec![1.0],
n: 2.4, },
}),
};
let cmyk_state = ExtGState::new().with_transfer_function(cmyk_functions);
println!("Created CMYK transfer functions: C=1.8, M=2.0, Y=2.2, K=2.4");
page.text()
.set_font(Font::HelveticaBold, 12.0)
.at(50.0, 480.0)
.write("Gradient Examples (visual reference):")?;
for i in 0..10 {
let gray = i as f64 / 9.0;
page.graphics()
.set_fill_color(Color::gray(gray))
.rect(50.0 + i as f64 * 25.0, 440.0, 23.0, 30.0)
.fill();
}
page.text()
.set_font(Font::Helvetica, 10.0)
.at(50.0, 425.0)
.write("Grayscale gradient (0% to 100%)")?;
let colors = [
(Color::red(), "Red"),
(Color::green(), "Green"),
(Color::blue(), "Blue"),
(Color::cyan(), "Cyan"),
(Color::rgb(1.0, 0.0, 1.0), "Magenta"),
(Color::yellow(), "Yellow"),
];
for (i, (color, _name)) in colors.iter().enumerate() {
page.graphics()
.set_fill_color(color.clone())
.rect(50.0 + i as f64 * 45.0, 380.0, 40.0, 30.0)
.fill();
}
page.text()
.set_font(Font::Helvetica, 10.0)
.at(50.0, 365.0)
.write("Color samples: R, G, B, C, M, Y")?;
page.text()
.set_font(Font::Helvetica, 10.0)
.at(50.0, 320.0)
.write("Transfer functions modify color values before output:")?;
page.text()
.set_font(Font::Helvetica, 9.0)
.at(50.0, 305.0)
.write("- Gamma correction compensates for display characteristics")?;
page.text()
.set_font(Font::Helvetica, 9.0)
.at(50.0, 290.0)
.write("- Linear transfer adjusts contrast and brightness")?;
page.text()
.set_font(Font::Helvetica, 9.0)
.at(50.0, 275.0)
.write("- Separate functions allow per-channel adjustment (CMYK/RGB)")?;
page.text()
.set_font(Font::Helvetica, 9.0)
.at(50.0, 260.0)
.write("- Black generation optimizes CMYK ink usage")?;
page.text()
.set_font(Font::HelveticaBold, 11.0)
.at(50.0, 220.0)
.write("ExtGState objects created:")?;
let states_info = [
"gamma_state - Gamma 2.2 correction",
"linear_state - Linear y = 0.8x + 0.1",
"identity_state - No transformation",
"custom_state - Exponential n=1.8",
"cmyk_state - Separate CMYK functions",
];
for (i, info) in states_info.iter().enumerate() {
page.text()
.set_font(Font::Courier, 9.0)
.at(60.0, 200.0 - i as f64 * 15.0)
.write(info)?;
}
doc.add_page(page);
let output_path = "examples/results/transfer_functions.pdf";
doc.save(output_path)?;
println!("\n✅ Transfer functions example created: {}", output_path);
println!(" - Demonstrates gamma correction");
println!(" - Shows linear transfer functions");
println!(" - Includes separate CMYK functions");
println!(" - Compares different transfer types");
println!("\nExtGState validation:");
println!(
" gamma_state: {:?}",
gamma_state.transfer_function.is_some()
);
println!(
" linear_state: {:?}",
linear_state.transfer_function.is_some()
);
println!(
" identity_state: {:?}",
identity_state.transfer_function.is_some()
);
println!(
" custom_state: {:?}",
custom_state.transfer_function.is_some()
);
println!(
" cmyk_state: {:?}",
cmyk_state.transfer_function.is_some()
);
Ok(())
}