source-class-Com.Tecnick.Barcode.Type.Linear.Imb

It appears that you are using AdBlocking software. The cost of running this website is covered by advertisements. If you like it please feel free to a small amount of money to secure the future of this website.
Overview

Classes

Exceptions

  1: <?php
  2: /**
  3:  * Imb.php
  4:  *
  5:  * @since       2015-02-21
  6:  * @category    Library
  7:  * @package     Barcode
  8:  * @author      Nicola Asuni <info@tecnick.com>
  9:  * @copyright   2015-2016 Nicola Asuni - Tecnick.com LTD
 10:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 11:  * @link        https://github.com/tecnickcom/tc-lib-barcode
 12:  *
 13:  * This file is part of tc-lib-barcode software library.
 14:  */
 15: 
 16: namespace Com\Tecnick\Barcode\Type\Linear;
 17: 
 18: use \Com\Tecnick\Barcode\Exception as BarcodeException;
 19: 
 20: /**
 21:  * Com\Tecnick\Barcode\Type\Linear\Imb;
 22:  *
 23:  * Imb Barcode type class
 24:  * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
 25:  *
 26:  * Intelligent Mail barcode is a 65-bar code for use on mail in the United States.
 27:  * The fields are described as follows:
 28:  *  * The Barcode Identifier shall be assigned by USPS to encode the presort identification that is currently
 29:  *    printed in human readable form on the optional endorsement line (OEL) as well as for future USPS use.
 30:  *    This shall be two digits, with the second digit in the range of 0–4. The allowable encoding ranges shall be
 31:  *    00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and 90–94.
 32:  *  * The Service Type Identifier shall be assigned by USPS for any combination of services requested on the mailpiece.
 33:  *    The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999.
 34:  *    Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s).
 35:  *    Each service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier
 36:  *    values.
 37:  *  * The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number that identifies
 38:  *    a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000- 899999, while the
 39:  *    allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.</li><li>The Serial or
 40:  *    Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces.
 41:  *    The allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999
 42:  *    when used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing
 43:  *    the mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point.
 44:  *    The length may be 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999,
 45:  *    000000000–999999999, and 00000000000–99999999999. An hyphen '-' is required before the zip/delivery point.
 46:  *
 47:  * @since       2015-02-21
 48:  * @category    Library
 49:  * @package     Barcode
 50:  * @author      Nicola Asuni <info@tecnick.com>
 51:  * @copyright   2015-2016 Nicola Asuni - Tecnick.com LTD
 52:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 53:  * @link        https://github.com/tecnickcom/tc-lib-barcode
 54:  */
 55: class Imb extends \Com\Tecnick\Barcode\Type\Linear
 56: {
 57:     /**
 58:      * Barcode format
 59:      *
 60:      * @var string
 61:      */
 62:     protected $format = 'IMB';
 63: 
 64:     /**
 65:      * ASC characters
 66:      *
 67:      * @var array
 68:      */
 69:     protected static $asc_chr = array(
 70:         4,0,2,6,3,5,1,9,8,7,
 71:         1,2,0,6,4,8,2,9,5,3,
 72:         0,1,3,7,4,6,8,9,2,0,
 73:         5,1,9,4,3,8,6,7,1,2,
 74:         4,3,9,5,7,8,3,0,2,1,
 75:         4,0,9,1,7,0,2,4,6,3,
 76:         7,1,9,5,8
 77:     );
 78:     
 79:     /**
 80:      * DSC characters
 81:      *
 82:      * @var array
 83:      */
 84:     protected static $dsc_chr = array(
 85:         7,1,9,5,8,0,2,4,6,3,
 86:         5,8,9,7,3,0,6,1,7,4,
 87:         6,8,9,2,5,1,7,5,4,3,
 88:         8,7,6,0,2,5,4,9,3,0,
 89:         1,6,8,2,0,4,5,9,6,7,
 90:         5,2,6,3,8,5,1,9,8,7,
 91:         4,0,2,6,3);
 92:     
 93:     /**
 94:      * ASC positions
 95:      *
 96:      * @var array
 97:      */
 98:     protected static $asc_pos = array(
 99:         3,0,8,11,1,12,8,11,10,6,4,12,2,7,9,6,7,9,2,8,4,0,12,7,10,9,0,7,10,5,7,9,
100:         6,8,2,12,1,4,2,0,1,5,4,6,12,1,0,9,4,7,5,10,2,6,9,11,2,12,6,7,5,11,0,3,2);
101:     
102:     /**
103:      * DSC positions
104:      *
105:      * @var array
106:      */
107:     protected static $dsc_pos = array(
108:         2,10,12,5,9,1,5,4,3,9,11,5,10,1,6,3,4,1,10,0,2,11,8,6,1,12,3,8,6,4,4,11,
109:         0,6,1,9,11,5,3,7,3,10,7,11,8,2,10,3,5,8,0,3,12,11,8,4,5,1,3,0,7,12,9,8,10);
110: 
111:     /**
112:      * Reverse unsigned short value
113:      *
114:      * @param int $num Value to reversr
115:      *
116:      * @return int reversed value
117:      */
118:     protected function getReversedUnsignedShort($num)
119:     {
120:         $rev = 0;
121:         for ($pos = 0; $pos < 16; ++$pos) {
122:             $rev <<= 1;
123:             $rev |= ($num & 1);
124:             $num >>= 1;
125:         }
126:         return $rev;
127:     }
128: 
129:     /**
130:      * Get the Frame Check Sequence
131:      *
132:      * @param array $code_arr Array of hexadecimal values (13 bytes holding 102 bits right justified).
133:      *
134:      * @return int 11 bit Frame Check Sequence as integer (decimal base)
135:      */
136:     protected function getFrameCheckSequence($code_arr)
137:     {
138:         $genpoly = 0x0F35; // generator polynomial
139:         $fcs = 0x07FF; // Frame Check Sequence
140:         // do most significant byte skipping the 2 most significant bits
141:         $data = hexdec($code_arr[0]) << 5;
142:         for ($bit = 2; $bit < 8; ++$bit) {
143:             if (($fcs ^ $data) & 0x400) {
144:                 $fcs = ($fcs << 1) ^ $genpoly;
145:             } else {
146:                 $fcs = ($fcs << 1);
147:             }
148:             $fcs &= 0x7FF;
149:             $data <<= 1;
150:         }
151:         // do rest of bytes
152:         for ($byte = 1; $byte < 13; ++$byte) {
153:             $data = hexdec($code_arr[$byte]) << 3;
154:             for ($bit = 0; $bit < 8; ++$bit) {
155:                 if (($fcs ^ $data) & 0x400) {
156:                     $fcs = ($fcs << 1) ^ $genpoly;
157:                 } else {
158:                     $fcs = ($fcs << 1);
159:                 }
160:                 $fcs &= 0x7FF;
161:                 $data <<= 1;
162:             }
163:         }
164:         return $fcs;
165:     }
166: 
167:     /**
168:      * Get the Nof13 tables
169:      *
170:      * @param int $type  Table type: 2 for 2of13 table, 5 for 5of13table
171:      * @param int $size Table size (78 for n=2 and 1287 for n=5)
172:      *
173:      * @return array requested table
174:      */
175:     protected function getTables($type, $size)
176:     {
177:         $table = array();
178:         $lli = 0; // LUT lower index
179:         $lui = $size - 1; // LUT upper index
180:         for ($count = 0; $count < 8192; ++$count) {
181:             $bit_count = 0;
182:             for ($bit_index = 0; $bit_index < 13; ++$bit_index) {
183:                 $bit_count += intval(($count & (1 << $bit_index)) != 0);
184:             }
185:             // if we don't have the right number of bits on, go on to the next value
186:             if ($bit_count == $type) {
187:                 $reverse = ($this->getReversedUnsignedShort($count) >> 3);
188:                 // if the reverse is less than count, we have already visited this pair before
189:                 if ($reverse >= $count) {
190:                     // If count is symmetric, place it at the first free slot from the end of the list.
191:                     // Otherwise, place it at the first free slot from the beginning of the list AND place
192:                     // $reverse ath the next free slot from the beginning of the list
193:                     if ($reverse == $count) {
194:                         $table[$lui] = $count;
195:                         --$lui;
196:                     } else {
197:                         $table[$lli] = $count;
198:                         ++$lli;
199:                         $table[$lli] = $reverse;
200:                         ++$lli;
201:                     }
202:                 }
203:             }
204:         }
205:         return $table;
206:     }
207: 
208:     /**
209:      * Get the routing code binary block
210:      *
211:      * @param string $routing_code the routing code
212:      *
213:      * @return string
214:      *
215:      * @throws BarcodeException in case of error
216:      */
217:     protected function getRoutingCode($routing_code)
218:     {
219:         // Conversion of Routing Code
220:         switch (strlen($routing_code)) {
221:             case 0:
222:                 return 0;
223:             case 5:
224:                 return bcadd($routing_code, '1');
225:             case 9:
226:                 return bcadd($routing_code, '100001');
227:             case 11:
228:                 return bcadd($routing_code, '1000100001');
229:         }
230:         throw new BarcodeException('Invalid routing code');
231:     }
232:     
233:     /**
234:      * Get the processed array of characters
235:      *
236:      * @return array
237:      *
238:      * @throws BarcodeException in case of error
239:      */
240:     protected function getCharsArray()
241:     {
242:         $this->ncols = 0;
243:         $this->nrows = 3;
244:         $this->bars = array();
245:         $code_arr = explode('-', $this->code);
246:         $tracking_number = $code_arr[0];
247:         $binary_code = 0;
248:         if (isset($code_arr[1])) {
249:             $binary_code = $this->getRoutingCode($code_arr[1]);
250:         }
251:         $binary_code = bcmul($binary_code, 10);
252:         $binary_code = bcadd($binary_code, $tracking_number[0]);
253:         $binary_code = bcmul($binary_code, 5);
254:         $binary_code = bcadd($binary_code, $tracking_number[1]);
255:         $binary_code .= substr($tracking_number, 2, 18);
256:         // convert to hexadecimal
257:         $binary_code = $this->convertDecToHex($binary_code);
258:         // pad to get 13 bytes
259:         $binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT);
260:         // convert string to array of bytes
261:         $binary_code_arr = chunk_split($binary_code, 2, "\r");
262:         $binary_code_arr = substr($binary_code_arr, 0, -1);
263:         $binary_code_arr = explode("\r", $binary_code_arr);
264:         // calculate frame check sequence
265:         $fcs = $this->getFrameCheckSequence($binary_code_arr);
266:         // exclude first 2 bits from first byte
267:         $first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2));
268:         $binary_code_102bit = $first_byte.substr($binary_code, 2);
269:         // convert binary data to codewords
270:         $codewords = array();
271:         $data = $this->convertHexToDec($binary_code_102bit);
272:         $codewords[0] = bcmod($data, 636) * 2;
273:         $data = bcdiv($data, 636);
274:         for ($pos = 1; $pos < 9; ++$pos) {
275:             $codewords[$pos] = bcmod($data, 1365);
276:             $data = bcdiv($data, 1365);
277:         }
278:         $codewords[9] = $data;
279:         if (($fcs >> 10) == 1) {
280:             $codewords[9] += 659;
281:         }
282:         // generate lookup tables
283:         $table2of13 = $this->getTables(2, 78);
284:         $table5of13 = $this->getTables(5, 1287);
285:         // convert codewords to characters
286:         $characters = array();
287:         $bitmask = 512;
288:         foreach ($codewords as $val) {
289:             if ($val <= 1286) {
290:                 $chrcode = $table5of13[$val];
291:             } else {
292:                 $chrcode = $table2of13[($val - 1287)];
293:             }
294:             if (($fcs & $bitmask) > 0) {
295:                 // bitwise invert
296:                 $chrcode = ((~$chrcode) & 8191);
297:             }
298:             $characters[] = $chrcode;
299:             $bitmask /= 2;
300:         }
301:         
302:         return array_reverse($characters);
303:     }
304: 
305:     /**
306:      * Get the bars array
307:      *
308:      * @throws BarcodeException in case of error
309:      */
310:     protected function setBars()
311:     {
312:         $chars = $this->getCharsArray();
313:         for ($pos = 0; $pos < 65; ++$pos) {
314:             $asc = (($chars[self::$asc_chr[$pos]] & pow(2, self::$asc_pos[$pos])) > 0);
315:             $dsc = (($chars[self::$dsc_chr[$pos]] & pow(2, self::$dsc_pos[$pos])) > 0);
316:             if ($asc and $dsc) {
317:                 // full bar (F)
318:                 $this->bars[] = array($this->ncols, 0, 1, 3);
319:             } elseif ($asc) {
320:                 // ascender (A)
321:                 $this->bars[] = array($this->ncols, 0, 1, 2);
322:             } elseif ($dsc) {
323:                 // descender (D)
324:                 $this->bars[] = array($this->ncols, 1, 1, 2);
325:             } else {
326:                 // tracker (T)
327:                 $this->bars[] = array($this->ncols, 1, 1, 1);
328:             }
329:             $this->ncols += 2;
330:         }
331:         --$this->ncols;
332:     }
333: }
334: 
 

© 2004-2017 – Nicola Asuni - Tecnick.com - All rights reserved.
about - disclaimer - privacy