1 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 ; 55 import java.awt.Color ; 56 import java.awt.image.MemoryImageSource ; 57 import java.util.Arrays ; 58 import java.io.UnsupportedEncodingException ; 59 import java.util.Hashtable ; 60 61 64 public class BarcodeDatamatrix { 65 68 public static final int DM_NO_ERROR = 0; 69 72 public static final int DM_ERROR_TEXT_TOO_BIG = 1; 73 76 public static final int DM_ERROR_INVALID_SQUARE = 3; 77 80 public static final int DM_ERROR_EXTENSION = 5; 81 82 85 public static final int DM_AUTO = 0; 86 89 public static final int DM_ASCII = 1; 90 93 public static final int DM_C40 = 2; 94 97 public static final int DM_TEXT = 3; 98 101 public static final int DM_B256 = 4; 102 105 public static final int DM_X21 = 5; 106 109 public static final int DM_EDIFACT = 6; 110 113 public static final int DM_RAW = 7; 114 115 118 public static final int DM_EXTENSION = 32; 119 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 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 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 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 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 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 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 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 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 681 public int generate(String text) throws UnsupportedEncodingException { 682 byte[] t = text.getBytes("iso-8859-1"); 683 return generate(t, 0, t.length); 684 } 685 686 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 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 769 public java.awt.Image createAwtImage(Color foreground, Color background) { 770 if (image == null) 771 return null; 772 int f = foreground.getRGB(); 773 int g = background.getRGB(); 774 Canvas canvas = new Canvas (); 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 img = canvas.createImage(new MemoryImageSource (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 820 public byte[] getImage() { 821 return image; 822 } 823 824 829 public int getHeight() { 830 return height; 831 } 832 833 869 public void setHeight(int height) { 870 this.height = height; 871 } 872 873 878 public int getWidth() { 879 return width; 880 } 881 882 918 public void setWidth(int width) { 919 this.width = width; 920 } 921 922 926 public int getWs() { 927 return ws; 928 } 929 930 934 public void setWs(int ws) { 935 this.ws = ws; 936 } 937 938 942 public int getOptions() { 943 return options; 944 } 945 946 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 cache = new Hashtable (); 982 983 private Placement() { 984 } 985 986 static short[] doPlacement(int nrow, int ncol) { 987 Integer key = new Integer (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 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 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 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 1059 private void ecc200(){ 1060 int row, col, chr; 1061 1062 Arrays.fill(array, (short)0); 1063 1064 chr = 1; row = 4; col = 0; 1065 do { 1066 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 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 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 1087 } while ((row < nrow) || (col < ncol)); 1088 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 |