Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add writing of image #217

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions pdf/src/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,8 +729,12 @@ pub fn serialize_ops(mut ops: &[Op]) -> Result<Vec<u8>> {
}
}
writeln!(f, "] TJ")?;
},
Op::InlineImage { image: _ } => unimplemented!(),
}
Op::InlineImage { ref image } => {
writeln!(f, "BI")?;
image.serialize(f)?;
writeln!(f, "EI")?;
}
Op::XObject { ref name } => {
serialize_name(name, f)?;
writeln!(f, " Do")?;
Expand Down Expand Up @@ -1148,7 +1152,17 @@ Gb"0F_%"1&#XD6"#B1qiGGG^V6GZ#ZkijB5'RjB4S^5I61&$Ni:Xh=4S_9KYN;c9MUZPn/h,c]oCLUmg
1KkO\Ls5+g0aoD*btT?l^#mD&ORf[0~>
EI
"###;
let before = data.to_vec();
let mut lexer = Lexer::new(data);
assert!(inline_image(&mut lexer, &NoResolve).is_ok());
let image = inline_image(&mut lexer, &NoResolve);
assert!(image.is_ok());

// serialize the image and compare
let image = image.unwrap();
let mut after = Vec::<u8>::with_capacity(before.len());
after.push(b'\n');
image.serialize(&mut after).unwrap();
after.extend_from_slice(b"EI\n");
assert_eq!(&before, &after);
}
}
18 changes: 18 additions & 0 deletions pdf/src/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::error::*;
use crate::object::{Object, Resolve, Stream};
use crate::primitive::{Primitive, Dictionary};
use std::convert::TryInto;
use std::fmt;
use std::io::{Read, Write};
use once_cell::sync::OnceCell;
use datasize::DataSize;
Expand Down Expand Up @@ -115,6 +116,23 @@ impl StreamFilter {
}
}

impl fmt::Display for StreamFilter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
StreamFilter::ASCIIHexDecode => write!(f, "AHx"),
StreamFilter::ASCII85Decode => write!(f, "A85"),
StreamFilter::LZWDecode(_) => write!(f, "LZW"),
StreamFilter::FlateDecode(_) => write!(f, "Fl"),
StreamFilter::JPXDecode => write!(f, "JPX"),
StreamFilter::DCTDecode(_) => write!(f, "DCT"),
StreamFilter::CCITTFaxDecode(_) => write!(f, "CCF"),
StreamFilter::JBIG2Decode(_) => write!(f, "JBIG2"),
StreamFilter::Crypt => write!(f, "Crypt"),
StreamFilter::RunLengthDecode => write!(f, "RL"),
}
}
}

#[inline]
pub fn decode_nibble(c: u8) -> Option<u8> {
match c {
Expand Down
84 changes: 84 additions & 0 deletions pdf/src/object/types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Models of PDF types

use std::collections::HashMap;
use std::io;
use datasize::DataSize;

use crate as pdf;
Expand Down Expand Up @@ -687,6 +688,89 @@ impl ImageXObject {
}
Ok(data.into())
}

pub fn serialize(&self, out: &mut impl io::Write) -> Result<()> {
println!("serialize image");
// println!("{:?}", self);
/* write dictionary (width, height, color space, bits per component, intent,
imagemask, mask, decode, decode params, interpolate, struct_parent, id, smask, other) */
writeln!(out, "/W {}", self.inner.width)?;
writeln!(out, "/H {}", self.inner.height)?;
match &self.inner.color_space {
Some(ColorSpace::DeviceGray) => writeln!(out, "/ColorSpace /DeviceGray")?,
Some(ColorSpace::DeviceRGB) => writeln!(out, "/ColorSpace /DeviceRGB")?,
Some(ColorSpace::DeviceCMYK) => writeln!(out, "/ColorSpace /DeviceCMYK")?,
Some(_) => unimplemented!(),
None => {}
}
writeln!(out, "/BPC {}", self.inner.bits_per_component.unwrap_or(8))?;
match self.inner.intent {
Some(intent) => match intent {
RenderingIntent::AbsoluteColorimetric => {
writeln!(out, "/Intent /AbsoluteColorimetric")?
}
RenderingIntent::RelativeColorimetric => {
writeln!(out, "/Intent /RelativeColorimetric")?
}
RenderingIntent::Perceptual => writeln!(out, "/Intent /Perceptual")?,
RenderingIntent::Saturation => writeln!(out, "/Intent /Saturation")?,
},
None => {}
}
writeln!(out, "/IM {}", self.inner.image_mask)?;
if let Some(mask) = &self.inner.mask {
writeln!(out, "/Mask {}", mask)?;
}
if let Some(decode) = &self.inner.decode {
writeln!(
out,
"/Decode {}",
decode
.iter()
.map(|f| f.to_string())
.collect::<Vec<_>>()
.join(" ")
)?;
}
// print filters
if !self.inner.filters.is_empty() {
write!(out, "/F [")?;
for (i, filter) in self.inner.filters.iter().enumerate() {
if i != 0 {
write!(out, " ")?;
}
write!(out, "/{}", filter)?;
}
writeln!(out, "]")?;
}
// writeln!(out, "/Interpolate {}", self.inner.interpolate)?;
if let Some(struct_parent) = self.inner.struct_parent {
writeln!(out, "/StructParent {}", struct_parent)?;
}
if let Some(id) = &self.inner.id {
write!(out, "/ID ")?;
id.serialize(out)?;
}
if let Some(smask) = &self.inner.smask {
// write!(out, "/SMask ")?;
unimplemented!()
}
/* write ID
encode data and write it */
writeln!(out, "ID")?;
match &self.inner.inner_data {
StreamData::Generated(data) => {
out.write_all(&data)?;
writeln!(out)?;
}
StreamData::Original(range, id) => {
println!("range: {:?}", range);
println!("id: {:?}", id);
unimplemented!()
}
}
Ok(())
}
}

#[derive(Object, Debug, DataSize, DeepClone, ObjectWrite)]
Expand Down