1 /*
2 * Copyright 2005 by Paulo Soares.
3 *
4 * The contents of this file are subject to the Mozilla Public License Version 1.1
5 * (the "License"); you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
7 *
8 * Software distributed under the License is distributed on an "AS IS" basis,
9 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10 * for the specific language governing rights and limitations under the License.
11 *
12 * The Original Code is 'iText, a free JAVA-PDF library'.
13 *
14 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
15 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
16 * All Rights Reserved.
17 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
18 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
19 *
20 * Contributor(s): all the names of the contributors are added in the source code
21 * where applicable.
22 *
23 * Alternatively, the contents of this file may be used under the terms of the
24 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
25 * provisions of LGPL are applicable instead of those above. If you wish to
26 * allow use of your version of this file only under the terms of the LGPL
27 * License and not to allow others to use your version of this file under
28 * the MPL, indicate your decision by deleting the provisions above and
29 * replace them with the notice and other provisions required by the LGPL.
30 * If you do not delete the provisions above, a recipient may use your version
31 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
32 *
33 * This library is free software; you can redistribute it and/or modify it
34 * under the terms of the MPL as stated above or under the terms of the GNU
35 * Library General Public License as published by the Free Software Foundation;
36 * either version 2 of the License, or any later version.
37 *
38 * This library is distributed in the hope that it will be useful, but WITHOUT
39 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
40 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
41 * details.
42 *
43 * If you didn't download this code from the following link, you should check if
44 * you aren't using an obsolete version:
45 * http://www.lowagie.com/iText/
46 *
47 * This code is base in the libtiff encoder
48 */
49 package com.lowagie.text.pdf.codec;
50
51 import com.lowagie.text.pdf.ByteBuffer;
52
53 /**
54 * Encodes data in the CCITT G4 FAX format.
55 */
56 public class CCITTG4Encoder {
57 private int rowbytes;
58 private int rowpixels;
59 private int bit = 8;
60 private int data;
61 private byte[] refline;
62 private ByteBuffer outBuf = new ByteBuffer(1024);
63 private byte[] dataBp;
64 private int offsetData;
65 private int sizeData;
66
67 /**
68 * Creates a new encoder.
69 * @param width the line width
70 */
71 public CCITTG4Encoder(int width) {
72 rowpixels = width;
73 rowbytes = (rowpixels + 7) / 8;
74 refline = new byte[rowbytes];
75 }
76
77 /**
78 * Encodes a number of lines.
79 * @param data the data to be encoded
80 * @param offset the offset into the data
81 * @param size the size of the data to be encoded
82 */
83 public void fax4Encode(byte[] data, int offset, int size) {
84 dataBp = data;
85 offsetData = offset;
86 sizeData = size;
87 while (sizeData > 0) {
88 Fax3Encode2DRow();
89 System.arraycopy(dataBp, offsetData, refline, 0, rowbytes);
90 offsetData += rowbytes;
91 sizeData -= rowbytes;
92 }
93 }
94
95
96 /**
97 * Encodes a full image.
98 * @param data the data to encode
99 * @param width the image width
100 * @param height the image height
101 * @return the encoded image
102 */
103 public static byte[] compress(byte[] data, int width, int height) {
104 CCITTG4Encoder g4 = new CCITTG4Encoder(width);
105 g4.fax4Encode(data, 0, g4.rowbytes * height);
106 return g4.close();
107 }
108
109 /**
110 * Encodes a number of lines.
111 * @param data the data to be encoded
112 * @param height the number of lines to encode
113 */
114 public void fax4Encode(byte[] data, int height) {
115 fax4Encode(data, 0, rowbytes * height);
116 }
117
118 private void putcode(int[] table) {
119 putBits(table[CODE], table[LENGTH]);
120 }
121
122 private void putspan(int span, int[][] tab) {
123 int code, length;
124
125 while (span >= 2624) {
126 int[] te = tab[63 + (2560>>6)];
127 code = te[CODE];
128 length = te[LENGTH];
129 putBits(code, length);
130 span -= te[RUNLEN];
131 }
132 if (span >= 64) {
133 int[] te = tab[63 + (span>>6)];
134 code = te[CODE];
135 length = te[LENGTH];
136 putBits(code, length);
137 span -= te[RUNLEN];
138 }
139 code = tab[span][CODE];
140 length = tab[span][LENGTH];
141 putBits(code, length);
142 }
143
144 private void putBits(int bits, int length) {
145 while (length > bit) {
146 data |= bits >> (length - bit);
147 length -= bit;
148 outBuf.append((byte)data);
149 data = 0;
150 bit = 8;
151 }
152 data |= (bits & msbmask[length]) << (bit - length);
153 bit -= length;
154 if (bit == 0) {
155 outBuf.append((byte)data);
156 data = 0;
157 bit = 8;
158 }
159 }
160
161 private void Fax3Encode2DRow() {
162 int a0 = 0;
163 int a1 = (pixel(dataBp, offsetData, 0) != 0 ? 0 : finddiff(dataBp, offsetData, 0, rowpixels, 0));
164 int b1 = (pixel(refline, 0, 0) != 0 ? 0 : finddiff(refline, 0, 0, rowpixels, 0));
165 int a2, b2;
166
167 for (;;) {
168 b2 = finddiff2(refline, 0, b1, rowpixels, pixel(refline, 0,b1));
169 if (b2 >= a1) {
170 int d = b1 - a1;
171 if (!(-3 <= d && d <= 3)) { /* horizontal mode */
172 a2 = finddiff2(dataBp, offsetData, a1, rowpixels, pixel(dataBp, offsetData,a1));
173 putcode(horizcode);
174 if (a0+a1 == 0 || pixel(dataBp, offsetData, a0) == 0) {
175 putspan(a1-a0, TIFFFaxWhiteCodes);
176 putspan(a2-a1, TIFFFaxBlackCodes);
177 } else {
178 putspan(a1-a0, TIFFFaxBlackCodes);
179 putspan(a2-a1, TIFFFaxWhiteCodes);
180 }
181 a0 = a2;
182 } else { /* vertical mode */
183 putcode(vcodes[d+3]);
184 a0 = a1;
185 }
186 } else { /* pass mode */
187 putcode(passcode);
188 a0 = b2;
189 }
190 if (a0 >= rowpixels)
191 break;
192 a1 = finddiff(dataBp, offsetData, a0, rowpixels, pixel(dataBp, offsetData,a0));
193 b1 = finddiff(refline, 0, a0, rowpixels, pixel(dataBp, offsetData,a0) ^ 1);
194 b1 = finddiff(refline, 0, b1, rowpixels, pixel(dataBp, offsetData,a0));
195 }
196 }
197
198 private void Fax4PostEncode() {
199 putBits(EOL, 12);
200 putBits(EOL, 12);
201 if (bit != 8) {
202 outBuf.append((byte)data);
203 data = 0;
204 bit = 8;
205 }
206 }
207
208 /**
209 * Closes the encoder and returns the encoded data.
210 * @return the encoded data
211 */
212 public byte[] close() {
213 Fax4PostEncode();
214 return outBuf.toByteArray();
215 }
216
217 private int pixel(byte[] data, int offset, int bit) {
218 if (bit >= rowpixels)
219 return 0;
220 return ((data[offset + (bit >> 3)] & 0xff) >> (7-((bit)&7))) & 1;
221 }
222
223 private static int find1span(byte[] bp, int offset, int bs, int be) {
224 int bits = be - bs;
225 int n, span;
226
227 int pos = offset + (bs >> 3);
228 /*
229 * Check partial byte on lhs.
230 */
231 if (bits > 0 && (n = (bs & 7)) != 0) {
232 span = oneruns[(bp[pos] << n) & 0xff];
233 if (span > 8-n) /* table value too generous */
234 span = 8-n;
235 if (span > bits) /* constrain span to bit range */
236 span = bits;
237 if (n+span < 8) /* doesn't extend to edge of byte */
238 return span;
239 bits -= span;
240 pos++;
241 } else
242 span = 0;
243 /*
244 * Scan full bytes for all 1's.
245 */
246 while (bits >= 8) {
247 if (bp[pos] != -1) /* end of run */
248 return (span + oneruns[bp[pos] & 0xff]);
249 span += 8;
250 bits -= 8;
251 pos++;
252 }
253 /*
254 * Check partial byte on rhs.
255 */
256 if (bits > 0) {
257 n = oneruns[bp[pos] & 0xff];
258 span += (n > bits ? bits : n);
259 }
260 return span;
261 }
262
263 private static int find0span(byte[] bp, int offset, int bs, int be) {
264 int bits = be - bs;
265 int n, span;
266
267 int pos = offset + (bs >> 3);
268 /*
269 * Check partial byte on lhs.
270 */
271 if (bits > 0 && (n = (bs & 7)) != 0) {
272 span = zeroruns[(bp[pos] << n) & 0xff];
273 if (span > 8-n) /* table value too generous */
274 span = 8-n;
275 if (span > bits) /* constrain span to bit range */
276 span = bits;
277 if (n+span < 8) /* doesn't extend to edge of byte */
278 return span;
279 bits -= span;
280 pos++;
281 } else
282 span = 0;
283 /*
284 * Scan full bytes for all 1's.
285 */
286 while (bits >= 8) {
287 if (bp[pos] != 0) /* end of run */
288 return (span + zeroruns[bp[pos] & 0xff]);
289 span += 8;
290 bits -= 8;
291 pos++;
292 }
293 /*
294 * Check partial byte on rhs.
295 */
296 if (bits > 0) {
297 n = zeroruns[bp[pos] & 0xff];
298 span += (n > bits ? bits : n);
299 }
300 return span;
301 }
302
303 private static int finddiff(byte[] bp, int offset, int bs, int be, int color) {
304 return bs + (color != 0 ? find1span(bp, offset, bs, be) : find0span(bp, offset, bs, be));
305 }
306
307 private static int finddiff2(byte[] bp, int offset, int bs, int be, int color) {
308 return bs < be ? finddiff(bp, offset, bs, be, color) : be;
309 }
310
311 private static byte zeroruns[] = {
312 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
313 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
314 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
315 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
316 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
317 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
318 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
319 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
325 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
326 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
327 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
328 };
329
330 private static byte oneruns[] = {
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
332 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
333 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
337 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
339 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
340 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
341 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
342 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
343 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
344 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
345 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
346 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8 /* 0xf0 - 0xff */
347 };
348
349 private static final int LENGTH = 0; /* bit length of g3 code */
350 private static final int CODE = 1; /* g3 code */
351 private static final int RUNLEN = 2; /* run length in bits */
352
353 private static final int EOL = 0x001; /* EOL code value - 0000 0000 0000 1 */
354
355 /* status values returned instead of a run length */
356 private static final int G3CODE_EOL = -1; /* NB: ACT_EOL - ACT_WRUNT */
357 private static final int G3CODE_INVALID = -2; /* NB: ACT_INVALID - ACT_WRUNT */
358 private static final int G3CODE_EOF = -3; /* end of input data */
359 private static final int G3CODE_INCOMP = -4; /* incomplete run code */
360
361 private int[][] TIFFFaxWhiteCodes = {
362 { 8, 0x35, 0 }, /* 0011 0101 */
363 { 6, 0x7, 1 }, /* 0001 11 */
364 { 4, 0x7, 2 }, /* 0111 */
365 { 4, 0x8, 3 }, /* 1000 */
366 { 4, 0xB, 4 }, /* 1011 */
367 { 4, 0xC, 5 }, /* 1100 */
368 { 4, 0xE, 6 }, /* 1110 */
369 { 4, 0xF, 7 }, /* 1111 */
370 { 5, 0x13, 8 }, /* 1001 1 */
371 { 5, 0x14, 9 }, /* 1010 0 */
372 { 5, 0x7, 10 }, /* 0011 1 */
373 { 5, 0x8, 11 }, /* 0100 0 */
374 { 6, 0x8, 12 }, /* 0010 00 */
375 { 6, 0x3, 13 }, /* 0000 11 */
376 { 6, 0x34, 14 }, /* 1101 00 */
377 { 6, 0x35, 15 }, /* 1101 01 */
378 { 6, 0x2A, 16 }, /* 1010 10 */
379 { 6, 0x2B, 17 }, /* 1010 11 */
380 { 7, 0x27, 18 }, /* 0100 111 */
381 { 7, 0xC, 19 }, /* 0001 100 */
382 { 7, 0x8, 20 }, /* 0001 000 */
383 { 7, 0x17, 21 }, /* 0010 111 */
384 { 7, 0x3, 22 }, /* 0000 011 */
385 { 7, 0x4, 23 }, /* 0000 100 */
386 { 7, 0x28, 24 }, /* 0101 000 */
387 { 7, 0x2B, 25 }, /* 0101 011 */
388 { 7, 0x13, 26 }, /* 0010 011 */
389 { 7, 0x24, 27 }, /* 0100 100 */
390 { 7, 0x18, 28 }, /* 0011 000 */
391 { 8, 0x2, 29 }, /* 0000 0010 */
392 { 8, 0x3, 30 }, /* 0000 0011 */
393 { 8, 0x1A, 31 }, /* 0001 1010 */
394 { 8, 0x1B, 32 }, /* 0001 1011 */
395 { 8, 0x12, 33 }, /* 0001 0010 */
396 { 8, 0x13, 34 }, /* 0001 0011 */
397 { 8, 0x14, 35 }, /* 0001 0100 */
398 { 8, 0x15, 36 }, /* 0001 0101 */
399 { 8, 0x16, 37 }, /* 0001 0110 */
400 { 8, 0x17, 38 }, /* 0001 0111 */
401 { 8, 0x28, 39 }, /* 0010 1000 */
402 { 8, 0x29, 40 }, /* 0010 1001 */
403 { 8, 0x2A, 41 }, /* 0010 1010 */
404 { 8, 0x2B, 42 }, /* 0010 1011 */
405 { 8, 0x2C, 43 }, /* 0010 1100 */
406 { 8, 0x2D, 44 }, /* 0010 1101 */
407 { 8, 0x4, 45 }, /* 0000 0100 */
408 { 8, 0x5, 46 }, /* 0000 0101 */
409 { 8, 0xA, 47 }, /* 0000 1010 */
410 { 8, 0xB, 48 }, /* 0000 1011 */
411 { 8, 0x52, 49 }, /* 0101 0010 */
412 { 8, 0x53, 50 }, /* 0101 0011 */
413 { 8, 0x54, 51 }, /* 0101 0100 */
414 { 8, 0x55, 52 }, /* 0101 0101 */
415 { 8, 0x24, 53 }, /* 0010 0100 */
416 { 8, 0x25, 54 }, /* 0010 0101 */
417 { 8, 0x58, 55 }, /* 0101 1000 */
418 { 8, 0x59, 56 }, /* 0101 1001 */
419 { 8, 0x5A, 57 }, /* 0101 1010 */
420 { 8, 0x5B, 58 }, /* 0101 1011 */
421 { 8, 0x4A, 59 }, /* 0100 1010 */
422 { 8, 0x4B, 60 }, /* 0100 1011 */
423 { 8, 0x32, 61 }, /* 0011 0010 */
424 { 8, 0x33, 62 }, /* 0011 0011 */
425 { 8, 0x34, 63 }, /* 0011 0100 */
426 { 5, 0x1B, 64 }, /* 1101 1 */
427 { 5, 0x12, 128 }, /* 1001 0 */
428 { 6, 0x17, 192 }, /* 0101 11 */
429 { 7, 0x37, 256 }, /* 0110 111 */
430 { 8, 0x36, 320 }, /* 0011 0110 */
431 { 8, 0x37, 384 }, /* 0011 0111 */
432 { 8, 0x64, 448 }, /* 0110 0100 */
433 { 8, 0x65, 512 }, /* 0110 0101 */
434 { 8, 0x68, 576 }, /* 0110 1000 */
435 { 8, 0x67, 640 }, /* 0110 0111 */
436 { 9, 0xCC, 704 }, /* 0110 0110 0 */
437 { 9, 0xCD, 768 }, /* 0110 0110 1 */
438 { 9, 0xD2, 832 }, /* 0110 1001 0 */
439 { 9, 0xD3, 896 }, /* 0110 1001 1 */
440 { 9, 0xD4, 960 }, /* 0110 1010 0 */
441 { 9, 0xD5, 1024 }, /* 0110 1010 1 */
442 { 9, 0xD6, 1088 }, /* 0110 1011 0 */
443 { 9, 0xD7, 1152 }, /* 0110 1011 1 */
444 { 9, 0xD8, 1216 }, /* 0110 1100 0 */
445 { 9, 0xD9, 1280 }, /* 0110 1100 1 */
446 { 9, 0xDA, 1344 }, /* 0110 1101 0 */
447 { 9, 0xDB, 1408 }, /* 0110 1101 1 */
448 { 9, 0x98, 1472 }, /* 0100 1100 0 */
449 { 9, 0x99, 1536 }, /* 0100 1100 1 */
450 { 9, 0x9A, 1600 }, /* 0100 1101 0 */
451 { 6, 0x18, 1664 }, /* 0110 00 */
452 { 9, 0x9B, 1728 }, /* 0100 1101 1 */
453 { 11, 0x8, 1792 }, /* 0000 0001 000 */
454 { 11, 0xC, 1856 }, /* 0000 0001 100 */
455 { 11, 0xD, 1920 }, /* 0000 0001 101 */
456 { 12, 0x12, 1984 }, /* 0000 0001 0010 */
457 { 12, 0x13, 2048 }, /* 0000 0001 0011 */
458 { 12, 0x14, 2112 }, /* 0000 0001 0100 */
459 { 12, 0x15, 2176 }, /* 0000 0001 0101 */
460 { 12, 0x16, 2240 }, /* 0000 0001 0110 */
461 { 12, 0x17, 2304 }, /* 0000 0001 0111 */
462 { 12, 0x1C, 2368 }, /* 0000 0001 1100 */
463 { 12, 0x1D, 2432 }, /* 0000 0001 1101 */
464 { 12, 0x1E, 2496 }, /* 0000 0001 1110 */
465 { 12, 0x1F, 2560 }, /* 0000 0001 1111 */
466 { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */
467 { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */
468 { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */
469 { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */
470 { 12, 0x0, G3CODE_INVALID } /* 0000 0000 0000 */
471 };
472
473 private int[][] TIFFFaxBlackCodes = {
474 { 10, 0x37, 0 }, /* 0000 1101 11 */
475 { 3, 0x2, 1 }, /* 010 */
476 { 2, 0x3, 2 }, /* 11 */
477 { 2, 0x2, 3 }, /* 10 */
478 { 3, 0x3, 4 }, /* 011 */
479 { 4, 0x3, 5 }, /* 0011 */
480 { 4, 0x2, 6 }, /* 0010 */
481 { 5, 0x3, 7 }, /* 0001 1 */
482 { 6, 0x5, 8 }, /* 0001 01 */
483 { 6, 0x4, 9 }, /* 0001 00 */
484 { 7, 0x4, 10 }, /* 0000 100 */
485 { 7, 0x5, 11 }, /* 0000 101 */
486 { 7, 0x7, 12 }, /* 0000 111 */
487 { 8, 0x4, 13 }, /* 0000 0100 */
488 { 8, 0x7, 14 }, /* 0000 0111 */
489 { 9, 0x18, 15 }, /* 0000 1100 0 */
490 { 10, 0x17, 16 }, /* 0000 0101 11 */
491 { 10, 0x18, 17 }, /* 0000 0110 00 */
492 { 10, 0x8, 18 }, /* 0000 0010 00 */
493 { 11, 0x67, 19 }, /* 0000 1100 111 */
494 { 11, 0x68, 20 }, /* 0000 1101 000 */
495 { 11, 0x6C, 21 }, /* 0000 1101 100 */
496 { 11, 0x37, 22 }, /* 0000 0110 111 */
497 { 11, 0x28, 23 }, /* 0000 0101 000 */
498 { 11, 0x17, 24 }, /* 0000 0010 111 */
499 { 11, 0x18, 25 }, /* 0000 0011 000 */
500 { 12, 0xCA, 26 }, /* 0000 1100 1010 */
501 { 12, 0xCB, 27 }, /* 0000 1100 1011 */
502 { 12, 0xCC, 28 }, /* 0000 1100 1100 */
503 { 12, 0xCD, 29 }, /* 0000 1100 1101 */
504 { 12, 0x68, 30 }, /* 0000 0110 1000 */
505 { 12, 0x69, 31 }, /* 0000 0110 1001 */
506 { 12, 0x6A, 32 }, /* 0000 0110 1010 */
507 { 12, 0x6B, 33 }, /* 0000 0110 1011 */
508 { 12, 0xD2, 34 }, /* 0000 1101 0010 */
509 { 12, 0xD3, 35 }, /* 0000 1101 0011 */
510 { 12, 0xD4, 36 }, /* 0000 1101 0100 */
511 { 12, 0xD5, 37 }, /* 0000 1101 0101 */
512 { 12, 0xD6, 38 }, /* 0000 1101 0110 */
513 { 12, 0xD7, 39 }, /* 0000 1101 0111 */
514 { 12, 0x6C, 40 }, /* 0000 0110 1100 */
515 { 12, 0x6D, 41 }, /* 0000 0110 1101 */
516 { 12, 0xDA, 42 }, /* 0000 1101 1010 */
517 { 12, 0xDB, 43 }, /* 0000 1101 1011 */
518 { 12, 0x54, 44 }, /* 0000 0101 0100 */
519 { 12, 0x55, 45 }, /* 0000 0101 0101 */
520 { 12, 0x56, 46 }, /* 0000 0101 0110 */
521 { 12, 0x57, 47 }, /* 0000 0101 0111 */
522 { 12, 0x64, 48 }, /* 0000 0110 0100 */
523 { 12, 0x65, 49 }, /* 0000 0110 0101 */
524 { 12, 0x52, 50 }, /* 0000 0101 0010 */
525 { 12, 0x53, 51 }, /* 0000 0101 0011 */
526 { 12, 0x24, 52 }, /* 0000 0010 0100 */
527 { 12, 0x37, 53 }, /* 0000 0011 0111 */
528 { 12, 0x38, 54 }, /* 0000 0011 1000 */
529 { 12, 0x27, 55 }, /* 0000 0010 0111 */
530 { 12, 0x28, 56 }, /* 0000 0010 1000 */
531 { 12, 0x58, 57 }, /* 0000 0101 1000 */
532 { 12, 0x59, 58 }, /* 0000 0101 1001 */
533 { 12, 0x2B, 59 }, /* 0000 0010 1011 */
534 { 12, 0x2C, 60 }, /* 0000 0010 1100 */
535 { 12, 0x5A, 61 }, /* 0000 0101 1010 */
536 { 12, 0x66, 62 }, /* 0000 0110 0110 */
537 { 12, 0x67, 63 }, /* 0000 0110 0111 */
538 { 10, 0xF, 64 }, /* 0000 0011 11 */
539 { 12, 0xC8, 128 }, /* 0000 1100 1000 */
540 { 12, 0xC9, 192 }, /* 0000 1100 1001 */
541 { 12, 0x5B, 256 }, /* 0000 0101 1011 */
542 { 12, 0x33, 320 }, /* 0000 0011 0011 */
543 { 12, 0x34, 384 }, /* 0000 0011 0100 */
544 { 12, 0x35, 448 }, /* 0000 0011 0101 */
545 { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */
546 { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */
547 { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */
548 { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */
549 { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */
550 { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */
551 { 13, 0x72, 896 }, /* 0000 0011 1001 0 */
552 { 13, 0x73, 960 }, /* 0000 0011 1001 1 */
553 { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */
554 { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */
555 { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */
556 { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */
557 { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */
558 { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */
559 { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */
560 { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */
561 { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */
562 { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */
563 { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */
564 { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */
565 { 11, 0x8, 1792 }, /* 0000 0001 000 */
566 { 11, 0xC, 1856 }, /* 0000 0001 100 */
567 { 11, 0xD, 1920 }, /* 0000 0001 101 */
568 { 12, 0x12, 1984 }, /* 0000 0001 0010 */
569 { 12, 0x13, 2048 }, /* 0000 0001 0011 */
570 { 12, 0x14, 2112 }, /* 0000 0001 0100 */
571 { 12, 0x15, 2176 }, /* 0000 0001 0101 */
572 { 12, 0x16, 2240 }, /* 0000 0001 0110 */
573 { 12, 0x17, 2304 }, /* 0000 0001 0111 */
574 { 12, 0x1C, 2368 }, /* 0000 0001 1100 */
575 { 12, 0x1D, 2432 }, /* 0000 0001 1101 */
576 { 12, 0x1E, 2496 }, /* 0000 0001 1110 */
577 { 12, 0x1F, 2560 }, /* 0000 0001 1111 */
578 { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */
579 { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */
580 { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */
581 { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */
582 { 12, 0x0, G3CODE_INVALID } /* 0000 0000 0000 */
583 };
584
585 private int[] horizcode =
586 { 3, 0x1, 0 }; /* 001 */
587 private int[] passcode =
588 { 4, 0x1, 0 }; /* 0001 */
589 private int[][] vcodes = {
590 { 7, 0x03, 0 }, /* 0000 011 */
591 { 6, 0x03, 0 }, /* 0000 11 */
592 { 3, 0x03, 0 }, /* 011 */
593 { 1, 0x1, 0 }, /* 1 */
594 { 3, 0x2, 0 }, /* 010 */
595 { 6, 0x02, 0 }, /* 0000 10 */
596 { 7, 0x02, 0 } /* 0000 010 */
597 };
598 private int[] msbmask =
599 { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
600 }