Skip to main content

pdf_min/
image.rs

1//!# Test example
2//!
3//! ```
4//!      use pdf_min::{Writer, html, writer::Fetcher, image::{ImageSpec,Image}};
5//!      struct MyFetcher;
6//!      impl Fetcher for MyFetcher {
7//!         fn image(&mut self, w: &mut Writer, _name: &str) -> Image {         
8//!             let mut data = Vec::new();
9//!             for i in 0..3 * 16 * 16 {
10//!                 data.push( i as u8 );  // Red
11//!                 data.push( (i + 85 ) as u8 ); // Green
12//!                 data.push( (i + 170 ) as u8 ); // Blue
13//!             }
14//!             let ims = ImageSpec{ data: &data, width:16, height:16,
15//!                 bits_per_component:8, color_space: b"/DeviceRGB", other: b"" };
16//!             Image::new( &ims, &mut w.b )
17//!         }
18//!      }
19//!      let mut w = Writer::default();
20//!      w.b.nocomp = true;
21//!      w.font_size = 20;
22//!      w.fetcher = Some(Box::new(MyFetcher));
23//!   
24//!      // Draw text with image
25//!      html( &mut w, b"<p><b>Bold Text Before Image</b> <img width=32 src=myimg> Text after image" );
26//!      let bytes = w.finish();
27//!   
28//!      use std::fs::File;
29//!      use std::io::prelude::*;
30//!   
31//!      let mut file = File::create("image_test.pdf").unwrap();
32//!      file.write_all(bytes).unwrap();
33//! ```
34//!
35//!# JPG Test example
36//! ```
37//!    // Setup the PDF Writer
38//!    let mut doc = pdf_min::Writer::default();
39//!    doc.b.nocomp = true;
40//!
41//!    // Read jpg from file
42//!    let file_bytes = std::fs::read("one.jpg").unwrap();
43//!
44//!    // Use jpeg_decoder::Decoder to get jpg info ( color space, bits_per_component, width, height ).
45//!    let mut decoder = jpeg_decoder::Decoder::new(std::io::Cursor::new(&file_bytes));
46//!    decoder.read_info().unwrap();
47//!    let info = decoder.info().unwrap();
48//!
49//!    use jpeg_decoder::{PixelFormat};
50//!    
51//!    let color_space: &[u8] = match info.pixel_format {
52//!        PixelFormat::RGB24 => b"/DeviceRGB",
53//!        PixelFormat::CMYK32 => b"/DeviceCMYK",
54//!        PixelFormat::L8 | PixelFormat::L16 => b"/DeviceGray",
55//!    };
56//!
57//!    let bits_per_component = match info.pixel_format {
58//!        PixelFormat::L16 => 16,
59//!        _ => 8
60//!    };
61//!
62//!    // Make the ImageSpec.
63//!    use pdf_min::{Px, image::{ImageSpec, Image}};
64//!    let ims = ImageSpec {
65//!        data: &file_bytes,
66//!        width: info.width as Px,
67//!        height: info.height as Px,
68//!        color_space,
69//!        bits_per_component,
70//!        other: b"/Filter/DCT",
71//!    };
72//!    
73//!    // Make the PDF Image from the ImageSpec.
74//!    let im = Image::new(&ims, &mut doc.b);
75//!
76//!    // Draw the image on the current page.
77//!    im.draw(&mut doc.p, 20.0, 40.0, 0.20);
78//!
79//!    // Save the pdf as a file.
80//!    let bytes = doc.finish();
81//!    let mut file = std::fs::File::create("jpg_image_test.pdf").unwrap();
82//!    use std::io::Write;
83//!    file.write_all(bytes).unwrap();
84//! ```
85
86use crate::BasicPdfWriter;
87use crate::page::Page;
88use crate::*;
89use format_bytes::write_bytes as wb;
90
91/// PDF image specification - byte data and attributes that describe how image is encoded.
92pub struct ImageSpec<'a> {
93    /// Image data - length is width * height * (bits_per_component/8) * 3 (for RGB).
94    pub data: &'a [u8],
95    /// Width
96    pub width: Px,
97    /// Height
98    pub height: Px,
99    /// Bits per component, usually 8
100    pub bits_per_component: u8,
101    /// Color space, such as b"/DeviceGray", b"/DeviceRGB", b"/DeviceCMYK"
102    pub color_space: &'a [u8],
103    /// Any other attributes, e.g. b"/Filter/DCT" for a jpeg
104    pub other: &'a [u8],
105}
106
107/// PDF image - obj id, width and height
108pub struct Image {
109    /// PDF obj id
110    pub obj: usize,
111    /// Width
112    pub width: Px,
113    /// Height
114    pub height: Px,
115}
116
117impl Image {
118    /// Writes the specified image attributes and data to the PDF, returns Image with obj id, width and height.
119    pub fn new(s: &ImageSpec, w: &mut BasicPdfWriter) -> Image {
120        let obj = w.begin();
121        let _ = wb!(
122            &mut w.b,
123            b"<</Type/XObject/Subtype/Image/Width {}/Height {}/ColorSpace{}/BitsPerComponent {}/Length {}{}>>stream\n",
124            s.width, s.height, s.color_space, s.bits_per_component, s.data.len(), s.other
125        );
126        w.b.extend_from_slice(s.data);
127        w.b.extend_from_slice(b"\nendstream");
128        w.end();
129        Image {
130            obj,
131            width: s.width,
132            height: s.height,
133        }
134    }
135
136    /// Draw image on page.
137    pub fn draw(&self, page: &mut Page, x: f32, y: f32, scale: f32) {
138        let w = (self.width as f32) * scale;
139        let h = (self.height as f32) * scale;
140        page.xobjs.insert(self.obj);
141        let _ = wb!(
142            &mut page.os,
143            b"\nq {} 0 0 {} {} {} cm /X{} Do Q",
144            w,
145            h,
146            x,
147            y,
148            self.obj
149        );
150    }
151}