#region PDFsharp - A .NET library for processing PDF // // Authors: // David Stephensen // // Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany) // // http://www.pdfsharp.com // http://sourceforge.net/projects/pdfsharp // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. #endregion using System; using System.Diagnostics; #if GDI using System.Drawing; using System.Drawing.Imaging; #endif #if WPF using System.Windows; using System.Windows.Media; #endif // WPFHACK #pragma warning disable 162 namespace PdfSharp.Drawing.BarCodes { /// /// Creates the XImage object for a DataMatrix. /// internal class DataMatrixImage { public static XImage GenerateMatrixImage(string text, string encoding, int rows, int columns) { DataMatrixImage dataMatrixImage = new DataMatrixImage(text, encoding, rows, columns); return dataMatrixImage.DrawMatrix(); } public DataMatrixImage(string text, string encoding, int rows, int columns) { _text = text; _encoding = encoding; _rows = rows; _columns = columns; } string _encoding; readonly string _text; readonly int _rows; readonly int _columns; /// /// Possible ECC200 Matrices. /// static Ecc200Block[] ecc200Sizes = { new Ecc200Block( 10, 10, 10, 10, 3, 3, 5), // new Ecc200Block( 12, 12, 12, 12, 5, 5, 7), // new Ecc200Block( 8, 18, 8, 18, 5, 5, 7), // new Ecc200Block( 14, 14, 14, 14, 8, 8, 10), // new Ecc200Block( 8, 32, 8, 16, 10, 10, 11), // new Ecc200Block( 16, 16, 16, 16, 12, 12, 12), // new Ecc200Block( 12, 26, 12, 26, 16, 16, 14), // new Ecc200Block( 18, 18, 18, 18, 18, 18, 14), // new Ecc200Block( 20, 20, 20, 20, 22, 22, 18), // new Ecc200Block( 12, 36, 12, 18, 22, 22, 18), // new Ecc200Block( 22, 22, 22, 22, 30, 30, 20), // Post new Ecc200Block( 16, 36, 16, 18, 32, 32, 24), // new Ecc200Block( 24, 24, 24, 24, 36, 36, 24), // new Ecc200Block( 26, 26, 26, 26, 44, 44, 28), // Post new Ecc200Block( 16, 48, 16, 24, 49, 49, 28), // new Ecc200Block( 32, 32, 16, 16, 62, 62, 36), // new Ecc200Block( 36, 36, 18, 18, 86, 86, 42), // new Ecc200Block( 40, 40, 20, 20, 114, 114, 48), // new Ecc200Block( 44, 44, 22, 22, 144, 144, 56), // new Ecc200Block( 48, 48, 24, 24, 174, 174, 68), // new Ecc200Block( 52, 52, 26, 26, 204, 102, 42), // new Ecc200Block( 64, 64, 16, 16, 280, 140, 56), // new Ecc200Block( 72, 72, 18, 18, 368, 92, 36), // new Ecc200Block( 80, 80, 20, 20, 456, 114, 48), // new Ecc200Block( 88, 88, 22, 22, 576, 144, 56), // new Ecc200Block( 96, 96, 24, 24, 696, 174, 68), // new Ecc200Block(104, 104, 26, 26, 816, 136, 56), // new Ecc200Block(120, 120, 20, 20, 1050, 175, 68), // new Ecc200Block(132, 132, 22, 22, 1304, 163, 62), // new Ecc200Block(144, 144, 24, 24, 1558, 156, 62), // 156*4+155*2 new Ecc200Block( 0, 0, 0, 0, 0, 0, 0) // terminate }; public XImage DrawMatrix() { return CreateImage(DataMatrix(), _rows, _columns); } /// /// Creates the DataMatrix code. /// internal char[] DataMatrix() { int matrixColumns = _columns; int matrixRows = _rows; int ecc = 200; if (String.IsNullOrEmpty(_encoding)) _encoding = new String('a', _text.Length); int len = 0; int maxlen = 0; int ecclen = 0; char[] grid = null; if (matrixColumns != 0 && matrixRows != 0 && (matrixColumns & 1) != 0 && (matrixRows & 1) != 0 && ecc == 200) throw new ArgumentException(BcgSR.DataMatrixNotSupported); grid = Iec16022Ecc200(matrixColumns, matrixRows, _encoding, _text.Length, _text, len, maxlen, ecclen); if (grid == null || matrixColumns == 0) throw new ArgumentException(BcgSR.DataMatrixNull); //DaSt: ever happen? return grid; } /// /// Encodes the DataMatrix. /// internal char[] Iec16022Ecc200(int columns, int rows, string encoding, int barcodeLength, string barcode, int len, int max, int ecc) { char[] binary = new char[3000]; // encoded raw data and ecc to place in barcode Ecc200Block matrix = new Ecc200Block(0, 0, 0, 0, 0, 0, 0); for (int i = 0; i < 3000; i++) binary[i] = (char)0; foreach (Ecc200Block eccmatrix in ecc200Sizes) { matrix = eccmatrix; if (matrix.Width == columns && matrix.Height == rows) break; } if (matrix.Width == 0) throw new ArgumentException(BcgSR.DataMatrixInvalid(columns, rows)); if (!Ecc200Encode(ref binary, matrix.Bytes, barcode, barcodeLength, encoding, ref len)) throw new ArgumentException(BcgSR.DataMatrixTooBig); // ecc code Ecc200(binary, matrix.Bytes, matrix.DataBlock, matrix.RSBlock); // placement int x; int y; int NR; int[] places; int NC = columns - 2 * (columns / matrix.CellWidth); NR = rows - 2 * (rows / matrix.CellHeight); places = new int[NC * NR]; Ecc200Placement(ref places, NR, NC); char[] grid = new char[columns * rows]; for (y = 0; y < rows; y += matrix.CellHeight) { for (x = 0; x < columns; x++) grid[y * columns + x] = (char)1; for (x = 0; x < columns; x += 2) grid[(y + matrix.CellHeight - 1) * columns + x] = (char)1; } for (x = 0; x < columns; x += matrix.CellWidth) { for (y = 0; y < rows; y++) grid[y * columns + x] = (char)1; for (y = 0; y < rows; y += 2) grid[y * columns + x + matrix.CellWidth - 1] = (char)1; } for (y = 0; y < NR; y++) { for (x = 0; x < NC; x++) { int v = places[(NR - y - 1) * NC + x]; if (v == 1 || v > 7 && ((binary[(v >> 3) - 1] & (1 << (v & 7))) != 0)) grid[(1 + y + 2 * (y / (matrix.CellHeight - 2))) * columns + 1 + x + 2 * (x / (matrix.CellWidth - 2))] = (char)1; } } return grid; } /// /// Encodes the barcode with the DataMatrix ECC200 Encoding. /// internal bool Ecc200Encode(ref char[] t, int targetLength, string s, int sourceLength, string encoding, ref int len) { char enc = 'a'; // start in ASCII encoding mode int targetposition = 0; int sourceposition = 0; if (encoding.Length < sourceLength) return false; // do the encoding while (sourceposition < sourceLength && targetposition < targetLength) { char newenc = enc; // suggest new encoding if (targetLength - targetposition <= 1 && (enc == 'c' || enc == 't') || targetLength - targetposition <= 2 && enc == 'x') enc = 'a'; // auto revert to ASCII #if !SILVERLIGHT // StL: Who wrote this nonsense? //newenc = char.Parse(encoding[sourceposition].ToString(CultureInfo.InvariantCulture).ToLower()); newenc = char.ToLower(encoding[sourceposition]); #else throw new NotImplementedException("char.Parse"); #endif switch (newenc) { // encode character case 'c': // C40 case 't': // Text case 'x': // X12 { char[] output = new char[6]; char p = (char)0; string e = null; string s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]_"; string s3 = null; if (newenc == 'c') { e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; s3 = "`abcdefghijklmnopqrstuvwxyz{|}~±"; } if (newenc == 't') { e = " 0123456789abcdefghijklmnopqrstuvwxyz"; s3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~±"; } if (newenc == 'x') e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r*>"; do { char c = s[sourceposition++]; char w; if ((c & 0x80) != 0) { if (newenc == 'x') { // fprintf (stderr, "Cannot encode char 0x%02X in X12\n", c); return false; } c &= (char)0x7f; output[p++] = (char)1; output[p++] = (char)30; } w = e.IndexOf(c) == -1 ? (char)0 : e[e.IndexOf(c)]; if (w != (char)0) output[p++] = (char)((e.IndexOf(w) + 3) % 40); else { if (newenc == 'x') { //fprintf (stderr, "Cannot encode char 0x%02X in X12\n", c); return false; } if (c < 32) { // shift 1 output[p++] = (char)0; output[p++] = c; } else { w = s2.IndexOf(c) == -1 ? (char)0 : (char)s2.IndexOf(c); if (w != (char)0) { // shift 2 output[p++] = (char)1; output[p++] = w; } else { w = s3.IndexOf(c) == -1 ? (char)0 : (char)s3.IndexOf(c); if (w != (char)0) { output[p++] = (char)2; output[p++] = w; } else //fprintf (stderr, "Could not encode 0x%02X, should not happen\n", c); return false; } } } if (p == 2 && targetposition + 2 == targetLength && sourceposition == sourceLength) output[p++] = (char)0; // shift 1 pad at end while (p >= 3) { int v = output[0] * 1600 + output[1] * 40 + output[2] + 1; if (enc != newenc) { if (enc == 'c' || enc == 't' || enc == 'x') t[targetposition++] = (char)254; // escape C40/text/X12 else if (enc == 'x') t[targetposition++] = (char)0x7C; // escape EDIFACT if (newenc == 'c') t[targetposition++] = (char)230; if (newenc == 't') t[targetposition++] = (char)239; if (newenc == 'x') t[targetposition++] = (char)238; enc = newenc; } t[targetposition++] = (char)(v >> 8); t[targetposition++] = (char)(v & 0xFF); p -= (char)3; output[0] = output[3]; output[1] = output[4]; output[2] = output[5]; } } while (p != (char)0 && sourceposition < sourceLength); } break; case 'e': // EDIFACT { char[] output = new char[4]; char p = (char)0; if (enc != newenc) { // can only be from C40/Text/X12 t[targetposition++] = (char)254; enc = 'a'; } while (sourceposition < sourceLength && /*encoding[sourceposition].ToString(CultureInfo.InvariantCulture).ToLower() == "e"*/ char.ToLower(encoding[sourceposition]) == 'e' && p < 4) output[p++] = s[sourceposition++]; if (p < 4) { output[p++] = (char)0x1F; enc = 'a'; } // termination t[targetposition] = (char)((s[0] & 0x3F) << 2); t[targetposition++] |= (char)((s[1] & 0x30) >> 4); t[targetposition] = (char)((s[1] & 0x0F) << 4); if (p == 2) targetposition++; else { t[targetposition++] |= (char)((s[2] & 0x3C) >> 2); t[targetposition] = (char)((s[2] & 0x03) << 6); t[targetposition++] |= (char)(s[3] & 0x3F); } } break; case 'a': // ASCII if (enc != newenc) { if (enc == 'c' || enc == 't' || enc == 'x') t[targetposition++] = (char)254; // escape C40/text/X12 else t[targetposition++] = (char)0x7C; // escape EDIFACT } enc = 'a'; if (sourceLength - sourceposition >= 2 && char.IsDigit(s[sourceposition]) && char.IsDigit(s[sourceposition + 1])) { t[targetposition++] = (char)((s[sourceposition] - '0') * 10 + s[sourceposition + 1] - '0' + 130); sourceposition += 2; } else if (s[sourceposition] > 127) { t[targetposition++] = (char)235; t[targetposition++] = (char)(s[sourceposition++] - 127); } else t[targetposition++] = (char)(s[sourceposition++] + 1); break; case 'b': // Binary { int l = 0; // how much to encode if (encoding != null) { int p; for (p = sourceposition; p < sourceLength && /*encoding[p].ToString(CultureInfo.InvariantCulture).ToLower() == "b"*/ char.ToLower(encoding[p]) == 'b'; p++) l++; } t[targetposition++] = (char)231; // base256 if (l < 250) { t[targetposition] = (char)State255(l, targetposition); targetposition++; } else { t[targetposition] = (char)State255(249 + (l / 250), targetposition); targetposition++; t[targetposition] = (char)State255(l % 250, targetposition); targetposition++; } while (l-- != 0 && targetposition < targetLength) { t[targetposition] = (char)State255(s[sourceposition++], targetposition); targetposition++; } enc = 'a'; // reverse to ASCII at end } break; // default: // fprintf (stderr, "Unknown encoding %c\n", newenc); // return 0; // failed } } if (len != 0) len = targetposition; if (targetposition < targetLength && enc != 'a') { if (enc == 'c' || enc == 'x' || enc == 't') t[targetposition++] = (char)254; // escape X12/C40/Text else t[targetposition++] = (char)0x7C; // escape EDIFACT } if (targetposition < targetLength) t[targetposition++] = (char)129; // pad while (targetposition < targetLength) { // more padding int v = 129 + (((targetposition + 1) * 149) % 253) + 1; // see Annex H if (v > 254) v -= 254; t[targetposition++] = (char)v; } if (targetposition > targetLength || sourceposition < sourceLength) return false; // did not fit return true; // OK } int State255(int value, int position) { return ((value + (((position + 1) * 149) % 255) + 1) % 256); } /// /// Places the data in the right positions according to Annex M of the ECC200 specification. /// void Ecc200Placement(ref int[] array, int NR, int NC) { int r; int c; int p; // invalidate for (r = 0; r < NR; r++) for (c = 0; c < NC; c++) array[r * NC + c] = 0; // start p = 1; r = 4; c = 0; do { // check corner if (r == NR && (c == 0)) Ecc200PlacementCornerA(ref array, NR, NC, p++); if (r == NR - 2 && c == 0 && ((NC % 4) != 0)) Ecc200PlacementCornerB(ref array, NR, NC, p++); if (r == NR - 2 && c == 0 && ((NC % 8) == 4)) Ecc200PlacementCornerC(ref array, NR, NC, p++); if (r == NR + 4 && c == 2 && ((NC % 8) == 0)) Ecc200PlacementCornerD(ref array, NR, NC, p++); // up/right do { if (r < NR && c >= 0 && array[r * NC + c] == 0) Ecc200PlacementBlock(ref array, NR, NC, r, c, p++); r -= 2; c += 2; } while (r >= 0 && c < NC); r++; c += 3; // down/left do { if (r >= 0 && c < NC && array[r * NC + c] == 0) Ecc200PlacementBlock(ref array, NR, NC, r, c, p++); r += 2; c -= 2; } while (r < NR && c >= 0); r += 3; c++; } while (r < NR || c < NC); // unfilled corner if (array[NR * NC - 1] == 0) array[NR * NC - 1] = array[NR * NC - NC - 2] = 1; } /// /// Places the ECC200 bits in the right positions. /// void Ecc200PlacementBit(ref int[] array, int NR, int NC, int r, int c, int p, int b) { if (r < 0) { r += NR; c += 4 - ((NR + 4) % 8); } if (c < 0) { c += NC; r += 4 - ((NC + 4) % 8); } array[r * NC + c] = (p << 3) + b; } void Ecc200PlacementBlock(ref int[] array, int NR, int NC, int r, int c, int p) { Ecc200PlacementBit(ref array, NR, NC, r - 2, c - 2, p, 7); Ecc200PlacementBit(ref array, NR, NC, r - 2, c - 1, p, 6); Ecc200PlacementBit(ref array, NR, NC, r - 1, c - 2, p, 5); Ecc200PlacementBit(ref array, NR, NC, r - 1, c - 1, p, 4); Ecc200PlacementBit(ref array, NR, NC, r - 1, c - 0, p, 3); Ecc200PlacementBit(ref array, NR, NC, r - 0, c - 2, p, 2); Ecc200PlacementBit(ref array, NR, NC, r - 0, c - 1, p, 1); Ecc200PlacementBit(ref array, NR, NC, r - 0, c - 0, p, 0); } void Ecc200PlacementCornerA(ref int[] array, int NR, int NC, int p) { Ecc200PlacementBit(ref array, NR, NC, NR - 1, 0, p, 7); Ecc200PlacementBit(ref array, NR, NC, NR - 1, 1, p, 6); Ecc200PlacementBit(ref array, NR, NC, NR - 1, 2, p, 5); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 2, p, 4); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 1, p, 3); Ecc200PlacementBit(ref array, NR, NC, 1, NC - 1, p, 2); Ecc200PlacementBit(ref array, NR, NC, 2, NC - 1, p, 1); Ecc200PlacementBit(ref array, NR, NC, 3, NC - 1, p, 0); } void Ecc200PlacementCornerB(ref int[] array, int NR, int NC, int p) { Ecc200PlacementBit(ref array, NR, NC, NR - 3, 0, p, 7); Ecc200PlacementBit(ref array, NR, NC, NR - 2, 0, p, 6); Ecc200PlacementBit(ref array, NR, NC, NR - 1, 0, p, 5); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 4, p, 4); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 3, p, 3); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 2, p, 2); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 1, p, 1); Ecc200PlacementBit(ref array, NR, NC, 1, NC - 1, p, 0); } void Ecc200PlacementCornerC(ref int[] array, int NR, int NC, int p) { Ecc200PlacementBit(ref array, NR, NC, NR - 3, 0, p, 7); Ecc200PlacementBit(ref array, NR, NC, NR - 2, 0, p, 6); Ecc200PlacementBit(ref array, NR, NC, NR - 1, 0, p, 5); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 2, p, 4); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 1, p, 3); Ecc200PlacementBit(ref array, NR, NC, 1, NC - 1, p, 2); Ecc200PlacementBit(ref array, NR, NC, 2, NC - 1, p, 1); Ecc200PlacementBit(ref array, NR, NC, 3, NC - 1, p, 0); } void Ecc200PlacementCornerD(ref int[] array, int NR, int NC, int p) { Ecc200PlacementBit(ref array, NR, NC, NR - 1, 0, p, 7); Ecc200PlacementBit(ref array, NR, NC, NR - 1, NC - 1, p, 6); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 3, p, 5); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 2, p, 4); Ecc200PlacementBit(ref array, NR, NC, 0, NC - 1, p, 3); Ecc200PlacementBit(ref array, NR, NC, 1, NC - 3, p, 2); Ecc200PlacementBit(ref array, NR, NC, 1, NC - 2, p, 1); Ecc200PlacementBit(ref array, NR, NC, 1, NC - 1, p, 0); } /// /// Calculate and append the Reed Solomon Code. /// void Ecc200(char[] binary, int bytes, int datablock, int rsblock) { int blocks = (bytes + 2) / datablock; int b; InitGalois(0x12d); InitReedSolomon(rsblock, 1); for (b = 0; b < blocks; b++) { int[] buf = new int[256]; int[] ecc = new int[256]; int n, p = 0; for (n = b; n < bytes; n += blocks) buf[p++] = binary[n]; EncodeReedSolomon(p, buf, ref ecc); p = rsblock - 1; // comes back reversed for (n = b; n < rsblock * blocks; n += blocks) binary[bytes + n] = (char)ecc[p--]; } } static int gfpoly; static int symsize; // in bits static int logmod; // 2**symsize - 1 static int rlen; static int[] log = null; static int[] alog = null; static int[] rspoly = null; /// /// Initialize the Galois Field. /// /// public static void InitGalois(int poly) { int m; int b; int p; int v; // Return storage from previous setup if (log != null) { log = null; alog = null; rspoly = null; } // Find the top bit, and hence the symbol size for (b = 1, m = 0; b <= poly; b <<= 1) m++; b >>= 1; m--; gfpoly = poly; symsize = m; // Calculate the log/alog tables logmod = (1 << m) - 1; log = new int[logmod + 1]; alog = new int[logmod]; for (p = 1, v = 0; v < logmod; v++) { alog[v] = p; log[p] = v; p <<= 1; if ((p & b) != 0) //DaSt: check! p ^= poly; } } /// /// Initializes the Reed-Solomon Encoder. /// public static void InitReedSolomon(int nsym, int index) { int i; int k; if (rspoly != null) rspoly = null; rspoly = new int[nsym + 1]; rlen = nsym; rspoly[0] = 1; for (i = 1; i <= nsym; i++) { rspoly[i] = 1; for (k = i - 1; k > 0; k--) { if (rspoly[k] != 0) //DaSt: check! rspoly[k] = alog[(log[rspoly[k]] + index) % logmod]; rspoly[k] ^= rspoly[k - 1]; } rspoly[0] = alog[(log[rspoly[0]] + index) % logmod]; index++; } } /// /// Encodes the Reed-Solomon encoding /// public void EncodeReedSolomon(int length, int[] data, ref int[] result) { int i; int k; int m; for (i = 0; i < rlen; i++) result[i] = 0; for (i = 0; i < length; i++) { m = result[rlen - 1] ^ data[i]; for (k = rlen - 1; k > 0; k--) { if ((m != 0) && (rspoly[k] != 0)) //DaSt: check! result[k] = result[k - 1] ^ alog[(log[m] + log[rspoly[k]]) % logmod]; else result[k] = result[k - 1]; } if ((m != 0) && (rspoly[0] != 0)) //DaSt: check! result[0] = alog[(log[m] + log[rspoly[0]]) % logmod]; else result[0] = 0; } } /// /// Creates a DataMatrix image object. /// /// A hex string like "AB 08 C3...". /// I.e. 26 for a 26x26 matrix public XImage CreateImage(char[] code, int size)//(string code, int size) { return CreateImage(code, size, size, 10); } /// /// Creates a DataMatrix image object. /// public XImage CreateImage(char[] code, int rows, int columns) { return CreateImage(code, rows, columns, 10); } /// /// Creates a DataMatrix image object. /// public XImage CreateImage(char[] code, int rows, int columns, int pixelsize) { #if GDI Bitmap bm = new Bitmap(columns * pixelsize, rows * pixelsize); using (Graphics gfx = Graphics.FromImage(bm)) { gfx.FillRectangle(System.Drawing.Brushes.White, new Rectangle(0, 0, columns * pixelsize, rows * pixelsize)); for (int i = rows - 1; i >= 0; i--) { for (int j = 0; j < columns; j++) { if (code[((rows - 1) - i) * columns + j] == (char)1) gfx.FillRectangle(System.Drawing.Brushes.Black, j * pixelsize, i * pixelsize, pixelsize, pixelsize); } } } XImage image = XImage.FromGdiPlusImage(bm); image.Interpolate = false; return image; #endif #if WPF // WPFHACK return null; #endif #if CORE || NETFX_CORE || UWP return null; #endif } struct Ecc200Block { public readonly int Height; public readonly int Width; public readonly int CellHeight; public readonly int CellWidth; public readonly int Bytes; public readonly int DataBlock; public readonly int RSBlock; public Ecc200Block(int h, int w, int ch, int cw, int bytes, int dataBlock, int rsBlock) { Height = h; Width = w; CellHeight = ch; CellWidth = cw; Bytes = bytes; DataBlock = dataBlock; RSBlock = rsBlock; } } } }