KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > BarcodeDatamatrix


1 /*
2  * $Id: BarcodeDatamatrix.java 2771 2007-05-21 10:53:31Z psoares33 $
3  *
4  * Copyright 2007 by Paulo Soares.
5  *
6  * The contents of this file are subject to the Mozilla Public License Version 1.1
7  * (the "License"); you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the License.
13  *
14  * The Original Code is 'iText, a free JAVA-PDF library'.
15  *
16  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18  * All Rights Reserved.
19  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21  *
22  * Contributor(s): all the names of the contributors are added in the source code
23  * where applicable.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27  * provisions of LGPL are applicable instead of those above. If you wish to
28  * allow use of your version of this file only under the terms of the LGPL
29  * License and not to allow others to use your version of this file under
30  * the MPL, indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by the LGPL.
32  * If you do not delete the provisions above, a recipient may use your version
33  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34  *
35  * This library is free software; you can redistribute it and/or modify it
36  * under the terms of the MPL as stated above or under the terms of the GNU
37  * Library General Public License as published by the Free Software Foundation;
38  * either version 2 of the License, or any later version.
39  *
40  * This library is distributed in the hope that it will be useful, but WITHOUT
41  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43  * details.
44  *
45  * If you didn't download this code from the following link, you should check if
46  * you aren't using an obsolete version:
47  * http://www.lowagie.com/iText/
48  */

49 package com.lowagie.text.pdf;
50
51 import com.lowagie.text.BadElementException;
52 import com.lowagie.text.Image;
53 import com.lowagie.text.pdf.codec.CCITTG4Encoder;
54 import java.awt.Canvas JavaDoc;
55 import java.awt.Color JavaDoc;
56 import java.awt.image.MemoryImageSource JavaDoc;
57 import java.util.Arrays JavaDoc;
58 import java.io.UnsupportedEncodingException JavaDoc;
59 import java.util.Hashtable JavaDoc;
60
61 /**
62  * A DataMatrix 2D barcode generator.
63  */

