pdf_min/image.rs
1//!# Test example
2//!
3//! ```
4//! use pdf_min::{Writer, html, image::{ImageSpec,Image}};
5//!
6//! let mut w = Writer::default();
7//! w.b.nocomp = true;
8//!
9//! let mut data = Vec::new();
10//! for i in 0..3 * 16 * 16 {
11//! data.push( i as u8 ); // Red
12//! data.push( ( i + 85 ) as u8 ); // Green
13//! data.push( ( i + 85 + 85 ) as u8 ); // Blue
14//! }
15//!
16//! let ims = ImageSpec{ data: &data, width:16, height:16, bits_per_component:8, color_space: b"/DeviceRGB", other: b"" };
17//! let im = Image::new( &ims, &mut w.b );
18//!
19//! // Draw some text on the current page.
20//! html( &mut w, b"<p>Hello <b>there</b><p>Hello <i>again</i>" );
21//!
22//! // Draw a rectangle on the current page.
23//! w.p.rect( 100.0, 200.0, 160.0, 100.0 );
24//!
25//! // Draw the image on the current page.
26//! im.draw( &mut w.p, 100.0, 300.0, 10.0 );
27//!
28//! // Flush text
29//! w.output_line();
30//!
31//! // Finish the page
32//! w.save_page();
33//!
34//! // Draw some more text on the next page.
35//! html( &mut w, b"<p>Some <b>more</b> text" );
36//!
37//! let bytes = w.finish();
38//!
39//! use std::fs::File;
40//! use std::io::prelude::*;
41//!
42//! let mut file = File::create("image_test.pdf").unwrap();
43//! file.write_all(bytes).unwrap();
44//!
45//! ```
46
47use crate::BasicPdfWriter;
48use crate::page::Page;
49use format_bytes::write_bytes as wb;
50
51/// PDF image specification - byte data and attributes that describe how image is encoded.
52pub struct ImageSpec<'a> {
53 /// Image data - length is width * height * (bits_per_component/8) * 3 (for RGB).
54 pub data: &'a [u8],
55 /// Width
56 pub width: usize,
57 /// Height
58 pub height: usize,
59 /// Bits per component, usually 8
60 pub bits_per_component: u8,
61 /// Color space, such as b"/DeviceGray", b"/DeviceRGB", b"/DeviceCMYK"
62 pub color_space: &'a [u8],
63 /// Any other attributes, e.g. b"/Filter/DCT" for a jpeg
64 pub other: &'a [u8],
65}
66
67/// PDF image - obj id, width and height
68pub struct Image {
69 /// PDF obj id
70 pub obj: usize,
71 /// Width
72 pub width: usize,
73 /// Height
74 pub height: usize,
75}
76
77impl Image {
78 /// Writes the specificed image attributes and data to the PDF, returns Image with obj id, width and height.
79 pub fn new(s: &ImageSpec, w: &mut BasicPdfWriter) -> Image {
80 let obj = w.begin();
81 let _ = wb!(
82 &mut w.b,
83 b"<</Type/XObject/Subtype/Image/Width {}/Height {}/ColorSpace{}/BitsPerComponent {}/Length {}{}>>stream\n",
84 s.width, s.height, s.color_space, s.bits_per_component, s.data.len(), s.other
85 );
86 w.b.extend_from_slice(s.data);
87 w.b.extend_from_slice(b"\nendstream");
88 w.end();
89 Image {
90 obj,
91 height: s.height,
92 width: s.width,
93 }
94 }
95
96 /// Draw image on page.
97 pub fn draw(&self, page: &mut Page, x: f32, y: f32, scale: f32) {
98 let obj = self.obj;
99 let w = (self.width as f32) * scale;
100 let h = (self.height as f32) * scale;
101 page.xobjs.insert(obj);
102 let _ = wb!(
103 &mut page.os,
104 b"\nq {} 0 0 {} {} {} cm /X{} Do Q",
105 w,
106 h,
107 x,
108 y,
109 obj
110 );
111 }
112}