forked from J-F-Liu/lopdf
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobject_streams.rs
More file actions
130 lines (109 loc) · 4.28 KB
/
object_streams.rs
File metadata and controls
130 lines (109 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use lopdf::dictionary;
use lopdf::{Document, Object, SaveOptions, Stream};
use lopdf::content::{Content, Operation};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a simple PDF document
let mut doc = Document::with_version("1.5");
let pages_id = doc.new_object_id();
// Add many objects to demonstrate object stream compression
let font_id = doc.add_object(dictionary! {
"Type" => "Font",
"Subtype" => "Type1",
"BaseFont" => "Helvetica"
});
let bold_font_id = doc.add_object(dictionary! {
"Type" => "Font",
"Subtype" => "Type1",
"BaseFont" => "Helvetica-Bold"
});
let italic_font_id = doc.add_object(dictionary! {
"Type" => "Font",
"Subtype" => "Type1",
"BaseFont" => "Helvetica-Oblique"
});
// Add some metadata objects
for i in 0..20 {
doc.add_object(dictionary! {
"Type" => format!("CustomData{}", i),
"Value" => i,
"Description" => format!("This is custom data object number {}", i)
});
}
let resources_id = doc.add_object(dictionary! {
"Font" => dictionary! {
"F1" => font_id,
"F2" => bold_font_id,
"F3" => italic_font_id,
},
});
// Create page content
let content = Content {
operations: vec![
Operation::new("BT", vec![]),
Operation::new("Tf", vec!["F1".into(), 24.into()]),
Operation::new("Td", vec![50.into(), 700.into()]),
Operation::new("Tj", vec![Object::string_literal("Object Streams Demo")]),
Operation::new("ET", vec![]),
Operation::new("BT", vec![]),
Operation::new("Tf", vec!["F2".into(), 16.into()]),
Operation::new("Td", vec![50.into(), 650.into()]),
Operation::new("Tj", vec![Object::string_literal("This PDF uses object streams!")]),
Operation::new("ET", vec![]),
Operation::new("BT", vec![]),
Operation::new("Tf", vec!["F1".into(), 12.into()]),
Operation::new("Td", vec![50.into(), 600.into()]),
Operation::new("Tj", vec![Object::string_literal("Multiple non-stream objects are compressed together.")]),
Operation::new("ET", vec![]),
],
};
let content_id = doc.add_object(Stream::new(
dictionary! {},
content.encode()?
));
let page_id = doc.add_object(dictionary! {
"Type" => "Page",
"Parent" => pages_id,
"Contents" => content_id,
"Resources" => resources_id,
"MediaBox" => vec![0.into(), 0.into(), 612.into(), 792.into()],
});
doc.objects.insert(pages_id, Object::Dictionary(dictionary! {
"Type" => "Pages",
"Kids" => vec![page_id.into()],
"Count" => 1,
}));
let catalog_id = doc.add_object(dictionary! {
"Type" => "Catalog",
"Pages" => pages_id,
});
doc.trailer.set("Root", catalog_id);
// Save with traditional format
let mut traditional_buffer = Vec::new();
doc.save_to(&mut traditional_buffer)?;
let traditional_size = traditional_buffer.len();
// Save with object streams
let mut modern_buffer = Vec::new();
doc.save_modern(&mut modern_buffer)?;
let modern_size = modern_buffer.len();
// Save with custom options
let mut custom_buffer = Vec::new();
let options = SaveOptions::builder()
.use_object_streams(true)
.use_xref_streams(true)
.max_objects_per_stream(10)
.compression_level(9)
.build();
doc.save_with_options(&mut custom_buffer, options)?;
let custom_size = custom_buffer.len();
// Compare sizes
println!("PDF Size Comparison:");
println!("Traditional format: {} bytes", traditional_size);
println!("With object streams: {} bytes", modern_size);
println!("With custom options: {} bytes", custom_size);
let reduction = 100.0 - (modern_size as f64 / traditional_size as f64 * 100.0);
println!("\nSize reduction: {:.1}%", reduction);
// Save the modern version to a file
std::fs::write("object_streams_demo.pdf", &modern_buffer)?;
println!("\nSaved modern PDF to: object_streams_demo.pdf");
Ok(())
}