Skip to content
Open
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
57 changes: 57 additions & 0 deletions src/decoders/ljpeg/decompressors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,63 @@ pub fn decode_ljpeg_4components(ljpeg: &LjpegDecompressor, out: &mut [u16], widt
Ok(())
}

pub fn decode_jlpeg_predictor7_3components(ljpeg: &LjpegDecompressor, out: &mut [u16], x: usize, stripwidth:usize, width: usize, height: usize) -> Result<(),String> {
if ljpeg.sof.width*3 < width || ljpeg.sof.height < height {
return Err(format!("ljpeg: trying to decode {}x{} into {}x{}",
ljpeg.sof.width*3, ljpeg.sof.height,
width, height).to_string())
}

let ref htable1 = ljpeg.dhts[ljpeg.sof.components[0].dc_tbl_num];
let ref htable2 = ljpeg.dhts[ljpeg.sof.components[1].dc_tbl_num];
let ref htable3 = ljpeg.dhts[ljpeg.sof.components[2].dc_tbl_num];
let mut pump = BitPumpJPEG::new(ljpeg.buffer);

let base_prediction = 1 << (ljpeg.sof.precision - ljpeg.point_transform -1);
out[x] = (base_prediction + htable1.huff_decode(&mut pump)?) as u16;
out[x+1] = (base_prediction + htable2.huff_decode(&mut pump)?) as u16;
out[x+2] = (base_prediction + htable3.huff_decode(&mut pump)?) as u16;
let skip_x = ljpeg.sof.width - width/3;

for row in 0..height {
let startcol = if row == 0 {x+3} else {x};
let prev_row_pos = (row-1) * stripwidth;
for col in (startcol..(width+x)).step_by(3) {
let pos_l = if col == x {
// At start of line predictor starts with start of previous line
(row-1)*stripwidth+x
} else {
// All other cases use the two previous pixels in the same line
row*stripwidth+col-3
};

let (p1,p2,p3) = if row == 0 {
(out[pos_l],out[pos_l+1],out[pos_l+2])
} else {
let pos_a = prev_row_pos + col;
(((out[pos_l] as u32 + out[pos_a] as u32) >> 1) as u16,
((out[pos_l+1] as u32 + out[pos_a+1] as u32) >> 1) as u16,
((out[pos_l+2] as u32 + out[pos_a+2] as u32) >> 1) as u16)
};

let diff1 = htable1.huff_decode(&mut pump)?;
let diff2 = htable2.huff_decode(&mut pump)?;
let diff3 = htable3.huff_decode(&mut pump)?;
out[row*stripwidth+col+0] = ((p1 as i32) + diff1) as u16;
out[row*stripwidth+col+1] = ((p2 as i32) + diff2) as u16;
out[row*stripwidth+col+2] = ((p3 as i32) + diff3) as u16;
}
// Skip extra encoded differences if the ljpeg frame is wider than the output
for _ in 0..skip_x {
htable1.huff_decode(&mut pump)?;
htable2.huff_decode(&mut pump)?;
htable3.huff_decode(&mut pump)?;
}
}

Ok(())
}

fn set_yuv_420(out: &mut [u16], row: usize, col: usize, width: usize, y1: i32, y2: i32, y3: i32, y4: i32, cb: i32, cr: i32) {
let pix1 = row*width+col;
let pix2 = pix1+3;
Expand Down
8 changes: 7 additions & 1 deletion src/decoders/ljpeg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl<'a> LjpegDecompressor<'a> {
if marker == m(Marker::SOF3) {
// Start of the frame, giving us the basic info
sof.parse_sof(&mut input)?;
if sof.precision > 16 || sof.precision < 12 {
if sof.precision > 16 || sof.precision < 10 {
return Err(format!("ljpeg: sof.precision {}", sof.precision).to_string())
}
} else if marker == m(Marker::DHT) {
Expand Down Expand Up @@ -264,6 +264,12 @@ impl<'a> LjpegDecompressor<'a> {
c => return Err(format!("ljpeg: {} component files not supported", c).to_string()),
}
},
7 => {
match self.sof.cps {
3 => decode_jlpeg_predictor7_3components(self, out, x, stripwidth, width, height),
c => return Err(format!("ljpeg: predictor 7, {} component files not supported", c).to_string())
}
}
8 => decode_hasselblad(self, out, width),
p => return Err(format!("ljpeg: predictor {} not supported", p).to_string()),
}
Expand Down