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}