diff --git a/src/qrcode/decoder/DataMaskTestCase.java b/src/qrcode/decoder/DataMaskTestCase.java deleted file mode 100644 index 913c7d3..0000000 --- a/src/qrcode/decoder/DataMaskTestCase.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.common.BitMatrix; -import org.junit.Assert; -import org.junit.Test; - -/** - * @author Sean Owen - */ -public final class DataMaskTestCase extends Assert { - - @Test - public void testMask0() { - testMaskAcrossDimensions(0, (i, j) -> (i + j) % 2 == 0); - } - - @Test - public void testMask1() { - testMaskAcrossDimensions(1, (i, j) -> i % 2 == 0); - } - - @Test - public void testMask2() { - testMaskAcrossDimensions(2, (i, j) -> j % 3 == 0); - } - - @Test - public void testMask3() { - testMaskAcrossDimensions(3, (i, j) -> (i + j) % 3 == 0); - } - - @Test - public void testMask4() { - testMaskAcrossDimensions(4, (i, j) -> (i / 2 + j / 3) % 2 == 0); - } - - @Test - public void testMask5() { - testMaskAcrossDimensions(5, (i, j) -> (i * j) % 2 + (i * j) % 3 == 0); - } - - @Test - public void testMask6() { - testMaskAcrossDimensions(6, (i, j) -> ((i * j) % 2 + (i * j) % 3) % 2 == 0); - } - - @Test - public void testMask7() { - testMaskAcrossDimensions(7, (i, j) -> ((i + j) % 2 + (i * j) % 3) % 2 == 0); - } - - private static void testMaskAcrossDimensions(int reference, MaskCondition condition) { - DataMask mask = DataMask.values()[reference]; - for (int version = 1; version <= 40; version++) { - int dimension = 17 + 4 * version; - testMask(mask, dimension, condition); - } - } - - private static void testMask(DataMask mask, int dimension, MaskCondition condition) { - BitMatrix bits = new BitMatrix(dimension); - mask.unmaskBitMatrix(bits, dimension); - for (int i = 0; i < dimension; i++) { - for (int j = 0; j < dimension; j++) { - assertEquals( - "(" + i + ',' + j + ')', - condition.isMasked(i, j), - bits.get(j, i)); - } - } - } - - @FunctionalInterface - private interface MaskCondition { - boolean isMasked(int i, int j); - } - -} diff --git a/src/qrcode/decoder/DataMaskTestCase.rs b/src/qrcode/decoder/DataMaskTestCase.rs new file mode 100644 index 0000000..b18e2df --- /dev/null +++ b/src/qrcode/decoder/DataMaskTestCase.rs @@ -0,0 +1,97 @@ +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::common::BitMatrix; + +use super::DataMask; + +/** + * @author Sean Owen + */ + +type MaskCondition = fn(u32, u32) -> bool; + +#[test] +fn testMask0() { + testMaskAcrossDimensions(DataMask::DATA_MASK_000, |i, j| ((i + j) % 2 == 0)); +} + +#[test] +fn testMask1() { + testMaskAcrossDimensions(DataMask::DATA_MASK_001, |i, j| i % 2 == 0); +} + +#[test] +fn testMask2() { + testMaskAcrossDimensions(DataMask::DATA_MASK_010, |i, j| j % 3 == 0); +} + +#[test] +fn testMask3() { + testMaskAcrossDimensions(DataMask::DATA_MASK_011, |i, j| (i + j) % 3 == 0); +} + +#[test] +fn testMask4() { + testMaskAcrossDimensions(DataMask::DATA_MASK_100, |i, j| (i / 2 + j / 3) % 2 == 0); +} + +#[test] +fn testMask5() { + testMaskAcrossDimensions(DataMask::DATA_MASK_101, |i, j| { + (i * j) % 2 + (i * j) % 3 == 0 + }); +} + +#[test] +fn testMask6() { + testMaskAcrossDimensions(DataMask::DATA_MASK_110, |i, j| { + ((i * j) % 2 + (i * j) % 3) % 2 == 0 + }); +} + +#[test] +fn testMask7() { + testMaskAcrossDimensions(DataMask::DATA_MASK_111, |i, j| { + ((i + j) % 2 + (i * j) % 3) % 2 == 0 + }); +} + +fn testMaskAcrossDimensions(mask: DataMask, condition: MaskCondition) { + // let mask = DataMask.values()[reference]; + for version in 1..=40 { + // for (int version = 1; version <= 40; version++) { + let dimension = 17 + 4 * version; + testMask(mask, dimension, condition); + } +} + +fn testMask(mask: DataMask, dimension: u32, condition: MaskCondition) { + let mut bits = BitMatrix::with_single_dimension(dimension); + mask.unmaskBitMatrix(&mut bits, dimension); + for i in 0..dimension { + // for (int i = 0; i < dimension; i++) { + for j in 0..dimension { + // for (int j = 0; j < dimension; j++) { + assert_eq!(condition(i, j), bits.get(j, i), "({},{})", i, j); + } + } +} + +// @FunctionalInterface +// private interface MaskCondition { +// boolean isMasked(int i, int j); +// } diff --git a/src/qrcode/decoder/DataMask.java b/src/qrcode/decoder/data_mask.rs similarity index 59% rename from src/qrcode/decoder/DataMask.java rename to src/qrcode/decoder/data_mask.rs index e60868d..70a6c96 100755 --- a/src/qrcode/decoder/DataMask.java +++ b/src/qrcode/decoder/data_mask.rs @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.google.zxing.qrcode.decoder; - -import com.google.zxing.common.BitMatrix; +use crate::common::BitMatrix; /** *

Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations @@ -29,9 +27,89 @@ import com.google.zxing.common.BitMatrix; * * @author Sean Owen */ -enum DataMask { +#[derive(Copy,Clone,Eq, PartialEq)] +pub enum DataMask { + // See ISO 18004:2006 6.8.1 + /** + * 000: mask bits for which (x + y) mod 2 == 0 + */ + DATA_MASK_000, - // See ISO 18004:2006 6.8.1 + /** + * 001: mask bits for which x mod 2 == 0 + */ + DATA_MASK_001, + + /** + * 010: mask bits for which y mod 3 == 0 + */ + DATA_MASK_010, + + /** + * 011: mask bits for which (x + y) mod 3 == 0 + */ + DATA_MASK_011, + + /** + * 100: mask bits for which (x/2 + y/3) mod 2 == 0 + */ + DATA_MASK_100, + + /** + * 101: mask bits for which xy mod 2 + xy mod 3 == 0 + * equivalently, such that xy mod 6 == 0 + */ + DATA_MASK_101, + + /** + * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0 + * equivalently, such that xy mod 6 < 3 + */ + DATA_MASK_110, + + /** + * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0 + * equivalently, such that (x + y + xy mod 3) mod 2 == 0 + */ + DATA_MASK_111, + // End of enum constants. +} + +impl DataMask { + /** + *

Implementations of this method reverse the data masking process applied to a QR Code and + * make its bits ready to read.

+ * + * @param bits representation of QR Code bits + * @param dimension dimension of QR Code, represented by bits, being unmasked + */ + pub fn unmaskBitMatrix(&self, bits: &mut BitMatrix, dimension: u32) { + for i in 0..dimension { + // for (int i = 0; i < dimension; i++) { + for j in 0..dimension { + // for (int j = 0; j < dimension; j++) { + if self.isMasked(i, j) { + bits.flip_coords(j, i); + } + } + } + } + + pub fn isMasked(&self, i: u32, j: u32) -> bool { + match self { + DataMask::DATA_MASK_000 => ((i + j) & 0x01) == 0, + DataMask::DATA_MASK_001 => (i & 0x01) == 0, + DataMask::DATA_MASK_010 => j % 3 == 0, + DataMask::DATA_MASK_011 => (i + j) % 3 == 0, + DataMask::DATA_MASK_100 => (((i / 2) + (j / 3)) & 0x01) == 0, + DataMask::DATA_MASK_101 => (i * j) % 6 == 0, + DataMask::DATA_MASK_110 => ((i * j) % 6) < 3, + DataMask::DATA_MASK_111 => ((i + j + ((i * j) % 3)) & 0x01) == 0, + } + } +} + +/* /** * 000: mask bits for which (x + y) mod 2 == 0 @@ -137,5 +215,4 @@ enum DataMask { } abstract boolean isMasked(int i, int j); - -} +*/ diff --git a/src/qrcode/decoder/mod.rs b/src/qrcode/decoder/mod.rs index e738d49..2f7f35b 100644 --- a/src/qrcode/decoder/mod.rs +++ b/src/qrcode/decoder/mod.rs @@ -4,6 +4,7 @@ mod error_correction_level; mod format_information; mod data_block; mod qr_code_decoder_metaData; +mod data_mask; #[cfg(test)] mod ErrorCorrectionLevelTestCase; @@ -13,10 +14,13 @@ mod ModeTestCase; mod VersionTestCase; #[cfg(test)] mod FormatInformationTestCase; +#[cfg(test)] +mod DataMaskTestCase; pub use version::*; pub use mode::*; pub use error_correction_level::*; pub use format_information::*; pub use data_block::*; -pub use qr_code_decoder_metaData::*; \ No newline at end of file +pub use qr_code_decoder_metaData::*; +pub use data_mask::*; \ No newline at end of file