Skip to main content

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}