1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
//! Data Matrix (ECC 200) decoding and encoding library with an optimizing encoder. //! //! # Usage example //! //! ```rust //! # use datamatrix::SymbolSize; //! let bitmap = datamatrix::encode( //! b"Hello, World!", //! SymbolSize::Min, //! ).unwrap(); //! print!("{}", bitmap.unicode()); //! ``` //! //! This toy example will print a Data Matrix using Unicode block characters. //! For guidance on how to generate other output formats see the helper functions //! defined for the [Bitmap struct](Bitmap), or the `examples/` directory of //! this project. //! //! You can specify other symbol sizes, see [SymbolSize] for details. //! //! # Character encoding notes for Data Matrix //! //! > **TL;DR** Data should be printable ASCII because many decoders lack a proper charset //! > handling. Latin 1 is the next best choice, otherwise you rely on auto detection hacks of //! > decoders. This does not apply if you have control over decoding or if you are not overly paranoidal. //! //! This full section also applies to QR codes. //! //! Be careful when encoding strings which contain non printable ASCII characters. //! While indicating for example UTF-8 encoding is possible through [ECI](https://en.wikipedia.org/wiki/Extended_Channel_Interpretation), //! we doubt that many decoders around the world implement this. //! Also notice that some decoders are used as a keyboard source (e.g., handheld scanners) //! which _may_ be constrained by platform/locale specific keyboard layouts with //! limited Unicode input capabilities. We therefore recommend to stay within //! the _printable_ ASCII characters unless you have control over the full encoding //! and decoding process. //! //! The Data Matrix specification defines ISO 8859-1 (Latin 1) as the standard //! charset. Our tests indicate that some decoders (smartphone scanner apps) are //! reluctant to follow this and return binary output if there are charactes in //! the upper range, which is a safe choice. Unfortunately, some decoders try to guess the charset //! or just always assume UTF-8. //! //! To forestall your question: The full 8bit range can be encoded and //! the decoder will also return this exact input. So the problems mentioned above //! are related to the _interpretation_ of the data and possible input limitations //! in the case of handheld scanners. //! //! # Current limitations //! //! No visual detection is currently implemented, but the decoding backend //! is done and exposed in the API. All that is missing is a detector to extract a matrix of true and false values //! from an image. A general purpose detector is planned for the future, though. //! //! Other limitations: Currently there is no support for GS1, FCN1 characters, //! macro characters, ECI, structured append, and //! reader programming. The decoding output format specified in ISO/IEC 15424 is //! also not implemented (metadata, ECI, etc.), if you have a use case for this //! let us know. mod decodation; mod encodation; pub mod errorcode; pub mod placement; mod symbol_size; pub mod data; pub use symbol_size::SymbolSize; use encodation::DataEncodingError; use placement::{Bitmap, MatrixMap, Visitor}; struct CodewordPlacer(Vec<u8>); impl Visitor<bool> for CodewordPlacer { fn visit(&mut self, idx: usize, bits: [&mut bool; 8]) { let codeword = self.0[idx]; for i in 0..8 { // 0 = MSB // 7 = LSB *bits[i] = ((codeword >> (7 - i)) & 1) == 1; } } } /// Encode data as a Data Matrix (ECC200). /// /// Please read the [module documentation](crate) for some charset notes. If you /// did that and your input can be represented with the Latin 1 charset you may /// use the conversion function in the [data module](crate::data). If you only /// use printable ASCII you can just pass the data as is. /// /// If the data does not fit into the given size encoding will fail. The encoder /// can automatically pick the smallest size which fits the data (see [SymbolSize]) /// but there is an upper limit. pub fn encode(data: &[u8], symbol_size: SymbolSize) -> Result<Bitmap<bool>, DataEncodingError> { let (mut codewords, symbol_size) = data::encode_data(data, symbol_size, None)?; let ecc = errorcode::encode_error(&codewords, symbol_size); codewords.extend_from_slice(&ecc); let mut map = MatrixMap::new(symbol_size); map.traverse(&mut CodewordPlacer(codewords)); Ok(map.bitmap()) } /// Encode a string as a Data Matrix (ECC200). #[doc(hidden)] pub fn encode_eci( data: &[u8], symbol_size: SymbolSize, eci: u32, ) -> Result<Bitmap<bool>, DataEncodingError> { let (mut codewords, symbol_size) = data::encode_data(data, symbol_size, Some(eci))?; let ecc = errorcode::encode_error(&codewords, symbol_size); codewords.extend_from_slice(&ecc); let mut map = MatrixMap::new(symbol_size); map.traverse(&mut CodewordPlacer(codewords)); Ok(map.bitmap()) }