123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446 |
- using FastReport.Utils;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Text;
- namespace FastReport.Barcode
- {
- /// <summary>
- /// Generates the 2D MaxiCode barcode.
- /// </summary>
- public class BarcodeMaxiCode : Barcode2DBase
- {
- /// <summary>
- /// Sets the MaxiCode mode to use. Only modes 2 to 6 are supported.
- /// </summary>
- [DefaultValue(4)]
- public int Mode
- {
- get
- {
- return mode;
- }
- set
- {
- mode = value;
- }
- }
- //public int ECI { get; set; }
- const float FieldSizeFactor = 2.47f;
- const float PenSizeFactor = 4.5f;
- MaxiCodeImpl maxiCodeImpl;
- int mode;
- /// <summary>
- /// Initializes a new instance of the <see cref="BarcodeMaxiCode"/> class with default settings.
- /// </summary>
- public BarcodeMaxiCode()
- {
- Mode = 4;
- }
- internal override void Initialize(string text, bool showText, int angle, float zoom)
- {
- base.Initialize(text, showText, angle, zoom);
- maxiCodeImpl = new MaxiCodeImpl(base.text);
- maxiCodeImpl.setMode(Mode);
- maxiCodeImpl.encode();
- }
- internal override SizeF CalcBounds()
- {
- int textAdd = showText ? 18 : 0;
- SizeF s = new SizeF();
- foreach(MaxiCodeImpl.Hexagon hex in maxiCodeImpl.hexagons)
- {
- for (int i = 0; i < hex.pointX.Length; i++)
- {
- float pointX = FieldSizeFactor * (float)hex.pointX[i];
- float pointY = FieldSizeFactor * (float)hex.pointY[i];
- if (pointX > s.Width)
- s.Width = pointX;
- if (pointY > s.Height)
- s.Height = pointY;
- }
- }
- if (s.Width <= 0)
- s.Width = 100;
- if (s.Height <= 0)
- s.Height = 100;
- s.Height += textAdd;
- return s;
- }
- internal override void Draw2DBarcode(IGraphics g, float kx, float ky)
- {
- Brush b = new SolidBrush(Color);
- Pen p = new Pen(Color, PenSizeFactor * ((kx + ky) / 2));
- foreach (MaxiCodeImpl.Hexagon hex in maxiCodeImpl.hexagons)
- {
- PointF[] points = new PointF[hex.pointX.Length];
- for (int i = 0; i < hex.pointX.Length; i++)
- points[i] = new PointF(FieldSizeFactor * kx * (float)hex.pointX[i], FieldSizeFactor * ky * (float)hex.pointY[i]);
- g.FillPolygon(b, points);
- }
-
- foreach (MaxiCodeImpl.Ellipse circle in maxiCodeImpl.target)
- {
- g.DrawEllipse(p,
- FieldSizeFactor * kx * (float)circle.x,
- FieldSizeFactor * ky * (float)circle.y,
- FieldSizeFactor * kx * ((float)circle.w - (float)circle.x),
- FieldSizeFactor * ky * ((float)circle.h - (float)circle.y));
- }
- b.Dispose();
- p.Dispose();
- }
- /// <inheritdoc/>
- public override void Assign(BarcodeBase source)
- {
- base.Assign(source);
- BarcodeMaxiCode src = source as BarcodeMaxiCode;
- Mode = src.Mode;
- }
- internal override void Serialize(FastReport.Utils.FRWriter writer, string prefix, BarcodeBase diff)
- {
- base.Serialize(writer, prefix, diff);
- BarcodeMaxiCode c = diff as BarcodeMaxiCode;
- if (c == null || Mode != c.Mode)
- writer.WriteInt(prefix + "Mode", Mode);
- }
- }
- /*
- * Copyright 2014-2015 Robin Stuart, Daniel Gredler
- *
- * 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.
- */
- /**
- * Implements MaxiCode according to ISO 16023:2000.
- *
- * MaxiCode employs a pattern of hexagons around a central 'bulls-eye'
- * finder pattern. Encoding in several modes is supported, but encoding in
- * Mode 2 and 3 require primary messages to be set. Input characters can be
- * any from the ISO 8859-1 (Latin-1) character set.
- *
- * TODO: Add ECI functionality.
- *
- * @author <a href="mailto:rstuart114@gmail.com">Robin Stuart</a>
- * @author Daniel Gredler
- */
- class MaxiCodeImpl
- {
- public class ReedSolomon
- {
- private int logmod;
- private int rlen;
- private int[] logt;
- private int[] alog;
- private int[] rspoly;
- public int[] res;
- public int getResult(int count)
- {
- return res[count];
- }
- public void init_gf(int poly)
- {
- int m, b, p, v;
- // Find the top bit, and hence the symbol size
- for (b = 1, m = 0; b <= poly; b <<= 1)
- {
- m++;
- }
- b >>= 1;
- m--;
- // Calculate the log/alog tables
- logmod = (1 << m) - 1;
- logt = new int[logmod + 1];
- alog = new int[logmod];
- for (p = 1, v = 0; v < logmod; v++)
- {
- alog[v] = p;
- logt[p] = v;
- p <<= 1;
- if ((p & b) != 0)
- {
- p ^= poly;
- }
- }
- }
- public void init_code(int nsym, int index)
- {
- int i, k;
- 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)
- {
- rspoly[k] = alog[(logt[rspoly[k]] + index) % logmod];
- }
- rspoly[k] ^= rspoly[k - 1];
- }
- rspoly[0] = alog[(logt[rspoly[0]] + index) % logmod];
- index++;
- }
- }
- public void encode(int len, int[] data)
- {
- int i, k, m;
- res = new int[rlen];
- for (i = 0; i < rlen; i++)
- {
- res[i] = 0;
- }
- for (i = 0; i < len; i++)
- {
- m = res[rlen - 1] ^ data[i];
- for (k = rlen - 1; k > 0; k--)
- {
- if ((m != 0) && (rspoly[k] != 0))
- {
- res[k] = res[k - 1] ^ alog[(logt[m] + logt[rspoly[k]]) % logmod];
- }
- else
- {
- res[k] = res[k - 1];
- }
- }
- if ((m != 0) && (rspoly[0] != 0))
- {
- res[0] = alog[(logt[m] + logt[rspoly[0]]) % logmod];
- }
- else
- {
- res[0] = 0;
- }
- }
- }
- }
- #if READONLY_STRUCTS
- public readonly struct Hexagon
- #else
- public struct Hexagon
- #endif
- {
- const double INK_SPREAD = 1.25;
- static readonly double[] OFFSET_X = new double[] { 0.0, 0.86, 0.86, 0.0, -0.86, -0.86 };
- static readonly double[] OFFSET_Y = new double[] { 1.0, 0.5, -0.5, -1.0, -0.5, 0.5 };
- public readonly double[] pointX;
- public readonly double[] pointY;
- public Hexagon(double centreX, double centreY)
- {
- pointX = new double[6];
- pointY = new double[6];
- for (int i = 0; i < 6; i++)
- {
- pointX[i] = centreX + (OFFSET_X[i] * INK_SPREAD);
- pointY[i] = centreY + (OFFSET_Y[i] * INK_SPREAD);
- }
- }
- }
- #if READONLY_STRUCTS
- public readonly struct Ellipse
- #else
- public struct Ellipse
- #endif
- {
- #pragma warning disable FR0006 // Field name of struct must be longer than 2 characters.
- public readonly double x;
- public readonly double y;
- public readonly double w;
- public readonly double h;
- #pragma warning restore FR0006 // Field name of struct must be longer than 2 characters.
- public Ellipse(double x, double y, double w, double h)
- {
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- }
- }
- private int eciMode = 3;
- private byte[] inputBytes;
- //string error_msg;
- public List<Hexagon> hexagons = new List<Hexagon>();
- public List<Ellipse> target = new List<Ellipse>();
- private string text;
- public MaxiCodeImpl(string text)
- {
- this.text = text;
- }
- //========================================================================
- /** MaxiCode module sequence, from ISO/IEC 16023 Figure 5 (30 x 33 data grid). */
- static int[] MAXICODE_GRID = {
- 122, 121, 128, 127, 134, 133, 140, 139, 146, 145, 152, 151, 158, 157, 164, 163, 170, 169, 176, 175, 182, 181, 188, 187, 194, 193, 200, 199, 0, 0,
- 124, 123, 130, 129, 136, 135, 142, 141, 148, 147, 154, 153, 160, 159, 166, 165, 172, 171, 178, 177, 184, 183, 190, 189, 196, 195, 202, 201, 817, 0,
- 126, 125, 132, 131, 138, 137, 144, 143, 150, 149, 156, 155, 162, 161, 168, 167, 174, 173, 180, 179, 186, 185, 192, 191, 198, 197, 204, 203, 819, 818,
- 284, 283, 278, 277, 272, 271, 266, 265, 260, 259, 254, 253, 248, 247, 242, 241, 236, 235, 230, 229, 224, 223, 218, 217, 212, 211, 206, 205, 820, 0,
- 286, 285, 280, 279, 274, 273, 268, 267, 262, 261, 256, 255, 250, 249, 244, 243, 238, 237, 232, 231, 226, 225, 220, 219, 214, 213, 208, 207, 822, 821,
- 288, 287, 282, 281, 276, 275, 270, 269, 264, 263, 258, 257, 252, 251, 246, 245, 240, 239, 234, 233, 228, 227, 222, 221, 216, 215, 210, 209, 823, 0,
- 290, 289, 296, 295, 302, 301, 308, 307, 314, 313, 320, 319, 326, 325, 332, 331, 338, 337, 344, 343, 350, 349, 356, 355, 362, 361, 368, 367, 825, 824,
- 292, 291, 298, 297, 304, 303, 310, 309, 316, 315, 322, 321, 328, 327, 334, 333, 340, 339, 346, 345, 352, 351, 358, 357, 364, 363, 370, 369, 826, 0,
- 294, 293, 300, 299, 306, 305, 312, 311, 318, 317, 324, 323, 330, 329, 336, 335, 342, 341, 348, 347, 354, 353, 360, 359, 366, 365, 372, 371, 828, 827,
- 410, 409, 404, 403, 398, 397, 392, 391, 80, 79, 0, 0, 14, 13, 38, 37, 3, 0, 45, 44, 110, 109, 386, 385, 380, 379, 374, 373, 829, 0,
- 412, 411, 406, 405, 400, 399, 394, 393, 82, 81, 41, 0, 16, 15, 40, 39, 4, 0, 0, 46, 112, 111, 388, 387, 382, 381, 376, 375, 831, 830,
- 414, 413, 408, 407, 402, 401, 396, 395, 84, 83, 42, 0, 0, 0, 0, 0, 6, 5, 48, 47, 114, 113, 390, 389, 384, 383, 378, 377, 832, 0,
- 416, 415, 422, 421, 428, 427, 104, 103, 56, 55, 17, 0, 0, 0, 0, 0, 0, 0, 21, 20, 86, 85, 434, 433, 440, 439, 446, 445, 834, 833,
- 418, 417, 424, 423, 430, 429, 106, 105, 58, 57, 0, 0, 0, 0, 0, 0, 0, 0, 23, 22, 88, 87, 436, 435, 442, 441, 448, 447, 835, 0,
- 420, 419, 426, 425, 432, 431, 108, 107, 60, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 90, 89, 438, 437, 444, 443, 450, 449, 837, 836,
- 482, 481, 476, 475, 470, 469, 49, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 54, 53, 464, 463, 458, 457, 452, 451, 838, 0,
- 484, 483, 478, 477, 472, 471, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 466, 465, 460, 459, 454, 453, 840, 839,
- 486, 485, 480, 479, 474, 473, 52, 51, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 43, 468, 467, 462, 461, 456, 455, 841, 0,
- 488, 487, 494, 493, 500, 499, 98, 97, 62, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 92, 91, 506, 505, 512, 511, 518, 517, 843, 842,
- 490, 489, 496, 495, 502, 501, 100, 99, 64, 63, 0, 0, 0, 0, 0, 0, 0, 0, 29, 28, 94, 93, 508, 507, 514, 513, 520, 519, 844, 0,
- 492, 491, 498, 497, 504, 503, 102, 101, 66, 65, 18, 0, 0, 0, 0, 0, 0, 0, 19, 30, 96, 95, 510, 509, 516, 515, 522, 521, 846, 845,
- 560, 559, 554, 553, 548, 547, 542, 541, 74, 73, 33, 0, 0, 0, 0, 0, 0, 11, 68, 67, 116, 115, 536, 535, 530, 529, 524, 523, 847, 0,
- 562, 561, 556, 555, 550, 549, 544, 543, 76, 75, 0, 0, 8, 7, 36, 35, 12, 0, 70, 69, 118, 117, 538, 537, 532, 531, 526, 525, 849, 848,
- 564, 563, 558, 557, 552, 551, 546, 545, 78, 77, 0, 34, 10, 9, 26, 25, 0, 0, 72, 71, 120, 119, 540, 539, 534, 533, 528, 527, 850, 0,
- 566, 565, 572, 571, 578, 577, 584, 583, 590, 589, 596, 595, 602, 601, 608, 607, 614, 613, 620, 619, 626, 625, 632, 631, 638, 637, 644, 643, 852, 851,
- 568, 567, 574, 573, 580, 579, 586, 585, 592, 591, 598, 597, 604, 603, 610, 609, 616, 615, 622, 621, 628, 627, 634, 633, 640, 639, 646, 645, 853, 0,
- 570, 569, 576, 575, 582, 581, 588, 587, 594, 593, 600, 599, 606, 605, 612, 611, 618, 617, 624, 623, 630, 629, 636, 635, 642, 641, 648, 647, 855, 854,
- 728, 727, 722, 721, 716, 715, 710, 709, 704, 703, 698, 697, 692, 691, 686, 685, 680, 679, 674, 673, 668, 667, 662, 661, 656, 655, 650, 649, 856, 0,
- 730, 729, 724, 723, 718, 717, 712, 711, 706, 705, 700, 699, 694, 693, 688, 687, 682, 681, 676, 675, 670, 669, 664, 663, 658, 657, 652, 651, 858, 857,
- 732, 731, 726, 725, 720, 719, 714, 713, 708, 707, 702, 701, 696, 695, 690, 689, 684, 683, 678, 677, 672, 671, 666, 665, 660, 659, 654, 653, 859, 0,
- 734, 733, 740, 739, 746, 745, 752, 751, 758, 757, 764, 763, 770, 769, 776, 775, 782, 781, 788, 787, 794, 793, 800, 799, 806, 805, 812, 811, 861, 860,
- 736, 735, 742, 741, 748, 747, 754, 753, 760, 759, 766, 765, 772, 771, 778, 777, 784, 783, 790, 789, 796, 795, 802, 801, 808, 807, 814, 813, 862, 0,
- 738, 737, 744, 743, 750, 749, 756, 755, 762, 761, 768, 767, 774, 773, 780, 779, 786, 785, 792, 791, 798, 797, 804, 803, 810, 809, 816, 815, 864, 863
- };
- /**
- * ASCII character to Code Set mapping, from ISO/IEC 16023 Appendix A.
- * 1 = Set A, 2 = Set B, 3 = Set C, 4 = Set D, 5 = Set E.
- * 0 refers to special characters that fit into more than one set (e.g. GS).
- */
- static int[] MAXICODE_SET = {
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 0, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2,
- 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 4, 5, 5, 5, 5, 5, 5, 4, 5, 3, 4, 3, 5, 5, 4, 4, 3, 3, 3,
- 4, 3, 5, 4, 4, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
- };
- /** ASCII character to symbol value, from ISO/IEC 16023 Appendix A. */
- static int[] MAXICODE_SYMBOL_CHAR = {
- 0, 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, 30, 28, 29, 30, 35, 32, 53, 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, 37,
- 38, 39, 40, 41, 52, 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, 42, 43, 44, 45, 46, 0, 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, 32, 54, 34, 35, 36, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 36,
- 37, 37, 38, 39, 40, 41, 42, 43, 38, 44, 37, 39, 38, 45, 46, 40, 41, 39, 40, 41,
- 42, 42, 47, 43, 44, 43, 44, 45, 45, 46, 47, 46, 0, 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, 32,
- 33, 34, 35, 36, 0, 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, 32, 33, 34, 35, 36
- };
- int mode;
- int structuredAppendPosition = 1;
- int structuredAppendTotal = 1;
- string primaryData = "";
- int[] codewords;
- int[] source;
- int[] set = new int[144];
- int[] character = new int[144];
- bool[,] grid = new bool[33,30];
- /**
- * Sets the MaxiCode mode to use. Only modes 2 to 6 are supported.
- *
- * @param mode the MaxiCode mode to use
- */
- public void setMode(int mode)
- {
- if (mode < 2 || mode > 6)
- {
- throw new ArgumentOutOfRangeException("Invalid MaxiCode mode: " + mode);
- }
- this.mode = mode;
- }
- /**
- * Returns the MaxiCode mode being used. Only modes 2 to 6 are supported.
- *
- * @return the MaxiCode mode being used
- */
- public int getMode()
- {
- return mode;
- }
- /**
- * If this MaxiCode symbol is part of a series of MaxiCode symbols appended in a structured format, this method sets the
- * position of this symbol in the series. Valid values are 1 through 8 inclusive.
- *
- * @param position the position of this MaxiCode symbol in the structured append series
- */
- public void setStructuredAppendPosition(int position)
- {
- if (position < 1 || position > 8)
- {
- throw new ArgumentOutOfRangeException("Invalid MaxiCode structured append position: " + position);
- }
- this.structuredAppendPosition = position;
- }
- /**
- * Returns the position of this MaxiCode symbol in a series of symbols using structured append. If this symbol is not part of
- * such a series, this method will return <code>1</code>.
- *
- * @return the position of this MaxiCode symbol in a series of symbols using structured append
- */
- public int getStructuredAppendPosition()
- {
- return structuredAppendPosition;
- }
- /**
- * If this MaxiCode symbol is part of a series of MaxiCode symbols appended in a structured format, this method sets the total
- * number of symbols in the series. Valid values are 1 through 8 inclusive. A value of 1 indicates that this symbol is not
- * part of a structured append series.
- *
- * @param total the total number of MaxiCode symbols in the structured append series
- */
- public void setStructuredAppendTotal(int total)
- {
- if (total < 1 || total > 8)
- {
- throw new ArgumentOutOfRangeException("Invalid MaxiCode structured append total: " + total);
- }
- this.structuredAppendTotal = total;
- }
- /**
- * Returns the size of the series of MaxiCode symbols using structured append that this symbol is part of. If this symbol is
- * not part of a structured append series, this method will return <code>1</code>.
- *
- * @return size of the series that this symbol is part of
- */
- public int getStructuredAppendTotal()
- {
- return structuredAppendTotal;
- }
- /**
- * Sets the primary data. Should only be used for modes 2 and 3. Must conform to the following structure:
- *
- * <table summary="Expected primary data structure.">
- * <tr><th>Characters</th><th>Meaning</th></tr>
- * <tr><td>1-9</td><td>Postal code data which can consist of up to 9 digits (for mode 2) or up to 6
- * alphanumeric characters (for mode 3). Remaining unused characters should be
- * filled with the SPACE character (ASCII 32).</td></tr>
- * <tr><td>10-12</td><td>Three-digit country code according to ISO-3166.</td></tr>
- * <tr><td>13-15</td><td>Three digit service code. This depends on your parcel courier.</td></tr>
- * </table>
- *
- * @param primary the primary data
- */
- public void setPrimary(String primary)
- {
- primaryData = primary;
- }
- /**
- * Returns the primary data for this MaxiCode symbol. Should only be used for modes 2 and 3.
- *
- * @return the primary data for this MaxiCode symbol
- */
- public String getPrimary()
- {
- return primaryData;
- }
- /** {@inheritDoc} */
- //@Override
- public bool encode()
- {
- inputBytes = Encoding.UTF8.GetBytes(text);
- // copy input data over into source
- int sourcelen = text.Length;
- source = new int[sourcelen];
- //eciProcess();
- for (int i = 0; i < sourcelen; i++)
- {
- source[i] = inputBytes[i] & 0xFF;
- }
- // mode 2 -> mode 3 if postal code isn't strictly numeric
- if (mode == 2)
- {
- for (int i = 0; i < 10 && i < primaryData.Length; i++)
- {
- if ((primaryData[i] < '0') || (primaryData[i] > '9'))
- {
- mode = 3;
- break;
- }
- }
- }
- // initialize the set and character arrays
- if (!processText())
- {
- //error_msg = "Input data too long";
- //return false;
- throw new Exception("Input data too long");
- }
- // start building the codeword array, starting with a copy of the character data
- // insert primary message if this is a structured carrier message; insert mode otherwise
- codewords = new int[character.Length];
- character.CopyTo(codewords, 0);
- if (mode == 2 || mode == 3)
- {
- int[] _primary = getPrimaryCodewords();
- if (_primary == null)
- {
- return false;
- }
- codewords = insert(codewords, 0, _primary);
- }
- else
- {
- codewords = insert(codewords, 0, new int[] { mode });
- }
- // insert structured append flag if necessary
- if (structuredAppendTotal > 1)
- {
- int[] flag = new int[2];
- flag[0] = 33; // padding
- flag[1] = ((structuredAppendPosition - 1) << 3) | (structuredAppendTotal - 1); // position + total
- int index;
- if (mode == 2 || mode == 3)
- {
- index = 10; // first two data symbols in the secondary message
- }
- else
- {
- index = 1; // first two data symbols in the primary message (first symbol at index 0 isn't a data symbol)
- }
- codewords = insert(codewords, index, flag);
- }
- int secondaryMax, secondaryECMax;
- if (mode == 5)
- {
- // 68 data codewords, 56 error corrections in secondary message
- secondaryMax = 68;
- secondaryECMax = 56;
- }
- else
- {
- // 84 data codewords, 40 error corrections in secondary message
- secondaryMax = 84;
- secondaryECMax = 40;
- }
- // truncate data codewords to maximum data space available
- int totalMax = secondaryMax + 10;
- if (codewords.Length > totalMax)
- {
- //codewords = codewords.Take(totalMax).ToArray();
- int[] __codewords = new int[totalMax];
- Array.Copy(codewords, __codewords, totalMax);
- codewords = __codewords;
- }
- // insert primary error correction between primary message and secondary message (always EEC)
- //int[] primary = codewords.Take(10).ToArray();
- int[] primary = new int[10];
- Array.Copy(codewords, 0, primary, 0, 10);
- int[] primaryCheck = getErrorCorrection(primary, 10);
- codewords = insert(codewords, 10, primaryCheck);
- // calculate secondary error correction
- //int[] secondary = codewords.Skip(20).ToArray();
- int[] secondary = new int[codewords.Length - 20];
- Array.Copy(codewords, 20, secondary, 0, secondary.Length);
- int[] secondaryOdd = new int[secondary.Length / 2];
- int[] secondaryEven = new int[secondary.Length / 2];
- for (int i = 0; i < secondary.Length; i++)
- {
- if ((i & 1) != 0)
- { // odd
- secondaryOdd[(i - 1) / 2] = secondary[i];
- }
- else
- { // even
- secondaryEven[i / 2] = secondary[i];
- }
- }
- int[] secondaryECOdd = getErrorCorrection(secondaryOdd, secondaryECMax / 2);
- int[] secondaryECEven = getErrorCorrection(secondaryEven, secondaryECMax / 2);
- // add secondary error correction after secondary message
- int[] _codewords = codewords;
- codewords = new int[codewords.Length + secondaryECOdd.Length + secondaryECEven.Length];
- Array.Copy(_codewords, codewords, _codewords.Length);
- //codewords = Arrays.copyOf(codewords, codewords.Length + secondaryECOdd.Length + secondaryECEven.Length);
- for (int i = 0; i < secondaryECOdd.Length; i++)
- {
- codewords[20 + secondaryMax + (2 * i) + 1] = secondaryECOdd[i];
- }
- for (int i = 0; i < secondaryECEven.Length; i++)
- {
- codewords[20 + secondaryMax + (2 * i)] = secondaryECEven[i];
- }
- //encodeInfo += "Mode: " + mode + "\n";
- //encodeInfo += "ECC Codewords: " + secondaryECMax + "\n";
- //encodeInfo += "Codewords: ";
- //for (int i = 0; i < codewords.Length; i++)
- //{
- // encodeInfo += Integer.toString(codewords[i]) + " ";
- //}
- //encodeInfo += "\n";
- // copy data into symbol grid
- int[] bit_pattern = new int[7];
- for (int i = 0; i < 33; i++)
- {
- for (int j = 0; j < 30; j++)
- {
- int block = (MAXICODE_GRID[(i * 30) + j] + 5) / 6;
- int bit = (MAXICODE_GRID[(i * 30) + j] + 5) % 6;
- if (block != 0)
- {
- bit_pattern[0] = (codewords[block - 1] & 0x20) >> 5;
- bit_pattern[1] = (codewords[block - 1] & 0x10) >> 4;
- bit_pattern[2] = (codewords[block - 1] & 0x8) >> 3;
- bit_pattern[3] = (codewords[block - 1] & 0x4) >> 2;
- bit_pattern[4] = (codewords[block - 1] & 0x2) >> 1;
- bit_pattern[5] = (codewords[block - 1] & 0x1);
- if (bit_pattern[bit] != 0)
- {
- grid[i,j] = true;
- }
- else
- {
- grid[i,j] = false;
- }
- }
- }
- }
- // add orientation markings
- grid[0,28] = true; // top right filler
- grid[0, 29] = true;
- grid[9, 10] = true; // top left marker
- grid[9, 11] = true;
- grid[10, 11] = true;
- grid[15, 7] = true; // left hand marker
- grid[16, 8] = true;
- grid[16, 20] = true; // right hand marker
- grid[17, 20] = true;
- grid[22, 10] = true; // bottom left marker
- grid[23, 10] = true;
- grid[22, 17] = true; // bottom right marker
- grid[23, 17] = true;
- // the following is provided for compatibility, but the results are not useful
- //row_count = 33;
- //readable = "";
- //pattern = new String[33];
- //row_height = new int[33];
- //for (int i = 0; i < 33; i++)
- //{
- // StringBuilder bin = new StringBuilder(30);
- // for (int j = 0; j < 30; j++)
- // {
- // if (grid[i][j])
- // {
- // bin.append("1");
- // }
- // else
- // {
- // bin.append("0");
- // }
- // }
- // pattern[i] = bin2pat(bin.toString());
- // row_height[i] = 1;
- //}
- //symbol_height = 72;
- //symbol_width = 74;
- plotSymbol();
- return true;
- }
- /**
- * Extracts the postal code, country code and service code from the primary data and returns the corresponding primary message
- * codewords.
- *
- * @return the primary message codewords
- */
- int[] getPrimaryCodewords()
- {
- //assert mode == 2 || mode == 3;
- if (primaryData.Length != 15)
- {
- //error_msg = "Invalid Primary String";
- //return null;
- throw new Exception("Invalid Primary String");
- }
- for (int i = 9; i < 15; i++)
- { /* check that country code and service are numeric */
- if ((primaryData[i] < '0') || (primaryData[i] > '9'))
- {
- //error_msg = "Invalid Primary String";
- //return null;
- throw new Exception("Invalid Primary String");
- }
- }
- String postcode;
- if (mode == 2)
- {
- postcode = primaryData.Substring(0, 9);
- int index = postcode.IndexOf(' ');
- if (index != -1)
- {
- postcode = postcode.Substring(0, index);
- }
- }
- else
- {
- // if (mode == 3)
- postcode = primaryData.Substring(0, 6);
- }
- int country = int.Parse(primaryData.Substring(9, 3));
- int service = int.Parse(primaryData.Substring(12, 3));
- //if (debug)
- //{
- // System.out.println("Using mode " + mode);
- // System.out.println(" Postcode: " + postcode);
- // System.out.println(" Country Code: " + country);
- // System.out.println(" Service: " + service);
- //}
- if (mode == 2)
- {
- return getMode2PrimaryCodewords(postcode, country, service);
- }
- else
- { // mode == 3
- return getMode3PrimaryCodewords(postcode, country, service);
- }
- }
- /**
- * Returns the primary message codewords for mode 2.
- *
- * @param postcode the postal code
- * @param country the country code
- * @param service the service code
- * @return the primary message, as codewords
- */
- static int[] getMode2PrimaryCodewords(String postcode, int country, int service)
- {
- for (int i = 0; i < postcode.Length; i++)
- {
- if (postcode[i] < '0' || postcode[i] > '9')
- {
- postcode = postcode.Substring(0, i);
- break;
- }
- }
- int postcodeNum = int.Parse(postcode);
- int[] primary = new int[10];
- primary[0] = ((postcodeNum & 0x03) << 4) | 2;
- primary[1] = ((postcodeNum & 0xfc) >> 2);
- primary[2] = ((postcodeNum & 0x3f00) >> 8);
- primary[3] = ((postcodeNum & 0xfc000) >> 14);
- primary[4] = ((postcodeNum & 0x3f00000) >> 20);
- primary[5] = ((postcodeNum & 0x3c000000) >> 26) | ((postcode.Length & 0x3) << 4);
- primary[6] = ((postcode.Length & 0x3c) >> 2) | ((country & 0x3) << 4);
- primary[7] = (country & 0xfc) >> 2;
- primary[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
- primary[9] = ((service & 0x3f0) >> 4);
- return primary;
- }
- /**
- * Returns the primary message codewords for mode 3.
- *
- * @param postcode the postal code
- * @param country the country code
- * @param service the service code
- * @return the primary message, as codewords
- */
- static int[] getMode3PrimaryCodewords(String postcode, int country, int service)
- {
- int[] postcodeNums = new int[postcode.Length];
- postcode = postcode.ToUpper();
- for (int i = 0; i < postcodeNums.Length; i++)
- {
- postcodeNums[i] = postcode[i];
- if (postcode[i] >= 'A' && postcode[i] <= 'Z')
- {
- // (Capital) letters shifted to Code Set A values
- postcodeNums[i] -= 64;
- }
- if (postcodeNums[i] == 27 || postcodeNums[i] == 31 || postcodeNums[i] == 33 || postcodeNums[i] >= 59)
- {
- // Not a valid postal code character, use space instead
- postcodeNums[i] = 32;
- }
- // Input characters lower than 27 (NUL - SUB) in postal code are interpreted as capital
- // letters in Code Set A (e.g. LF becomes 'J')
- }
- int[] primary = new int[10];
- primary[0] = ((postcodeNums[5] & 0x03) << 4) | 3;
- primary[1] = ((postcodeNums[4] & 0x03) << 4) | ((postcodeNums[5] & 0x3c) >> 2);
- primary[2] = ((postcodeNums[3] & 0x03) << 4) | ((postcodeNums[4] & 0x3c) >> 2);
- primary[3] = ((postcodeNums[2] & 0x03) << 4) | ((postcodeNums[3] & 0x3c) >> 2);
- primary[4] = ((postcodeNums[1] & 0x03) << 4) | ((postcodeNums[2] & 0x3c) >> 2);
- primary[5] = ((postcodeNums[0] & 0x03) << 4) | ((postcodeNums[1] & 0x3c) >> 2);
- primary[6] = ((postcodeNums[0] & 0x3c) >> 2) | ((country & 0x3) << 4);
- primary[7] = (country & 0xfc) >> 2;
- primary[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
- primary[9] = ((service & 0x3f0) >> 4);
- return primary;
- }
- /**
- * Formats text according to Appendix A, populating the {@link #set} and {@link #character} arrays.
- *
- * @return true if the content fits in this symbol and was formatted; false otherwise
- */
- bool processText()
- {
- int Length = text.Length;
- int i, j, count, current_set;
- if (Length > 138)
- {
- return false;
- }
- for (i = 0; i < 144; i++)
- {
- set[i] = -1;
- character[i] = 0;
- }
- for (i = 0; i < Length; i++)
- {
- /* Look up characters in table from Appendix A - this gives
- value and code set for most characters */
- set[i] = MAXICODE_SET[source[i]];
- character[i] = MAXICODE_SYMBOL_CHAR[source[i]];
- }
- // If a character can be represented in more than one code set, pick which version to use.
- if (set[0] == 0)
- {
- if (character[0] == 13)
- {
- character[0] = 0;
- }
- set[0] = 1;
- }
- for (i = 1; i < Length; i++)
- {
- if (set[i] == 0)
- {
- /* Special character that can be represented in more than one code set. */
- if (character[i] == 13)
- {
- /* Carriage Return */
- set[i] = bestSurroundingSet(i, Length, 1, 5);
- if (set[i] == 5)
- {
- character[i] = 13;
- }
- else
- {
- character[i] = 0;
- }
- }
- else if (character[i] == 28)
- {
- /* FS */
- set[i] = bestSurroundingSet(i, Length, 1, 2, 3, 4, 5);
- if (set[i] == 5)
- {
- character[i] = 32;
- }
- }
- else if (character[i] == 29)
- {
- /* GS */
- set[i] = bestSurroundingSet(i, Length, 1, 2, 3, 4, 5);
- if (set[i] == 5)
- {
- character[i] = 33;
- }
- }
- else if (character[i] == 30)
- {
- /* RS */
- set[i] = bestSurroundingSet(i, Length, 1, 2, 3, 4, 5);
- if (set[i] == 5)
- {
- character[i] = 34;
- }
- }
- else if (character[i] == 32)
- {
- /* Space */
- set[i] = bestSurroundingSet(i, Length, 1, 2, 3, 4, 5);
- if (set[i] == 1)
- {
- character[i] = 32;
- }
- else if (set[i] == 2)
- {
- character[i] = 47;
- }
- else
- {
- character[i] = 59;
- }
- }
- else if (character[i] == 44)
- {
- /* Comma */
- set[i] = bestSurroundingSet(i, Length, 1, 2);
- if (set[i] == 2)
- {
- character[i] = 48;
- }
- }
- else if (character[i] == 46)
- {
- /* Full Stop */
- set[i] = bestSurroundingSet(i, Length, 1, 2);
- if (set[i] == 2)
- {
- character[i] = 49;
- }
- }
- else if (character[i] == 47)
- {
- /* Slash */
- set[i] = bestSurroundingSet(i, Length, 1, 2);
- if (set[i] == 2)
- {
- character[i] = 50;
- }
- }
- else if (character[i] == 58)
- {
- /* Colon */
- set[i] = bestSurroundingSet(i, Length, 1, 2);
- if (set[i] == 2)
- {
- character[i] = 51;
- }
- }
- }
- }
- for (i = Length; i < set.Length; i++)
- {
- /* Add the padding */
- if (set[Length - 1] == 2)
- {
- set[i] = 2;
- }
- else
- {
- set[i] = 1;
- }
- character[i] = 33;
- }
- /* Find candidates for number compression (not allowed in primary message in modes 2 and 3). */
- if (mode == 2 || mode == 3)
- {
- j = 9;
- }
- else
- {
- j = 0;
- }
- count = 0;
- for (i = j; i < 143; i++)
- {
- if (set[i] == 1 && character[i] >= 48 && character[i] <= 57)
- {
- /* Character is a number */
- count++;
- }
- else
- {
- count = 0;
- }
- if (count == 9)
- {
- /* Nine digits in a row can be compressed */
- set[i] = 6;
- set[i - 1] = 6;
- set[i - 2] = 6;
- set[i - 3] = 6;
- set[i - 4] = 6;
- set[i - 5] = 6;
- set[i - 6] = 6;
- set[i - 7] = 6;
- set[i - 8] = 6;
- count = 0;
- }
- }
- /* Add shift and latch characters */
- current_set = 1;
- i = 0;
- do
- {
- if ((set[i] != current_set) && (set[i] != 6))
- {
- switch (set[i])
- {
- case 1:
- if (i + 1 < set.Length && set[i + 1] == 1)
- {
- if (i + 2 < set.Length && set[i + 2] == 1)
- {
- if (i + 3 < set.Length && set[i + 3] == 1)
- {
- /* Latch A */
- insert(i, 63);
- current_set = 1;
- Length++;
- i += 3;
- }
- else
- {
- /* 3 Shift A */
- insert(i, 57);
- Length++;
- i += 2;
- }
- }
- else
- {
- /* 2 Shift A */
- insert(i, 56);
- Length++;
- i++;
- }
- }
- else
- {
- /* Shift A */
- insert(i, 59);
- Length++;
- }
- break;
- case 2:
- if (i + 1 < set.Length && set[i + 1] == 2)
- {
- /* Latch B */
- insert(i, 63);
- current_set = 2;
- Length++;
- i++;
- }
- else
- {
- /* Shift B */
- insert(i, 59);
- Length++;
- }
- break;
- case 3:
- if (i + 3 < set.Length && set[i + 1] == 3 && set[i + 2] == 3 && set[i + 3] == 3)
- {
- /* Lock In C */
- insert(i, 60);
- insert(i, 60);
- current_set = 3;
- Length++;
- i += 3;
- }
- else
- {
- /* Shift C */
- insert(i, 60);
- Length++;
- }
- break;
- case 4:
- if (i + 3 < set.Length && set[i + 1] == 4 && set[i + 2] == 4 && set[i + 3] == 4)
- {
- /* Lock In D */
- insert(i, 61);
- insert(i, 61);
- current_set = 4;
- Length++;
- i += 3;
- }
- else
- {
- /* Shift D */
- insert(i, 61);
- Length++;
- }
- break;
- case 5:
- if (i + 3 < set.Length && set[i + 1] == 5 && set[i + 2] == 5 && set[i + 3] == 5)
- {
- /* Lock In E */
- insert(i, 62);
- insert(i, 62);
- current_set = 5;
- Length++;
- i += 3;
- }
- else
- {
- /* Shift E */
- insert(i, 62);
- Length++;
- }
- break;
- default:
- throw new Exception("Unexpected set " + set[i] + " at index " + i + ".");
- }
- i++;
- }
- i++;
- } while (i < set.Length);
- /* Number compression has not been forgotten! It's handled below. */
- i = 0;
- do
- {
- if (set[i] == 6)
- {
- /* Number compression */
- int value = 0;
- for (j = 0; j < 9; j++)
- {
- value *= 10;
- value += (character[i + j] - '0');
- }
- character[i] = 31; /* NS */
- character[i + 1] = (value & 0x3f000000) >> 24;
- character[i + 2] = (value & 0xfc0000) >> 18;
- character[i + 3] = (value & 0x3f000) >> 12;
- character[i + 4] = (value & 0xfc0) >> 6;
- character[i + 5] = (value & 0x3f);
- i += 6;
- for (j = i; j < 140; j++)
- {
- set[j] = set[j + 3];
- character[j] = character[j + 3];
- }
- Length -= 3;
- }
- else
- {
- i++;
- }
- } while (i < set.Length);
- /* Inject ECI codes to beginning of data, according to Table 3 */
- if (eciMode != 3)
- {
- insert(0, 27); // ECI
- if ((eciMode >= 0) && (eciMode <= 31))
- {
- insert(1, eciMode & 0x1F);
- Length += 2;
- }
- if ((eciMode >= 32) && (eciMode <= 1023))
- {
- insert(1, 0x20 + (eciMode >> 6));
- insert(2, eciMode & 0x3F);
- Length += 3;
- }
- if ((eciMode >= 1024) && (eciMode <= 32767))
- {
- insert(1, 0x30 + (eciMode >> 12));
- insert(2, (eciMode >> 6) & 0x3F);
- insert(3, eciMode & 0x3F);
- Length += 4;
- }
- if ((eciMode >= 32768) && (eciMode <= 999999))
- {
- insert(1, 0x38 + (eciMode >> 18));
- insert(2, (eciMode >> 12) & 0x3F);
- insert(3, (eciMode >> 6) & 0x3F);
- insert(4, eciMode & 0x3F);
- Length += 5;
- }
- }
- /* Make sure we haven't exceeded the maximum data Length. */
- if ((mode == 2 || mode == 3) && Length > 84)
- {
- return false;
- }
- if ((mode == 4 || mode == 6) && Length > 93)
- {
- return false;
- }
- if (mode == 5 && Length > 77)
- {
- return false;
- }
- return true;
- }
- /**
- * Guesses the best set to use at the specified index by looking at the surrounding sets. In general, characters in
- * lower-numbered sets are more common, so we choose them if we can. If no good surrounding sets can be found, the default
- * value returned is the first value from the valid set.
- *
- * @param index the current index
- * @param Length the maximum Length to look at
- * @param valid the valid sets for this index
- * @return the best set to use at the specified index
- */
- int bestSurroundingSet(int index, int Length, params int[] valid)
- {
- int option1 = set[index - 1];
- if (index + 1 < Length)
- {
- // we have two options to check
- int option2 = set[index + 1];
- if (contains(valid, option1) && contains(valid, option2))
- {
- return Math.Min(option1, option2);
- }
- else if (contains(valid, option1))
- {
- return option1;
- }
- else if (contains(valid, option2))
- {
- return option2;
- }
- else
- {
- return valid[0];
- }
- }
- else
- {
- // we only have one option to check
- if (contains(valid, option1))
- {
- return option1;
- }
- else
- {
- return valid[0];
- }
- }
- }
- /**
- * Moves everything up so that the specified shift or latch character can be inserted.
- *
- * @param position the position beyond which everything needs to be shifted
- * @param c the latch or shift character to insert at the specified position, after everything has been shifted
- */
- void insert(int position, int c)
- {
- for (int i = 143; i > position; i--)
- {
- set[i] = set[i - 1];
- character[i] = character[i - 1];
- }
- character[position] = c;
- }
- /**
- * Returns the error correction codewords for the specified data codewords.
- *
- * @param codewords the codewords that we need error correction codewords for
- * @param ecclen the number of error correction codewords needed
- * @return the error correction codewords for the specified data codewords
- */
- static int[] getErrorCorrection(int[] codewords, int ecclen)
- {
- ReedSolomon rs = new ReedSolomon();
- rs.init_gf(0x43);
- rs.init_code(ecclen, 1);
- rs.encode(codewords.Length, codewords);
- int[] results = new int[ecclen];
- for (int i = 0; i < ecclen; i++)
- {
- results[i] = rs.getResult(results.Length - 1 - i);
- }
- return results;
- }
- /** {@inheritDoc} */
- //@Override
- protected void plotSymbol()
- {
- // hexagons
- for (int row = 0; row < 33; row++)
- {
- for (int col = 0; col < 30; col++)
- {
- if (grid[row,col])
- {
- double x = (2.46 * col) + 1.23;
- if ((row & 1) != 0)
- {
- x += 1.23;
- }
- double y = (2.135 * row) + 1.43;
- hexagons.Add(new Hexagon(x, y));
- }
- }
- }
- // circles
- //double[] radii = { 10.85, 8.97, 7.10, 5.22, 3.31, 1.43 };
- double[] radii = { 9.91, 6.16, 2.37 };
- for (int i = 0; i < radii.Length; i++)
- {
- target.Add(new Ellipse(
- 35.76 - radii[i],
- 35.60 - radii[i],
- 35.76 + radii[i],
- 35.60 + radii[i]));
- }
- }
- /** {@inheritDoc} */
- //@Override
- protected int[] getCodewords()
- {
- return codewords;
- }
- //========================================================================
- int[] insert(int[] original, int index, int[] inserted)
- {
- int[] modified = new int[original.Length + inserted.Length];
- Array.Copy(original, 0, modified, 0, index);
- Array.Copy(inserted, 0, modified, index, inserted.Length);
- Array.Copy(original, index, modified, index + inserted.Length, modified.Length - index - inserted.Length);
- return modified;
- }
- bool contains(int[] values, int value)
- {
- for (int i = 0; i < values.Length; i++)
- {
- if (values[i] == value)
- {
- return true;
- }
- }
- return false;
- }
- }
- }
|