├── .travis.yml ├── README.md ├── config.m4 ├── doc └── en │ └── reference │ └── zbarcode │ ├── .cvsignore │ ├── book.xml │ ├── configure.xml │ ├── constants.xml │ ├── examples.xml │ ├── reference.xml │ ├── setup.xml │ ├── versions.xml │ ├── zbarcode.xml │ ├── zbarcodeexception.xml │ ├── zbarcodeimage.xml │ ├── zbarcodeimage │ ├── clear.xml │ ├── construct.xml │ ├── count.xml │ └── read.xml │ ├── zbarcodescanner.xml │ └── zbarcodescanner │ ├── scan.xml │ └── setconfig.xml ├── imagemagick.m4 ├── php_zbarcode.h ├── tests ├── 001-construct.phpt ├── 002-read-barcode.phpt ├── 003-setconfig.phpt ├── 004-paged-reading.phpt ├── 005-count.phpt ├── 006-imagick.phpt ├── 007-test-gd.phpt ├── ean13.jpg └── skipif.inc.php └── zbarcode.c /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 7.4 4 | - 7.3 5 | - 7.2 6 | - 7.1 7 | - 7.0 8 | 9 | 10 | 11 | before_install: 12 | - sudo apt-get update 13 | - sudo apt-get install libzbar0 libzbar-dev imagemagick libmagickwand-6.q16-dev 14 | - sudo ln -s /usr/lib/x86_64-linux-gnu/ImageMagick-6.8.9/bin-Q16/MagickWand-config /usr/bin 15 | script: 16 | - export NO_INTERACTION=1 17 | - export REPORT_EXIT_STATUS=1 18 | - phpize 19 | - ./configure 20 | - make 21 | - make test 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Simple extension to read barcodes from images 2 | 3 | [![Build Status](https://travis-ci.org/mkoppanen/php-zbarcode.svg?branch=master)](https://travis-ci.org/mkoppanen/php-zbarcode) 4 | 5 | ## Upgrade at 2018-12-05 6 | 7 | Support PHP7, And fix some bug that may cause crash. 8 | 9 | ## Basic usage: 10 | 11 | scan($image); 20 | 21 | /* Loop through possible barcodes */ 22 | if (!empty($barcode)) { 23 | foreach ($barcode as $code) { 24 | printf("Found type %s barcode with data %s\n", $code['type'], $code['data']); 25 | } 26 | } 27 | ?> 28 | 29 | The EAN13 image in the tests/ directory is from 30 | http://en.wikipedia.org/wiki/File:Ean-13-5901234123457.png 31 | 32 | ## Dependencies: 33 | 34 | ZBar 35 | http://zbar.sourceforge.net/ 36 | 37 | ImageMagick 38 | http://www.imagemagick.org/ 39 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(zbarcode, whether to enable the zbarcode extension, 2 | [ --with-zbarcode[=DIR] Enables the zbarcode extension.], no) 3 | 4 | PHP_ARG_WITH(zbarcode-imagemagick-dir, path to ImageMagick library, 5 | [ --with-zbarcode-imagemagick-dir[=DIR] path to ImageMagick library.], no) 6 | 7 | PHP_ARG_ENABLE(zbarcode-imagick, whether to enable zbarcode Imagick support, 8 | [ --enable-zbarcode-imagick whether to enable zbarcode Imagick support], no, no) 9 | 10 | PHP_ARG_ENABLE(zbarcode-gd, whether to enable zbarcode GD Imagick support, 11 | [ --enable-zbarcode-gd whether to enable zbarcode GD support], no, no) 12 | 13 | if test $PHP_ZBARCODE != "no"; then 14 | 15 | # 16 | # ImageMagick macros 17 | # 18 | m4_include([imagemagick.m4]) 19 | IM_FIND_IMAGEMAGICK(6002004, $PHP_ZBARCODE_IMAGEMAGICK_DIR) 20 | 21 | AC_MSG_CHECKING(zbar installation) 22 | if test "x$PHP_ZBARCODE" = "xyes"; then 23 | if test "x${PKG_CONFIG_PATH}" = "x"; then 24 | # 25 | # "By default, pkg-config looks in the directory prefix/lib/pkgconfig for these files" 26 | # 27 | # Add a bit more search paths for common installation locations. Can be overridden by setting 28 | # PKG_CONFIG_PATH env variable or passing --with-zbarcode=PATH 29 | # 30 | export PKG_CONFIG_PATH="/usr/local/${PHP_LIBDIR}/pkgconfig:/usr/${PHP_LIBDIR}/pkgconfig:/opt/${PHP_LIBDIR}/pkgconfig:/opt/local/${PHP_LIBDIR}/pkgconfig" 31 | fi 32 | else 33 | export PKG_CONFIG_PATH="${PHP_ZBARCODE}/${PHP_LIBDIR}/pkgconfig" 34 | fi 35 | 36 | if $PKG_CONFIG --exists zbar; then 37 | PHP_ZBAR_VERSION=`$PKG_CONFIG zbar --modversion` 38 | PHP_ZBAR_PREFIX=`$PKG_CONFIG zbar --variable=prefix` 39 | 40 | AC_MSG_RESULT([found version $PHP_ZMQ_VERSION, under $PHP_ZBAR_PREFIX]) 41 | PHP_ZBAR_LIBS=`$PKG_CONFIG zbar --libs` 42 | PHP_ZBAR_INCS=`$PKG_CONFIG zbar --cflags` 43 | 44 | PHP_EVAL_LIBLINE($PHP_ZBAR_LIBS, ZBARCODE_SHARED_LIBADD) 45 | PHP_EVAL_INCLINE($PHP_ZBAR_INCS) 46 | else 47 | AC_MSG_ERROR(Unable to find zbar installation) 48 | fi 49 | 50 | 51 | PHP_CHECK_LIBRARY(zbar, zbar_symbol_get_quality, [ 52 | AC_DEFINE(HAVE_ZBAR_SYMBOL_GET_QUALITY,1,[ ]) 53 | ],[],[ 54 | -L$PHP_ZBAR_PREFIX/$PHP_LIBDIR 55 | ]) 56 | 57 | # 58 | # Imagick support 59 | # 60 | if test $PHP_ZBARCODE_IMAGICK != "no"; then 61 | AC_MSG_CHECKING(php_imagick_shared.h header file) 62 | 63 | if test -z "$PHP_CONFIG"; then 64 | AC_MSG_ERROR([php-config not found]) 65 | fi 66 | 67 | PHP_IMAGICK_HEADER="`$PHP_CONFIG --include-dir`/ext/imagick/php_imagick_shared.h" 68 | 69 | if test -r $PHP_IMAGICK_HEADER; then 70 | AC_MSG_RESULT(found.) 71 | AC_DEFINE(HAVE_ZBARCODE_IMAGICK,1,[ ]) 72 | 73 | PHP_ADD_EXTENSION_DEP(zbarcode, imagick) 74 | else 75 | AC_MSG_ERROR(not found. Run with --disable-zbarcode-imagick to disable this feature) 76 | fi 77 | fi 78 | 79 | # 80 | # GD support 81 | # 82 | if test $PHP_ZBARCODE_GD != "no"; then 83 | 84 | AC_MSG_CHECKING(ext/gd/php_gd.h header file) 85 | 86 | if test -z "$PHP_CONFIG"; then 87 | AC_MSG_ERROR([php-config not found]) 88 | fi 89 | 90 | PHP_GD_CHECK_HEADER="`$PHP_CONFIG --include-dir`/ext/gd/php_gd.h" 91 | 92 | if test -r $PHP_GD_CHECK_HEADER; then 93 | AC_MSG_RESULT(found.) 94 | else 95 | AC_MSG_ERROR(not found. Run with --disable-zbarcode-gd to disable this feature) 96 | fi 97 | 98 | PHP_ADD_EXTENSION_DEP(zbarcode, gd) 99 | AC_DEFINE(HAVE_ZBARCODE_GD,1,[ ]) 100 | fi 101 | 102 | PHP_EVAL_LIBLINE($IM_IMAGEMAGICK_LIBS, ZBARCODE_SHARED_LIBADD) 103 | PHP_EVAL_INCLINE($IM_IMAGEMAGICK_CFLAGS) 104 | 105 | AC_DEFINE(HAVE_ZBARCODE,1,[ ]) 106 | PHP_SUBST(ZBARCODE_SHARED_LIBADD) 107 | PHP_NEW_EXTENSION(zbarcode, zbarcode.c, $ext_shared,,$IM_IMAGEMAGICK_CFLAGS) 108 | fi 109 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/.cvsignore: -------------------------------------------------------------------------------- 1 | entities.*.xml -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zbarcode 6 | Zbarcode 7 | 8 | 9 | &reftitle.intro; 10 | 11 | zbarcode can be used to scan barcodes from images. ImageMagick is used to handle image reading and conversion 12 | and ZBar library is used to scan barcodes from images. 13 | 14 | 15 | 16 | &reference.zbarcode.setup; 17 | &reference.zbarcode.constants; 18 | &reference.zbarcode.examples; 19 | &reference.zbarcode.reference; 20 | 21 | 22 | 23 | 43 | 44 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/configure.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | &reftitle.install; 6 | 7 | 8 | Use when compiling PHP. The DIR is an 9 | optional parameter to ZBar library installation. 10 | 11 | 12 | 13 | Use 14 | to specify location of the ImageMagick library. 15 | 16 | 17 |
18 | 19 | 20 | 40 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/constants.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | &reftitle.constants; 6 | &no.constants; 7 | 8 | 9 | 29 | 30 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/examples.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | &reftitle.examples; 6 | 7 | Example of basic usage of the library 8 | 9 | 10 | Zbarcode Example 11 | 12 | scan($image); 22 | 23 | /* Loop through possible barcodes */ 24 | if (!empty($barcode)) { 25 | foreach ($barcode as $code) { 26 | printf("Found type %s barcode with data %s\n", $code['type'], $code['data']); 27 | } 28 | } 29 | ?> 30 | ]]> 31 | 32 | &example.outputs.similar; 33 | 34 | 37 | 38 | 39 | 40 | 41 | 61 | 62 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/reference.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zbarcode &Functions; 6 | 7 | &reference.zbarcode.entities.functions; 8 | 9 | 10 | 11 | 31 | 32 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/setup.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | &reftitle.setup; 6 | 7 |
8 | &reftitle.required; 9 | 10 | 11 | This extension requires ZBar library version 0.8+ and ImageMagick 6.2.4+. 12 | 13 |
14 | 15 | 16 |
17 | &reftitle.install; 18 | &no.install; 19 |
20 | 21 | 22 | 23 |
24 | 25 | 45 | 46 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/versions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 46 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcode.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The ZBarCode class 7 | ZBarCode 8 | 9 | 10 | 11 | 12 |
13 | &reftitle.intro; 14 | 15 | ZBarCode class contains all constants provided by this extension. 16 | 17 |
18 | 19 | 20 |
21 | &reftitle.classsynopsis; 22 | 23 | 24 | 25 | ZBarCode 26 | 27 | 28 | 29 | 30 | ZBarCode 31 | 32 | 33 | 34 | Constants 35 | 36 | const 37 | boolean 38 | zbarcode::HAVE_IMAGICK 39 | false 40 | 41 | 42 | const 43 | boolean 44 | zbarcode::HAVE_GD 45 | false 46 | 47 | 48 | const 49 | integer 50 | zbarcode::CFG_ENABLE 51 | 0 52 | 53 | 54 | const 55 | integer 56 | zbarcode::CFG_ADD_CHECK 57 | 1 58 | 59 | 60 | const 61 | integer 62 | zbarcode::CFG_EMIT_CHECK 63 | 2 64 | 65 | 66 | const 67 | integer 68 | zbarcode::CFG_ASCII 69 | 3 70 | 71 | 72 | const 73 | integer 74 | zbarcode::CFG_NUM 75 | 4 76 | 77 | 78 | const 79 | integer 80 | zbarcode::CFG_MIN_LEN 81 | 32 82 | 83 | 84 | const 85 | integer 86 | zbarcode::CFG_MAX_LEN 87 | 33 88 | 89 | 90 | const 91 | integer 92 | zbarcode::CFG_X_DENSITY 93 | 256 94 | 95 | 96 | const 97 | integer 98 | zbarcode::CFG_Y_DENSITY 99 | 257 100 | 101 | 102 | const 103 | integer 104 | zbarcode::SYM_ALL 105 | 0 106 | 107 | 108 | const 109 | integer 110 | zbarcode::SYM_NONE 111 | 0 112 | 113 | 114 | const 115 | integer 116 | zbarcode::SYM_PARTIAL 117 | 1 118 | 119 | 120 | const 121 | integer 122 | zbarcode::SYM_EAN8 123 | 8 124 | 125 | 126 | const 127 | integer 128 | zbarcode::SYM_UPCE 129 | 9 130 | 131 | 132 | const 133 | integer 134 | zbarcode::SYM_ISBN10 135 | 10 136 | 137 | 138 | const 139 | integer 140 | zbarcode::SYM_UPCA 141 | 12 142 | 143 | 144 | const 145 | integer 146 | zbarcode::SYM_EAN13 147 | 13 148 | 149 | 150 | const 151 | integer 152 | zbarcode::SYM_ISBN13 153 | 14 154 | 155 | 156 | const 157 | integer 158 | zbarcode::SYM_I25 159 | 25 160 | 161 | 162 | const 163 | integer 164 | zbarcode::SYM_CODE39 165 | 39 166 | 167 | 168 | const 169 | integer 170 | zbarcode::SYM_PDF417 171 | 57 172 | 173 | 174 | const 175 | integer 176 | zbarcode::SYM_CODE128 177 | 128 178 | 179 | 180 | const 181 | integer 182 | zbarcode::SYM_SYMBOL 183 | 255 184 | 185 | 186 | const 187 | integer 188 | zbarcode::SYM_ADDON2 189 | 512 190 | 191 | 192 | const 193 | integer 194 | zbarcode::SYM_ADDON5 195 | 1280 196 | 197 | 198 | const 199 | integer 200 | zbarcode::SYM_ADDON 201 | 1792 202 | 203 | 204 | const 205 | integer 206 | zbarcode::OPT_RESOLUTION 207 | 1 208 | 209 | 210 | const 211 | integer 212 | zbarcode::OPT_ENHANCE 213 | 2 214 | 215 | 216 | const 217 | integer 218 | zbarcode::OPT_SHARPEN 219 | 4 220 | 221 | 222 | Methods 223 | 224 | 225 | 226 | 227 |
228 | 229 | 230 |
231 | &reftitle.constants; 232 |
233 | zbarcode Node Types 234 | 235 | 236 | 237 | zbarcode::HAVE_IMAGICK 238 | 239 | &true; if Imagick support is enabled 240 | 241 | 242 | 243 | 244 | zbarcode::HAVE_GD 245 | 246 | &true; if GD support is enabled 247 | 248 | 249 | 250 | 251 | zbarcode::CFG_ENABLE 252 | 253 | Enable configuration item 254 | 255 | 256 | 257 | 258 | zbarcode::CFG_ADD_CHECK 259 | 260 | Enable check digit when optional 261 | 262 | 263 | 264 | 265 | zbarcode::CFG_EMIT_CHECK 266 | 267 | Return check digit when present 268 | 269 | 270 | 271 | 272 | zbarcode::CFG_ASCII 273 | 274 | Enable full ASCII character set 275 | 276 | 277 | 278 | 279 | zbarcode::CFG_NUM 280 | 281 | Number of boolean decoder configs 282 | 283 | 284 | 285 | 286 | zbarcode::CFG_MIN_LEN 287 | 288 | Minimum data length for valid decode 289 | 290 | 291 | 292 | 293 | zbarcode::CFG_MAX_LEN 294 | 295 | Maximum data length for valid decode 296 | 297 | 298 | 299 | 300 | zbarcode::CFG_X_DENSITY 301 | 302 | Image scanner vertical scan density 303 | 304 | 305 | 306 | 307 | zbarcode::CFG_Y_DENSITY 308 | 309 | Image scanner horizontal scan density 310 | 311 | 312 | 313 | 314 | zbarcode::SYM_ALL 315 | 316 | All symbols 317 | 318 | 319 | 320 | 321 | zbarcode::SYM_NONE 322 | 323 | No symbol specified. Same as SYM_ALL 324 | 325 | 326 | 327 | 328 | zbarcode::SYM_PARTIAL 329 | 330 | Intermediate status 331 | 332 | 333 | 334 | 335 | zbarcode::SYM_EAN8 336 | 337 | EAN8 symbol 338 | 339 | 340 | 341 | 342 | zbarcode::SYM_UPCE 343 | 344 | UPCE symbol 345 | 346 | 347 | 348 | 349 | zbarcode::SYM_ISBN10 350 | 351 | ISBN10 symbol 352 | 353 | 354 | 355 | 356 | zbarcode::SYM_UPCA 357 | 358 | UPCA symbol 359 | 360 | 361 | 362 | 363 | zbarcode::SYM_EAN13 364 | 365 | EAN13 symbol 366 | 367 | 368 | 369 | 370 | zbarcode::SYM_ISBN13 371 | 372 | ISBN13 symbol 373 | 374 | 375 | 376 | 377 | zbarcode::SYM_I25 378 | 379 | I25 symbol 380 | 381 | 382 | 383 | 384 | zbarcode::SYM_CODE39 385 | 386 | CODE39 symbol 387 | 388 | 389 | 390 | 391 | zbarcode::SYM_PDF417 392 | 393 | PDF417 symbol 394 | 395 | 396 | 397 | 398 | zbarcode::SYM_CODE128 399 | 400 | CODE128 symbol 401 | 402 | 403 | 404 | 405 | zbarcode::SYM_SYMBOL 406 | 407 | Mask for base symbol type 408 | 409 | 410 | 411 | 412 | zbarcode::SYM_ADDON2 413 | 414 | 2-digit add-on flag 415 | 416 | 417 | 418 | 419 | zbarcode::SYM_ADDON5 420 | 421 | 5-digit add-on flag 422 | 423 | 424 | 425 | 426 | zbarcode::SYM_ADDON 427 | 428 | Add-on flag mask 429 | 430 | 431 | 432 | 433 | zbarcode::OPT_RESOLUTION 434 | 435 | Improve the resolution during reading 436 | 437 | 438 | 439 | 440 | zbarcode::OPT_ENHANCE 441 | 442 | Reduce image noise 443 | 444 | 445 | 446 | 447 | zbarcode::OPT_SHARPEN 448 | 449 | Sharpen the image 450 | 451 | 452 | 453 | 454 |
455 |
456 | 457 | 458 | 459 |
460 | 461 | &reference.zbarcode.entities.zbarcode; 462 | 463 |
464 | 465 | 485 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodeexception.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The zbarcodeexception class 7 | zbarcodeexception 8 | 9 | 10 | 11 | 12 |
13 | &reftitle.intro; 14 | 15 | The class used in exceptions. 16 | 17 |
18 | 19 | 20 |
21 | &reftitle.classsynopsis; 22 | 23 | 24 | 25 | zbarcodeexception 26 | 27 | 28 | 29 | 30 | zbarcodeexception 31 | 32 | 33 | 34 | extends 35 | Exception 36 | 37 | 38 | 39 | Properties 40 | 41 | 42 | Methods 43 | 44 | 45 | Inherited methods 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 |
56 | &reftitle.properties; 57 | 58 | 59 | message 60 | 61 | Exception message 62 | 63 | 64 | 65 | code 66 | 67 | Exception code 68 | 69 | 70 | 71 | file 72 | 73 | Filename 74 | 75 | 76 | 77 | line 78 | 79 | Line 80 | 81 | 82 | 83 |
84 | 85 | 86 | 87 |
88 | 89 | &reference.zbarcode.entities.zbarcodeexception; 90 | 91 |
92 | 93 | 113 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodeimage.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The ZBarCodeImage class 7 | ZBarCodeImage 8 | 9 | 10 | 11 | 12 |
13 | &reftitle.intro; 14 | 15 | This class represents image from which to read the barcode. Each object contains 16 | single image which can be passed to the scanner. 17 | 18 |
19 | 20 | 21 |
22 | &reftitle.classsynopsis; 23 | 24 | 25 | 26 | ZBarCodeImage 27 | 28 | 29 | 30 | 31 | ZBarCodeImage 32 | 33 | 34 | 35 | 36 | Methods 37 | 38 | 39 | 40 | 41 |
42 | 43 |
44 | 45 | &reference.zbarcode.entities.zbarcodeimage; 46 | 47 |
48 | 49 | 69 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodeimage/clear.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZBarCodeImage::clear 7 | Clear the pages 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public ZBarCodeImageZBarCodeImage::clear 14 | 15 | 16 | 17 | Removes all pages from the ZBarCodeImage object. 18 | 19 | 20 | 21 | 22 | &reftitle.returnvalues; 23 | 24 | Returns the current object on success and throws ZBarCodeException on failure. 25 | 26 | 27 | 28 | 29 | &reftitle.seealso; 30 | 31 | 32 | ZBarCodeScanner::scan 33 | 34 | 35 | 36 | 37 | 38 | 39 | 59 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodeimage/construct.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZBarCodeImage::__construct 7 | Construct a new image object 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | ZBarCodeImage::__construct 14 | stringfilename 15 | integerenhance 16 | 17 | 18 | The constructor for the ZBarCodeImage class. 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | 25 | 26 | 27 | filename 28 | 29 | 30 | Optional filename. If filename is not empty the image is read 31 | 32 | 33 | 34 | 35 | enhance 36 | 37 | 38 | Bitmask of ZBarCode::OPT_* constants. 39 | Usually specifying ZBarCode::OPT_RESOLUTION improves results with PDFs. 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | &reftitle.returnvalues; 49 | 50 | If filename is set and reading of the image fails throws ZBarCodeException. 51 | 52 | 53 | 54 | 55 | &reftitle.examples; 56 | 57 | 58 | <methodname>ZBarCodeImage::__construct</methodname> example 59 | 60 | 66 | ]]> 67 | 68 | 69 | 70 | 71 | 72 | 73 | &reftitle.seealso; 74 | 75 | 76 | ZBarCodeScanner::scan 77 | 78 | 79 | 80 | 81 | 82 | 83 | 103 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodeimage/count.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZBarCodeImage::count 7 | Count the pages 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public integerZBarCodeImage::count 14 | 15 | 16 | 17 | Counts the number of pages in the object 18 | 19 | 20 | 21 | 22 | &reftitle.returnvalues; 23 | 24 | Returns an integer representing the number of pages in the object. 25 | 26 | 27 | 28 | 29 | &reftitle.examples; 30 | 31 | 32 | <methodname>ZBarCodeImage::count</methodname> example 33 | 34 | read("page1.jpg"); 38 | 39 | echo "Pages: " . $image->count() . "\n"; 40 | $image->read("page1.jpg"); 41 | 42 | echo "Pages: " . $image->count() . "\n"; 43 | 44 | /* Scan the second page */ 45 | $scanner = new ZBarCodeScanner(); 46 | $barcodes = $scanner->scan($image, 2); 47 | ?> 48 | ]]> 49 | 50 | &example.outputs.similar; 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | &reftitle.seealso; 63 | 64 | 65 | ZBarCodeImage::read 66 | 67 | 68 | 69 | 70 | 71 | 72 | 92 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodeimage/read.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZBarCodeImage::read 7 | Read an image 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public ZBarCodeImageZBarCodeImage::read 14 | stringfilename 15 | intenhance 16 | 17 | 18 | Read an image into the ZBarCodeImage object. The object can hold multiple images 19 | at the same time. This is convenient with for example multi-page PDF files. 20 | 21 | 22 | 23 | 24 | &reftitle.parameters; 25 | 26 | 27 | 28 | filename 29 | 30 | 31 | Filename of an image to read. 32 | 33 | 34 | 35 | 36 | enhance 37 | 38 | 39 | Bitmask of ZBarCode::OPT_* constants. 40 | Usually specifying ZBarCode::OPT_RESOLUTION improves results with PDFs. 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | &reftitle.returnvalues; 50 | 51 | Returns the current object on success and throws ZBarCodeException on failure. 52 | 53 | 54 | 55 | 56 | &reftitle.examples; 57 | 58 | 59 | <methodname>ZBarCodeImage::read</methodname> example 60 | 61 | read("test1.jpg") 68 | ->read("test2.jpg") 69 | ->read("test3.jpg"); 70 | 71 | /* Create scanner */ 72 | $scanner = new ZBarCodeScanner(); 73 | 74 | /* Read the second page, test2.jpg */ 75 | var_dump($scanner->scan($pages, 2)); 76 | ?> 77 | ]]> 78 | 79 | &example.outputs.similar; 80 | 81 | 84 | array(2) { 85 | ["data"]=> 86 | string(13) "5901234123457" 87 | ["type"]=> 88 | string(6) "EAN-13" 89 | } 90 | } 91 | ]]> 92 | 93 | 94 | 95 | 96 | 97 | 98 | &reftitle.seealso; 99 | 100 | 101 | ZBarCodeScanner::scan 102 | 103 | 104 | 105 | 106 | 107 | 108 | 128 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodescanner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The ZBarCodeScanner class 7 | ZBarCodeScanner 8 | 9 | 10 | 11 | 12 |
13 | &reftitle.intro; 14 | 15 | The barcode scanner class. This class reads barcodes from ZBarCodeImage objects. 16 | 17 |
18 | 19 | 20 |
21 | &reftitle.classsynopsis; 22 | 23 | 24 | 25 | ZBarCodeScanner 26 | 27 | 28 | 29 | 30 | ZBarCodeScanner 31 | 32 | 33 | 34 | 35 | Methods 36 | 37 | 38 | 39 | 40 |
41 | 42 |
43 | 44 | &reference.zbarcode.entities.zbarcodescanner; 45 | 46 |
47 | 48 | 68 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodescanner/scan.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZBarCodeScanner::scan 7 | Scan image object 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public arrayZBarCodeScanner::scan 14 | mixedimage 15 | integerpage_num 16 | booleanextended_info 17 | 18 | 19 | Scans image object for barcodes and returns an array representing barcodes 20 | found on the page. 21 | 22 | 23 | 24 | 25 | 26 | &reftitle.parameters; 27 | 28 | 29 | 30 | image 31 | 32 | 33 | Image object to scan for barcodes. This parameter can be one of the following: ZBarCodeImage object, 34 | Imagick object or GD resource. Imagick and GD support has to be enabled separately during installation. 35 | Imagick support requires Imagick 2.3.1 or newer. 36 | 37 | 38 | 39 | 40 | page_num 41 | 42 | 43 | The page to scan. Pass 0 for all pages. (Default: 1) 44 | 45 | 46 | 47 | 48 | extended_info 49 | 50 | 51 | If &true; location polygon of each barcode is returned within the array. (Default: &false;) 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | &reftitle.returnvalues; 61 | 62 | Returns an array describing the barcodes or an empty array if no barcodes were found. On successfull execution the 63 | array will contain elements 'data' and 'type'. If extended_info is &true; the array will 64 | contain 'location' element which is an an array of coordinates for the bounding polygon of the barcode. 65 | 'quality' element is available with ZBar 0.9 and higher. 66 | 67 | 68 | 69 | 70 | &reftitle.examples; 71 | 72 | 73 | <methodname>ZBarCodeScanner::scan</methodname> single page reading 74 | 75 | read("ean13.jpg"); 79 | 80 | $scanner = new ZBarcodeScanner(); 81 | var_dump($scanner->scan($image)); 82 | ?> 83 | ]]> 84 | 85 | &example.outputs.similar; 86 | 87 | 90 | array(2) { 91 | ["data"]=> 92 | string(13) "5901234123457" 93 | ["type"]=> 94 | string(6) "EAN-13" 95 | } 96 | } 97 | ]]> 98 | 99 | 100 | 101 | 102 | 103 | <methodname>ZBarCodeScanner::scan</methodname> multi-page reading 104 | 105 | read("invoice.pdf"); 109 | 110 | $scanner = new ZBarcodeScanner(); 111 | var_dump($scanner->scan($image, 0)); 112 | ?> 113 | ]]> 114 | 115 | &example.outputs.similar; 116 | 117 | 120 | array(1) { 121 | [0]=> 122 | array(2) { 123 | ["data"]=> 124 | string(13) "5901234123457" 125 | ["type"]=> 126 | string(6) "EAN-13" 127 | } 128 | [1]=> 129 | array(2) { 130 | ["data"]=> 131 | string(13) "5901234123457" 132 | ["type"]=> 133 | string(6) "EAN-13" 134 | } 135 | } 136 | [2]=> 137 | array(1) { 138 | [0]=> 139 | array(2) { 140 | ["data"]=> 141 | string(13) "5901234123457" 142 | ["type"]=> 143 | string(6) "EAN-13" 144 | } 145 | } 146 | } 147 | ]]> 148 | 149 | 150 | 151 | 152 | 153 | 154 | 174 | -------------------------------------------------------------------------------- /doc/en/reference/zbarcode/zbarcodescanner/setconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ZBarCodeScanner::setConfig 7 | Set config value 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public ZBarCodeScannerZBarCodeScanner::setConfig 14 | integername 15 | integervalue 16 | integersymbology 17 | 18 | 19 | Sets a configuration value for specific symbology or all of them. 20 | 21 | 22 | 23 | 24 | &reftitle.parameters; 25 | 26 | 27 | 28 | name 29 | 30 | 31 | One of the ZBarCode::CFG_* constants 32 | 33 | 34 | 35 | 36 | value 37 | 38 | 39 | The value of the configuration item 40 | 41 | 42 | 43 | 44 | symbology 45 | 46 | 47 | One of the ZBarCode::SYM_* barcode type constants 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | &reftitle.returnvalues; 57 | 58 | Returns the current object on success and throws ZBarCodeException on failure. 59 | 60 | 61 | 62 | 63 | &reftitle.examples; 64 | 65 | 66 | <methodname>ZBarCodeScanner::setConfig</methodname> example 67 | 68 | setConfig(ZBarcode::CFG_MIN_LEN, 1); 73 | } catch (Exception $e) { 74 | echo "Failed to set config"; 75 | } 76 | ?> 77 | ]]> 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 105 | -------------------------------------------------------------------------------- /imagemagick.m4: -------------------------------------------------------------------------------- 1 | ######################################################### 2 | # Locate ImageMagick configuration program 3 | # ImageMagick has the config program: 4 | # bin/Wand-config 5 | # bin/MagickWand-config 6 | # 7 | # Sets 8 | # IM_WAND_BINARY 9 | # IM_IMAGEMAGICK_PREFIX 10 | # IM_IMAGEMAGICK_VERSION 11 | # IM_IMAGEMAGICK_VERSION_MASK 12 | # 13 | 14 | ######################################################### 15 | 16 | AC_DEFUN([IM_FIND_IMAGEMAGICK],[ 17 | 18 | AC_PATH_PROG(PKG_CONFIG, pkg-config, no) 19 | if test "x$PKG_CONFIG" = "xno"; then 20 | AC_MSG_RESULT([pkg-config not found]) 21 | AC_MSG_ERROR([Please reinstall the pkg-config distribution]) 22 | fi 23 | 24 | if test -z "$AWK"; then 25 | AC_MSG_ERROR([awk not found]) 26 | fi 27 | 28 | AC_MSG_CHECKING(ImageMagick MagickWand API configuration program) 29 | 30 | if test "$2" != "yes"; then 31 | for i in "$2" /usr/local /usr /opt /opt/local; 32 | do 33 | if test -r "${i}/bin/MagickWand-config"; then 34 | IM_WAND_BINARY="${i}/bin/MagickWand-config" 35 | IM_IMAGEMAGICK_PREFIX=$i 36 | break 37 | fi 38 | 39 | if test -r "${i}/bin/Wand-config"; then 40 | IM_WAND_BINARY="${i}/bin/Wand-config" 41 | IM_IMAGEMAGICK_PREFIX=$i 42 | break 43 | fi 44 | done 45 | else 46 | for i in /usr/local /usr /opt /opt/local; 47 | do 48 | if test -r "${i}/bin/MagickWand-config"; then 49 | IM_WAND_BINARY="${i}/bin/MagickWand-config" 50 | IM_IMAGEMAGICK_PREFIX=$i 51 | break 52 | fi 53 | 54 | if test -r "${i}/bin/Wand-config"; then 55 | IM_WAND_BINARY="${i}/bin/Wand-config" 56 | IM_IMAGEMAGICK_PREFIX=$i 57 | break 58 | fi 59 | done 60 | fi 61 | 62 | if test "x" = "x$IM_WAND_BINARY"; then 63 | AC_MSG_ERROR(not found. Please provide a path to MagickWand-config or Wand-config program.) 64 | fi 65 | AC_MSG_RESULT([found in $IM_WAND_BINARY]) 66 | 67 | # This is used later for cflags and libs 68 | export PKG_CONFIG_PATH="${IM_IMAGEMAGICK_PREFIX}/${PHP_LIBDIR}/pkgconfig" 69 | 70 | # Check version 71 | # 72 | IM_IMAGEMAGICK_VERSION=`$IM_WAND_BINARY --version` 73 | IM_IMAGEMAGICK_VERSION_MASK=`echo $IM_IMAGEMAGICK_VERSION | $AWK 'BEGIN { FS = "."; } { printf "%d", ($[1] * 1000 + $[2]) * 1000 + $[3];}'` 74 | 75 | AC_MSG_CHECKING(if ImageMagick version is at least $1) 76 | if test "$IM_IMAGEMAGICK_VERSION_MASK" -ge $1; then 77 | AC_MSG_RESULT(found version $IM_IMAGEMAGICK_VERSION) 78 | else 79 | AC_MSG_ERROR(no. You need at least Imagemagick version $1 to use this extension.) 80 | fi 81 | 82 | # Potential locations for the header 83 | # include/wand/magick-wand.h 84 | # include/ImageMagick/wand/MagickWand.h 85 | # include/ImageMagick-6/wand/MagickWand.h 86 | # include/ImageMagick-7/MagickWand/MagickWand.h 87 | 88 | AC_MSG_CHECKING(for MagickWand.h or magick-wand.h header) 89 | 90 | IM_PREFIX=`$IM_WAND_BINARY --prefix` 91 | IM_MAJOR_VERSION=`echo $IM_IMAGEMAGICK_VERSION | $AWK 'BEGIN { FS = "."; } {print $[1]}'` 92 | 93 | # Try the header formats from newest to oldest 94 | if test -r "${IM_PREFIX}/include/ImageMagick-${IM_MAJOR_VERSION}/MagickWand/MagickWand.h"; then 95 | 96 | IM_INCLUDE_FORMAT="MagickWand/MagickWand.h" 97 | IM_HEADER_STYLE="SEVEN" 98 | AC_DEFINE([IM_MAGICKWAND_HEADER_STYLE_SEVEN], [1], [ImageMagick 7.x style header]) 99 | 100 | AC_MSG_RESULT([${IM_PREFIX}/include/ImageMagick-${IM_MAJOR_VERSION}/MagickWand/MagickWand.h]) 101 | 102 | elif test -r "${IM_PREFIX}/include/ImageMagick-${IM_MAJOR_VERSION}/wand/MagickWand.h"; then 103 | 104 | IM_INCLUDE_FORMAT="wand/MagickWand.h" 105 | IM_HEADER_STYLE="SIX" 106 | AC_DEFINE([IM_MAGICKWAND_HEADER_STYLE_SIX], [1], [ImageMagick 6.x style header]) 107 | 108 | AC_MSG_RESULT([${IM_PREFIX}/include/ImageMagick-${IM_MAJOR_VERSION}/wand/MagickWand.h]) 109 | 110 | elif test -r "${IM_PREFIX}/include/ImageMagick/wand/MagickWand.h"; then 111 | 112 | IM_INCLUDE_FORMAT="wand/MagickWand.h" 113 | IM_HEADER_STYLE="SIX" 114 | AC_DEFINE([IM_MAGICKWAND_HEADER_STYLE_SIX], [1], [ImageMagick 6.x style header]) 115 | 116 | AC_MSG_RESULT([${IM_PREFIX}/include/ImageMagick/wand/MagickWand.h]) 117 | 118 | elif test -r "${IM_PREFIX}/include/ImageMagick/wand/magick-wand.h"; then 119 | 120 | IM_INCLUDE_FORMAT="wand/magick-wand.h" 121 | IM_HEADER_STYLE="OLD" 122 | AC_DEFINE([IM_MAGICKWAND_HEADER_STYLE_OLD], [1], [ImageMagick old style header]) 123 | 124 | AC_MSG_RESULT([${IM_PREFIX}/include/wand/magick-wand.h]) 125 | 126 | else 127 | AC_MSG_ERROR([Unable to find MagickWand.h or magick-wand.h header]) 128 | fi 129 | 130 | # 131 | # The cflags and libs 132 | # 133 | IM_IMAGEMAGICK_LIBS=`$IM_WAND_BINARY --libs` 134 | IM_IMAGEMAGICK_CFLAGS=`$IM_WAND_BINARY --cflags` 135 | 136 | export IM_IMAGEMAGICK_PREFIX 137 | export IM_WAND_BINARY 138 | export IM_IMAGEMAGICK_VERSION 139 | export IM_IMAGEMAGICK_VERSION_MASK 140 | export IM_INCLUDE_FORMAT 141 | export IM_HEADER_STYLE 142 | 143 | export IM_IMAGEMAGICK_LIBS 144 | export IM_IMAGEMAGICK_CFLAGS 145 | ]) 146 | 147 | -------------------------------------------------------------------------------- /php_zbarcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 / zbarcode | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2009 Mikko Koppanen | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Mikko Kopppanen | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | #ifndef _PHP_ZBARCODE_H_ 19 | # define _PHP_ZBARCODE_H_ 20 | 21 | #define PHP_ZBARCODE_EXTNAME "zbarcode" 22 | #define PHP_ZBARCODE_EXTVER "0.0.2-dev" 23 | 24 | #ifdef HAVE_CONFIG_H 25 | # include "config.h" 26 | #endif 27 | 28 | #ifdef ZTS 29 | # include "TSRM.h" 30 | #endif 31 | 32 | /* Include magic wand header */ 33 | #if defined (IM_MAGICKWAND_HEADER_STYLE_SEVEN) 34 | # include 35 | #elif defined (IM_MAGICKWAND_HEADER_STYLE_OLD) 36 | # include 37 | #else 38 | # include 39 | #endif 40 | 41 | #include "php.h" 42 | #include "Zend/zend_exceptions.h" 43 | 44 | #include 45 | 46 | /* {{{ typedef struct _php_zbarcode_object 47 | */ 48 | typedef struct _php_zbarcode_object { 49 | zend_object zo; 50 | } php_zbarcode_object; 51 | /* }}} */ 52 | 53 | /* {{{ typedef struct _php_zbarcode_scanner_object 54 | */ 55 | typedef struct _php_zbarcode_scanner_object { 56 | zbar_image_scanner_t *scanner; 57 | zend_object zo; 58 | } php_zbarcode_scanner_object; 59 | /* }}} */ 60 | 61 | /* {{{ typedef struct _php_zbarcode_image_object 62 | */ 63 | typedef struct _php_zbarcode_image_object { 64 | MagickWand *magick_wand; 65 | zend_object zo; 66 | } php_zbarcode_image_object; 67 | /* }}} */ 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /tests/001-construct.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test construction 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | 14 | --EXPECT-- 15 | OK 16 | OK -------------------------------------------------------------------------------- /tests/002-read-barcode.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test reading image and scanning barcode 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | read(dirname(__FILE__) . "/ean13.jpg")); 11 | 12 | echo "-----------------------------\n"; 13 | 14 | $scanner = new ZBarcodeScanner(); 15 | var_dump($scanner->scan($image)); 16 | 17 | $info = $scanner->scan($image, 0, true); 18 | echo gettype($info[1][0]['location']) . "\n"; 19 | 20 | /* Try to scan empty object */ 21 | $image->clear(); 22 | try { 23 | var_dump($scanner->scan($image)); 24 | } catch (ZBarCodeException $e) { 25 | echo "Got exception"; 26 | } 27 | ?> 28 | --EXPECTF-- 29 | object(zbarcodeimage)#%d (0) { 30 | } 31 | ----------------------------- 32 | array(1) { 33 | [0]=> 34 | array(3) { 35 | ["data"]=> 36 | string(13) "5901234123457" 37 | ["type"]=> 38 | string(6) "EAN-13" 39 | ["quality"]=> 40 | int(539) 41 | } 42 | } 43 | array 44 | Got exception -------------------------------------------------------------------------------- /tests/003-setconfig.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test setting config 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | setConfig(ZBarcode::CFG_MIN_LEN, 1)); 11 | var_dump($scanner->setConfig(ZBarcode::CFG_MIN_LEN, 10, ZBarcode::SYM_ALL)); 12 | 13 | var_dump($scanner->setConfig(ZBarcode::CFG_MAX_LEN, 50)); 14 | var_dump($scanner->setConfig(ZBarcode::CFG_MAX_LEN, 15, ZBarcode::SYM_ALL)); 15 | 16 | ?> 17 | --EXPECT-- 18 | object(zbarcodescanner)#1 (0) { 19 | } 20 | object(zbarcodescanner)#1 (0) { 21 | } 22 | object(zbarcodescanner)#1 (0) { 23 | } 24 | object(zbarcodescanner)#1 (0) { 25 | } -------------------------------------------------------------------------------- /tests/004-paged-reading.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test multipage reading and single page reading 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | read(dirname(__FILE__) . "/ean13.jpg") 11 | ->read(dirname(__FILE__) . "/ean13.jpg") 12 | ->read(dirname(__FILE__) . "/ean13.jpg") 13 | ->read(dirname(__FILE__) . "/ean13.jpg"); 14 | 15 | $scanner = new ZBarcodeScanner(); 16 | var_dump($scanner->scan($image, 0)); 17 | 18 | echo "-----------------------------\n"; 19 | 20 | var_dump($scanner->scan($image, 4)); 21 | 22 | echo "-----------------------------\n"; 23 | 24 | $image->clear(); 25 | $image->read(dirname(__FILE__) . "/ean13.jpg"); 26 | var_dump($scanner->scan($image)); 27 | 28 | ?> 29 | --EXPECT-- 30 | array(4) { 31 | [1]=> 32 | array(1) { 33 | [0]=> 34 | array(3) { 35 | ["data"]=> 36 | string(13) "5901234123457" 37 | ["type"]=> 38 | string(6) "EAN-13" 39 | ["quality"]=> 40 | int(539) 41 | } 42 | } 43 | [2]=> 44 | array(1) { 45 | [0]=> 46 | array(3) { 47 | ["data"]=> 48 | string(13) "5901234123457" 49 | ["type"]=> 50 | string(6) "EAN-13" 51 | ["quality"]=> 52 | int(540) 53 | } 54 | } 55 | [3]=> 56 | array(1) { 57 | [0]=> 58 | array(3) { 59 | ["data"]=> 60 | string(13) "5901234123457" 61 | ["type"]=> 62 | string(6) "EAN-13" 63 | ["quality"]=> 64 | int(540) 65 | } 66 | } 67 | [4]=> 68 | array(1) { 69 | [0]=> 70 | array(3) { 71 | ["data"]=> 72 | string(13) "5901234123457" 73 | ["type"]=> 74 | string(6) "EAN-13" 75 | ["quality"]=> 76 | int(540) 77 | } 78 | } 79 | } 80 | ----------------------------- 81 | array(1) { 82 | [0]=> 83 | array(3) { 84 | ["data"]=> 85 | string(13) "5901234123457" 86 | ["type"]=> 87 | string(6) "EAN-13" 88 | ["quality"]=> 89 | int(540) 90 | } 91 | } 92 | ----------------------------- 93 | array(1) { 94 | [0]=> 95 | array(3) { 96 | ["data"]=> 97 | string(13) "5901234123457" 98 | ["type"]=> 99 | string(6) "EAN-13" 100 | ["quality"]=> 101 | int(540) 102 | } 103 | } -------------------------------------------------------------------------------- /tests/005-count.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test count 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | read(dirname(__FILE__) . "/ean13.jpg") 11 | ->read(dirname(__FILE__) . "/ean13.jpg") 12 | ->read(dirname(__FILE__) . "/ean13.jpg") 13 | ->read(dirname(__FILE__) . "/ean13.jpg"); 14 | 15 | echo "Count: " . $image->count() . "\n"; 16 | $image->clear(); 17 | echo "Count: " . $image->count() . "\n"; 18 | sleep(1); 19 | 20 | ?> 21 | --EXPECT-- 22 | Count: 4 23 | Count: 0 -------------------------------------------------------------------------------- /tests/006-imagick.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check whether imagick integration works 3 | --SKIPIF-- 4 | 16 | --FILE-- 17 | scan($image), $scanner->scan($image))); 23 | 24 | ?> 25 | --EXPECT-- 26 | array(0) { 27 | } -------------------------------------------------------------------------------- /tests/007-test-gd.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test GD support 3 | --SKIPIF-- 4 | 15 | --FILE-- 16 | scan($image)); 21 | ?> 22 | --EXPECT-- 23 | array(1) { 24 | [1]=> 25 | array(1) { 26 | [0]=> 27 | array(2) { 28 | ["data"]=> 29 | string(13) "5901234123457" 30 | ["type"]=> 31 | string(6) "EAN-13" 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /tests/ean13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkoppanen/php-zbarcode/1c613bf112e9f62427698ea89b3feee5201a1816/tests/ean13.jpg -------------------------------------------------------------------------------- /tests/skipif.inc.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /zbarcode.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 / zbarcode | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2009 Mikko Koppanen | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Mikko Kopppanen | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | #include "php_zbarcode.h" 20 | #include "ext/standard/info.h" 21 | 22 | /* Handlers */ 23 | static zend_object_handlers php_zbarcode_object_handlers; 24 | static zend_object_handlers php_zbarcode_scanner_object_handlers; 25 | static zend_object_handlers php_zbarcode_image_object_handlers; 26 | 27 | /* Class entries */ 28 | zend_class_entry *php_zbarcode_sc_entry; 29 | zend_class_entry *php_zbarcode_image_sc_entry; 30 | zend_class_entry *php_zbarcode_scanner_sc_entry; 31 | zend_class_entry *php_zbarcode_exception_class_entry; 32 | 33 | /* Imagick support */ 34 | #ifdef HAVE_ZBARCODE_IMAGICK 35 | # include "ext/imagick/php_imagick_shared.h" 36 | #endif 37 | 38 | /* GD support */ 39 | #if HAVE_ZBARCODE_GD 40 | # include "ext/gd/php_gd.h" 41 | # if HAVE_GD_BUNDLED 42 | # include "ext/gd/libgd/gd.h" 43 | # else 44 | # include "gd.h" 45 | # endif 46 | #endif 47 | 48 | #define PHP_ZBARCODE_RESOLUTION 1 49 | #define PHP_ZBARCODE_ENHANCE 2 50 | #define PHP_ZBARCODE_SHARPEN 4 51 | 52 | static inline php_zbarcode_object *php_zbarcode_fetch_object(zend_object *obj) { 53 | return (php_zbarcode_object *)((char *)obj - XtOffsetOf(php_zbarcode_object, zo)); 54 | } 55 | #define Z_ZBARCODE_OBJ_P(zv) php_zbarcode_fetch_object(Z_OBJ_P(zv)); 56 | 57 | static inline php_zbarcode_image_object *php_zbarcode_image_fetch_object(zend_object *obj) { 58 | return (php_zbarcode_image_object *)((char *)obj - XtOffsetOf(php_zbarcode_image_object, zo)); 59 | } 60 | #define Z_ZBARCODE_IMAGE_OBJ_P(zv) php_zbarcode_image_fetch_object(Z_OBJ_P(zv)); 61 | 62 | static inline php_zbarcode_scanner_object *php_zbarcode_scanner_fetch_object(zend_object *obj) { 63 | return (php_zbarcode_scanner_object *)((char *)obj - XtOffsetOf(php_zbarcode_scanner_object, zo)); 64 | } 65 | #define Z_ZBARCODE_SCANNER_OBJ_P(zv) php_zbarcode_scanner_fetch_object(Z_OBJ_P(zv)); 66 | 67 | static 68 | void s_throw_image_exception (MagickWand *magick_wand, const char *message TSRMLS_DC) 69 | { 70 | ExceptionType severity; 71 | char *magick_msg; 72 | 73 | magick_msg = MagickGetException (magick_wand, &severity); 74 | MagickClearException (magick_wand); 75 | 76 | if (magick_msg && strlen (magick_msg) > 0) { 77 | zend_throw_exception(php_zbarcode_exception_class_entry, magick_msg, 1 TSRMLS_CC); 78 | magick_msg = MagickRelinquishMemory(magick_msg); 79 | return; 80 | } 81 | 82 | if (magick_msg) { 83 | MagickRelinquishMemory(magick_msg); 84 | } 85 | 86 | zend_throw_exception(php_zbarcode_exception_class_entry, message, 1 TSRMLS_CC); 87 | } 88 | 89 | #define PHP_ZBARCODE_CHAIN_METHOD RETURN_ZVAL(getThis(), 1, 0); 90 | 91 | static 92 | zend_bool s_php_zbarcode_read(MagickWand *wand, char *filename, long enhance) 93 | { 94 | if (enhance & PHP_ZBARCODE_RESOLUTION) { 95 | MagickSetResolution(wand, 200, 200); 96 | } 97 | 98 | if (MagickReadImage(wand, filename) == MagickFalse) { 99 | ClearMagickWand(wand); 100 | return 0; 101 | } 102 | 103 | if (enhance & PHP_ZBARCODE_ENHANCE) { 104 | MagickEnhanceImage(wand); 105 | } 106 | 107 | if (enhance & PHP_ZBARCODE_SHARPEN) { 108 | MagickSharpenImage(wand, 0, 0.5); 109 | } 110 | 111 | return 1; 112 | } 113 | 114 | /* {{{ zBarcodeImage zBarcodeImage::__construct([string filename, int enhance]) 115 | Construct a new zBarcodeImage object 116 | */ 117 | PHP_METHOD(zbarcodeimage, __construct) 118 | { 119 | php_zbarcode_image_object *intern; 120 | zend_string *filename = NULL; 121 | long enhance = 0; 122 | char resolved_path[MAXPATHLEN]; 123 | 124 | ZEND_PARSE_PARAMETERS_START(0, 2) 125 | Z_PARAM_OPTIONAL 126 | Z_PARAM_STR(filename) 127 | Z_PARAM_LONG(enhance) 128 | ZEND_PARSE_PARAMETERS_END(); 129 | 130 | if (filename == NULL || !filename->len) { 131 | return; 132 | } 133 | 134 | if (!tsrm_realpath(filename->val, resolved_path TSRMLS_CC)) { 135 | zend_throw_exception(php_zbarcode_exception_class_entry, "The file does not exist or cannot be read", 1 TSRMLS_CC); 136 | return; 137 | } 138 | 139 | if (php_check_open_basedir(resolved_path TSRMLS_CC)) { 140 | return; 141 | } 142 | 143 | intern = (php_zbarcode_image_object *)Z_ZBARCODE_IMAGE_OBJ_P(getThis()); 144 | 145 | if (!s_php_zbarcode_read(intern->magick_wand, resolved_path, enhance)) { 146 | s_throw_image_exception (intern->magick_wand, "Unable to read the image" TSRMLS_CC); 147 | return; 148 | } 149 | return; 150 | } 151 | /* }}} */ 152 | 153 | /* {{{ zBarcodeImage zBarcodeImage::read(string filename[, int enhance]) 154 | Read an image 155 | */ 156 | PHP_METHOD(zbarcodeimage, read) 157 | { 158 | php_zbarcode_image_object *intern; 159 | zend_string *filename = NULL; 160 | long enhance = 0; 161 | char resolved_path[MAXPATHLEN]; 162 | 163 | ZEND_PARSE_PARAMETERS_START(1, 2) 164 | Z_PARAM_STR(filename) 165 | Z_PARAM_OPTIONAL 166 | Z_PARAM_LONG(enhance) 167 | ZEND_PARSE_PARAMETERS_END(); 168 | 169 | if (!tsrm_realpath(filename->val, resolved_path TSRMLS_CC)) { 170 | zend_throw_exception(php_zbarcode_exception_class_entry, "The file does not exist or cannot be read", 1 TSRMLS_CC); 171 | return; 172 | } 173 | 174 | if (php_check_open_basedir(resolved_path TSRMLS_CC)) { 175 | return; 176 | } 177 | 178 | intern = (php_zbarcode_image_object *)Z_ZBARCODE_IMAGE_OBJ_P(getThis()); 179 | 180 | if (!s_php_zbarcode_read(intern->magick_wand, resolved_path, enhance)) { 181 | s_throw_image_exception (intern->magick_wand, "Unable to read the image" TSRMLS_CC); 182 | return; 183 | } 184 | PHP_ZBARCODE_CHAIN_METHOD; 185 | } 186 | /* }}} */ 187 | 188 | /* {{{ zBarcodeImage zBarcodeImage:clear() 189 | Remove existing pages 190 | */ 191 | PHP_METHOD(zbarcodeimage, clear) 192 | { 193 | php_zbarcode_image_object *intern; 194 | 195 | if (zend_parse_parameters_none() == FAILURE) { 196 | return; 197 | } 198 | 199 | intern = (php_zbarcode_image_object *)Z_ZBARCODE_IMAGE_OBJ_P(getThis()); 200 | ClearMagickWand(intern->magick_wand); 201 | 202 | PHP_ZBARCODE_CHAIN_METHOD; 203 | } 204 | /* }}} */ 205 | 206 | /* {{{ integer zBarcodeImage:count() 207 | Count pages 208 | */ 209 | PHP_METHOD(zbarcodeimage, count) 210 | { 211 | php_zbarcode_image_object *intern; 212 | 213 | if (zend_parse_parameters_none() == FAILURE) { 214 | return; 215 | } 216 | 217 | intern = (php_zbarcode_image_object *)Z_ZBARCODE_IMAGE_OBJ_P(getThis()); 218 | RETURN_LONG(MagickGetNumberImages(intern->magick_wand)); 219 | } 220 | /* }}} */ 221 | 222 | static 223 | zbar_image_t *s_php_zbarcode_image_create(unsigned long width, unsigned long height, unsigned char *image_data) 224 | { 225 | zbar_image_t *image = zbar_image_create(); 226 | 227 | if (!image) { 228 | return NULL; 229 | } 230 | 231 | zbar_image_set_format(image, *(int*)"Y800"); 232 | zbar_image_set_size(image, width, height); 233 | zbar_image_set_data(image, (void *)image_data, width * height, zbar_image_free_data); 234 | return image; 235 | } 236 | 237 | static 238 | zbar_image_t *s_php_zbarcode_get_page(MagickWand *wand) 239 | { 240 | unsigned long width, height; 241 | unsigned char *image_data; 242 | size_t image_size; 243 | 244 | if (MagickSetImageDepth(wand, 8) == MagickFalse) { 245 | return NULL; 246 | } 247 | 248 | if (MagickSetImageFormat(wand, "GRAY") == MagickFalse) { 249 | return NULL; 250 | } 251 | 252 | width = MagickGetImageWidth(wand); 253 | height = MagickGetImageHeight(wand); 254 | 255 | image_data = calloc(width * height, sizeof (char)); 256 | 257 | if (!MagickExportImagePixels(wand, 0, 0, width, height, "I", CharPixel, image_data)) { 258 | return NULL; 259 | } 260 | return s_php_zbarcode_image_create(width, height, image_data); 261 | } 262 | 263 | static 264 | zval *s_php_zbarcode_scan_page(zbar_image_scanner_t *scanner, zbar_image_t *image, zend_bool extended, zval *return_array TSRMLS_DC) 265 | { 266 | int n; 267 | const zbar_symbol_t *symbol; 268 | 269 | array_init(return_array); 270 | 271 | /* scan the image for barcodes */ 272 | n = zbar_scan_image(scanner, image); 273 | 274 | /* extract results */ 275 | symbol = zbar_image_first_symbol(image); 276 | 277 | /* Loop through all all symbols */ 278 | for(; symbol; symbol = zbar_symbol_next(symbol)) { 279 | zval symbol_array, loc_array; 280 | zbar_symbol_type_t symbol_type; 281 | const char *data; 282 | unsigned int loc_size; 283 | 284 | /* Initialize array element */ 285 | array_init(&symbol_array); 286 | 287 | /* Get symbol type and data in it */ 288 | symbol_type = zbar_symbol_get_type(symbol); 289 | data = zbar_symbol_get_data(symbol); 290 | 291 | add_assoc_string(&symbol_array, "data", (char *)data); 292 | add_assoc_string(&symbol_array, "type", (char *)zbar_get_symbol_name(symbol_type)); 293 | #ifdef HAVE_ZBAR_SYMBOL_GET_QUALITY 294 | add_assoc_long(&symbol_array, "quality", zbar_symbol_get_quality(symbol)); 295 | #endif 296 | if (extended) { 297 | unsigned int i; 298 | 299 | array_init(&loc_array); 300 | loc_size = zbar_symbol_get_loc_size(symbol); 301 | 302 | for (i = 0; i < loc_size; i++) { 303 | zval coords; 304 | array_init(&coords); 305 | 306 | add_assoc_long(&coords, "x", zbar_symbol_get_loc_x(symbol, i)); 307 | add_assoc_long(&coords, "y", zbar_symbol_get_loc_y(symbol, i)); 308 | 309 | add_next_index_zval(&loc_array, &coords); 310 | } 311 | add_assoc_zval(&symbol_array, "location", &loc_array); 312 | } 313 | add_next_index_zval(return_array, &symbol_array); 314 | } 315 | return return_array; 316 | } 317 | 318 | /* {{{ array zBarCodeScanner::scan(mixed image[, int page_num, bool extended]) 319 | Scan an image 320 | */ 321 | PHP_METHOD(zbarcodescanner, scan) 322 | { 323 | zval *image; 324 | MagickWand *magick_wand; 325 | 326 | zbar_image_t *page; 327 | php_zbarcode_scanner_object *intern; 328 | 329 | zval *object; 330 | int i = 1; 331 | zend_bool extended = 0; 332 | long page_num = 1, image_count; 333 | zend_bool free_ptr = 0; 334 | 335 | ZEND_PARSE_PARAMETERS_START(1, 3) 336 | Z_PARAM_ZVAL(image) 337 | Z_PARAM_OPTIONAL 338 | Z_PARAM_LONG(page_num) 339 | Z_PARAM_BOOL(extended) 340 | ZEND_PARSE_PARAMETERS_END(); 341 | 342 | #ifdef HAVE_ZBARCODE_GD 343 | if (Z_TYPE_P(image) != IS_OBJECT && Z_TYPE_P(image) != IS_RESOURCE) { 344 | zend_throw_exception(php_zbarcode_exception_class_entry, "The first parameter must be a valid object or a GD resource", 1 TSRMLS_CC); 345 | return; 346 | } 347 | #else 348 | if (Z_TYPE_P(image) != IS_OBJECT) { 349 | zend_throw_exception(php_zbarcode_exception_class_entry, "The first parameter must be a valid object", 1 TSRMLS_CC); 350 | return; 351 | } 352 | #endif 353 | 354 | intern = (php_zbarcode_scanner_object *)Z_ZBARCODE_SCANNER_OBJ_P(getThis()); 355 | 356 | if (Z_TYPE_P(image) == IS_OBJECT && instanceof_function_ex(Z_OBJCE_P(image), php_zbarcode_image_sc_entry, 0 TSRMLS_CC)) { 357 | php_zbarcode_image_object *intern_image; 358 | 359 | intern_image = (php_zbarcode_image_object *)Z_ZBARCODE_IMAGE_OBJ_P(image); 360 | magick_wand = intern_image->magick_wand; 361 | } 362 | #ifdef HAVE_ZBARCODE_IMAGICK 363 | else if (Z_TYPE_P(image) == IS_OBJECT && instanceof_function_ex(Z_OBJCE_P(image), php_imagick_get_class_entry(), 0 TSRMLS_CC)) { 364 | php_zbarcode_image_object *intern_image; 365 | intern_image = (php_zbarcode_image_object *)Z_ZBARCODE_IMAGE_OBJ_P(image); 366 | magick_wand = intern_image->magick_wand; 367 | } 368 | #endif 369 | #ifdef HAVE_ZBARCODE_GD 370 | /* Handle GD resource */ 371 | else if (Z_TYPE_P(image) == IS_RESOURCE) { 372 | gdImagePtr gd_image = NULL; 373 | MagickWand *wand; 374 | unsigned long image_w, image_h; 375 | PixelWand *color; 376 | MagickBooleanType status; 377 | unsigned char *pixels; 378 | int x, y, pixel_pos = 0; 379 | zend_bool has_pixels = 0; 380 | 381 | ZEND_FETCH_RESOURCE(gd_image, gdImagePtr, &image, -1, "Image", phpi_get_le_gd()); 382 | 383 | if (!gd_image) { 384 | zend_throw_exception(php_zbarcode_exception_class_entry, "The given resource is not a valid GD image", 1 TSRMLS_CC); 385 | return; 386 | } 387 | 388 | image_w = gdImageSX(gd_image); 389 | image_h = gdImageSY(gd_image); 390 | 391 | pixels = emalloc((3 * image_w) * image_h); 392 | 393 | for (y = 0; y < image_h; y++) { 394 | for (x = 0; x < image_w; x++) { 395 | int pixel = 0; 396 | if (gdImageTrueColor(gd_image)) { 397 | if (gd_image->tpixels && gdImageBoundsSafe(gd_image, x, y)) { 398 | pixel = gdImageTrueColorPixel(gd_image, x, y); 399 | pixels[pixel_pos++] = (pixel >> 16) & 0xFF; 400 | pixels[pixel_pos++] = (pixel >> 8) & 0xFF; 401 | pixels[pixel_pos++] = pixel & 0xFF; 402 | has_pixels = 1; 403 | } 404 | } else { 405 | if (gd_image->pixels && gdImageBoundsSafe(gd_image, x, y)) { 406 | pixel = gd_image->pixels[y][x]; 407 | pixels[pixel_pos++] = gd_image->red[pixel]; 408 | pixels[pixel_pos++] = gd_image->green[pixel]; 409 | pixels[pixel_pos++] = gd_image->blue[pixel]; 410 | has_pixels = 1; 411 | } 412 | } 413 | } 414 | } 415 | 416 | if (!has_pixels) { 417 | efree(pixels); 418 | zend_throw_exception(php_zbarcode_exception_class_entry, "Unable to get pixels from GD resource", 1 TSRMLS_CC); 419 | return; 420 | } 421 | 422 | wand = NewMagickWand(); 423 | if (!wand) { 424 | efree(pixels); 425 | zend_throw_exception(php_zbarcode_exception_class_entry, "Failed to allocate MagickWand structure", 1 TSRMLS_CC); 426 | return; 427 | } 428 | 429 | color = NewPixelWand(); 430 | if (!color) { 431 | efree(pixels); 432 | DestroyMagickWand(wand); 433 | zend_throw_exception(php_zbarcode_exception_class_entry, "Failed to allocate PixelWand structure", 1 TSRMLS_CC); 434 | return; 435 | } 436 | 437 | if (MagickNewImage(wand, image_w, image_h, color) == MagickFalse) { 438 | efree(pixels); 439 | DestroyMagickWand(wand); 440 | DestroyPixelWand(color); 441 | return; 442 | } 443 | DestroyPixelWand(color); 444 | 445 | status = MagickSetImagePixels(wand, 0, 0, image_w, image_h, "RGB", CharPixel, pixels); 446 | efree(pixels); 447 | 448 | if (status == MagickFalse) { 449 | DestroyMagickWand(wand); 450 | return; 451 | } 452 | 453 | magick_wand = wand; 454 | page_num = 0; 455 | free_ptr = 1; 456 | } 457 | #endif 458 | else { 459 | zend_throw_exception(php_zbarcode_exception_class_entry, "Invalid parameter type", 1 TSRMLS_CC); 460 | return; 461 | } 462 | 463 | image_count = MagickGetNumberImages(magick_wand); 464 | 465 | if (image_count == 0) { 466 | zend_throw_exception(php_zbarcode_exception_class_entry, "The image object does not contain images", 1 TSRMLS_CC); 467 | return; 468 | } 469 | 470 | if (page_num > 0) { 471 | if (image_count < page_num) { 472 | if (free_ptr) { 473 | DestroyMagickWand(magick_wand); 474 | } 475 | zend_throw_exception_ex(php_zbarcode_exception_class_entry, 1 TSRMLS_CC, "Invalid page specified. The object contains %ld page(s)", image_count); 476 | return; 477 | } 478 | 479 | if (MagickSetIteratorIndex(magick_wand, page_num - 1) == MagickFalse) { 480 | if (free_ptr) { 481 | DestroyMagickWand(magick_wand); 482 | } 483 | zend_throw_exception(php_zbarcode_exception_class_entry, "Failed to set the page number", 1 TSRMLS_CC); 484 | return; 485 | } 486 | /* Read page */ 487 | page = s_php_zbarcode_get_page(magick_wand); 488 | 489 | if (!page) { 490 | if (free_ptr) { 491 | DestroyMagickWand(magick_wand); 492 | } 493 | zend_throw_exception(php_zbarcode_exception_class_entry, "Failed to get the page", 1 TSRMLS_CC); 494 | return; 495 | } 496 | 497 | /* Scan the page for barcodes */ 498 | s_php_zbarcode_scan_page(intern->scanner, page, extended, return_value TSRMLS_CC); 499 | } else { 500 | array_init(return_value); 501 | 502 | MagickResetIterator(magick_wand); 503 | while (MagickNextImage(magick_wand) != MagickFalse) { 504 | zval page_array; 505 | 506 | /* Read the current page */ 507 | page = s_php_zbarcode_get_page(magick_wand); 508 | 509 | /* Reading current page failed */ 510 | if (!page) { 511 | i++; 512 | continue; 513 | } 514 | /* Scan the page for barcodes */ 515 | 516 | s_php_zbarcode_scan_page(intern->scanner, page, extended, &page_array TSRMLS_CC); 517 | add_index_zval(return_value, i++, &page_array); 518 | } 519 | } 520 | 521 | if (free_ptr) { 522 | DestroyMagickWand(magick_wand); 523 | } 524 | 525 | return; 526 | } 527 | /* }}} */ 528 | 529 | /* {{{ zBarCodeScanner zBarCodeScanner::setConfig(int name, int value[, int symbology]) 530 | Set config option 531 | */ 532 | PHP_METHOD(zbarcodescanner, setconfig) 533 | { 534 | php_zbarcode_scanner_object *intern; 535 | long symbology = 0, name, value; 536 | 537 | ZEND_PARSE_PARAMETERS_START(2, 3) 538 | Z_PARAM_LONG(name) 539 | Z_PARAM_LONG(value) 540 | Z_PARAM_OPTIONAL 541 | Z_PARAM_LONG(symbology) 542 | ZEND_PARSE_PARAMETERS_END(); 543 | 544 | intern = (php_zbarcode_scanner_object *)Z_ZBARCODE_SCANNER_OBJ_P(getThis()); 545 | 546 | if (zbar_image_scanner_set_config(intern->scanner, symbology, name, value) != 0) { 547 | zend_throw_exception(php_zbarcode_exception_class_entry, "Config does not apply to specified symbology, or value out of range", 1 TSRMLS_CC); 548 | return; 549 | } 550 | PHP_ZBARCODE_CHAIN_METHOD; 551 | } 552 | /* }}} */ 553 | 554 | static zend_function_entry php_zbarcode_class_methods[] = 555 | { 556 | { NULL, NULL, NULL } 557 | }; 558 | 559 | ZEND_BEGIN_ARG_INFO_EX(zbarcode_image_construct_args, 0, 0, 0) 560 | ZEND_ARG_INFO(0, filename) 561 | ZEND_ARG_INFO(0, enhance) 562 | ZEND_END_ARG_INFO() 563 | 564 | ZEND_BEGIN_ARG_INFO_EX(zbarcode_image_read_args, 0, 0, 1) 565 | ZEND_ARG_INFO(0, filename) 566 | ZEND_ARG_INFO(0, enhance) 567 | ZEND_END_ARG_INFO() 568 | 569 | ZEND_BEGIN_ARG_INFO_EX(zbarcode_image_no_args, 0, 0, 0) 570 | ZEND_END_ARG_INFO() 571 | 572 | static zend_function_entry php_zbarcode_image_class_methods[] = 573 | { 574 | PHP_ME(zbarcodeimage, __construct, zbarcode_image_construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) 575 | PHP_ME(zbarcodeimage, read, zbarcode_image_read_args, ZEND_ACC_PUBLIC) 576 | PHP_ME(zbarcodeimage, clear, zbarcode_image_no_args, ZEND_ACC_PUBLIC) 577 | PHP_ME(zbarcodeimage, count, zbarcode_image_no_args, ZEND_ACC_PUBLIC) 578 | { NULL, NULL, NULL } 579 | }; 580 | 581 | ZEND_BEGIN_ARG_INFO_EX(zbarcode_scanner_scan_args, 0, 0, 1) 582 | ZEND_ARG_INFO(0, image) 583 | ZEND_ARG_INFO(0, page_num) 584 | ZEND_ARG_INFO(0, extended) 585 | ZEND_END_ARG_INFO() 586 | 587 | ZEND_BEGIN_ARG_INFO_EX(zbarcode_scanner_setconfig_args, 0, 0, 2) 588 | ZEND_ARG_INFO(0, name) 589 | ZEND_ARG_INFO(0, value) 590 | ZEND_ARG_INFO(0, symbology) 591 | ZEND_END_ARG_INFO() 592 | 593 | static zend_function_entry php_zbarcode_scanner_class_methods[] = 594 | { 595 | PHP_ME(zbarcodescanner, scan, zbarcode_scanner_scan_args, ZEND_ACC_PUBLIC) 596 | PHP_ME(zbarcodescanner, setconfig, zbarcode_scanner_setconfig_args, ZEND_ACC_PUBLIC) 597 | { NULL, NULL, NULL } 598 | }; 599 | 600 | /* {{{ static void php_zbarcode_object_free_storage(zend_object *object) 601 | */ 602 | static void php_zbarcode_object_free_storage(zend_object *object) 603 | { 604 | php_zbarcode_object *intern = php_zbarcode_fetch_object(object); 605 | 606 | if (!intern) { 607 | return; 608 | } 609 | if (&intern->zo) { 610 | zend_object_std_dtor(&intern->zo); 611 | } 612 | } 613 | /* }}} */ 614 | 615 | /* {{{ static void php_zbarcode_scanner_object_free_storage(zend_object *object) 616 | */ 617 | static void php_zbarcode_scanner_object_free_storage(zend_object *object) 618 | { 619 | php_zbarcode_scanner_object *intern = php_zbarcode_scanner_fetch_object(object); 620 | 621 | if (!intern) { 622 | return; 623 | } 624 | 625 | if (intern->scanner) { 626 | zbar_image_scanner_destroy(intern->scanner); 627 | intern->scanner = NULL; 628 | } 629 | zend_object_std_dtor(&intern->zo); 630 | } 631 | /* }}} */ 632 | 633 | /* {{{ static void php_zbarcode_image_object_free_storage(zend_object *object) 634 | */ 635 | static void php_zbarcode_image_object_free_storage(zend_object *object) 636 | { 637 | php_zbarcode_image_object *intern = php_zbarcode_image_fetch_object(object); 638 | 639 | if (!intern) { 640 | return; 641 | } 642 | 643 | if (intern->magick_wand) { 644 | DestroyMagickWand(intern->magick_wand); 645 | intern->magick_wand = NULL; 646 | } 647 | 648 | zend_object_std_dtor(&intern->zo); 649 | } 650 | /* }}} */ 651 | 652 | /* PHP 5.4 */ 653 | #if PHP_VERSION_ID < 50399 654 | # define object_properties_init(zo, class_type) { \ 655 | zval *tmp; \ 656 | zend_hash_copy((*zo).properties, \ 657 | &class_type->default_properties, \ 658 | (copy_ctor_func_t) zval_add_ref, \ 659 | (void *) &tmp, \ 660 | sizeof(zval *)); \ 661 | } 662 | #endif 663 | 664 | /* {{{ static zend_object *php_zbarcode_object_new(zend_class_entry *ce) 665 | */ 666 | static zend_object *php_zbarcode_object_new(zend_class_entry *ce) 667 | { 668 | php_zbarcode_object *intern = ecalloc(1, sizeof(php_zbarcode_object) + zend_object_properties_size(ce)); 669 | 670 | zend_object_std_init(&intern->zo, ce); 671 | object_properties_init(&intern->zo, ce); 672 | 673 | intern->zo.handlers = &php_zbarcode_object_handlers; 674 | return &intern->zo; 675 | } 676 | /* }}} */ 677 | 678 | /* {{{ static zend_object *php_zbarcode_scanner_object_new(zend_class_entry *ce) 679 | */ 680 | static zend_object *php_zbarcode_scanner_object_new(zend_class_entry *ce) 681 | { 682 | php_zbarcode_scanner_object *intern = ecalloc(1, sizeof(php_zbarcode_scanner_object) + zend_object_properties_size(ce)); 683 | 684 | zend_object_std_init(&intern->zo, ce); 685 | object_properties_init(&intern->zo, ce); 686 | 687 | /* Initialize reader */ 688 | intern->scanner = zbar_image_scanner_create(); 689 | 690 | intern->zo.handlers = &php_zbarcode_scanner_object_handlers; 691 | return &intern->zo; 692 | } 693 | /* }}} */ 694 | 695 | /* {{{ static zend_object *php_zbarcode_image_object_new(zend_class_entry *ce) 696 | */ 697 | static zend_object *php_zbarcode_image_object_new(zend_class_entry *ce) 698 | { 699 | php_zbarcode_image_object *intern = ecalloc(1, sizeof(php_zbarcode_image_object) + zend_object_properties_size(ce)); 700 | 701 | zend_object_std_init(&intern->zo, ce); 702 | object_properties_init(&intern->zo, ce); 703 | 704 | /* Initialize reader */ 705 | intern->magick_wand = NewMagickWand(); 706 | 707 | intern->zo.handlers = &php_zbarcode_image_object_handlers; 708 | return &intern->zo; 709 | } 710 | /* }}} */ 711 | 712 | /* {{{ PHP_MINIT_FUNCTION(zbarcode) 713 | */ 714 | PHP_MINIT_FUNCTION(zbarcode) 715 | { 716 | zend_class_entry ce; 717 | memcpy(&php_zbarcode_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 718 | memcpy(&php_zbarcode_scanner_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 719 | memcpy(&php_zbarcode_image_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 720 | 721 | MagickWandGenesis(); 722 | 723 | /* 724 | Initialize exceptions (zbarcode exception) 725 | */ 726 | INIT_CLASS_ENTRY(ce, "zbarcodeexception", NULL); 727 | php_zbarcode_exception_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C)); 728 | php_zbarcode_exception_class_entry->ce_flags |= ZEND_ACC_FINAL; 729 | 730 | /* 731 | Initialize the class (zbarcode). This class is just a container for constants 732 | */ 733 | INIT_CLASS_ENTRY(ce, "zbarcode", php_zbarcode_class_methods); 734 | ce.create_object = php_zbarcode_object_new; 735 | php_zbarcode_object_handlers.clone_obj = NULL; 736 | php_zbarcode_object_handlers.free_obj = php_zbarcode_object_free_storage; 737 | php_zbarcode_object_handlers.offset = XtOffsetOf(php_zbarcode_object, zo); 738 | php_zbarcode_sc_entry = zend_register_internal_class(&ce TSRMLS_CC); 739 | 740 | /* 741 | Initialize the class (zbarcode image) 742 | */ 743 | INIT_CLASS_ENTRY(ce, "zbarcodeimage", php_zbarcode_image_class_methods); 744 | ce.create_object = php_zbarcode_image_object_new; 745 | php_zbarcode_image_object_handlers.clone_obj = NULL; 746 | php_zbarcode_image_object_handlers.free_obj = php_zbarcode_image_object_free_storage; 747 | php_zbarcode_image_object_handlers.offset = XtOffsetOf(php_zbarcode_image_object, zo); 748 | php_zbarcode_image_sc_entry = zend_register_internal_class(&ce TSRMLS_CC); 749 | 750 | /* 751 | Initialize the class (zbarcode scanner) 752 | */ 753 | INIT_CLASS_ENTRY(ce, "zbarcodescanner", php_zbarcode_scanner_class_methods); 754 | ce.create_object = php_zbarcode_scanner_object_new; 755 | php_zbarcode_scanner_object_handlers.clone_obj = NULL; 756 | php_zbarcode_scanner_object_handlers.free_obj = php_zbarcode_scanner_object_free_storage; 757 | php_zbarcode_scanner_object_handlers.offset = XtOffsetOf(php_zbarcode_scanner_object, zo); 758 | php_zbarcode_scanner_sc_entry = zend_register_internal_class(&ce TSRMLS_CC); 759 | 760 | /* Do we have imagick support */ 761 | #ifdef HAVE_ZBARCODE_IMAGICK 762 | zend_declare_class_constant_bool(php_zbarcode_sc_entry, "HAVE_IMAGICK", sizeof("HAVE_IMAGICK")-1, 1 TSRMLS_CC); 763 | #else 764 | zend_declare_class_constant_bool(php_zbarcode_sc_entry, "HAVE_IMAGICK", sizeof("HAVE_IMAGICK")-1, 0 TSRMLS_CC); 765 | #endif 766 | 767 | /* Do we have GD support */ 768 | #ifdef HAVE_ZBARCODE_GD 769 | zend_declare_class_constant_bool(php_zbarcode_sc_entry, "HAVE_GD", sizeof("HAVE_GD")-1, 1 TSRMLS_CC); 770 | #else 771 | zend_declare_class_constant_bool(php_zbarcode_sc_entry, "HAVE_GD", sizeof("HAVE_GD")-1, 0 TSRMLS_CC); 772 | #endif 773 | 774 | #define PHP_ZBARCODE_REGISTER_CONST_LONG(const_name, value) \ 775 | zend_declare_class_constant_long(php_zbarcode_sc_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC); 776 | 777 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_ENABLE", ZBAR_CFG_ENABLE); /**< enable symbology/feature */ 778 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_ADD_CHECK", ZBAR_CFG_ADD_CHECK); /**< enable check digit when optional */ 779 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_EMIT_CHECK", ZBAR_CFG_EMIT_CHECK); /**< return check digit when present */ 780 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_ASCII", ZBAR_CFG_ASCII); /**< enable full ASCII character set */ 781 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_NUM", ZBAR_CFG_NUM); /**< number of boolean decoder configs */ 782 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_MIN_LEN", ZBAR_CFG_MIN_LEN); /**< minimum data length for valid decode */ 783 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_MAX_LEN", ZBAR_CFG_MAX_LEN); /**< maximum data length for valid decode */ 784 | #ifdef HAVE_ZBAR_SYMBOL_GET_QUALITY 785 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_POSITION", ZBAR_CFG_POSITION); /**< enable scanner to collect position data */ 786 | #endif 787 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_X_DENSITY", ZBAR_CFG_X_DENSITY); /**< image scanner vertical scan density */ 788 | PHP_ZBARCODE_REGISTER_CONST_LONG("CFG_Y_DENSITY", ZBAR_CFG_Y_DENSITY); /**< image scanner horizontal scan density */ 789 | 790 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_ALL", 0); /**< all symbologies */ 791 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_NONE", ZBAR_NONE); /**< no symbol decoded */ 792 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_PARTIAL", ZBAR_PARTIAL); /**< intermediate status */ 793 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_EAN8", ZBAR_EAN8); /**< EAN-8 */ 794 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_UPCE", ZBAR_UPCE); /**< UPC-E */ 795 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_ISBN10", ZBAR_ISBN10); /**< ISBN-10 (from EAN-13).*/ 796 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_UPCA", ZBAR_UPCA); /**< UPC-A */ 797 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_EAN13", ZBAR_EAN13); /**< EAN-13 */ 798 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_ISBN13", ZBAR_ISBN13); /**< ISBN-13 (from EAN-13). */ 799 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_I25", ZBAR_I25); /**< Interleaved 2 of 5. */ 800 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_CODE39", ZBAR_CODE39); /**< Code 39. */ 801 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_PDF417", ZBAR_PDF417); /**< PDF417. */ 802 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_CODE128", ZBAR_CODE128); /**< Code 128 */ 803 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_SYMBOL", ZBAR_SYMBOL); /**< mask for base symbol type */ 804 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_ADDON2", ZBAR_ADDON2); /**< 2-digit add-on flag */ 805 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_ADDON5", ZBAR_ADDON5); /**< 5-digit add-on flag */ 806 | PHP_ZBARCODE_REGISTER_CONST_LONG("SYM_ADDON", ZBAR_ADDON); /**< add-on flag mask */ 807 | PHP_ZBARCODE_REGISTER_CONST_LONG("OPT_RESOLUTION", PHP_ZBARCODE_RESOLUTION); /**< Set higher resolution */ 808 | PHP_ZBARCODE_REGISTER_CONST_LONG("OPT_ENHANCE", PHP_ZBARCODE_ENHANCE); /**< Reduce noise */ 809 | PHP_ZBARCODE_REGISTER_CONST_LONG("OPT_SHARPEN", PHP_ZBARCODE_SHARPEN); /**< Sharpen */ 810 | 811 | #undef PHP_ZBARCODE_REGISTER_CONST_LONG 812 | 813 | return SUCCESS; 814 | } 815 | /* }}} */ 816 | 817 | /* {{{ PHP_MSHUTDOWN_FUNCTION(zbarcode) 818 | */ 819 | PHP_MSHUTDOWN_FUNCTION(zbarcode) 820 | { 821 | MagickWandTerminus(); 822 | return SUCCESS; 823 | } 824 | /* }}} */ 825 | 826 | /* {{{ PHP_MINFO_FUNCTION(zbarcode) 827 | */ 828 | PHP_MINFO_FUNCTION(zbarcode) 829 | { 830 | unsigned int major = 0, minor = 0, patch = 0; 831 | char *zbar_ver = NULL; 832 | unsigned long magick_version; 833 | 834 | zbar_version(&major, &minor, &patch); 835 | spprintf(&zbar_ver, 24, "%d.%d.%d", major, minor,patch); 836 | 837 | php_info_print_table_start(); 838 | php_info_print_table_row(2, "zbarcode module", "enabled"); 839 | php_info_print_table_row(2, "zbarcode module version", PHP_ZBARCODE_EXTVER); 840 | php_info_print_table_row(2, "ZBar library version", zbar_ver); 841 | php_info_print_table_row(2, "ImageMagick version", MagickGetVersion(&magick_version)); 842 | 843 | #ifdef HAVE_ZBARCODE_IMAGICK 844 | php_info_print_table_row(2, "Imagick support", "enabled"); 845 | #else 846 | php_info_print_table_row(2, "Imagick support", "disabled"); 847 | #endif 848 | 849 | #ifdef HAVE_ZBARCODE_GD 850 | php_info_print_table_row(2, "GD support", "enabled"); 851 | #else 852 | php_info_print_table_row(2, "GD support", "disabled"); 853 | #endif 854 | 855 | php_info_print_table_end(); 856 | efree(zbar_ver); 857 | } 858 | /* }}} */ 859 | 860 | static zend_function_entry php_zbarcode_functions[] = 861 | { 862 | { NULL, NULL, NULL } 863 | }; 864 | 865 | zend_module_entry zbarcode_module_entry = 866 | { 867 | #if ZEND_MODULE_API_NO >= 20010901 868 | STANDARD_MODULE_HEADER, 869 | #endif 870 | PHP_ZBARCODE_EXTNAME, 871 | php_zbarcode_functions, /* Functions */ 872 | PHP_MINIT(zbarcode), /* MINIT */ 873 | PHP_MSHUTDOWN(zbarcode), /* MSHUTDOWN */ 874 | NULL, /* RINIT */ 875 | NULL, /* RSHUTDOWN */ 876 | PHP_MINFO(zbarcode), /* MINFO */ 877 | #if ZEND_MODULE_API_NO >= 20010901 878 | PHP_ZBARCODE_EXTVER, 879 | #endif 880 | STANDARD_MODULE_PROPERTIES 881 | }; 882 | 883 | #ifdef COMPILE_DL_ZBARCODE 884 | ZEND_GET_MODULE(zbarcode) 885 | #endif --------------------------------------------------------------------------------