64 public class BarcodeDatamatrix {
65     /**
66      * No error.
67      */

68     public static final int DM_NO_ERROR = 0;
69     /**
70      * The text is too big for the symbology capabilities.
71      */

72     public static final int DM_ERROR_TEXT_TOO_BIG = 1;
73     /**
74      * The dimensions given for the symbol are illegal.
75      */

76     public static final int DM_ERROR_INVALID_SQUARE = 3;
77     /**
78      * An error while parsing an extension.
79      */

80     public static final int DM_ERROR_EXTENSION = 5;
81
82     /**
83      * The best encodation will be used.
84      */

85     public static final int DM_AUTO = 0;
86     /**
87      * ASCII encodation.
88      */

89     public static final int DM_ASCII = 1;
90     /**
91      * C40 encodation.
92      */

93     public static final int DM_C40 = 2;
94     /**
95      * TEXT encodation.
96      */

97     public static final int DM_TEXT = 3;
98     /**
99      * Binary encodation.
100      */

101     public static final int DM_B256 = 4;
102     /**
103      * X21 encodation.
104      */

105     public static final int DM_X21 = 5;
106     /**
107      * EDIFACT encodation.
108      */

109     public static final int DM_EDIFACT = 6;
110     /**
111      * No encodation needed. The bytes provided are already encoded.
112      */

113     public static final int DM_RAW = 7;
114
115     /**
116      * Allows extensions to be embedded at the start of the text.
117      */

118     public static final int DM_EXTENSION = 32;
119     /**
120      * Doesn't generate the image but returns all the other information.
121      */

122     public static final int DM_TEST = 64;
123
124     private final static DmParams[] dmSizes = {
125         new DmParams(10, 10, 10, 10, 3, 3, 5),
126         new DmParams(12, 12, 12, 12, 5, 5, 7),
127         new DmParams(8, 18, 8, 18, 5, 5, 7),
128         new DmParams(14, 14, 14, 14, 8, 8, 10),
129         new DmParams(8, 32, 8, 16, 10, 10, 11),
130         new DmParams(16, 16, 16, 16, 12, 12, 12),
131         new DmParams(12, 26, 12, 26, 16, 16, 14),
132         new DmParams(18, 18, 18, 18, 18, 18, 14),
133         new DmParams(20, 20, 20, 20, 22, 22, 18),
134         new DmParams(12, 36, 12, 18, 22, 22, 18),
135         new DmParams(22, 22, 22, 22, 30, 30, 20),
136         new DmParams(16, 36, 16, 18, 32, 32, 24),
137         new DmParams(24, 24, 24, 24, 36, 36, 24),
138         new DmParams(26, 26, 26, 26, 44, 44, 28),
139         new DmParams(16, 48, 16, 24, 49, 49, 28),
140         new DmParams(32, 32, 16, 16, 62, 62, 36),
141         new DmParams(36, 36, 18, 18, 86, 86, 42),
142         new DmParams(40, 40, 20, 20, 114, 114, 48),
143         new DmParams(44, 44, 22, 22, 144, 144, 56),
144         new DmParams(48, 48, 24, 24, 174, 174, 68),
145         new DmParams(52, 52, 26, 26, 204, 102, 42),
146         new DmParams(64, 64, 16, 16, 280, 140, 56),
147         new DmParams(72, 72, 18, 18, 368, 92, 36),
148         new DmParams(80, 80, 20, 20, 456, 114, 48),
149         new DmParams(88, 88, 22, 22, 576, 144, 56),
150         new DmParams(96, 96, 24, 24, 696, 174, 68),
151         new DmParams(104, 104, 26, 26, 816, 136, 56),
152         new DmParams(120, 120, 20, 20, 1050, 175, 68),
153         new DmParams(132, 132, 22, 22, 1304, 163, 62),
154         new DmParams(144, 144, 24, 24, 1558, 156, 62)};
155
156     private static final String JavaDoc x12 = "\r*> 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
157     private int extOut;
158     private short[] place;
159     private byte[] image;
160     private int height;
161     private int width;
162     private int ws;
163     private int options;
164     
165     /**
166      * Creates an instance of this class.
167      */

168     public BarcodeDatamatrix() {
169     }
170
171     private void setBit(int x, int y, int xByte) {
172         image[y * xByte + x / 8] |= (byte)(128 >> (x & 7));
173     }
174
175     private void draw(byte[] data, int dataSize, DmParams dm) {
176         int i, j, p, x, y, xs, ys, z;
177         int xByte = (dm.width + ws * 2 + 7) / 8;
178         Arrays.fill(image, (byte)0);
179         //alignment patterns
180
//dotted horizontal line
181
for (i = ws; i < dm.height + ws; i += dm.heightSection) {
182             for (j = ws; j < dm.width + ws; j += 2) {
183                 setBit(j, i, xByte);
184             }
185         }
186         //solid horizontal line
187
for (i = dm.heightSection - 1 + ws; i < dm.height + ws; i += dm.heightSection) {
188             for (j = ws; j < dm.width + ws; ++j) {
189                 setBit(j, i, xByte);
190             }
191         }
192         //solid vertical line
193
for (i = ws; i < dm.width + ws; i += dm.widthSection) {
194             for (j = ws; j < dm.height + ws; ++j) {
195                 setBit(i, j, xByte);
196             }
197         }
198         //dotted vertical line
199
for (i = dm.widthSection - 1 + ws; i < dm.width + ws; i += dm.widthSection) {
200             for (j = 1 + ws; j < dm.height + ws; j += 2) {
201                 setBit(i, j, xByte);
202             }
203         }
204         p = 0;
205         for (ys = 0; ys < dm.height; ys += dm.heightSection) {
206             for (y = 1; y < dm.heightSection - 1; ++y) {
207                 for (xs = 0; xs < dm.width; xs += dm.widthSection) {
208                     for (x = 1; x < dm.widthSection - 1; ++x) {
209                         z = place[p++];
210                         if (z == 1 || (z > 1 && ((data[z/8-1] & 0xff) & (128 >> (z%8))) != 0))
211                             setBit(x + xs + ws, y + ys + ws, xByte);
212                     }
213                 }
214             }
215         }
216     }
217
218     private static void makePadding(byte[] data, int position, int count) {
219         //already in ascii mode
220
if (count <= 0)
221             return;
222         data[position++] = (byte)129;
223         while (--count > 0) {
224             int t = 129 + (((position + 1) * 149) % 253) + 1;
225             if (t > 254)
226                 t -= 254;
227             data[position++] = (byte)t;
228         }
229     }
230
231     private static boolean isDigit(int c) {
232         return c >= '0' && c <= '9';
233     }
234     
235     private static int asciiEncodation(byte[] text, int textOffset, int textLength, byte[] data, int dataOffset, int dataLength) {
236         int ptrIn, ptrOut, c;
237         ptrIn = textOffset;
238         ptrOut = dataOffset;
239         textLength += textOffset;
240         dataLength += dataOffset;
241         while (ptrIn < textLength) {
242             if (ptrOut >= dataLength)
243                 return -1;
244             c = text[ptrIn++] & 0xff;
245             if (isDigit(c) && ptrIn < textLength && isDigit(text[ptrIn] & 0xff)) {
246                 data[ptrOut++] = (byte)((c - '0') * 10 + (text[ptrIn++] & 0xff) - '0' + 130);
247             }
248             else if (c > 127) {
249                 if (ptrOut + 1 >= dataLength)
250                     return -1;
251                 data[ptrOut++] = (byte)235;
252                 data[ptrOut++] = (byte)(c - 128 + 1);
253             }
254             else {
255                 data[ptrOut++] = (byte)(c + 1);
256             }
257         }
258         return ptrOut - dataOffset;
259     }
260
261     private static int b256Encodation(byte[] text, int textOffset, int textLength, byte[] data, int dataOffset, int dataLength) {
262         int k, j, prn, tv, c;
263         if (textLength == 0)
264             return 0;
265         if (textLength < 250 && textLength + 2 > dataLength)
266             return -1;
267         if (textLength >= 250 && textLength + 3 > dataLength)
268             return -1;
269         data[dataOffset] = (byte)231;
270         if (textLength < 250) {
271             data[dataOffset + 1] = (byte)textLength;
272             k = 2;
273         }
274         else {
275             data[dataOffset + 1] = (byte)(textLength / 250 + 249);
276             data[dataOffset + 2] = (byte)(textLength % 250);
277             k = 3;
278         }
279         System.arraycopy(text, textOffset, data, k + dataOffset, textLength);
280         k += textLength + dataOffset;
281         for (j = dataOffset + 1; j < k; ++j) {
282             c = data[j] & 0xff;
283             prn = ((149 * (j + 1)) % 255) + 1;
284             tv = c + prn;
285             if (tv > 255)
286                 tv -= 256;
287             data[j] = (byte)tv;
288
289         }
290         return k - dataOffset;
291     }
292
293     private static int X12Encodation(byte[] text, int textOffset, int textLength, byte[] data, int dataOffset, int dataLength) {
294         int ptrIn, ptrOut, count, k, n, ci;
295         byte c;
296         if (textLength == 0)
297             return 0;
298         ptrIn = 0;
299         ptrOut = 0;
300         byte[] x = new byte[textLength];
301         count = 0;
302         for (; ptrIn < textLength; ++ptrIn) {
303             int i = x12.indexOf((char)text[ptrIn + textOffset]);
304             if (i >= 0) {
305                 x[ptrIn] = (byte)i;
306                 ++count;
307             }
308             else {
309                 x[ptrIn] = 100;
310                 if (count >= 6)
311                     count -= (count / 3) * 3;
312                 for (k = 0; k < count; ++k)
313                     x[ptrIn - k - 1] = 100;
314                 count = 0;
315             }
316         }
317         if (count >= 6)
318             count -= (count / 3) * 3;
319         for (k = 0; k < count; ++k)
320             x[ptrIn - k - 1] = 100;
321         ptrIn = 0;
322         c = 0;
323         for (; ptrIn < textLength; ++ptrIn) {
324             c = x[ptrIn];
325             if (ptrOut >= dataLength)
326                 break;
327             if (c < 40) {
328                 if (ptrIn == 0 || (ptrIn > 0 && x[ptrIn - 1] > 40))
329                     data[dataOffset + ptrOut++] = (byte)238;
330                 if (ptrOut + 2 > dataLength)
331                     break;
332                 n = 1600 * x[ptrIn] + 40 * x[ptrIn + 1] + x[ptrIn + 2] + 1;
333                 data[dataOffset + ptrOut++] = (byte)(n / 256);
334                 data[dataOffset + ptrOut++] = (byte)n;
335                 ptrIn += 2;
336             }
337             else {
338                 if (ptrIn > 0 && x[ptrIn - 1] < 40)
339                     data[dataOffset + ptrOut++] = (byte)254;
340                 ci = text[ptrIn + textOffset] & 0xff;
341                 if (ci > 127) {
342                     data[dataOffset + ptrOut++] = (byte)235;
343                     ci -= 128;
344                 }
345                 if (ptrOut >= dataLength)
346                     break;
347                 data[dataOffset + ptrOut++] = (byte)(ci + 1);
348             }
349         }
350         c = 100;
351         if (textLength > 0)
352             c = x[textLength - 1];
353         if (ptrIn != textLength || (c < 40 && ptrOut >= dataLength))
354             return -1;
355         if (c < 40)
356             data[dataOffset + ptrOut++] = (byte)(254);
357         return ptrOut;
358     }
359
360     private static int EdifactEncodation(byte[] text, int textOffset, int textLength, byte[] data, int dataOffset, int dataLength) {
361         int ptrIn, ptrOut, edi, pedi, c;
362         if (textLength == 0)
363             return 0;
364         ptrIn = 0;
365         ptrOut = 0;
366         edi = 0;
367         pedi = 18;
368         boolean ascii = true;
369         for (; ptrIn < textLength; ++ptrIn) {
370             c = text[ptrIn + textOffset] & 0xff;
371             if (((c & 0xe0) == 0x40 || (c & 0xe0) == 0x20) && c != '_') {
372                 if (ascii) {
373                     if (ptrOut + 1 > dataLength)
374                         break;
375                     data[dataOffset + ptrOut++] = (byte)240;
376                     ascii = false;
377                 }
378                 c &= 0x3f;
379                 edi |= c << pedi;
380                 if (pedi == 0) {
381                     if (ptrOut + 3 > dataLength)
382                         break;
383                     data[dataOffset + ptrOut++] = (byte)(edi >> 16);
384                     data[dataOffset + ptrOut++] = (byte)(edi >> 8);
385                     data[dataOffset + ptrOut++] = (byte)edi;
386                     edi = 0;
387                     pedi = 18;
388                 }
389                 else
390                     pedi -= 6;
391             }
392             else {
393                 if (!ascii) {
394                     edi |= ('_' & 0x3f) << pedi;
395                     if (ptrOut + (3 - pedi / 8) > dataLength)
396                         break;
397                     data[dataOffset + ptrOut++] = (byte)(edi >> 16);
398                     if (pedi <= 12)
399                         data[dataOffset + ptrOut++] = (byte)(edi >> 8);
400                     if (pedi <= 6)
401                         data[dataOffset + ptrOut++] = (byte)edi;
402                     ascii = true;
403                     pedi = 18;
404                     edi = 0;
405                 }
406                 if (c > 127) {
407                     if (ptrOut >= dataLength)
408                         break;
409                     data[dataOffset + ptrOut++] = (byte)235;
410                     c -= 128;
411                 }
412                 if (ptrOut >= dataLength)
413                     break;
414                 data[dataOffset + ptrOut++] = (byte)(c + 1);
415             }
416         }
417         if (ptrIn != textLength)
418             return -1;
419         if (!ascii) {
420             edi |= ('_' & 0x3f) << pedi;
421             if (ptrOut + (3 - pedi / 8) > dataLength)
422                 return -1;
423             data[dataOffset + ptrOut++] = (byte)(edi >> 16);
424             if (pedi <= 12)
425                 data[dataOffset + ptrOut++] = (byte)(edi >> 8);
426             if (pedi <= 6)
427                 data[dataOffset + ptrOut++] = (byte)edi;
428         }
429         return ptrOut;
430     }
431
432     private static int C40OrTextEncodation(byte[] text, int textOffset, int textLength, byte[] data, int dataOffset, int dataLength, boolean c40) {
433         int ptrIn, ptrOut, encPtr, last0, last1, i, a, c;
434         String JavaDoc basic, shift2, shift3;
435         if (textLength == 0)
436             return 0;
437         ptrIn = 0;
438         ptrOut = 0;
439         if (c40)
440             data[dataOffset + ptrOut++] = (byte)230;
441         else
442             data[dataOffset + ptrOut++] = (byte)239;
443         shift2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_";
444         if (c40) {
445             basic = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
446             shift3 = "`abcdefghijklmnopqrstuvwxyz{|}~\177";
447         }
448         else {
449             basic = " 0123456789abcdefghijklmnopqrstuvwxyz";
450             shift3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177";
451         }
452         int[] enc = new int[textLength * 4 + 10];
453         encPtr = 0;
454         last0 = 0;
455         last1 = 0;
456         while (ptrIn < textLength) {
457             if ((encPtr % 3) == 0) {
458                 last0 = ptrIn;
459                 last1 = encPtr;
460             }
461             c = text[textOffset + ptrIn++] & 0xff;
462             if (c > 127) {
463                 c -= 128;
464                 enc[encPtr++] = 1;
465                 enc[encPtr++] = 30;
466             }
467             int idx = basic.indexOf((char)c);
468             if (idx >= 0) {
469                 enc[encPtr++] = idx + 3;
470             }
471             else if (c < 32) {
472                 enc[encPtr++] = 0;
473                 enc[encPtr++] = c;
474             }
475             else if ((idx = shift2.indexOf((char)c)) >= 0) {
476                 enc[encPtr++] = 1;
477                 enc[encPtr++] = idx;
478             }
479             else if ((idx = shift3.indexOf((char)c)) >= 0) {
480                 enc[encPtr++] = 2;
481                 enc[encPtr++] = idx;
482             }
483         }
484         if ((encPtr % 3) != 0) {
485             ptrIn = last0;
486             encPtr = last1;
487         }
488         if (encPtr / 3 * 2 > dataLength - 2) {
489             return -1;
490         }
491         i = 0;
492         for (; i < encPtr; i += 3) {
493             a = 1600 * enc[i] + 40 * enc[i + 1] + enc[i + 2] + 1;
494             data[dataOffset + ptrOut++] = (byte)(a / 256);
495             data[dataOffset + ptrOut++] = (byte)a;
496         }
497         data[ptrOut++] = (byte)254;
498         i = asciiEncodation(text, ptrIn, textLength - ptrIn, data, ptrOut, dataLength - ptrOut);
499         if (i < 0)
500             return i;
501         return ptrOut + i;
502     }
503
504     private static int getEncodation(byte[] text, int textOffset, int textSize, byte[] data, int dataOffset, int dataSize, int options, boolean firstMatch) {
505         int e, j, k;
506         int[] e1 = new int[6];
507         if (dataSize < 0)
508             return -1;
509         e = -1;
510         options &= 7;
511         if (options == 0) {
512             e1[0] = asciiEncodation(text, textOffset, textSize, data, dataOffset, dataSize);
513             if (firstMatch && e1[0] >= 0)
514                 return e1[0];
515             e1[1] = C40OrTextEncodation(text, textOffset, textSize, data, dataOffset, dataSize, false);
516             if (firstMatch && e1[1] >= 0)
517                 return e1[1];
518             e1[2] = C40OrTextEncodation(text, textOffset, textSize, data, dataOffset, dataSize, true);
519             if (firstMatch && e1[2] >= 0)
520                 return e1[2];
521             e1[3] = b256Encodation(text, textOffset, textSize, data, dataOffset, dataSize);
522             if (firstMatch && e1[3] >= 0)
523                 return e1[3];
524             e1[4] = X12Encodation(text, textOffset, textSize, data, dataOffset, dataSize);
525             if (firstMatch && e1[4] >= 0)
526                 return e1[4];
527             e1[5] = EdifactEncodation(text, textOffset, textSize, data, dataOffset, dataSize);
528             if (firstMatch && e1[5] >= 0)
529                 return e1[5];
530             if (e1[0] < 0 && e1[1] < 0 && e1[2] < 0 && e1[3] < 0 && e1[4] < 0 && e1[5] < 0) {
531                 return -1;
532             }
533             j = 0;
534             e = 99999;
535             for (k = 0; k < 6; ++k) {
536                 if (e1[k] >= 0 && e1[k] < e) {
537                     e = e1[k];
538                     j = k;
539                 }
540             }
541             if (j == 0)
542                 e = asciiEncodation(text, textOffset, textSize, data, dataOffset, dataSize);
543             else if (j == 1)
544                 e = C40OrTextEncodation(text, textOffset, textSize, data, dataOffset, dataSize, false);
545             else if (j == 2)
546                 e = C40OrTextEncodation(text, textOffset, textSize, data, dataOffset, dataSize, true);
547             else if (j == 3)
548                 e = b256Encodation(text, textOffset, textSize, data, dataOffset, dataSize);
549             else if (j == 4)
550                 e = X12Encodation(text, textOffset, textSize, data, dataOffset, dataSize);
551             return e;
552         }
553         switch (options) {
554         case DM_ASCII:
555             return asciiEncodation(text, textOffset, textSize, data, dataOffset, dataSize);
556         case DM_C40:
557             return C40OrTextEncodation(text, textOffset, textSize, data, dataOffset, dataSize, true);
558         case DM_TEXT:
559             return C40OrTextEncodation(text, textOffset, textSize, data, dataOffset, dataSize, false);
560         case DM_B256:
561             return b256Encodation(text, textOffset, textSize, data, dataOffset, dataSize);
562         case DM_X21:
563             return X12Encodation(text, textOffset, textSize, data, dataOffset, dataSize);
564         case DM_EDIFACT:
565             return EdifactEncodation(text, textOffset, textSize, data, dataOffset, dataSize);
566         case DM_RAW:
567             if (textSize > dataSize)
568                 return -1;
569             System.arraycopy(text, textOffset, data, dataOffset, textSize);
570             return textSize;
571         }
572         return -1;
573     }
574
575     private static int getNumber(byte[] text, int ptrIn, int n) {
576         int v, j, c;
577         v = 0;
578         for (j = 0; j < n; ++j) {
579             c = text[ptrIn++] &0xff;
580             if (c < '0' || c > '9')
581                 return -1;
582             v = v * 10 + c - '0';
583         }
584         return v;
585     }
586
587     private int processExtensions(byte[] text, int textOffset, int textSize, byte[] data) {
588         int order, ptrIn, ptrOut, eci, fn, ft, fi, c;
589         if ((options & DM_EXTENSION) == 0)
590             return 0;
591         order = 0;
592         ptrIn = 0;
593         ptrOut = 0;
594         while (ptrIn < textSize) {
595             if (order > 20)
596                 return -1;
597             c = text[textOffset + ptrIn++] &0xff;
598             ++order;
599             switch (c) {
600             case '.':
601                 extOut = ptrIn;
602                 return ptrOut;
603             case 'e':
604                 if (ptrIn + 6 > textSize)
605                     return -1;
606                 eci = getNumber(text, textOffset + ptrIn, 6);
607                 if (eci < 0)
608                     return -1;
609                 ptrIn += 6;
610                 data[ptrOut++] = (byte)241;
611                 if (eci < 127)
612                     data[ptrOut++] = (byte)(eci + 1);
613                 else if (eci < 16383) {
614                     data[ptrOut++] = (byte)((eci - 127) / 254 + 128);
615                     data[ptrOut++] = (byte)(((eci - 127) % 254) + 1);
616                 }
617                 else {
618                     data[ptrOut++] = (byte)((eci - 16383) / 64516 + 192);
619                     data[ptrOut++] = (byte)((((eci - 16383) / 254) % 254) + 1);
620                     data[ptrOut++] = (byte)(((eci - 16383) % 254) + 1);
621                 }
622                 break;
623             case 's':
624                 if (order != 1)
625                     return -1;
626                 if (ptrIn + 9 > textSize)
627                     return -1;
628                 fn = getNumber(text, textOffset + ptrIn, 2);
629                 if (fn <= 0 || fn > 16)
630                     return -1;
631                 ptrIn += 2;
632                 ft = getNumber(text, textOffset + ptrIn, 2);
633                 if (ft <= 1 || ft > 16)
634                     return -1;
635                 ptrIn += 2;
636                 fi = getNumber(text, textOffset + ptrIn, 5);
637                 if (fi < 0 || fn >= 64516)
638                     return -1;
639                 ptrIn += 5;
640                 data[ptrOut++] = (byte)(233);
641                 data[ptrOut++] = (byte)(((fn - 1) << 4) | (17 - ft));
642                 data[ptrOut++] = (byte)(fi / 254 + 1);
643                 data[ptrOut++] = (byte)((fi % 254) + 1);
644                 break;
645             case 'p':
646                 if (order != 1)
647                     return -1;
648                 data[ptrOut++] = (byte)(234);
649                 break;
650             case 'm':
651                 if (order != 1)
652                     return -1;
653                 if (ptrIn + 1 > textSize)
654                     return -1;
655                 c = text[textOffset + ptrIn++] &0xff;
656                 if (c != '5' && c != '5')
657                     return -1;
658                 data[ptrOut++] = (byte)(234);
659                 data[ptrOut++] = (byte)(c == '5' ? 236 : 237);
660                 break;
661             case 'f':
662                 if (order != 1 && (order != 2 || (text[textOffset] != 's' && text[textOffset] != 'm')))
663                     return -1;
664                 data[ptrOut++] = (byte)(232);
665             }
666         }
667         return -1;
668     }
669
670     /**
671      * Creates a barcode. The <CODE>String</CODE> is interpreted with the ISO-8859-1 encoding
672      * @param text the text
673      * @return the status of the generation. It can be one of this values:
674      * <p>
675      * <CODE>DM_NO_ERROR</CODE> - no error.<br>
676      * <CODE>DM_ERROR_TEXT_TOO_BIG</CODE> - the text is too big for the symbology capabilities.<br>
677      * <CODE>DM_ERROR_INVALID_SQUARE</CODE> - the dimensions given for the symbol are illegal.<br>
678      * <CODE>DM_ERROR_EXTENSION</CODE> - an error was while parsing an extension.
679      * @throws java.io.UnsupportedEncodingException on error
680      */

681     public int generate(String JavaDoc text) throws UnsupportedEncodingException JavaDoc {
682         byte[] t = text.getBytes("iso-8859-1");
683         return generate(t, 0, t.length);
684     }
685     
686     /**
687      * Creates a barcode.
688      * @param text the text
689      * @param textOffset the offset to the start of the text
690      * @param textSize the text size
691      * @return the status of the generation. It can be one of this values:
692      * <p>
693      * <CODE>DM_NO_ERROR</CODE> - no error.<br>
694      * <CODE>DM_ERROR_TEXT_TOO_BIG</CODE> - the text is too big for the symbology capabilities.<br>
695      * <CODE>DM_ERROR_INVALID_SQUARE</CODE> - the dimensions given for the symbol are illegal.<br>
696      * <CODE>DM_ERROR_EXTENSION</CODE> - an error was while parsing an extension.
697      */

698     public int generate(byte[] text, int textOffset, int textSize) {
699         int extCount, e, k, full;
700         DmParams dm, last;
701         byte[] data = new byte[2500];
702         extOut = 0;
703         extCount = processExtensions(text, textOffset, textSize, data);
704         if (extCount < 0) {
705             return DM_ERROR_EXTENSION;
706         }
707         e = -1;
708         if (height == 0 || width == 0) {
709             last = dmSizes[dmSizes.length - 1];
710             e = getEncodation(text, textOffset + extOut, textSize - extOut, data, extCount, last.dataSize - extCount, options, false);
711             if (e < 0) {
712                 return DM_ERROR_TEXT_TOO_BIG;
713             }
714             e += extCount;
715             for (k = 0; k < dmSizes.length; ++k) {
716                 if (dmSizes[k].dataSize >= e)
717                     break;
718             }
719             dm = dmSizes[k];
720             height = dm.height;
721             width = dm.width;
722         }
723         else {
724             for (k = 0; k < dmSizes.length; ++k) {
725                 if (height == dmSizes[k].height && width == dmSizes[k].width)
726                     break;
727             }
728             if (k == dmSizes.length) {
729                 return DM_ERROR_INVALID_SQUARE;
730             }
731             dm = dmSizes[k];
732             e = getEncodation(text, textOffset + extOut, textSize - extOut, data, extCount, dm.dataSize - extCount, options, true);
733             if (e < 0) {
734                 return DM_ERROR_TEXT_TOO_BIG;
735             }
736             e += extCount;
737         }
738         if ((options & DM_TEST) != 0) {
739             return DM_NO_ERROR;
740         }
741         image = new byte[(((dm.width + 2 * ws) + 7) / 8) * (dm.height + 2 * ws)];
742         makePadding(data, e, dm.dataSize - e);
743         place = Placement.doPlacement(dm.height - (dm.height / dm.heightSection * 2), dm.width - (dm.width / dm.widthSection * 2));
744         full = dm.dataSize + ((dm.dataSize + 2) / dm.dataBlock) * dm.errorBlock;
745         ReedSolomon.generateECC(data, dm.dataSize, dm.dataBlock, dm.errorBlock);
746         draw(data, full, dm);
747         return DM_NO_ERROR;
748     }
749
750     /** Gets an <CODE>Image</CODE> with the barcode. A successful call to the method <CODE>generate()</CODE>
751      * before calling this method is required.
752      * @return the barcode <CODE>Image</CODE>
753      * @throws BadElementException on error
754      */

755     public Image createImage() throws BadElementException {
756         if (image == null)
757             return null;
758         byte g4[] = CCITTG4Encoder.compress(image, width + 2 * ws, height + 2 * ws);
759         return Image.getInstance(width + 2 * ws, height + 2 * ws, false, Image.CCITTG4, 0, g4, null);
760     }
761     
762     /**
763      * Creates a <CODE>java.awt.Image</CODE>. A successful call to the method <CODE>generate()</CODE>
764      * before calling this method is required.
765      * @param foreground the color of the bars
766      * @param background the color of the background
767      * @return the image
768      */

769     public java.awt.Image JavaDoc createAwtImage(Color JavaDoc foreground, Color JavaDoc background) {
770         if (image == null)
771             return null;
772         int f = foreground.getRGB();
773         int g = background.getRGB();
774         Canvas JavaDoc canvas = new Canvas JavaDoc();
775
776         int w = width + 2 * ws;
777         int h = height + 2 * ws;
778         int pix[] = new int[w * h];
779         int stride = (w + 7) / 8;
780         int ptr = 0;
781         for (int k = 0; k < h; ++k) {
782             int p = k * stride;
783             for (int j = 0; j < w; ++j) {
784                 int b = image[p + (j / 8)] & 0xff;
785                 b <<= j % 8;
786                 pix[ptr++] = (b & 0x80) == 0 ? g : f;
787             }
788         }
789         java.awt.Image JavaDoc img = canvas.createImage(new MemoryImageSource JavaDoc(w, h, pix, 0, w));
790         return img;
791     }
792     
793     private static class DmParams {
794         DmParams(int height, int width, int heightSection, int widthSection, int dataSize, int dataBlock, int errorBlock) {
795             this.height = height;
796             this.width = width;
797             this.heightSection = heightSection;
798             this.widthSection = widthSection;
799             this.dataSize = dataSize;
800             this.dataBlock = dataBlock;
801             this.errorBlock = errorBlock;
802         }
803
804         int height;
805         int width;
806         int heightSection;
807         int widthSection;
808         int dataSize;
809         int dataBlock;
810         int errorBlock;
811     };
812
813     /**
814      * Gets the generated image. The image is represented as a stream of bytes, each byte representing
815      * 8 pixels, 0 for white and 1 for black, with the high-order bit of each byte first. Each row
816      * is aligned at byte boundaries. The dimensions of the image are defined by height and width
817      * plus 2 * ws.
818      * @return the generated image
819      */

820     public byte[] getImage() {
821         return image;
822     }
823
824     /**
825      * Gets the height of the barcode. Will contain the real height used after a successful call
826      * to <CODE>generate()</CODE>. This height doesn't include the whitespace border, if any.
827      * @return the height of the barcode
828      */

829     public int getHeight() {
830         return height;
831     }
832
833     /**
834      * Sets the height of the barcode. If the height is zero it will be calculated. This height doesn't include the whitespace border, if any.
835      * <p>
836      * The allowed dimensions are (height, width):<p>
837      * 10, 10<br>
838      * 12, 12<br>
839      * 8, 18<br>
840      * 14, 14<br>
841      * 8, 32<br>
842      * 16, 16<br>
843      * 12, 26<br>
844      * 18, 18<br>
845      * 20, 20<br>
846      * 12, 36<br>
847      * 22, 22<br>
848      * 16, 36<br>
849      * 24, 24<br>
850      * 26, 26<br>
851      * 16, 48<br>
852      * 32, 32<br>
853      * 36, 36<br>
854      * 40, 40<br>
855      * 44, 44<br>
856      * 48, 48<br>
857      * 52, 52<br>
858      * 64, 64<br>
859      * 72, 72<br>
860      * 80, 80<br>
861      * 88, 88<br>
862      * 96, 96<br>
863      * 104, 104<br>
864      * 120, 120<br>
865      * 132, 132<br>
866      * 144, 144<br>
867      * @param height the height of the barcode
868      */

869     public void setHeight(int height) {
870         this.height = height;
871     }
872
873     /**
874      * Gets the width of the barcode. Will contain the real width used after a successful call
875      * to <CODE>generate()</CODE>. This width doesn't include the whitespace border, if any.
876      * @return the width of the barcode
877      */

878     public int getWidth() {
879         return width;
880     }
881
882     /**
883      * Sets the width of the barcode. If the width is zero it will be calculated. This width doesn't include the whitespace border, if any.
884      * <p>
885      * The allowed dimensions are (height, width):<p>
886      * 10, 10<br>
887      * 12, 12<br>
888      * 8, 18<br>
889      * 14, 14<br>
890      * 8, 32<br>
891      * 16, 16<br>
892      * 12, 26<br>
893      * 18, 18<br>
894      * 20, 20<br>
895      * 12, 36<br>
896      * 22, 22<br>
897      * 16, 36<br>
898      * 24, 24<br>
899      * 26, 26<br>
900      * 16, 48<br>
901      * 32, 32<br>
902      * 36, 36<br>
903      * 40, 40<br>
904      * 44, 44<br>
905      * 48, 48<br>
906      * 52, 52<br>
907      * 64, 64<br>
908      * 72, 72<br>
909      * 80, 80<br>
910      * 88, 88<br>
911      * 96, 96<br>
912      * 104, 104<br>
913      * 120, 120<br>
914      * 132, 132<br>
915      * 144, 144<br>
916      * @param width the width of the barcode
917      */

918     public void setWidth(int width) {
919         this.width = width;
920     }
921
922     /**
923      * Gets the whitespace border around the barcode.
924      * @return the whitespace border around the barcode
925      */

926     public int getWs() {
927         return ws;
928     }
929
930     /**
931      * Sets the whitespace border around the barcode.
932      * @param ws the whitespace border around the barcode
933      */

934     public void setWs(int ws) {
935         this.ws = ws;
936     }
937
938     /**
939      * Gets the barcode options.
940      * @return the barcode options
941      */

942     public int getOptions() {
943         return options;
944     }
945
946     /**
947      * Sets the options for the barcode generation. The options can be:<p>
948      * One of:<br>
949      * <CODE>DM_AUTO</CODE> - the best encodation will be used<br>
950      * <CODE>DM_ASCII</CODE> - ASCII encodation<br>
951      * <CODE>DM_C40</CODE> - C40 encodation<br>
952      * <CODE>DM_TEXT</CODE> - TEXT encodation<br>
953      * <CODE>DM_B256</CODE> - binary encodation<br>
954      * <CODE>DM_X21</CODE> - X21 encodation<br>
955      * <CODE>DM_EDIFACT</CODE> - EDIFACT encodation<br>
956      * <CODE>DM_RAW</CODE> - no encodation. The bytes provided are already encoded and will be added directly to the barcode, using padding if needed. It assumes that the encodation state is left at ASCII after the last byte.<br>
957      * <p>
958      * One of:<br>
959      * <CODE>DM_EXTENSION</CODE> - allows extensions to be embedded at the start of the text:<p>
960      * exxxxxx - ECI number xxxxxx<br>
961      * m5 - macro 5<br>
962      * m6 - macro 6<br>
963      * f - FNC1<br>
964      * saabbccccc - Structured Append, aa symbol position (1-16), bb total number of symbols (2-16), ccccc file identification (0-64515)<br>
965      * p - Reader programming<br>
966      * . - extension terminator<p>
967      * Example for a structured append, symbol 2 of 6, with FNC1 and ECI 000005. The actual text is "Hello".<p>
968      * s020600075fe000005.Hello<p>
969      * One of:<br>
970      * <CODE>DM_TEST</CODE> - doesn't generate the image but returns all the other information.
971      * @param options the barcode options
972      */

973     public void setOptions(int options) {
974         this.options = options;
975     }
976     
977     static class Placement {
978         private int nrow;
979         private int ncol;
980         private short[] array;
981         private static final Hashtable JavaDoc cache = new Hashtable JavaDoc();
982
983         private Placement() {
984         }
985         
986         static short[] doPlacement(int nrow, int ncol) {
987             Integer JavaDoc key = new Integer JavaDoc(nrow * 1000 + ncol);
988             short[] pc = (short[])cache.get(key);
989             if (pc != null)
990                 return pc;
991             Placement p = new Placement();
992             p.nrow = nrow;
993             p.ncol = ncol;
994             p.array = new short[nrow * ncol];
995             p.ecc200();
996             cache.put(key, p.array);
997             return p.array;
998         }
999
1000        /* "module" places "chr+bit" with appropriate wrapping within array[] */
1001        private void module(int row, int col, int chr, int bit) {
1002            if (row < 0) { row += nrow; col += 4 - ((nrow+4)%8); }
1003            if (col < 0) { col += ncol; row += 4 - ((ncol+4)%8); }
1004            array[row*ncol+col] = (short)(8*chr + bit);
1005        }
1006        /* "utah" places the 8 bits of a utah-shaped symbol character in ECC200 */
1007        private void utah(int row, int col, int chr) {
1008            module(row-2,col-2,chr,0);
1009            module(row-2,col-1,chr,1);
1010            module(row-1,col-2,chr,2);
1011            module(row-1,col-1,chr,3);
1012            module(row-1,col,chr,4);
1013            module(row,col-2,chr,5);
1014            module(row,col-1,chr,6);
1015            module(row,col,chr,7);
1016        }
1017        /* "cornerN" places 8 bits of the four special corner cases in ECC200 */
1018        private void corner1(int chr) {
1019            module(nrow-1,0,chr,0);
1020            module(nrow-1,1,chr,1);
1021            module(nrow-1,2,chr,2);
1022            module(0,ncol-2,chr,3);
1023            module(0,ncol-1,chr,4);
1024            module(1,ncol-1,chr,5);
1025            module(2,ncol-1,chr,6);
1026            module(3,ncol-1,chr,7);
1027        }
1028        private void corner2(int chr){
1029            module(nrow-3,0,chr,0);
1030            module(nrow-2,0,chr,1);
1031            module(nrow-1,0,chr,2);
1032            module(0,ncol-4,chr,3);
1033            module(0,ncol-3,chr,4);
1034            module(0,ncol-2,chr,5);
1035            module(0,ncol-1,chr,6);
1036            module(1,ncol-1,chr,7);
1037        }
1038        private void corner3(int chr){
1039            module(nrow-3,0,chr,0);
1040            module(nrow-2,0,chr,1);
1041            module(nrow-1,0,chr,2);
1042            module(0,ncol-2,chr,3);
1043            module(0,ncol-1,chr,4);
1044            module(1,ncol-1,chr,5);
1045            module(2,ncol-1,chr,6);
1046            module(3,ncol-1,chr,7);
1047        }
1048        private void corner4(int chr){
1049            module(nrow-1,0,chr,0);
1050            module(nrow-1,ncol-1,chr,1);
1051            module(0,ncol-3,chr,2);
1052            module(0,ncol-2,chr,3);
1053            module(0,ncol-1,chr,4);
1054            module(1,ncol-3,chr,5);
1055            module(1,ncol-2,chr,6);
1056            module(1,ncol-1,chr,7);
1057        }
1058        /* "ECC200" fills an nrow x ncol array with appropriate values for ECC200 */
1059        private void ecc200(){
1060            int row, col, chr;
1061            /* First, fill the array[] with invalid entries */
1062            Arrays.fill(array, (short)0);
1063            /* Starting in the correct location for character #1, bit 8,... */
1064            chr = 1; row = 4; col = 0;
1065            do {
1066                /* repeatedly first check for one of the special corner cases, then... */
1067                if ((row == nrow) && (col == 0)) corner1(chr++);
1068                if ((row == nrow-2) && (col == 0) && (ncol%4 != 0)) corner2(chr++);
1069                if ((row == nrow-2) && (col == 0) && (ncol%8 == 4)) corner3(chr++);
1070                if ((row == nrow+4) && (col == 2) && (ncol%8 == 0)) corner4(chr++);
1071                /* sweep upward diagonally, inserting successive characters,... */
1072                do {
1073                    if ((row < nrow) && (col >= 0) && array[row*ncol+col] == 0)
1074                        utah(row,col,chr++);
1075                    row -= 2; col += 2;
1076                } while ((row >= 0) && (col < ncol));
1077                row += 1; col += 3;
1078                /* & then sweep downward diagonally, inserting successive characters,... */
1079
1080                do {
1081                    if ((row >= 0) && (col < ncol) && array[row*ncol+col] == 0)
1082                        utah(row,col,chr++);
1083                    row += 2; col -= 2;
1084                } while ((row < nrow) && (col >= 0));
1085                row += 3; col += 1;
1086                /* ... until the entire array is scanned */
1087            } while ((row < nrow) || (col < ncol));
1088            /* Lastly, if the lower righthand corner is untouched, fill in fixed pattern */
1089            if (array[nrow*ncol-1] == 0) {
1090                array[nrow*ncol-1] = array[nrow*ncol-ncol-2] = 1;
1091            }
1092        }
1093    }
1094    
1095    static class ReedSolomon {
1096
1097        private static final int log[] = {
1098               0, 255, 1, 240, 2, 225, 241, 53, 3, 38, 226, 133, 242, 43, 54, 210,
1099               4, 195, 39, 114, 227, 106, 134, 28, 243, 140, 44, 23, 55, 118, 211, 234,
1100               5, 219, 196, 96, 40, 222, 115, 103, 228, 78, 107, 125, 135, 8, 29, 162,
1101             244, 186, 141, 180, 45, 99, 24, 49, 56, 13, 119, 153, 212, 199, 235, 91,
1102               6, 76, 220, 217, 197, 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193,
1103             229, 86, 79, 171, 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84,
1104             245, 173, 187, 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207,
1105              57, 147, 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176,
1106               7, 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179,
1107              42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194, 113,
1108             230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127, 247, 146, 66,
1109             137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73, 164, 144, 85, 170,
1110             246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82, 72, 182, 215, 191, 251,
1111              47, 178, 89, 151, 101, 94, 160, 123, 26, 112, 232, 21, 51, 238, 208, 131,
1112              58, 69, 148, 18, 15, 16, 68, 17, 121, 149, 129, 19, 155, 59, 249, 70,
1113             214, 250, 168, 71, 201, 156, 64, 60, 237, 130, 111, 20, 93, 122, 177, 150
1114        };
1115
1116        private static final int alog[] = {
1117               1, 2, 4, 8, 16, 32, 64, 128, 45, 90, 180, 69, 138, 57, 114, 228,
1118             229, 231, 227, 235, 251, 219, 155, 27, 54, 108, 216, 157, 23, 46, 92, 184,
1119              93, 186, 89, 178, 73, 146, 9, 18, 36, 72, 144, 13, 26, 52, 104, 208,
1120             141, 55, 110, 220, 149, 7, 14, 28, 56, 112, 224, 237, 247, 195, 171, 123,
1121             246, 193, 175, 115, 230, 225, 239, 243, 203, 187, 91, 182, 65, 130, 41, 82,
1122             164, 101, 202, 185, 95, 190, 81, 162, 105, 210, 137, 63, 126, 252, 213, 135,
1123              35, 70, 140, 53, 106, 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250,
1124             217, 159, 19, 38, 76, 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172,
1125             117, 234, 249, 223, 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200,
1126             189, 87, 174, 113, 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107,
1127             214, 129, 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169,
1128             127, 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206,
1129             177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161, 111,
1130             222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132, 37, 74,
1131             148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248, 221, 151,
1132               3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75, 150, 1
1133        };
1134
1135        private static final int poly5[] = {
1136             228, 48, 15, 111, 62
1137        };
1138
1139        private static final int poly7[] = {
1140              23, 68, 144, 134, 240, 92, 254
1141        };
1142
1143        private static final int poly10[] = {
1144              28, 24, 185, 166, 223, 248, 116, 255, 110, 61
1145        };
1146
1147        private static final int poly11[] = {
1148             175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120
1149        };
1150
1151        private static final int poly12[] = {
1152              41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242
1153        };
1154
1155        private static final int poly14[] = {
1156             156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185
1157        };
1158
1159        private static final int poly18[] = {
1160              83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254, 225, 48,
1161              90, 188
1162        };
1163
1164        private static final int poly20[] = {
1165              15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, 108, 82,
1166              27, 174, 186, 172
1167        };
1168
1169        private static final int poly24[] = {
1170              52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172,
1171             254, 124, 12, 181, 184, 96, 50, 193
1172        };
1173
1174        private static final int poly28[] = {
1175             211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34, 249, 121,
1176              17, 138, 110, 213, 141, 136, 120, 151, 233, 168, 93, 255
1177        };
1178
1179        private static final int poly36[] = {
1180             245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220, 251, 80, 182,
1181             229, 18, 2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59, 25,
1182             225, 98, 81, 112
1183        };
1184
1185        private static final int poly42[] = {
1186              77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133, 242, 8,
1187             175, 95, 100, 9, 167, 105, 214, 111, 57, 121, 21, 1, 253, 57, 54, 101,
1188             248, 202, 69, 50, 150, 177, 226, 5, 9, 5
1189        };
1190
1191        private static final int poly48[] = {
1192             245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, 188, 237, 87,
1193             191, 106, 16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100, 66, 138,
1194             186, 240, 82, 44, 176, 87, 187, 147, 160, 175, 69, 213, 92, 253, 225, 19
1195        };
1196
1197        private static final int poly56[] = {
1198             175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192, 215, 235,
1199             150, 159, 36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117, 203, 29, 232,
1200             144, 238, 22, 150, 201, 117, 62, 207, 164, 13, 137, 245, 127, 67, 247, 28,
1201             155, 43, 203, 107, 233, 53, 143, 46
1202        };
1203
1204        private static final int poly62[] = {
1205             242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, 108, 196, 37,
1206             185, 112, 134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175, 64, 114, 71,
1207             161, 44, 147, 6, 27, 218, 51, 63, 87, 10, 40, 130, 188, 17, 163, 31,
1208             176, 170, 4, 107, 232, 7, 94, 166, 224, 124, 86, 47, 11, 204
1209        };
1210
1211        private static final int poly68[] = {
1212             220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36, 73, 127,
1213             213, 136, 248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15, 160, 227, 236,
1214              66, 139, 153, 185, 202, 167, 179, 25, 220, 232, 96, 210, 231, 136, 223, 239,
1215             181, 241, 59, 52, 172, 25, 49, 232, 211, 189, 64, 54, 108, 153, 132, 63,
1216              96, 103, 82, 186
1217        };
1218
1219        private static int[] getPoly(int nc) {
1220            switch (nc) {
1221            case 5:
1222                return poly5;
1223            case 7:
1224                return poly7;
1225            case 10:
1226                return poly10;
1227            case 11:
1228                return poly11;
1229            case 12:
1230                return poly12;
1231            case 14:
1232                return poly14;
1233            case 18:
1234                return poly18;
1235            case 20:
1236                return poly20;
1237            case 24:
1238                return poly24;
1239            case 28:
1240                return poly28;
1241            case 36:
1242                return poly36;
1243            case 42:
1244                return poly42;
1245            case 48:
1246                return poly48;
1247            case 56:
1248                return poly56;
1249            case 62:
1250                return poly62;
1251            case 68:
1252                return poly68;
1253            }
1254            return null;
1255        }
1256
1257        private static void reedSolomonBlock(byte[] wd, int nd, byte[] ncout, int nc, int[] c) {
1258            int i, j, k;
1259
1260            for (i=0; i<=nc; i++) ncout[i] = 0;
1261            for (i=0; i<nd; i++) {
1262                k = (ncout[0] ^ wd[i]) & 0xff;
1263                for (j=0; j<nc; j++) {
1264                    ncout[j] = (byte)(ncout[j+1] ^ (k == 0 ? 0 : (byte)alog[(log[k] + log[c[nc-j-1]]) % (255)]));
1265                }
1266            }
1267        }
1268
1269        static void generateECC(byte[] wd, int nd, int datablock, int nc) {
1270            int blocks = (nd + 2) / datablock;
1271            int b;
1272            byte[] buf = new byte[256];
1273            byte[] ecc = new byte[256];
1274            int[] c = getPoly(nc);
1275            for (b = 0; b < blocks; b++)
1276            {
1277                int n, p = 0;
1278                for (n = b; n < nd; n += blocks)
1279                    buf[p++] = wd[n];
1280                reedSolomonBlock(buf, p, ecc, nc, c);
1281                p = 0;
1282                for (n = b; n < nc * blocks; n += blocks)
1283                    wd[nd + n] = ecc[p++];
1284            }
1285        }
1286
1287    }
1288}
Popular Tags