1use crate::bit_writer::BitWriter;
8use crate::error::Result;
9
10#[derive(Debug, Clone, Copy)]
17pub struct FrameCrop {
18 pub x0: i32,
20 pub y0: i32,
22 pub width: u32,
24 pub height: u32,
26}
27
28#[derive(Debug, Clone, Default)]
33pub struct FrameOptions {
34 pub have_animation: bool,
36 pub have_timecodes: bool,
38 pub duration: u32,
40 pub is_last: bool,
42 pub crop: Option<FrameCrop>,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48#[repr(u8)]
49pub enum FrameType {
50 #[default]
52 Regular = 0,
53 LfFrame = 1,
55 ReferenceOnly = 2,
57 SkipProgressive = 3,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
63#[repr(u8)]
64pub enum Encoding {
65 #[default]
67 VarDct = 0,
68 Modular = 1,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
74#[repr(u8)]
75pub enum BlendMode {
76 #[default]
78 Replace = 0,
79 Add = 1,
81 Blend = 2,
83 AlphaWeightedAdd = 3,
85 Mul = 4,
87}
88
89pub const ENABLE_NOISE: u64 = 0x01;
91pub const PATCHES_FLAG: u64 = 0x02;
93pub const SPLINES_FLAG: u64 = 0x10;
95pub const USE_LF_FRAME: u64 = 0x20;
97pub const SKIP_ADAPTIVE_LF_SMOOTHING: u64 = 0x80;
99
100#[derive(Debug, Clone)]
105pub struct FrameHeader {
106 pub frame_type: FrameType,
108 pub encoding: Encoding,
110 pub xyb_encoded: bool,
113 pub flags: u64,
116 pub do_ycbcr: bool,
118 pub jpeg_upsampling: [u8; 3],
120 pub upsampling: u32,
122 pub ec_upsampling: Vec<u32>,
124 pub group_size_shift: u32,
126 pub x_qm_scale: u32,
128 pub b_qm_scale: u32,
130 pub num_passes: u32,
132 pub pass_shifts: Vec<u32>,
136 pub num_ds: u32,
138 pub ds_downsample: Vec<u32>,
140 pub ds_last_pass: Vec<u32>,
142 pub x0: i32,
144 pub y0: i32,
146 pub width: u32,
148 pub height: u32,
150 pub blend_mode: BlendMode,
152 pub ec_blend_modes: Vec<BlendMode>,
154 pub blend_source: u32,
156 pub alpha_blend_channel: u32,
158 pub save_as_reference: u32,
160 pub save_before_ct: bool,
162 pub name: String,
164 pub have_animation: bool,
167 pub have_timecodes: bool,
169 pub duration: u32,
171 pub timecode: u32,
173 pub is_last: bool,
175 pub lf_level: u32,
178 pub gaborish: bool,
180 pub epf_iters: u32,
182}
183
184impl Default for FrameHeader {
185 fn default() -> Self {
186 Self {
187 frame_type: FrameType::Regular,
188 encoding: Encoding::VarDct,
189 xyb_encoded: true,
190 flags: 0,
191 do_ycbcr: false,
192 jpeg_upsampling: [0; 3],
193 upsampling: 1,
194 ec_upsampling: Vec::new(),
195 group_size_shift: 1,
196 x_qm_scale: 2,
197 b_qm_scale: 2,
198 num_passes: 1,
199 pass_shifts: Vec::new(),
200 num_ds: 0,
201 ds_downsample: Vec::new(),
202 ds_last_pass: Vec::new(),
203 x0: 0,
204 y0: 0,
205 width: 0,
206 height: 0,
207 blend_mode: BlendMode::Replace,
208 blend_source: 0,
209 ec_blend_modes: Vec::new(),
210 alpha_blend_channel: 0,
211 save_as_reference: 0,
212 save_before_ct: false,
213 name: String::new(),
214 have_animation: false,
215 have_timecodes: false,
216 duration: 0,
217 timecode: 0,
218 is_last: true,
219 lf_level: 0,
220 gaborish: true,
221 epf_iters: 2,
222 }
223 }
224}
225
226impl FrameHeader {
227 pub fn lossy() -> Self {
232 Self {
233 encoding: Encoding::VarDct,
234 xyb_encoded: true,
235 flags: 0x80, gaborish: true,
237 epf_iters: 2,
238 ..Default::default()
239 }
240 }
241
242 pub fn lossless() -> Self {
247 Self {
248 encoding: Encoding::Modular,
249 xyb_encoded: false,
250 do_ycbcr: false,
251 flags: 0,
252 group_size_shift: 1,
253 gaborish: false,
254 epf_iters: 0,
255 ..Default::default()
256 }
257 }
258
259 pub fn lf_frame(width: u32, height: u32, lf_level: u32) -> Self {
265 Self {
266 frame_type: FrameType::LfFrame,
267 encoding: Encoding::Modular,
268 xyb_encoded: true,
269 flags: SKIP_ADAPTIVE_LF_SMOOTHING,
270 gaborish: false,
271 epf_iters: 0,
272 is_last: false,
273 save_before_ct: false,
274 width,
275 height,
276 lf_level,
277 group_size_shift: 1, ..Default::default()
279 }
280 }
281
282 pub fn write(&self, writer: &mut BitWriter) -> Result<()> {
286 let all_default = self.is_all_default();
291 writer.write_bit(all_default)?;
292 if all_default {
293 return Ok(());
294 }
295
296 writer.write(2, self.frame_type as u64)?;
298
299 writer.write(1, self.encoding as u64)?;
301
302 writer.write_u64_coder(self.flags)?;
304
305 if !self.xyb_encoded {
307 writer.write_bit(self.do_ycbcr)?;
308 }
309
310 if self.encoding == Encoding::VarDct && self.do_ycbcr && !self.xyb_encoded {
312 for &up in &self.jpeg_upsampling {
313 writer.write(2, up as u64)?;
314 }
315 }
316
317 if self.flags & USE_LF_FRAME == 0 {
320 writer.write_u32_coder(self.upsampling, 1, 2, 4, 8, 0)?;
322
323 for &ecu in &self.ec_upsampling {
325 writer.write_u32_coder(ecu, 1, 2, 4, 8, 0)?;
326 }
327 }
328
329 if self.encoding == Encoding::Modular {
331 writer.write(2, self.group_size_shift as u64)?;
332 }
333
334 if self.encoding == Encoding::VarDct && self.xyb_encoded {
336 writer.write(3, self.x_qm_scale as u64)?;
337 writer.write(3, self.b_qm_scale as u64)?;
338 }
339
340 if self.frame_type != FrameType::ReferenceOnly {
342 writer.write_u32_coder(self.num_passes, 1, 2, 3, 4, 3)?;
344 if self.num_passes != 1 {
345 self.write_passes(writer)?;
346 }
347 }
348
349 if self.frame_type == FrameType::LfFrame {
352 writer.write_u32_coder(self.lf_level, 1, 2, 3, 4, 0)?;
353 }
354
355 if self.frame_type != FrameType::LfFrame {
357 let have_crop = self.x0 != 0 || self.y0 != 0 || self.width != 0 || self.height != 0;
358 writer.write_bit(have_crop)?;
359 if have_crop {
360 if self.frame_type != FrameType::ReferenceOnly {
362 self.write_crop_origin(writer)?;
363 }
364 Self::write_crop_u32(writer, self.width)?;
366 Self::write_crop_u32(writer, self.height)?;
367 }
368 }
369
370 let normal_frame =
372 self.frame_type == FrameType::Regular || self.frame_type == FrameType::SkipProgressive;
373 if normal_frame {
374 self.write_blending_info(writer)?;
375 }
376
377 for &mode in &self.ec_blend_modes {
379 self.write_ec_blending_info(mode, writer)?;
380 }
381
382 if normal_frame && self.have_animation {
384 match self.duration {
386 0 => writer.write(2, 0)?,
387 1 => writer.write(2, 1)?,
388 d if d <= 255 => {
389 writer.write(2, 2)?;
390 writer.write(8, d as u64)?;
391 }
392 d => {
393 writer.write(2, 3)?;
394 writer.write(32, d as u64)?;
395 }
396 }
397 if self.have_timecodes {
398 writer.write(32, self.timecode as u64)?;
399 }
400 }
401
402 if normal_frame {
404 writer.write_bit(self.is_last)?;
405 }
406
407 if !self.is_last && self.frame_type != FrameType::LfFrame {
409 writer.write(2, self.save_as_reference as u64)?;
410
411 if self.frame_type == FrameType::ReferenceOnly {
415 writer.write_bit(self.save_before_ct)?;
416 } else {
417 let full_frame =
418 self.x0 == 0 && self.y0 == 0 && self.width == 0 && self.height == 0;
419 let resets_canvas = self.blend_mode == BlendMode::Replace && full_frame;
420 let can_be_referenced = self.duration == 0 || self.save_as_reference != 0;
421 if resets_canvas && can_be_referenced && normal_frame {
422 writer.write_bit(self.save_before_ct)?;
423 }
424 }
425 }
426
427 self.write_name(writer)?;
429
430 self.write_loop_filter(writer)?;
432
433 writer.write_u64_coder(0)?;
435
436 Ok(())
437 }
438
439 fn write_crop_origin(&self, writer: &mut BitWriter) -> Result<()> {
445 let x0u = if self.x0 >= 0 {
446 (self.x0 as u32) << 1
447 } else {
448 (((-self.x0 - 1) as u32) << 1) | 1
449 };
450 let y0u = if self.y0 >= 0 {
451 (self.y0 as u32) << 1
452 } else {
453 (((-self.y0 - 1) as u32) << 1) | 1
454 };
455 Self::write_crop_u32(writer, x0u)?;
456 Self::write_crop_u32(writer, y0u)?;
457 Ok(())
458 }
459
460 fn write_crop_u32(writer: &mut BitWriter, value: u32) -> Result<()> {
462 if value < 256 {
463 writer.write(2, 0)?; writer.write(8, value as u64)?;
465 } else if value < 2304 {
466 writer.write(2, 1)?; writer.write(11, (value - 256) as u64)?;
468 } else if value < 18688 {
469 writer.write(2, 2)?; writer.write(14, (value - 2304) as u64)?;
471 } else {
472 writer.write(2, 3)?; writer.write(30, (value - 18688) as u64)?;
474 }
475 Ok(())
476 }
477
478 fn write_blending_info(&self, writer: &mut BitWriter) -> Result<()> {
480 writer.write_u32_coder(self.blend_mode as u32, 0, 1, 2, 3, 2)?;
481
482 let full_frame = self.x0 == 0 && self.y0 == 0 && self.width == 0 && self.height == 0;
485 if !(full_frame && self.blend_mode == BlendMode::Replace) {
486 writer.write(2, self.blend_source as u64)?;
487 }
488
489 if self.blend_mode == BlendMode::Blend || self.blend_mode == BlendMode::AlphaWeightedAdd {
490 writer.write_u32_coder(self.alpha_blend_channel, 0, 1, 2, 3, 3)?;
491 writer.write_bit(false)?; }
493
494 Ok(())
495 }
496
497 fn write_ec_blending_info(&self, mode: BlendMode, writer: &mut BitWriter) -> Result<()> {
499 writer.write_u32_coder(mode as u32, 0, 1, 2, 3, 2)?;
500
501 let full_frame = self.x0 == 0 && self.y0 == 0 && self.width == 0 && self.height == 0;
502 if !(full_frame && mode == BlendMode::Replace) {
503 writer.write(2, 0)?; }
505
506 if mode == BlendMode::Blend || mode == BlendMode::AlphaWeightedAdd {
507 writer.write_u32_coder(0, 0, 1, 2, 3, 3)?; writer.write_bit(false)?; }
510
511 Ok(())
512 }
513
514 fn write_name(&self, writer: &mut BitWriter) -> Result<()> {
516 let name_len = self.name.len() as u32;
517 if name_len == 0 {
518 writer.write(2, 0)?; } else if name_len < 4 {
520 writer.write(2, 0)?; } else if name_len < 20 {
522 writer.write(2, 2)?;
523 writer.write(4, (name_len - 4) as u64)?;
524 } else {
525 writer.write(2, 3)?;
526 writer.write(10, (name_len - 20) as u64)?;
527 }
528 for byte in self.name.bytes() {
529 writer.write(8, byte as u64)?;
530 }
531 Ok(())
532 }
533
534 fn write_loop_filter(&self, writer: &mut BitWriter) -> Result<()> {
536 let lf_all_default = self.gaborish && self.epf_iters == 2;
538
539 writer.write_bit(lf_all_default)?;
540 if lf_all_default {
541 return Ok(());
542 }
543
544 writer.write_bit(self.gaborish)?;
546 if self.gaborish {
547 writer.write_bit(false)?; }
549
550 writer.write(2, self.epf_iters as u64)?;
552
553 if self.epf_iters > 0 {
555 writer.write_bit(false)?; writer.write_bit(false)?; writer.write_bit(false)?; }
559
560 writer.write_u64_coder(0)?;
562
563 Ok(())
564 }
565
566 fn write_passes(&self, writer: &mut BitWriter) -> Result<()> {
574 writer.write_u32_coder(self.num_ds, 0, 1, 2, 3, 1)?;
576
577 for i in 0..self.num_passes.saturating_sub(1) as usize {
579 let shift = self.pass_shifts.get(i).copied().unwrap_or(0);
580 writer.write(2, shift as u64)?;
581 }
582
583 for i in 0..self.num_ds as usize {
585 let ds = self.ds_downsample.get(i).copied().unwrap_or(1);
586 writer.write_u32_coder(ds, 1, 2, 4, 8, 0)?;
587 }
588
589 for i in 0..self.num_ds as usize {
591 let lp = self.ds_last_pass.get(i).copied().unwrap_or(0);
592 writer.write_u32_coder(lp, 0, 1, 2, 0, 3)?;
593 }
594
595 Ok(())
596 }
597
598 fn is_all_default(&self) -> bool {
604 self.frame_type == FrameType::Regular
605 && self.encoding == Encoding::VarDct
606 && self.xyb_encoded
607 && self.flags == 0
608 && self.do_ycbcr
609 && self.upsampling == 1
610 && self.ec_upsampling.is_empty()
611 && self.ec_blend_modes.is_empty()
612 && self.group_size_shift == 1
613 && self.x_qm_scale == 2
614 && self.b_qm_scale == 2
615 && self.num_passes == 1
616 && self.pass_shifts.is_empty()
617 && self.x0 == 0
618 && self.y0 == 0
619 && self.width == 0
620 && self.height == 0
621 && self.blend_mode == BlendMode::Replace
622 && self.blend_source == 0
623 && self.save_as_reference == 0
624 && !self.save_before_ct
625 && self.name.is_empty()
626 && !self.have_animation
627 && self.is_last
628 && self.gaborish
629 && self.epf_iters == 2
630 }
631}
632
633#[cfg(test)]
634mod tests {
635 use super::*;
636
637 #[test]
638 fn test_default_frame() {
639 let frame = FrameHeader::lossy();
640 let mut writer = BitWriter::new();
641 frame.write(&mut writer).unwrap();
642 }
643
644 #[test]
645 fn test_lossless_frame() {
646 let frame = FrameHeader::lossless();
647 assert_eq!(frame.encoding, Encoding::Modular);
648 assert!(!frame.do_ycbcr);
649 assert!(!frame.gaborish);
650 assert_eq!(frame.epf_iters, 0);
651
652 let mut writer = BitWriter::new();
653 frame.write(&mut writer).unwrap();
654 assert!(writer.bits_written() > 0);
655 }
656
657 #[test]
658 fn test_frame_type_values() {
659 assert_eq!(FrameType::Regular as u8, 0);
660 assert_eq!(FrameType::LfFrame as u8, 1);
661 assert_eq!(FrameType::ReferenceOnly as u8, 2);
662 assert_eq!(FrameType::SkipProgressive as u8, 3);
663 }
664
665 #[test]
666 fn test_encoding_values() {
667 assert_eq!(Encoding::VarDct as u8, 0);
668 assert_eq!(Encoding::Modular as u8, 1);
669 }
670
671 #[test]
672 fn test_blend_mode_values() {
673 assert_eq!(BlendMode::Replace as u8, 0);
674 assert_eq!(BlendMode::Add as u8, 1);
675 assert_eq!(BlendMode::Blend as u8, 2);
676 assert_eq!(BlendMode::AlphaWeightedAdd as u8, 3);
677 assert_eq!(BlendMode::Mul as u8, 4);
678 }
679
680 #[test]
681 fn test_frame_with_crop() {
682 let mut frame = FrameHeader::lossy();
683 frame.x0 = 0;
684 frame.y0 = 0;
685 frame.width = 20000;
686 frame.height = 20000;
687
688 let mut writer = BitWriter::new();
689 frame.write(&mut writer).unwrap();
690 assert!(writer.bits_written() > 10);
691 }
692
693 #[test]
694 fn test_frame_with_large_crop_offset() {
695 let mut frame = FrameHeader::lossy();
696 frame.x0 = 128;
697 frame.y0 = 128;
698 frame.width = 20000;
699 frame.height = 20000;
700
701 let mut writer = BitWriter::new();
702 frame.write(&mut writer).unwrap();
703 assert!(writer.bits_written() > 10);
704 }
705
706 #[test]
707 fn test_frame_with_name() {
708 let mut frame = FrameHeader::lossy();
709 frame.name = "TestFrame".to_string();
710
711 let mut writer = BitWriter::new();
712 frame.write(&mut writer).unwrap();
713 assert!(writer.bits_written() > 80);
714 }
715
716 #[test]
717 fn test_frame_with_long_name() {
718 let mut frame = FrameHeader::lossy();
719 frame.name = "ThisIsAVeryLongFrameName".to_string();
720
721 let mut writer = BitWriter::new();
722 frame.write(&mut writer).unwrap();
723 assert!(writer.bits_written() > 200);
724 }
725
726 #[test]
727 fn test_lf_frame_type() {
728 let frame = FrameHeader::lf_frame(32, 32, 1);
730
731 let mut writer = BitWriter::new();
732 frame.write(&mut writer).unwrap();
733 assert!(writer.bits_written() > 0);
734 }
735
736 #[test]
737 fn test_reference_only_frame() {
738 let mut frame = FrameHeader::lossy();
739 frame.frame_type = FrameType::ReferenceOnly;
740
741 let mut writer = BitWriter::new();
742 frame.write(&mut writer).unwrap();
743 assert!(writer.bits_written() > 0);
744 }
745
746 #[test]
747 fn test_skip_progressive_frame() {
748 let mut frame = FrameHeader::lossy();
749 frame.frame_type = FrameType::SkipProgressive;
750
751 let mut writer = BitWriter::new();
752 frame.write(&mut writer).unwrap();
753 assert!(writer.bits_written() > 0);
754 }
755
756 #[test]
757 fn test_blend_mode_add() {
758 let mut frame = FrameHeader::lossy();
759 frame.blend_mode = BlendMode::Add;
760
761 let mut writer = BitWriter::new();
762 frame.write(&mut writer).unwrap();
763 assert!(writer.bits_written() > 0);
764 }
765
766 #[test]
767 fn test_blend_mode_blend_with_alpha() {
768 let mut frame = FrameHeader::lossy();
769 frame.blend_mode = BlendMode::Blend;
770 frame.alpha_blend_channel = 1;
771
772 let mut writer = BitWriter::new();
773 frame.write(&mut writer).unwrap();
774 assert!(writer.bits_written() > 0);
775 }
776
777 #[test]
778 fn test_blend_mode_alpha_weighted_add() {
779 let mut frame = FrameHeader::lossy();
780 frame.blend_mode = BlendMode::AlphaWeightedAdd;
781 frame.alpha_blend_channel = 2;
782
783 let mut writer = BitWriter::new();
784 frame.write(&mut writer).unwrap();
785 assert!(writer.bits_written() > 0);
786 }
787
788 #[test]
789 fn test_blend_mode_mul() {
790 let mut frame = FrameHeader::lossy();
791 frame.blend_mode = BlendMode::Mul;
792
793 let mut writer = BitWriter::new();
794 frame.write(&mut writer).unwrap();
795 assert!(writer.bits_written() > 0);
796 }
797
798 #[test]
799 fn test_upsampling_factors() {
800 for upsampling in [1, 2, 4, 8] {
801 let mut frame = FrameHeader::lossy();
802 frame.upsampling = upsampling;
803
804 let mut writer = BitWriter::new();
805 frame.write(&mut writer).unwrap();
806 assert!(writer.bits_written() > 0);
807 }
808 }
809
810 #[test]
811 fn test_ec_upsampling() {
812 let mut frame = FrameHeader::lossy();
813 frame.ec_upsampling = vec![2, 4, 8];
814
815 let mut writer = BitWriter::new();
816 frame.write(&mut writer).unwrap();
817 assert!(writer.bits_written() > 0);
818 }
819
820 #[test]
821 fn test_group_size_shift() {
822 for shift in 0..4 {
823 let mut frame = FrameHeader::lossless();
824 frame.group_size_shift = shift;
825
826 let mut writer = BitWriter::new();
827 frame.write(&mut writer).unwrap();
828 assert!(writer.bits_written() > 0);
829 }
830 }
831
832 #[test]
833 fn test_save_as_reference() {
834 let mut frame = FrameHeader::lossy();
835 frame.save_as_reference = 2;
836 frame.is_last = false; let mut writer = BitWriter::new();
839 frame.write(&mut writer).unwrap();
840 assert!(writer.bits_written() > 0);
841 }
842
843 #[test]
844 fn test_not_last_frame() {
845 let mut frame = FrameHeader::lossy();
846 frame.is_last = false;
847
848 let mut writer = BitWriter::new();
849 frame.write(&mut writer).unwrap();
850 assert!(writer.bits_written() > 0);
851 }
852
853 #[test]
854 fn test_vardct_loop_filter_all_default() {
855 let frame = FrameHeader::lossy();
857 assert!(frame.gaborish && frame.epf_iters == 2);
858
859 let mut writer = BitWriter::new();
860 frame.write(&mut writer).unwrap();
861 }
862
863 #[test]
864 fn test_vardct_no_gaborish() {
865 let mut frame = FrameHeader::lossy();
866 frame.gaborish = false;
867 frame.epf_iters = 1;
868
869 let mut writer = BitWriter::new();
870 frame.write(&mut writer).unwrap();
871 assert!(writer.bits_written() > 0);
872 }
873
874 #[test]
875 fn test_vardct_no_epf() {
876 let mut frame = FrameHeader::lossy();
877 frame.gaborish = true;
878 frame.epf_iters = 0;
879
880 let mut writer = BitWriter::new();
881 frame.write(&mut writer).unwrap();
882 assert!(writer.bits_written() > 0);
883 }
884
885 #[test]
886 fn test_vardct_with_noise() {
887 let mut frame = FrameHeader::lossy();
888 frame.flags = 0x80 | 0x01; let mut writer = BitWriter::new();
891 frame.write(&mut writer).unwrap();
892 assert!(writer.bits_written() > 0);
893 }
894
895 #[test]
896 fn test_vardct_custom_qm_scale() {
897 let mut frame = FrameHeader::lossy();
898 frame.x_qm_scale = 5;
899 frame.b_qm_scale = 4;
900
901 let mut writer = BitWriter::new();
902 frame.write(&mut writer).unwrap();
903 assert!(writer.bits_written() > 0);
904 }
905
906 #[test]
907 fn test_vardct_with_extra_channels() {
908 let mut frame = FrameHeader::lossy();
909 frame.ec_upsampling = vec![1]; frame.ec_blend_modes = vec![BlendMode::Replace];
911
912 let mut writer = BitWriter::new();
913 frame.write(&mut writer).unwrap();
914 assert!(writer.bits_written() > 0);
915 }
916
917 #[test]
918 fn test_lossless_with_extra_channels() {
919 let mut frame = FrameHeader::lossless();
920 frame.ec_upsampling = vec![1]; frame.ec_blend_modes = vec![BlendMode::Replace];
922
923 let mut writer = BitWriter::new();
924 frame.write(&mut writer).unwrap();
925 assert!(writer.bits_written() > 0);
926 }
927
928 #[test]
931 fn test_vardct_bit_exact_vs_old() {
932 let mut old_writer = BitWriter::new();
935 old_writer.write(1, 0).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(2, 2).unwrap(); old_writer.write(8, 128 - 17).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(3, 3).unwrap(); old_writer.write(3, 2).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 1).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(1, 1).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(2, 1).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(2, 0).unwrap(); let mut new_writer = BitWriter::new();
961 let mut frame = FrameHeader::lossy();
962 frame.x_qm_scale = 3;
963 frame.b_qm_scale = 2;
964 frame.epf_iters = 1;
965 frame.write(&mut new_writer).unwrap();
966
967 assert_eq!(
969 old_writer.bits_written(),
970 new_writer.bits_written(),
971 "VarDCT frame header bit count should match"
972 );
973 old_writer.zero_pad_to_byte();
975 new_writer.zero_pad_to_byte();
976 assert_eq!(
977 old_writer.finish(),
978 new_writer.finish(),
979 "VarDCT frame header should be bit-exact"
980 );
981 }
982
983 #[test]
985 fn test_vardct_lf_all_default_bit_exact() {
986 let mut old_writer = BitWriter::new();
987 old_writer.write(1, 0).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(2, 2).unwrap(); old_writer.write(8, 128 - 17).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(3, 3).unwrap(); old_writer.write(3, 2).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 0).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 1).unwrap(); old_writer.write(2, 0).unwrap(); old_writer.write(1, 1).unwrap(); old_writer.write(2, 0).unwrap(); let mut new_writer = BitWriter::new();
1004 let mut frame = FrameHeader::lossy();
1005 frame.x_qm_scale = 3;
1006 frame.b_qm_scale = 2;
1007 frame.gaborish = true;
1008 frame.epf_iters = 2;
1009 frame.write(&mut new_writer).unwrap();
1010
1011 assert_eq!(
1012 old_writer.bits_written(),
1013 new_writer.bits_written(),
1014 "VarDCT lf all_default bit count should match"
1015 );
1016 old_writer.zero_pad_to_byte();
1017 new_writer.zero_pad_to_byte();
1018 assert_eq!(
1019 old_writer.finish(),
1020 new_writer.finish(),
1021 "VarDCT with lf all_default should be bit-exact"
1022 );
1023 }
1024}