1 use nihav_core::io::byteio::{ByteReader,MemoryReader};
2 use nihav_core::io::bitreader::*;
3 use nihav_core::io::codebook::*;
4 use nihav_core::codecs::*;
5 use nihav_codec_support::codecs::ZIGZAG;
15 const ROW_SHIFT: u8 = 8;
16 const COL_SHIFT: u8 = 14;
18 #[allow(clippy::erasing_op)]
19 fn idct_row(row: &mut [i16]) {
20 let in0 = ((i32::from(row[0])) << 11) + (1 << (ROW_SHIFT - 1));
21 let in1 = (i32::from(row[4])) << 11;
22 let in2 = i32::from(row[6]);
23 let in3 = i32::from(row[2]);
24 let in4 = i32::from(row[1]);
25 let in5 = i32::from(row[7]);
26 let in6 = i32::from(row[5]);
27 let in7 = i32::from(row[3]);
29 let tmp = W7 * (in4 + in5);
30 let a4 = tmp + (W1 - W7) * in4;
31 let a5 = tmp - (W1 + W7) * in5;
33 let tmp = W3 * (in6 + in7);
34 let a6 = tmp - (W3 - W5) * in6;
35 let a7 = tmp - (W3 + W5) * in7;
40 let t1 = W6 * (in2 + in3);
41 let a2 = t1 - (W2 + W6) * in2;
42 let a3 = t1 + (W2 - W6) * in3;
52 let b2 = (W8 * (b4 + t2) + 128) >> 8;
53 let b4 = (W8 * (b4 - t2) + 128) >> 8;
55 row[0] = ((b7 + b1) >> ROW_SHIFT) as i16;
56 row[7] = ((b7 - b1) >> ROW_SHIFT) as i16;
57 row[1] = ((b3 + b2) >> ROW_SHIFT) as i16;
58 row[6] = ((b3 - b2) >> ROW_SHIFT) as i16;
59 row[2] = ((b0 + b4) >> ROW_SHIFT) as i16;
60 row[5] = ((b0 - b4) >> ROW_SHIFT) as i16;
61 row[3] = ((b5 + b6) >> ROW_SHIFT) as i16;
62 row[4] = ((b5 - b6) >> ROW_SHIFT) as i16;
65 #[allow(clippy::erasing_op)]
66 #[allow(clippy::identity_op)]
67 fn idct_col(blk: &mut [i16; 64], off: usize) {
68 let in0 = ((i32::from(blk[off + 0*8])) << 8) + (1 << (COL_SHIFT - 1));
69 let in1 = (i32::from(blk[off + 4*8])) << 8;
70 let in2 = i32::from(blk[off + 6*8]);
71 let in3 = i32::from(blk[off + 2*8]);
72 let in4 = i32::from(blk[off + 1*8]);
73 let in5 = i32::from(blk[off + 7*8]);
74 let in6 = i32::from(blk[off + 5*8]);
75 let in7 = i32::from(blk[off + 3*8]);
77 let tmp = W7 * (in4 + in5);
78 let a4 = (tmp + (W1 - W7) * in4) >> 3;
79 let a5 = (tmp - (W1 + W7) * in5) >> 3;
81 let tmp = W3 * (in6 + in7);
82 let a6 = (tmp - (W3 - W5) * in6) >> 3;
83 let a7 = (tmp - (W3 + W5) * in7) >> 3;
88 let t1 = W6 * (in2 + in3);
89 let a2 = (t1 - (W2 + W6) * in2) >> 3;
90 let a3 = (t1 + (W2 - W6) * in3) >> 3;
100 let b2 = (W8 * (b4 + t2) + 128) >> 8;
101 let b4 = (W8 * (b4 - t2) + 128) >> 8;
103 blk[off + 0*8] = ((b7 + b1) >> COL_SHIFT) as i16;
104 blk[off + 7*8] = ((b7 - b1) >> COL_SHIFT) as i16;
105 blk[off + 1*8] = ((b3 + b2) >> COL_SHIFT) as i16;
106 blk[off + 6*8] = ((b3 - b2) >> COL_SHIFT) as i16;
107 blk[off + 2*8] = ((b0 + b4) >> COL_SHIFT) as i16;
108 blk[off + 5*8] = ((b0 - b4) >> COL_SHIFT) as i16;
109 blk[off + 3*8] = ((b5 + b6) >> COL_SHIFT) as i16;
110 blk[off + 4*8] = ((b5 - b6) >> COL_SHIFT) as i16;
113 fn idct(blk: &mut [i16; 64]) {
114 for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
115 for i in 0..8 { idct_col(blk, i); }
118 fn put_block(blk: &[i16; 64], dst: &mut [u8], stride: usize) {
119 for (drow, srow) in dst.chunks_mut(stride).zip(blk.chunks(8)) {
120 for (del, &pix) in drow.iter_mut().zip(srow.iter()) {
121 *del = pix.max(0).min(255) as u8;
126 #[derive(Clone,Copy,Default)]
127 struct ComponentInfo {
133 #[derive(Debug,PartialEq)]
148 info: NACodecInfoRef,
149 quant: [[i16; 64]; 4],
150 qselect: [u8; MAX_CHROMATONS],
151 comp_id: [u8; MAX_CHROMATONS],
152 subsamp: [u8; MAX_CHROMATONS],
153 codebook: [[Option<Codebook<u8>>; 4]; 2],
160 fn read_dc(br: &mut BitReader, cb: &Codebook<u8>) -> DecoderResult<i16> {
161 let cat = br.read_cb(cb)?;
166 let add_bits = br.read(cat)? as i16;
167 let pivot = 1 << (cat - 1);
168 if add_bits < pivot {
169 Ok(add_bits + 1 - pivot * 2)
176 fn read_ac(br: &mut BitReader, cb: &Codebook<u8>) -> DecoderResult<(usize, i16)> {
177 let val = br.read_cb(cb)?;
178 let run = usize::from(val >> 4);
180 let level = if cat != 0 {
182 let add_bits = br.read(cat)? as i16;
183 let pivot = 1 << (cat - 1);
184 if add_bits < pivot {
185 add_bits + 1 - pivot * 2
190 validate!(run == 0 || run == 15);
196 fn read_block(br: &mut BitReader, blk: &mut [i16; 64], dc_cb: &Codebook<u8>, ac_cb: &Codebook<u8>, ss: usize, se: usize, qmat: &[i16; 64]) -> DecoderResult<()> {
198 blk[0] = read_dc(br, dc_cb)?;
203 let (run, level) = read_ac(br, ac_cb)?;
204 if run == 0 && level == 0 {
209 blk[ZIGZAG[idx]] = level * qmat[idx];
217 let dummy_info = NACodecInfo::new_dummy();
222 qselect: [0; MAX_CHROMATONS],
223 subsamp: [0; MAX_CHROMATONS],
224 comp_id: [0; MAX_CHROMATONS],
225 codebook: [[None, None, None, None], [None, None, None, None]],
232 fn reset(&mut self) {
233 self.quant = [[0; 64]; 4];
234 self.codebook = [[None, None, None, None], [None, None, None, None]];
240 #[allow(clippy::many_single_char_names)]
241 fn parse_sof(&mut self, br: &mut ByteReader) -> DecoderResult<NABufferType> {
242 validate!(self.width == 0);
244 let len = br.read_u16be()? as usize;
245 validate!(len >= 11);
246 let p = br.read_byte()?;
249 return Err(DecoderError::NotImplemented);
251 let y = br.read_u16be()? as usize;
252 let x = br.read_u16be()? as usize;
255 return Err(DecoderError::NotImplemented);
260 let nf = br.read_byte()? as usize;
262 validate!(len == 8 + nf * 3);
263 if nf > MAX_CHROMATONS {
264 return Err(DecoderError::NotImplemented);
269 let c = br.read_byte()?;
271 let hv = br.read_byte()?;
272 let t = br.read_byte()?;
275 self.subsamp[i] = hv;
277 validate!(hs == 1 || hs == 2);
279 validate!(vs == 1 || vs == 2);
280 max_h = max_h.max(hs);
281 max_v = max_v.max(vs);
283 let mut chromatons = [None; MAX_CHROMATONS];
284 for (i, chr) in chromatons[..nf].iter_mut().enumerate() {
285 let h_ss = match max_h / (self.subsamp[i] >> 4) {
290 let v_ss = match max_v / (self.subsamp[i] & 0xF) {
293 _ => return Err(DecoderError::InvalidData),
296 *chr = Some(NAPixelChromaton {
302 next_elem: (p + 7) >> 3,
307 validate!(self.comp_id[i] != self.comp_id[j]);
310 let formaton = NAPixelFormaton {
311 model: ColorModel::YUV(YUVSubmodel::YUVJ),
312 components: nf as u8,
313 comp_info: chromatons,
316 alpha: nf == 2 || nf == 4,
319 let vinfo = NAVideoInfo::new(x, y, false, formaton);
320 Ok(alloc_video_buffer(vinfo, 4)?)
323 fn decode_scan(&mut self, src: &[u8], mut buf: NAVideoBufferRef<u8>, ci: &[ComponentInfo], ss: usize, se: usize) -> DecoderResult<usize> {
324 let num_components = ci.len();
325 let mut last_dc = [1024; MAX_CHROMATONS];
326 let mut dc_cbs = Vec::with_capacity(num_components);
327 let mut ac_cbs = Vec::with_capacity(num_components);
328 let mut qmats = [&self.quant[0]; MAX_CHROMATONS];
329 for (i, cinfo) in ci.iter().enumerate() {
330 dc_cbs.push(if let Some(ref cb) = self.codebook[0][cinfo.dc_table_id] {
332 } else { unreachable!(); });
333 ac_cbs.push(if let Some(ref cb) = self.codebook[1][cinfo.ac_table_id] {
335 } else { unreachable!(); });
336 qmats[i] = &self.quant[self.qselect[cinfo.component_id] as usize];
339 let frm = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
341 let mut br = BitReader::new(src, BitReaderMode::BE);
343 let mut offs = frm.offset;
344 let mut nblks = [0; MAX_CHROMATONS];
345 let mut xstep = [0; MAX_CHROMATONS];
346 let mut ystep = [0; MAX_CHROMATONS];
349 for i in 0..num_components {
350 let hs = (self.subsamp[i] >> 4) as usize;
351 let vs = (self.subsamp[i] & 0xF) as usize;
352 hstep = hstep.max(hs * 8);
353 vstep = vstep.max(vs * 8);
360 for _y in (0..self.height).step_by(vstep) {
361 for x in 0..(self.width + hstep - 1) / hstep {
362 for i in 0..num_components {
363 blocks = [[0; 64]; 4];
364 for blk in blocks[..nblks[i]].iter_mut() {
365 read_block(&mut br, blk, dc_cbs[i], ac_cbs[i], ss, se, qmats[i])?;
366 blk[0] += last_dc[i];
370 match self.subsamp[i] {
372 put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], frm.stride[i]);
375 put_block(&blocks[0], &mut frm.data[offs[i] + x * 16..], frm.stride[i]);
376 put_block(&blocks[1], &mut frm.data[offs[i] + x * 16 + 8..], frm.stride[i]);
379 put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], frm.stride[i]);
380 put_block(&blocks[1], &mut frm.data[offs[i] + x * 8 + frm.stride[i] * 8..], frm.stride[i]);
384 put_block(&blocks[j], &mut frm.data[offs[i] + x * 16 + (j & 1) * 8 + (j >> 1) * 8 * frm.stride[i]..], frm.stride[i]);
391 for i in 0..num_components {
392 offs[i] += frm.stride[i] * ystep[i];
396 Ok((br.tell() + 7) / 8)
400 struct HuffDescReader<'a> {
406 impl<'a> CodebookDescReader<u8> for HuffDescReader<'a> {
407 fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] }
408 fn code(&mut self, idx: usize) -> u32 { u32::from(self.codes[idx]) }
409 fn sym (&mut self, idx: usize) -> u8 { self.syms[idx] }
410 fn len(&mut self) -> usize { self.syms.len() }
413 fn generate_cb(lens: &[u8; 16], syms: &[u8]) -> DecoderResult<Codebook<u8>> {
414 let mut codes = [0; 256];
415 let mut bits = [0; 256];
417 let mut iter = bits.iter_mut();
418 for (i, &len) in lens.iter().enumerate() {
420 *iter.next().unwrap() = (i + 1) as u8;
424 let mut si = bits[0];
426 while idx < syms.len() {
427 while idx < syms.len() && bits[idx] == si {
432 while idx < syms.len() && bits[idx] != si {
438 let mut cbr = HuffDescReader { codes: &codes, bits: &bits, syms };
439 Ok(Codebook::new(&mut cbr, CodebookMode::MSB)?)
442 fn build_default_cb(dc: bool, idx: usize) -> DecoderResult<Codebook<u8>> {
444 generate_cb(&DC_LENS[idx], &DC_SYMS)
446 generate_cb(&AC_LENS[idx], &AC_SYMS[idx])
450 impl NADecoder for JPEGDecoder {
451 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
452 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
453 let w = vinfo.get_width();
454 let h = vinfo.get_height();
455 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, YUV420_FORMAT));
456 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
459 Err(DecoderError::InvalidData)
462 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
463 let src = pkt.get_buffer();
464 if src.len() <= 4 { return Err(DecoderError::ShortData); }
466 let mut bufinfo = NABufferType::None;
467 let mut mr = MemoryReader::new_read(&src);
468 let mut br = ByteReader::new(&mut mr);
469 let start_tag = br.read_u16be()?;
470 validate!(start_tag == 0xFFD8);
472 let mut jtype = JPEGType::None;
473 let mut arith = false;
476 let tag = br.read_u16be()?;
478 0xFFC0 => { //baseline DCT header
479 jtype = JPEGType::Baseline;
481 bufinfo = self.parse_sof(&mut br)?;
484 jtype = JPEGType::Extended;
486 bufinfo = self.parse_sof(&mut br)?;
489 jtype = JPEGType::Progressive;
491 bufinfo = self.parse_sof(&mut br)?;
494 jtype = JPEGType::Lossless;
496 bufinfo = self.parse_sof(&mut br)?;
499 jtype = JPEGType::Differential;
501 bufinfo = self.parse_sof(&mut br)?;
504 jtype = JPEGType::DiffProgressive;
506 bufinfo = self.parse_sof(&mut br)?;
509 jtype = JPEGType::DiffLossless;
511 bufinfo = self.parse_sof(&mut br)?;
513 0xFFC8 => return Err(DecoderError::NotImplemented),
515 jtype = JPEGType::Extended;
517 bufinfo = self.parse_sof(&mut br)?;
520 jtype = JPEGType::Progressive;
522 bufinfo = self.parse_sof(&mut br)?;
525 jtype = JPEGType::Lossless;
527 bufinfo = self.parse_sof(&mut br)?;
530 jtype = JPEGType::Differential;
532 bufinfo = self.parse_sof(&mut br)?;
535 jtype = JPEGType::DiffProgressive;
537 bufinfo = self.parse_sof(&mut br)?;
540 jtype = JPEGType::DiffLossless;
542 bufinfo = self.parse_sof(&mut br)?;
544 0xFFC4 => { //huff table
546 let len = u64::from(br.read_u16be()?);
548 let end = br.tell() + len - 2;
549 let mut lens = [0; 16];
550 let mut syms = [0; 256];
551 while br.tell() < end {
552 let tctn = br.read_byte()? as usize;
553 let tclass = tctn >> 4;
554 validate!(tclass < 2);
557 br.read_buf(&mut lens)?;
558 let mut tot_len = 0usize;
559 for &el in lens.iter() {
560 tot_len += usize::from(el);
562 validate!(tot_len > 0 && tot_len <= 256);
563 br.read_buf(&mut syms[..tot_len])?;
564 self.codebook[tclass][id] = Some(generate_cb(&lens, &syms[..tot_len])?);
566 validate!(br.tell() == end);
568 0xFFCC => { // arith coding conditioning
569 return Err(DecoderError::NotImplemented);
571 0xFFD0..=0xFFD7 => return Err(DecoderError::NotImplemented),
573 0xFFDA => { //start of scan
574 let len = br.read_u16be()? as usize;
575 let ns = br.read_byte()? as usize;
576 validate!(len == ns * 2 + 6);
577 let mut ci = [ComponentInfo::default(); MAX_CHROMATONS];
578 for info in ci[..ns].iter_mut() {
579 let id = br.read_byte()?;
580 let mut found = false;
581 for (i, &c_id) in self.comp_id.iter().enumerate() {
583 info.component_id = i;
589 let tdta = br.read_byte()? as usize;
590 let dc_id = tdta >> 4;
591 validate!(dc_id < 4);
592 if self.codebook[0][dc_id].is_none() {
593 validate!(dc_id < 2);
594 self.codebook[0][dc_id] = Some(build_default_cb(true, dc_id)?);
596 let ac_id = tdta & 0xF;
597 validate!(ac_id < 4);
598 if self.codebook[1][ac_id].is_none() {
599 validate!(ac_id < 2);
600 self.codebook[1][ac_id] = Some(build_default_cb(false, ac_id)?);
602 info.dc_table_id = dc_id;
603 info.ac_table_id = ac_id;
605 let ss = br.read_byte()? as usize;
606 let se = br.read_byte()? as usize;
607 let ahal = br.read_byte()?;
611 JPEGType::Baseline | JPEGType::Extended => {
613 return Err(DecoderError::NotImplemented);
615 validate!(ss == 0 && se == 63);
616 validate!(ah == 0 && al == 0);
617 if let Some(buf) = bufinfo.get_vbuf() {
618 let max_size = src.len() - (br.tell() as usize);
620 self.buf.reserve(max_size);
622 let b = br.read_byte()?;
626 let b2 = br.read_byte()?;
630 br.seek(std::io::SeekFrom::Current(-2))?;
636 let mut data = Vec::new();
637 std::mem::swap(&mut self.buf, &mut data);
638 let ret = self.decode_scan(&data, buf, &ci[..ns], ss, se);
639 std::mem::swap(&mut self.buf, &mut data);
640 if let Err(err) = ret {
643 } else { unreachable!(); }
645 JPEGType::Progressive => {
646 validate!(ss < 64 && se < 64 && se >= ss);
647 validate!(ah < 14 && al < 14);
648 return Err(DecoderError::NotImplemented);
650 JPEGType::Lossless => {
651 validate!(ss >= 1 && ss < 8 && se == 0);
653 return Err(DecoderError::NotImplemented);
655 _ => return Err(DecoderError::NotImplemented),
657 let tag = br.peek_u16be()?;
658 validate!((tag >= 0xFFD0 && tag <= 0xFFD7) || (tag == 0xFFD9));
660 0xFFDB => { //quant tables
661 let mut len = br.read_u16be()? as usize;
662 validate!(len >= 64 + 3);
665 let pt = br.read_byte()?;
666 let precision = pt >> 4;
667 validate!(precision < 2);
668 let id = (pt & 0xF) as usize;
670 let qsize = if precision == 0 { 64 } else { 64 * 2 } + 1;
671 validate!(len >= qsize);
673 for el in self.quant[id].iter_mut() {
674 *el = i16::from(br.read_byte()?);
677 for el in self.quant[id].iter_mut() {
678 *el = br.read_u16be()? as i16;
684 0xFFDC => { //number of lines
685 return Err(DecoderError::NotImplemented);
688 let len = br.read_u16be()?;
690 let ri = br.read_u16be()?;
692 println!("restart interval {}", ri);
693 return Err(DecoderError::NotImplemented);
696 0xFFDE => return Err(DecoderError::NotImplemented),
697 0xFFDF => return Err(DecoderError::NotImplemented),
698 0xFFE0..=0xFFEF => { // application data
699 let len = br.read_u16be()? as usize;
701 br.read_skip(len - 2)?;
703 0xFFF0..=0xFFF6 => return Err(DecoderError::NotImplemented),
705 //jtype = JPEGType::JPEGLS;
707 return Err(DecoderError::NotImplemented);
709 0xFFF8 => return Err(DecoderError::NotImplemented), //JPEG-LS parameters
710 0xFFF9..=0xFFFD => return Err(DecoderError::NotImplemented),
711 0xFFFE => { //comment
712 let len = br.read_u16be()? as usize;
714 br.read_skip(len - 2)?;
716 0xFF01 => return Err(DecoderError::NotImplemented),
717 0xFF02..=0xFFBF => return Err(DecoderError::NotImplemented),
718 _ => return Err(DecoderError::InvalidData),
721 validate!(jtype != JPEGType::None);
723 if let NABufferType::None = bufinfo {
724 return Err(DecoderError::InvalidData);
727 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
728 frm.set_keyframe(true);
729 frm.set_frame_type(FrameType::I);
732 fn flush(&mut self) {
736 impl NAOptionHandler for JPEGDecoder {
737 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
738 fn set_options(&mut self, _options: &[NAOption]) { }
739 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
742 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
743 Box::new(JPEGDecoder::new())
748 use nihav_core::codecs::RegisteredDecoders;
749 use nihav_core::demuxers::RegisteredDemuxers;
750 use nihav_codec_support::test::dec_video::*;
751 use crate::generic_register_all_decoders;
752 use crate::generic_register_all_demuxers;
755 let mut dmx_reg = RegisteredDemuxers::new();
756 generic_register_all_demuxers(&mut dmx_reg);
757 let mut dec_reg = RegisteredDecoders::new();
758 generic_register_all_decoders(&mut dec_reg);
759 // sample: self-created with avconv
760 test_decoding("avi", "jpeg", "assets/Misc/mjpeg.avi", Some(1), &dmx_reg,
761 &dec_reg, ExpectedTestResult::MD5Frames(vec![
762 [0xe07f7128, 0x8c55eb5d, 0x03bfdee5, 0x358b24a4],
763 [0xd3ec3f92, 0x1664c56d, 0xfc049754, 0xf65165b9]]));
767 const DC_LENS: [[u8; 16]; 2] = [
768 [ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 ],
769 [ 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ]
771 const DC_SYMS: [u8; 12] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
772 const AC_LENS: [[u8; 16]; 2] = [
773 [ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 ],
774 [ 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119 ]
776 const AC_SYMS: [&[u8]; 2] = [
778 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
779 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
780 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
781 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
782 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
783 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
784 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
785 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
786 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
787 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
788 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
789 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
790 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
791 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
792 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
793 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
794 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
795 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
796 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
797 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
801 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
802 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
803 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
804 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
805 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
806 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
807 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
808 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
809 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
810 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
811 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
812 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
813 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
814 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
815 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
816 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
817 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
818 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
819 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
820 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,