├── COPYING ├── Makefile ├── Makefile.avr ├── README ├── dofbit.c ├── ecctable.h ├── imageproc ├── Makefile ├── QuickFinderFinder.java ├── finder.c ├── hist.c └── quickie.c ├── lcd.c ├── qrbits.h ├── qrenc.c ├── qrencode.c ├── qrencode.h ├── qrframe.c ├── qrjpeg.c └── regtest.sh /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS:=-Wall -g -O6 2 | #CC=avr-gcc -mmcu=atmega328p 3 | CC=gcc 4 | 5 | all: qrencode qrjpeg 6 | 7 | qrjpeg: qrjpeg.o qrencode.o qrframe.o 8 | 9 | dofbit: dofbit.o qrframe.o 10 | 11 | qrencode: qrenc.o qrencode.o qrframe.o 12 | 13 | clean: 14 | rm -rf qrencode *.o qrjpeg dofbit 15 | 16 | realclean: clean 17 | rm -rf *~ \#* 18 | 19 | -------------------------------------------------------------------------------- /Makefile.avr: -------------------------------------------------------------------------------- 1 | HOSTGCC=gcc 2 | 3 | all: lcd.hex oled.hex qrjpeg.hex 4 | 5 | .SUFFIXES: .elf .hex .eep .lss .sym .upload .dsm 6 | 7 | #CPU=m328p 8 | CPU=atmega328p 9 | PORT=/dev/ttyUSB0 10 | 11 | XTAL=8000000 #Arduino 3.3v Pro 12 | CFLAGS=-g -DF_CPU=$(XTAL) -I ../uart -DTXBUFBITS=8 -DRXBUFBITS=8 -O 13 | 14 | .elf.dsm: 15 | avr-objdump --disassemble -S $^ >$@ 16 | 17 | .c.s: 18 | avr-gcc $(CFLAGS) -Wall -mmcu=$(CPU) -S $^ -o $@ 19 | 20 | MAP=-Wl,"-Map" -Wl,"$@.map" -Wl,"--cref" 21 | 22 | .c.o: 23 | avr-gcc $(CFLAGS) -Wall -mmcu=$(CPU) $< -o $@ -c 24 | 25 | .elf.hex: 26 | avr-objcopy -O ihex -R .eeprom $< $@ 27 | 28 | .hex.upload: 29 | avrdude -F -p $(CPU) -P $(PORT) -c arduino -b 57600 -U $^ 30 | 31 | lcd.elf: lcd.o qrencode.o qrv6l1.o #qrframe.o 32 | avr-gcc $(CFLAGS) -Wall -mmcu=$(CPU) $^ -o $@ 33 | 34 | oled.elf: oled.o qrencode.o qrv6l1.o #qrframe.o 35 | avr-gcc $(CFLAGS) -Wall -mmcu=$(CPU) $^ -o $@ $(MAP) 36 | 37 | qrjpeg.elf: qrjpeg.o qrencode.o qrframe.o 38 | avr-gcc $(CFLAGS) -Wall -mmcu=$(CPU) $^ -o $@ $(MAP) 39 | 40 | clean: 41 | rm -rf qrencode *.o *.elf dofbit qrv6l1.* *.map 42 | 43 | qrv6l1.c: dofbit 44 | ./dofbit 6 1 >qrv6l1.c 45 | 46 | dofbit: dofbit.c qrframe.c 47 | $(HOSTGCC) $^ -o $@ 48 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | EMBEDDED QR CODE GENERATOR 2 | 3 | Copyright 2010, tz@execpc.com. 4 | 5 | Relased under ther terms of the GNU General Public License v3. 6 | 7 | Targetd toward limited RAM systems - it tends to use more code and is slower but fits within an Arduino. 8 | 9 | For linux/posix, type make. For arduino, type make -f Makefile.avr. 10 | 11 | qrenc defaults to version 6, level L ecc, but you can specify the version, or the version and the error level. 12 | 13 | dofbits will generate a C file with the frame for one version/ecc level which will save a lot of RAM. This file will link with qrencode.c 14 | -------------------------------------------------------------------------------- /dofbit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern void initframe(void); 4 | extern void initecc(unsigned char, unsigned char); 5 | extern unsigned char neccblk1; 6 | extern unsigned char neccblk2 ; 7 | extern unsigned char datablkw; 8 | extern unsigned char eccblkwid; 9 | extern unsigned char VERSION; 10 | extern unsigned char ECCLEVEL; 11 | extern unsigned char WD, WDB; // filled in from verison by initframe 12 | extern unsigned char *framebase; 13 | extern unsigned char *framask; 14 | 15 | #ifndef __AVR__ 16 | #define PROGMEM 17 | #define memcpy_P memcpy 18 | #define __LPM(x) x 19 | #else 20 | #include 21 | #endif 22 | 23 | #include "ecctable.h" 24 | 25 | #include 26 | #include 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | unsigned char i, j, b; 31 | 32 | if( argc != 3 ) 33 | printf( "params: Version (1-40) ECC-level (1-4)" ); 34 | 35 | unsigned ecc = atoi(argv[2]); 36 | if( ecc < 1 || ecc > 4 ) 37 | return -1; 38 | unsigned char vers = atoi(argv[1]); 39 | if( vers > 40 ) 40 | return -1; 41 | 42 | initecc(ecc, vers); 43 | 44 | printf( "const unsigned char neccblk1 = %d;\n", neccblk1 ); 45 | printf( "const unsigned char neccblk2 = %d;\n", neccblk2 ); 46 | printf( "const unsigned char datablkw = %d;\n", datablkw ); 47 | printf( "const unsigned char eccblkwid = %d;\n", eccblkwid ); 48 | printf( "const unsigned char VERSION = %d;\n", VERSION ); 49 | printf( "const unsigned char ECCLEVEL = %d;\n", ECCLEVEL ); 50 | printf( "const unsigned char WD = %d;\n", WD ); 51 | printf( "const unsigned char WDB = %d;\n", WDB ); 52 | printf( "unsigned char strinbuf[%d];\n", WD*WDB );//(datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2 ); 53 | printf( "unsigned char qrframe[%d];\n", WD*WDB < 600? 600 : WD*WDB ); 54 | printf( "unsigned char rlens[%d];\n", WD+1 ); 55 | 56 | printf( "#ifndef __AVR__\n#define PROGMEM\n#define memcpy_P memcpy\n#define __LPM(x) *x\n#else\n" 57 | "#include \n#endif\nconst unsigned char framebase[] PROGMEM = {\n" ); 58 | 59 | initframe(); 60 | 61 | for (j = 0; j < WD; j++) { 62 | for (i = 0; i < WDB; i++) { 63 | b = framebase[j*WDB+i]; 64 | printf("0x%02x,", b ); 65 | } 66 | printf("\n"); 67 | } 68 | printf( "};\n\nconst unsigned char framask[] PROGMEM = {" ); 69 | unsigned tt, tri = WD*(WD+1)/2; 70 | tri = (tri+7)/8; 71 | for( tt = 0; tt < tri; tt++ ) { 72 | if( !(tt % WDB) ) 73 | printf("\n"); 74 | printf("0x%02x,", framask[tt] ); 75 | } 76 | printf( "\n};\n" ); 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /ecctable.h: -------------------------------------------------------------------------------- 1 | static const unsigned char eccblocks[] PROGMEM = { 2 | 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, 3 | 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28, 4 | 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, 5 | 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16, 6 | 1, 0,108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, 7 | 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, 8 | 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26, 9 | 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, 10 | 2, 0,116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24, 11 | 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, 12 | 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, 13 | 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28, 14 | 4, 0,107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, 15 | 3, 1,115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24, 16 | 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, 17 | 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3,13, 15, 30, 18 | 1, 5,107, 28, 10, 1, 46, 28, 1,15, 22, 28, 2,17, 14, 28, 19 | 5, 1,120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2,19, 14, 28, 20 | 3, 4,113, 28, 3,11, 44, 26, 17, 4, 21, 26, 9,16, 13, 26, 21 | 3, 5,107, 28, 3,13, 41, 26, 15, 5, 24, 30, 15,10, 15, 28, 22 | 4, 4,116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, 23 | 2, 7,111, 28, 17, 0, 46, 28, 7,16, 24, 30, 34, 0, 13, 24, 24 | 4, 5,121, 30, 4,14, 47, 28, 11,14, 24, 30, 16,14, 15, 30, 25 | 6, 4,117, 30, 6,14, 45, 28, 11,16, 24, 30, 30, 2, 16, 30, 26 | 8, 4,106, 26, 8,13, 47, 28, 7,22, 24, 30, 22,13, 15, 30, 27 | 10, 2,114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, 28 | 8, 4,122, 30, 22, 3, 45, 28, 8,26, 23, 30, 12,28, 15, 30, 29 | 3,10,117, 30, 3,23, 45, 28, 4,31, 24, 30, 11,31, 15, 30, 30 | 7, 7,116, 30, 21, 7, 45, 28, 1,37, 23, 30, 19,26, 15, 30, 31 | 5,10,115, 30, 19,10, 47, 28, 15,25, 24, 30, 23,25, 15, 30, 32 | 13, 3,115, 30, 2,29, 46, 28, 42, 1, 24, 30, 23,28, 15, 30, 33 | 17, 0,115, 30, 10,23, 46, 28, 10,35, 24, 30, 19,35, 15, 30, 34 | 17, 1,115, 30, 14,21, 46, 28, 29,19, 24, 30, 11,46, 15, 30, 35 | 13, 6,115, 30, 14,23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30, 36 | 12, 7,121, 30, 12,26, 47, 28, 39,14, 24, 30, 22,41, 15, 30, 37 | 6,14,121, 30, 6,34, 47, 28, 46,10, 24, 30, 2,64, 15, 30, 38 | 17, 4,122, 30, 29,14, 46, 28, 49,10, 24, 30, 24,46, 15, 30, 39 | 4,18,122, 30, 13,32, 46, 28, 48,14, 24, 30, 42,32, 15, 30, 40 | 20, 4,117, 30, 40, 7, 47, 28, 43,22, 24, 30, 10,67, 15, 30, 41 | 19, 6,118, 30, 18,31, 47, 28, 34,34, 24, 30, 20,61, 15, 30, 42 | }; 43 | -------------------------------------------------------------------------------- /imageproc/Makefile: -------------------------------------------------------------------------------- 1 | all: hist finder quickie 2 | 3 | CFLAGS = -g -O6 -Wall -U_FORTIFY_SOURCE 4 | 5 | clean: 6 | rm -f hist finder quickie -------------------------------------------------------------------------------- /imageproc/QuickFinderFinder.java: -------------------------------------------------------------------------------- 1 | // Copyright 2010, tz, released under the GNU General Public License v3. 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import java.awt.image.*; 6 | import java.io.*; 7 | import javax.imageio.*; 8 | import javax.swing.*; 9 | 10 | public class QuickFinderFinder extends Component { 11 | BufferedImage img; 12 | 13 | 14 | // line 7, 1 pixel per module would be a special case I don't handle 15 | int lasty; 16 | 17 | long ave; 18 | int modwidx8; 19 | int finds; 20 | 21 | int[] fx = new int[32]; 22 | int[] fy = new int[32]; 23 | int[] fw = new int[32]; 24 | int[] fh = new int[32]; 25 | 26 | int width, height; 27 | 28 | int getlum(int y, int x) { 29 | int argb = img.getRGB(x,y); 30 | argb = argb >> 8; 31 | argb = argb & 255; 32 | return argb; 33 | } 34 | 35 | int iabs(int a) 36 | { 37 | if (a < 0) 38 | return -a; 39 | return a; 40 | } 41 | 42 | int center(int x, int y, long lave) 43 | { 44 | // use u d l r 45 | int r, v, s; 46 | int fl, fr, ft, fb; 47 | int fl1, fr1, ft1, fb1; 48 | 49 | for (r = x - 1; r > 0; r--) 50 | if (getlum(y, r) > lave) 51 | break; 52 | s = r; 53 | for (; s > 0; s--) 54 | if (getlum(y, s) < lave) 55 | break; 56 | fl = r - s; 57 | for (; s > 0; s--) 58 | if (getlum(y, s) > lave) 59 | break; 60 | fl1 = r - s - fl; 61 | 62 | r++; 63 | for (v = x + 1; v < width; v++) 64 | if (getlum(y, v) > lave) 65 | break; 66 | s = v; 67 | for (; s < width; s++) 68 | if (getlum(y, s) < lave) 69 | break; 70 | fr = s - v; 71 | for (; s < width; s++) 72 | if (getlum(y, s) > lave) 73 | break; 74 | fr1 = s - v - fr; 75 | v--; 76 | x = (r + v) / 2; 77 | fx[finds] = x; 78 | fw[finds] = v - r; 79 | 80 | for (r = y - 1; r > 0; r--) 81 | if (getlum(r, x) > lave) 82 | break; 83 | s = r; 84 | for (; s > 0; s--) 85 | if (getlum(s, x) < lave) 86 | break; 87 | ft = r - s; 88 | for (; s > 0; s--) 89 | if (getlum(s, x) > lave) 90 | break; 91 | ft1 = r - s - ft; 92 | 93 | r++; 94 | for (v = y + 1; v < height; v++) 95 | if (getlum(v, x) > lave) 96 | break; 97 | s = v; 98 | for (; s < height; s++) 99 | if (getlum(s, x) < lave) 100 | break; 101 | fb = s - v; 102 | for (; s < height; s++) 103 | if (getlum(s, x) > lave) 104 | break; 105 | fb1 = s - v - fb; 106 | v--; 107 | y = (r + v) / 2; 108 | fy[finds] = y; 109 | fh[finds] = v - r; 110 | 111 | System.out.print("C"+finds+": "+fx[finds]+" "+fy[finds]+" "+fw[finds]+" "+fh[finds]); 112 | System.out.print(" "+fl+" "+fr+" "+ft+" "+fb); 113 | System.out.println(" "+fl1+" "+fr1+" "+ft1+" "+fb1); 114 | 115 | if (fw[finds] * 3 < fh[finds] * 2) 116 | return 0; 117 | if (fw[finds] * 2 > fh[finds] * 3) 118 | return 0; 119 | if (0 != modwidx8) { 120 | if (fw[finds] * 4 < modwidx8 || fw[finds] > modwidx8 / 2) 121 | return 0; 122 | if (fh[finds] * 4 < modwidx8 || fh[finds] > modwidx8 / 2) 123 | return 0; 124 | // for j==0 too could check lrtb for same width and trace out a square - already checked in scan direction but not perpindicular 125 | if (fl * 3 > modwidx8 || fr * 3 > modwidx8 || ft * 3 > modwidx8 || fb * 3 > modwidx8) 126 | return 0; 127 | if (fl1 * 3 > modwidx8 || fr1 * 3 > modwidx8 || ft1 * 3 > modwidx8 || fb1 * 3 > modwidx8) 128 | return 0; 129 | finds++; 130 | return 1; 131 | } 132 | 133 | v = fw[finds] + fh[finds] + (ft + fb + fl + fr) / 2; 134 | // thresholding unstable so maybe shut off 135 | if (fl * 3 > v || fr * 3 > v || ft * 3 > v || fb * 3 > v) 136 | return 0; 137 | if (fl1 * 3 > v || fr1 * 3 > v || ft1 * 3 > v || fb1 * 3 > v) 138 | return 0; 139 | modwidx8 = v; 140 | finds++; 141 | return 1; 142 | } 143 | 144 | int runs[] = new int[8]; 145 | 146 | int checkfinder() 147 | { 148 | int a, b, c, d, e, m; 149 | a = runs[1]; 150 | e = runs[5]; 151 | if (iabs(a - e) > (a + e + 1) / 4) 152 | return 0; 153 | b = runs[2]; 154 | d = runs[4]; 155 | if (iabs(b - d) > (b + d + 1) / 4) 156 | return 0; 157 | if ((a + e) * 2 < (b + d)) 158 | return 0; 159 | if ((b + d) * 2 < (a + e)) 160 | return 0; 161 | c = runs[3]; 162 | if (0 != modwidx8) { 163 | if (c * 10 < modwidx8 * 3) 164 | return 0; 165 | if (c * 6 > modwidx8 * 3) 166 | return 0; 167 | } 168 | m = a + e + (b + d + 1) / 2; 169 | if (iabs(c - m) > (c + m) / 4) 170 | return 0; 171 | return 1; 172 | } 173 | 174 | byte findit() 175 | { 176 | int x0, x, y, r, xx, mx; 177 | byte i, b, v; 178 | 179 | // 13 for 2 pixel min, do line 7 if simple 1 ppmod 180 | finds = 0; 181 | for (y = lasty; y < height || y < width; y += 2, lasty += 2) { 182 | x0 = 0; 183 | if (y >= height) // off bottom, don't count 184 | x0 = 1 + y - height; 185 | mx = y; 186 | if( y > width ) 187 | mx = width; 188 | // System.out.println(y+" "+ave+" "+mx+" "+x0); 189 | ave = 0; 190 | for (x = x0; x < mx ; x++) 191 | ave += getlum(y - x, x); 192 | ave = ave / (mx - x0); 193 | b = 0; r = 0; i = 0; 194 | // Note that we only need the current 5 runs, not a list 195 | runs[i] = 0; 196 | for (x = x0; x < mx; x++) { 197 | if( getlum(y - x, x) < ave ) 198 | v = 1; 199 | else 200 | v = 0; 201 | if (v == b) { 202 | r++; 203 | continue; 204 | } 205 | b = v; 206 | 207 | runs[i++] = r; 208 | runs[i] = 0; 209 | r = 1; 210 | if (i > 6) { 211 | for (v = 0; v < 6; v++) 212 | runs[v] = runs[v + 2]; 213 | i -= 2; 214 | } 215 | if (i < 6) 216 | continue; 217 | //System.out.println(runs[1]+" "+runs[2]+" "+runs[3]+" "+runs[4]+" "+runs[5]); 218 | if (0 == checkfinder()) 219 | continue; 220 | xx = x - runs[5] - runs[4] - (runs[3] / 2); 221 | center(xx, y - xx, ave); 222 | if (0 != modwidx8) 223 | return 1; 224 | } 225 | } 226 | return 0; 227 | } 228 | 229 | void findnexty(int x, int y) 230 | { 231 | byte b = 0; 232 | byte v; 233 | byte i = 0; 234 | int r = 0; 235 | long avey = ave * 64; 236 | runs[0] = 0; 237 | for (; y < height; y++) { 238 | avey += getlum(y, x); 239 | avey -= avey / 64; 240 | if( getlum(y, x) <= avey / 64 ) 241 | v = 1; 242 | else 243 | v = 0; 244 | 245 | if (v == b) { 246 | r++; 247 | if (y + 1 != height) 248 | continue; 249 | } 250 | b = v; 251 | runs[i++] = r; 252 | runs[i] = 0; 253 | r = 1; 254 | if (i > 6) { 255 | for (v = 0; v < 6; v++) 256 | runs[v] = runs[v + 2]; 257 | i -= 2; 258 | } 259 | if (i < 6) 260 | continue; 261 | if (runs[1] * 10 < modwidx8 || runs[1] * 6 > modwidx8) 262 | continue; 263 | if (0 == checkfinder()) 264 | continue; 265 | center(x, y - runs[5] - runs[4] - runs[3] / 2, avey / 64); 266 | } 267 | return; 268 | } 269 | 270 | void findnextx(int x, int y) 271 | { 272 | byte b = 0; 273 | byte v; 274 | byte i = 0; 275 | int r = 0; 276 | long avex = ave * 64; 277 | runs[0] = 0; 278 | for (; x < width; x++) { 279 | avex += getlum(y, x); 280 | avex -= avex / 64; 281 | if( getlum(y, x) <= avex / 64 ) 282 | v = 1; 283 | else 284 | v = 0; 285 | 286 | if (v == b) { 287 | r++; 288 | if (x + 1 != width) 289 | continue; 290 | } 291 | b = v; 292 | runs[i++] = r; 293 | runs[i] = 0; 294 | r = 1; 295 | if (i > 6) { 296 | for (v = 0; v < 6; v++) 297 | runs[v] = runs[v + 2]; 298 | i -= 2; 299 | } 300 | if (i < 6) 301 | continue; 302 | if (runs[1] * 10 < modwidx8 || runs[1] * 6 > modwidx8) 303 | continue; 304 | if (0 == checkfinder()) 305 | continue; 306 | center(x - runs[5] - runs[4] - (runs[3] / 2), y, avex / 64); 307 | } 308 | return; 309 | } 310 | 311 | int TEST(int x,int y) { return (x*y/modwidx8); } 312 | 313 | void findfinders() { 314 | 315 | width = img.getWidth(); 316 | height = img.getHeight(); 317 | 318 | for( lasty = 13; lasty < width || lasty < height; lasty += 2 ) { 319 | 320 | if (0 == findit()) 321 | return; 322 | findnexty(fx[0], fy[0]); 323 | findnextx(fx[0], fy[0]); 324 | 325 | // System.out.println("Found2:" + finds); 326 | int i,j; 327 | 328 | j = finds; 329 | i = 1; 330 | while (i < j) { 331 | findnexty(fx[i], fy[i]); 332 | findnextx(fx[i], fy[i]); 333 | i++; 334 | } 335 | 336 | i = j + 1; 337 | j = finds; 338 | while (i < j) { 339 | findnexty(fx[i], fy[i]); 340 | findnextx(fx[i], fy[i]); 341 | i++; 342 | } 343 | 344 | if (finds < 3) { 345 | // try harder, misalignment 346 | findnexty(fx[0] - fw[0] / 2, fy[0]); 347 | findnexty(fx[0] + fw[0] / 2, fy[0]); 348 | findnextx(fx[0], fy[0] - fh[0] / 2); 349 | findnextx(fx[0], fy[0] + fh[0] / 2); 350 | } 351 | 352 | for (i = 0; i < finds - 1; i++) 353 | for (j = i + 1; j < finds; j++) 354 | if (iabs(fx[i] - fx[j]) < modwidx8 / 2 && iabs(fy[i] - fy[j]) < modwidx8 / 2) { // coincident centers 355 | // fprintf(stderr, "DUP - %d,%d %d %d\n", fx[i], fy[i], fw[i], fh[i]); 356 | if (j < finds - 1) { 357 | fx[j] = fx[finds - 1]; 358 | fy[j] = fy[finds - 1]; 359 | fw[j] = fw[finds - 1]; 360 | fh[j] = fh[finds - 1]; 361 | j--; 362 | } 363 | finds--; 364 | } 365 | 366 | int besti = 1; 367 | int bestj = 2; 368 | int bestk = 0; 369 | if (finds > 2) { 370 | for (i = 1; i < finds - 1; i++) 371 | for (j = i + 1; j < finds; j++) { 372 | int k, m; 373 | // smallest side of largest rectangle 374 | 375 | k = TEST(iabs(fx[0] - fx[i]), iabs(fy[0] - fy[i])); 376 | m = TEST(iabs(fx[0] - fx[j]), iabs(fy[0] - fy[j])); 377 | if (m > k) 378 | k = m; 379 | m = TEST(iabs(fx[j] - fx[i]), iabs(fy[j] - fy[i])); 380 | if (m > k) 381 | k = m; 382 | if (k > bestk) { 383 | besti = i; 384 | bestj = j; 385 | bestk = k; 386 | } 387 | // fprintf(stderr, "A %d %d = %d\n", i, j, k); 388 | } 389 | } 390 | 391 | // pick most likely 3 392 | for (i = 0; i < finds; i++) { 393 | // fprintf(stderr, "%d : %d,%d %d %d\n", (i == 0 || i == besti || i == bestj), fx[i], fy[i], fw[i], fh[i]); 394 | System.out.println(i+":"+fx[i]+":"+fy[i]+":"+fw[i]+":"+fh[i]); 395 | if( finds > 2 && (i == 0 || i == besti || i == bestj) ) { 396 | 397 | // Mark Found Finder 398 | for (j = 0; j < fw[i]; j++) 399 | img.setRGB( fx[i] - fw[i] / 2 + j, fy[i], img.getRGB(fx[i] - fw[i] / 2 + j, fy[i]) | (255<<8) ); 400 | for (j = 0; j < fh[i]; j++) 401 | img.setRGB( fx[i], fy[i] - fh[i] / 2 + j, img.getRGB( fx[i], fy[i] - fh[i] / 2 + j) | (255<<8) ); 402 | } 403 | else { 404 | for (j = 0; j < 3; j++) 405 | img.setRGB( fx[i] - 1 + j, fy[i], img.getRGB( fx[i] - 1 + j, fy[i]) | (255<<16) ); 406 | for (j = 0; j < 3; j++) 407 | img.setRGB( fx[i], fy[i] - 1 + j, img.getRGB( fx[i], fy[i] - 1 + j) | (255<<16) ); 408 | } 409 | } 410 | 411 | // try harder at next diagonal 412 | if( finds > 2 ) 413 | break; 414 | } 415 | } 416 | 417 | //////////////////////////////////////////////////////////////////////// 418 | 419 | 420 | 421 | 422 | public void paint(Graphics g) { 423 | g.drawImage(img, 0, 0, null); 424 | } 425 | 426 | public QuickFinderFinder(String s) { 427 | try { 428 | img = ImageIO.read(new File(s)); 429 | findfinders(); 430 | } catch (IOException e) { 431 | } 432 | } 433 | public Dimension getPreferredSize() { 434 | if (img == null) 435 | return new Dimension(10,10); 436 | else 437 | return new Dimension(img.getWidth(null), img.getHeight(null)); 438 | } 439 | public static void main(String[] args) { 440 | JFrame f = new JFrame("Quick Finder Finder"); 441 | 442 | f.addWindowListener(new WindowAdapter(){ 443 | public void windowClosing(WindowEvent e) { 444 | System.exit(0); 445 | } 446 | }); 447 | f.add(new QuickFinderFinder(args[0])); 448 | f.pack(); 449 | f.setVisible(true); 450 | } 451 | } 452 | -------------------------------------------------------------------------------- /imageproc/finder.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned w, h; 4 | unsigned char f[4000][4000]; 5 | unsigned runs[4000]; 6 | unsigned iabs(int a) 7 | { 8 | if (a < 0) 9 | return -a; 10 | return a; 11 | } 12 | 13 | #if 0 14 | int despeckle(int max) 15 | { 16 | int x, y; 17 | 18 | for (x = 1; x < max - 1; x++) { 19 | if (runs[x] != 1) 20 | continue; 21 | if (runs[x - 1] == 1) 22 | continue; 23 | if (runs[x + 1] == 1) 24 | continue; 25 | runs[x - 1] += 1 + runs[x + 1]; 26 | max -= 2; 27 | for (y = x; y < max - 1; y++) 28 | runs[y] = runs[y + 2]; 29 | x--; 30 | } 31 | return max; 32 | } 33 | #endif 34 | 35 | int isfinder(int x) 36 | { 37 | int a, b, c, d, e, m; 38 | a = runs[x]; 39 | e = runs[x + 4]; 40 | if (iabs(a - e) > (a + e) / 4) 41 | return 0; 42 | b = runs[x + 1]; 43 | d = runs[x + 3]; 44 | if (iabs(b - d) > (b + d) / 4) 45 | return 0; 46 | c = runs[x + 2]; 47 | m = a + e + (b + d) / 2; 48 | if (iabs(c - m) > (c + m) / 4) 49 | return 0; 50 | #if 0 51 | m = runs[x - 1] + runs[x + 5]; // 4 module border 52 | if (m < c + b) 53 | return 2; 54 | #endif 55 | return 1; 56 | } 57 | 58 | void readimage() 59 | { 60 | char buf[512]; 61 | unsigned x, y; 62 | int cx; 63 | scanf("%2s", buf); 64 | scanf("%u %u", &w, &h); 65 | for (y = 0; y < h; y++) 66 | for (x = 0; x < w; x++) { 67 | for (;;) { 68 | cx = getchar(); 69 | if (cx < 0) 70 | break; 71 | if (cx == '1') { 72 | f[y][x] = 1; 73 | break; 74 | } 75 | if (cx == '0') { 76 | f[y][x] = 0; 77 | break; 78 | } 79 | } 80 | } 81 | } 82 | 83 | void horizontalruns() 84 | { 85 | unsigned x, y; 86 | unsigned r, b, i, m; 87 | // horizontal runs 88 | for (y = 0; y < h; y++) { 89 | b = 0, r = 0, i = 0; 90 | runs[i] = 0; 91 | for (x = 0; x < w; x++) { 92 | if ((1 & f[y][x]) == b) { 93 | r++; 94 | continue; 95 | } 96 | b = 1 & f[y][x]; 97 | runs[i++] = r; 98 | runs[i] = 0; 99 | r = 1; 100 | } 101 | runs[i++] = r; // last 102 | runs[i++] = 1; // edge 103 | if (i < 6) 104 | continue; 105 | #if 0 106 | i = despeckle(i); 107 | if (i < 6) 108 | continue; 109 | #endif 110 | r = 0; 111 | for (x = 1; x < i - 4; x += 2) { 112 | r += runs[x] + runs[x - 1]; 113 | if (!isfinder(x)) 114 | continue; 115 | m = runs[x + 2]; 116 | for (b = 0; b < m; b++) 117 | f[y][r + runs[x + 1] + b] |= 2; 118 | } 119 | } 120 | } 121 | 122 | void verticalruns() 123 | { 124 | unsigned x, y; 125 | unsigned r, b, i, m; 126 | // vertical runs 127 | for (y = 0; y < w; y++) { 128 | b = 0, r = 0, i = 0; 129 | runs[i] = 0; 130 | for (x = 0; x < h; x++) { 131 | if ((1 & f[x][y]) == b) { 132 | r++; 133 | continue; 134 | } 135 | b = 1 & f[x][y]; 136 | runs[i++] = r; 137 | runs[i] = 0; 138 | r = 1; 139 | } 140 | runs[i++] = r; 141 | runs[i++] = 1; 142 | if (i < 6) 143 | continue; 144 | #if 0 145 | i = despeckle(i); 146 | if (i < 6) 147 | continue; 148 | #endif 149 | r = 0; 150 | for (x = 1; x < i - 4; x += 2) { 151 | r += runs[x] + runs[x - 1]; 152 | if (!isfinder(x)) 153 | continue; 154 | m = runs[x + 2]; 155 | for (b = 0; b < m; b++) 156 | f[r + runs[x + 1] + b][y] |= 4; 157 | } 158 | } 159 | } 160 | 161 | void lrdilate() 162 | { 163 | unsigned x, y, b, c; 164 | for (y = 0; y < h; y++) 165 | for (x = 0; x < w - 1; x++) { 166 | if (y > 0 && f[y - 1][x] == 7) 167 | continue; 168 | if (f[y][x] == 7 && f[y][x + 1] & 1) { 169 | b = 0; 170 | c = 0; 171 | // find height and adjacent black 172 | while (f[y + b][x] == 7 && y + b < h) { 173 | if (f[y + b][x + 1] & 1) 174 | c++; 175 | b++; 176 | } 177 | // black adjacent? - despeckle 178 | if (c < b) 179 | continue; 180 | for (c = 0; c < b; c++) 181 | f[y + c][x + 1] |= 6; 182 | } 183 | } 184 | } 185 | 186 | void rldilate() 187 | { 188 | unsigned x, y, b, c; 189 | for (y = 0; y < h; y++) 190 | for (x = w; x > 1; x--) { 191 | if (y > 0 && f[y - 1][x] == 7) 192 | continue; 193 | if (f[y][x] == 7 && f[y][x - 1] & 1) { 194 | b = 0; 195 | c = 0; 196 | // find height and adjacent black 197 | while (f[y + b][x] == 7 && y + b < h) { 198 | if (f[y + b][x - 1] & 1) 199 | c++; 200 | b++; 201 | } 202 | // black adjacent? - despeckle 203 | if (c < b) 204 | continue; 205 | for (c = 0; c < b; c++) 206 | f[y + c][x - 1] |= 6; 207 | } 208 | } 209 | } 210 | 211 | void tbdilate() 212 | { 213 | unsigned x, y, b, c; 214 | for (y = 0; y < h - 1; y++) 215 | for (x = 0; x < w; x++) { 216 | if (x > 0 && f[y][x - 1] == 7) 217 | continue; 218 | if (f[y][x] == 7 && f[y + 1][x] & 1) { 219 | b = 0; 220 | c = 0; 221 | // find height and adjacent black 222 | while (f[y][x + b] == 7 && x + b < w) { 223 | if (f[y + 1][x + b] & 1) 224 | c++; 225 | b++; 226 | } 227 | // black adjacent? - despeckle 228 | if (c < b) 229 | continue; 230 | for (c = 0; c < b; c++) 231 | f[y + 1][x + c] |= 6; 232 | } 233 | } 234 | } 235 | 236 | void btdilate() 237 | { 238 | unsigned x, y, b, c; 239 | for (y = h; y > 1; y--) 240 | for (x = 0; x < w; x++) { 241 | if (x > 0 && f[y][x - 1] == 7) 242 | continue; 243 | if (f[y][x] == 7 && f[y - 1][x] & 1) { 244 | b = 0; 245 | c = 0; 246 | // find height and adjacent black 247 | while (f[y][x + b] == 7 && x + b < w) { 248 | if (f[y - 1][x + b] & 1) 249 | c++; 250 | b++; 251 | } 252 | // black adjacent? - despeckle 253 | if (c < b) 254 | continue; 255 | for (c = 0; c < b; c++) 256 | f[y - 1][x + c] |= 6; 257 | } 258 | } 259 | } 260 | 261 | int main() 262 | { 263 | readimage(); 264 | horizontalruns(); 265 | verticalruns(); 266 | 267 | lrdilate(); 268 | tbdilate(); 269 | rldilate(); 270 | btdilate(); 271 | 272 | unsigned x, y; 273 | printf("P2\n%u %u\n255\n", w, h); 274 | for (y = 0; y < h; y++) 275 | for (x = 0; x < w; x++) { 276 | #if 0 277 | printf("%d ", f[y][x]); 278 | continue; 279 | #endif 280 | if (f[y][x] == 7) 281 | printf("%d ", 255); 282 | else 283 | #if 0 284 | printf("%d ", (7 & f[y][x]) << 4); 285 | #else 286 | printf("%d ", 128 - ((1 & f[y][x]) << 6)); 287 | #endif 288 | } 289 | 290 | } 291 | -------------------------------------------------------------------------------- /imageproc/hist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | unsigned char f[4000][4000], g[4000][4000]; 5 | unsigned char hist[256]; 6 | unsigned w, h; 7 | 8 | unsigned iabs(int a) 9 | { 10 | if (a < 0) 11 | return -a; 12 | return a; 13 | } 14 | 15 | void hdynhist() 16 | { 17 | // moving histogram over lines 18 | int t, mn, mx, x, y; 19 | for (y = 0; y < h; y++) { 20 | memset(hist, 0, sizeof(hist)); 21 | // prime the pump 22 | for (x = 0; x < 64; x++) 23 | hist[f[y][x]]++; 24 | mn = 255; 25 | for (t = 0; mn == 255; t++) 26 | if (hist[t]) 27 | mn = t; 28 | mx = 0; 29 | for (t = 255; !mx; t--) 30 | if (hist[t]) 31 | mx = t; 32 | t = (mn + mx) / 2; 33 | 34 | for (x = 0; x < 32; x++) 35 | g[y][x] |= f[y][x] > t; 36 | 37 | for (x = 32; x < w - 32; x++) { 38 | t = f[y][x - 32]; 39 | hist[t]--; 40 | if (t == mn && !hist[t]) 41 | while (!hist[mn]) 42 | mn++; 43 | if (t == mx && !hist[t]) 44 | while (!hist[mx]) 45 | mx--; 46 | t = f[y][x + 32]; 47 | hist[t]++; 48 | if (t > mx) 49 | mx = t; 50 | if (t < mn) 51 | mn = t; 52 | 53 | t = (mn + mx) / 2; 54 | // try t = midpoint (where half are above, half are below) 55 | g[y][x] |= f[y][x] > t; 56 | } 57 | for (x = w - 32; x < w; x++) 58 | g[y][x] |= f[y][x] > t; 59 | } 60 | } 61 | 62 | void vdynhist() 63 | { 64 | // moving histogram over lines 65 | int t, mn, mx, x, y; 66 | // moving histogram over vertical lines 67 | for (y = 0; y < w; y++) { 68 | memset(hist, 0, sizeof(hist)); 69 | // prime the pump 70 | for (x = 0; x < 64; x++) 71 | hist[f[x][y]]++; 72 | mn = 255; 73 | for (t = 0; mn == 255; t++) 74 | if (hist[t]) 75 | mn = t; 76 | mx = 0; 77 | for (t = 255; !mx; t--) 78 | if (hist[t]) 79 | mx = t; 80 | t = (mn + mx) / 2; 81 | 82 | for (x = 0; x < 32; x++) 83 | g[x][y] |= f[x][y] > t; 84 | 85 | for (x = 32; x < h - 32; x++) { 86 | t = f[x - 32][y]; 87 | hist[t]--; 88 | if (t == mn && !hist[t]) 89 | while (!hist[mn]) 90 | mn++; 91 | if (t == mx && !hist[t]) 92 | while (!hist[mx]) 93 | mx--; 94 | t = f[x + 32][y]; 95 | hist[t]++; 96 | if (t > mx) 97 | mx = t; 98 | if (t < mn) 99 | mn = t; 100 | 101 | t = (mn + mx) / 2; 102 | g[x][y] |= f[x][y] > t; 103 | } 104 | for (x = h - 32; x < h; x++) 105 | g[x][y] |= f[x][y] > t; 106 | } 107 | } 108 | 109 | void readgray() 110 | { 111 | char buf[512]; 112 | unsigned x, y, m, s; 113 | scanf("%2s", buf); 114 | scanf("%u %u", &w, &h); 115 | scanf("%u", &s); 116 | for (y = 0; y < h; y++) 117 | for (x = 0; x < w; x++) { 118 | g[y][x] = 0; 119 | scanf("%u", &m); 120 | f[y][x] = m; 121 | } 122 | } 123 | 124 | main() 125 | { 126 | 127 | readgray(); 128 | 129 | hdynhist(); 130 | vdynhist(); 131 | 132 | unsigned x, y; 133 | printf("P1\n%u %u\n", w, h); 134 | for (y = 0; y < h; y++) 135 | for (x = 0; x < w; x++) 136 | printf("%u ", !(1 & g[y][x])); 137 | 138 | } 139 | -------------------------------------------------------------------------------- /imageproc/quickie.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // line 7, 1 pixel per module would be a special case I don't handle 5 | unsigned lasty; 6 | 7 | unsigned long ave; 8 | unsigned modwidx8; 9 | unsigned finds; 10 | #define MAXFINDS 16 11 | unsigned fx[MAXFINDS]; 12 | unsigned fy[MAXFINDS]; 13 | unsigned fh[MAXFINDS]; 14 | unsigned fw[MAXFINDS]; 15 | 16 | unsigned char *image; 17 | unsigned width, height; 18 | 19 | unsigned char getlum(unsigned y, unsigned x) { 20 | return image[ y * width + x ]; 21 | } 22 | 23 | unsigned iabs(int a) 24 | { 25 | if (a < 0) 26 | return -a; 27 | return a; 28 | } 29 | 30 | int center(unsigned x, unsigned y, unsigned lave) 31 | { 32 | // use u d l r 33 | unsigned r, v, s; 34 | unsigned fl, fr, ft, fb; 35 | unsigned fl1, fr1, ft1, fb1; 36 | 37 | for (r = x - 1; r > 0; r--) 38 | if (getlum(y, r) > lave) 39 | break; 40 | s = r; 41 | for (; s > 0; s--) 42 | if (getlum(y, s) < lave) 43 | break; 44 | fl = r - s; 45 | for (; s > 0; s--) 46 | if (getlum(y, s) > lave) 47 | break; 48 | fl1 = r - s - fl; 49 | 50 | r++; 51 | for (v = x + 1; v < width; v++) 52 | if (getlum(y, v) > lave) 53 | break; 54 | s = v; 55 | for (; s < width; s++) 56 | if (getlum(y, s) < lave) 57 | break; 58 | fr = s - v; 59 | for (; s < width; s++) 60 | if (getlum(y, s) > lave) 61 | break; 62 | fr1 = s - v - fr; 63 | v--; 64 | x = (r + v) / 2; 65 | fx[finds] = x; 66 | fw[finds] = v - r; 67 | 68 | for (r = y - 1; r > 0; r--) 69 | if (getlum(r, x) > lave) 70 | break; 71 | s = r; 72 | for (; s > 0; s--) 73 | if (getlum(s, x) < lave) 74 | break; 75 | ft = r - s; 76 | for (; s > 0; s--) 77 | if (getlum(s, x) > lave) 78 | break; 79 | ft1 = r - s - ft; 80 | 81 | r++; 82 | for (v = y + 1; v < height; v++) 83 | if (getlum(v, x) > lave) 84 | break; 85 | s = v; 86 | for (; s < height; s++) 87 | if (getlum(s, x) < lave) 88 | break; 89 | fb = s - v; 90 | for (; s < height; s++) 91 | if (getlum(s, x) > lave) 92 | break; 93 | fb1 = s - v - fb; 94 | v--; 95 | y = (r + v) / 2; 96 | fy[finds] = y; 97 | fh[finds] = v - r; 98 | 99 | #if 0 100 | fprintf(stderr, "C%d: %d,%d %d %d %d %d %d %d %d %d %d %d\n", finds, fx[finds], fy[finds], fw[finds], fh[finds], 101 | fl, fr, ft, fb, fl1, fr1, ft1, fb1); 102 | #endif 103 | if (fw[finds] * 3 < fh[finds] * 2) 104 | return 0; 105 | if (fw[finds] * 2 > fh[finds] * 3) 106 | return 0; 107 | if (modwidx8) { 108 | if (fw[finds] * 4 < modwidx8 || fw[finds] > modwidx8 / 2) 109 | return 0; 110 | if (fh[finds] * 4 < modwidx8 || fh[finds] > modwidx8 / 2) 111 | return 0; 112 | // for j==0 too could check lrtb for same width and trace out a square - already checked in scan direction but not perpindicular 113 | if (fl * 3 > modwidx8 || fr * 3 > modwidx8 || ft * 3 > modwidx8 || fb * 3 > modwidx8) 114 | return 0; 115 | if (fl1 * 3 > modwidx8 || fr1 * 3 > modwidx8 || ft1 * 3 > modwidx8 || fb1 * 3 > modwidx8) 116 | return 0; 117 | finds++; 118 | return 1; 119 | } 120 | 121 | v = fw[finds] + fh[finds] + (ft + fb + fl + fr) / 2; 122 | // thresholding unstable so maybe shut off 123 | #if 1 124 | if (fl * 3 > v || fr * 3 > v || ft * 3 > v || fb * 3 > v) 125 | return 0; 126 | if (fl1 * 3 > v || fr1 * 3 > v || ft1 * 3 > v || fb1 * 3 > v) 127 | return 0; 128 | #endif 129 | modwidx8 = v; 130 | finds++; 131 | return 1; 132 | } 133 | 134 | unsigned runs[8]; 135 | 136 | int checkfinder() 137 | { 138 | int a, b, c, d, e, m; 139 | a = runs[1]; 140 | e = runs[5]; 141 | if (iabs(a - e) > (a + e + 1) / 4) 142 | return 0; 143 | b = runs[2]; 144 | d = runs[4]; 145 | if (iabs(b - d) > (b + d + 1) / 4) 146 | return 0; 147 | if ((a + e) * 2 < (b + d)) 148 | return 0; 149 | if ((b + d) * 2 < (a + e)) 150 | return 0; 151 | c = runs[3]; 152 | if (modwidx8) { 153 | #if 0 154 | fprintf( stderr, "r %d - %d %d %d %d %d , %d\n", 155 | finds, runs[1],runs[2],runs[3],runs[4],runs[5], modwidx8 ); 156 | #endif 157 | if (c * 10 < modwidx8 * 3) 158 | return 0; 159 | if (c * 6 > modwidx8 * 3) 160 | return 0; 161 | } 162 | m = a + e + (b + d + 1) / 2; 163 | if (iabs(c - m) > (c + m) / 4) 164 | return 0; 165 | return 1; 166 | } 167 | 168 | unsigned char findit() 169 | { 170 | unsigned x0, x, y, r, xx, mx; 171 | unsigned char i, b, v; 172 | 173 | // 13 for 2 pixel min, do line 7 if simple 1 ppmod 174 | finds = 0; 175 | for (y = lasty; y < height || y < width; y += 2, lasty += 2) { 176 | x0 = 0; 177 | if (y >= height) // off bottom, don't count 178 | x0 = 1 + y - height; 179 | mx = y; 180 | if( y > width ) 181 | mx = width; 182 | ave = 0; 183 | for (x = x0; x < mx ; x++) 184 | ave += getlum(y - x, x); 185 | ave /= mx - x0; 186 | b = 0; r = 0; i = 0; 187 | // Note that we only need the current 5 runs, not a list 188 | runs[i] = 0; 189 | for (x = x0; x < mx; x++) { 190 | v = getlum(y - x, x) < ave; 191 | if (v == b) { 192 | r++; 193 | continue; 194 | } 195 | b = v; 196 | runs[i++] = r; 197 | runs[i] = 0; 198 | r = 1; 199 | if (i > 6) { 200 | for (v = 0; v < 6; v++) 201 | runs[v] = runs[v + 2]; 202 | i -= 2; 203 | } 204 | if (i < 6) 205 | continue; 206 | if (!checkfinder()) 207 | continue; 208 | xx = x - runs[5] - runs[4] - (runs[3] / 2); 209 | center(xx, y - xx, ave); 210 | if (modwidx8) 211 | return 1; 212 | } 213 | } 214 | return 0; 215 | } 216 | 217 | void findnexty(unsigned x, unsigned y) 218 | { 219 | unsigned char b = 0, v, i = 0; 220 | unsigned r = 0; 221 | unsigned avey = ave * 64; 222 | runs[0] = 0; 223 | for (; y < height; y++) { 224 | avey += getlum(y, x); 225 | avey -= avey / 64; 226 | v = getlum(y, x) <= avey / 64; 227 | if (v == b) { 228 | r++; 229 | if (y + 1 != height) 230 | continue; 231 | } 232 | b = v; 233 | runs[i++] = r; 234 | runs[i] = 0; 235 | r = 1; 236 | if (i > 6) { 237 | for (v = 0; v < 6; v++) 238 | runs[v] = runs[v + 2]; 239 | i -= 2; 240 | } 241 | if (i < 6) 242 | continue; 243 | if (runs[1] * 10 < modwidx8 || runs[1] * 6 > modwidx8) 244 | continue; 245 | if (!checkfinder()) 246 | continue; 247 | center(x, y - runs[5] - runs[4] - runs[3] / 2, avey / 64); 248 | } 249 | return; 250 | } 251 | 252 | void findnextx(unsigned x, unsigned y) 253 | { 254 | unsigned char b = 0, v, i = 0; 255 | unsigned r = 0; 256 | unsigned avex = ave * 64; 257 | runs[0] = 0; 258 | for (; x < width; x++) { 259 | avex += getlum(y, x); 260 | avex -= avex / 64; 261 | v = getlum(y, x) <= avex / 64; 262 | if (v == b) { 263 | r++; 264 | if (x + 1 != width) 265 | continue; 266 | } 267 | b = v; 268 | runs[i++] = r; 269 | runs[i] = 0; 270 | r = 1; 271 | if (i > 6) { 272 | for (v = 0; v < 6; v++) 273 | runs[v] = runs[v + 2]; 274 | i -= 2; 275 | } 276 | if (i < 6) 277 | continue; 278 | if (runs[1] * 10 < modwidx8 || runs[1] * 6 > modwidx8) 279 | continue; 280 | if (!checkfinder()) 281 | continue; 282 | center(x - runs[5] - runs[4] - (runs[3] / 2), y, avex / 64); 283 | } 284 | return; 285 | } 286 | 287 | void readgray() 288 | { 289 | char buf[8]; 290 | unsigned x, y, m, s; 291 | scanf("%2s", buf); 292 | scanf("%u %u", &width, &height); 293 | scanf("%u", &s); 294 | image = malloc(width*height); 295 | for (y = 0; y < height; y++) 296 | for (x = 0; x < width; x++) { 297 | scanf("%u", &m); 298 | image[y*width+x] = m * 255 / s; 299 | } 300 | } 301 | 302 | int main(int argc, char *argv[]) 303 | { 304 | int i, j; 305 | readgray(); 306 | 307 | // For true quickie, the || should be && here and in findit since the finder should be in the UL corner 308 | for (lasty = 13; lasty < width || lasty < height ; lasty += 2) { 309 | modwidx8 = 0; 310 | if (!findit()) 311 | return 1; 312 | 313 | findnexty(fx[0], fy[0]); 314 | findnextx(fx[0], fy[0]); 315 | 316 | j = finds; 317 | i = 1; 318 | while (i < j) { 319 | findnexty(fx[i], fy[i]); 320 | findnextx(fx[i], fy[i]); 321 | i++; 322 | } 323 | 324 | i = j + 1; 325 | j = finds; 326 | while (i < j) { 327 | findnexty(fx[i], fy[i]); 328 | findnextx(fx[i], fy[i]); 329 | i++; 330 | } 331 | 332 | if (finds < 3) { 333 | // try harder, misalignment 334 | findnexty(fx[0] - fw[0] / 2, fy[0]); 335 | findnexty(fx[0] + fw[0] / 2, fy[0]); 336 | findnextx(fx[0], fy[0] - fh[0] / 2); 337 | findnextx(fx[0], fy[0] + fh[0] / 2); 338 | } 339 | 340 | for (i = 0; i < finds - 1; i++) 341 | for (j = i + 1; j < finds; j++) 342 | if (iabs(fx[i] - fx[j]) < modwidx8 / 2 343 | && iabs(fy[i] - fy[j]) < modwidx8 / 2) { // coincident centers 344 | // fprintf(stderr, "DUP - %d,%d %d %d\n", fx[i], fy[i], fw[i], fh[i]); 345 | if (j < finds - 1) { 346 | fx[j] = fx[finds - 1]; 347 | fy[j] = fy[finds - 1]; 348 | fw[j] = fw[finds - 1]; 349 | fh[j] = fh[finds - 1]; 350 | j--; 351 | } 352 | finds--; 353 | } 354 | 355 | int besti = 1; 356 | int bestj = 2; 357 | int bestk = 0; 358 | if (finds > 2) { 359 | for (i = 1; i < finds - 1; i++) 360 | for (j = i + 1; j < finds; j++) { 361 | int k, m; 362 | // smallest side of largest rectangle 363 | #define TEST(x,y) (x*y) 364 | k = TEST(iabs(fx[0] - fx[i]), iabs(fy[0] - fy[i])); 365 | m = TEST(iabs(fx[0] - fx[j]), iabs(fy[0] - fy[j])); 366 | if (m > k) 367 | k = m; 368 | m = TEST(iabs(fx[j] - fx[i]), iabs(fy[j] - fy[i])); 369 | if (m > k) 370 | k = m; 371 | if (k > bestk) { 372 | besti = i; 373 | bestj = j; 374 | bestk = k; 375 | } 376 | fprintf(stderr, "A %d %d = %d\n", i, j, k); 377 | } 378 | } 379 | 380 | // pick most likely 3 381 | for (i = 0; i < finds; i++) { 382 | fprintf(stderr, "%d : %d,%d %d %d\n", (i == 0 || i == besti || i == bestj), fx[i], fy[i], fw[i], fh[i]); 383 | if( i && finds < 3 ) 384 | continue; 385 | if( finds > 2 && (i == 0 || i == besti || i == bestj) ) { 386 | for (j = 0; j < fw[i]; j++) 387 | image[fy[i] * width + fx[i] - fw[i] / 2 + j] = 255; 388 | for (j = 0; j < fh[i]; j++) 389 | image[(fy[i] - fh[i] / 2 + j) * width + fx[i]] = 255; 390 | } 391 | else { 392 | for (j = 0; j < 3; j++) 393 | image[fy[i] * width + fx[i] - 1 + j] = 255; 394 | for (j = 0; j < 3; j++) 395 | image[(fy[i] - 1 + j) * width + fx[i]] = 255; 396 | } 397 | } 398 | fprintf(stderr, "\n"); 399 | 400 | // try harder at next diagonal 401 | if (finds > 2) 402 | break; 403 | } 404 | 405 | printf("P2\n%u %u\n255\n", width, height); 406 | for (j = 0; j < height; j++) 407 | for (i = 0; i < width; i++) 408 | printf("%u ", getlum(j, i)); 409 | 410 | return 0; 411 | } 412 | -------------------------------------------------------------------------------- /lcd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void LcdWrite(unsigned char dc, unsigned char data) 4 | { 5 | int i; 6 | if( dc ) 7 | PORTD |= 0x20; 8 | else 9 | PORTD &= ~0x20; 10 | PORTD &= ~0x80; 11 | for( i = 0 ; i < 8 ; i++ ) { 12 | if( (data >> (7 - i)) & 1 ) 13 | PORTD |= 16; 14 | else 15 | PORTD &= ~16; 16 | PORTD |= 8; 17 | PORTD &= ~8; 18 | } 19 | PORTD |= 0x80; 20 | PORTB ^= 0x20; 21 | } 22 | 23 | #include "qrencode.h" 24 | 25 | #include 26 | int main() 27 | { 28 | DDRB |= 0x20; 29 | PORTB |= 0xf8; 30 | 31 | DDRD |= 0xf8; 32 | PORTD &= ~8; 33 | PORTD &= ~0x40; 34 | PORTD |= 0x40; 35 | unsigned char b = 0x55; 36 | unsigned i, k, t; 37 | LcdWrite(0, 0x22); 38 | LcdWrite(0, 0x0C); 39 | for ( k = 0; k < 84 ; k++, b ^= 0xff ) 40 | for ( i = 0; i < 6 ; i++) 41 | LcdWrite(1, b); 42 | 43 | strcpy((char *)strinbuf, "http://harleyhacking.blogspot.com"); 44 | qrencode(); 45 | 46 | 47 | LcdWrite(0, 0x22); 48 | LcdWrite(0, 0x0C); 49 | for ( k = 0; k < 84 ; k++ ) 50 | for ( i = 0; i < 6 ; i++) 51 | LcdWrite(1, 0); 52 | 53 | PORTB &= ~0x20; 54 | t = 0; 55 | b = 0; 56 | for ( k = 0; k < 84 ; k++) { 57 | for ( i = 0; i < 48 ; i++) { 58 | b >>= 1; 59 | if( i < WD && k < WD ) 60 | if( QRBIT(WD-i-1,k) ) 61 | b |= 0x80; 62 | if( ++t > 7 ) { 63 | t = 0; 64 | LcdWrite(1, b); 65 | b = 0; 66 | } 67 | } 68 | } 69 | for(;;); 70 | } 71 | -------------------------------------------------------------------------------- /qrbits.h: -------------------------------------------------------------------------------- 1 | #define QRBIT(x,y) ( ( qrframe[((x)>>3) + (y) * WDB] >> (7-((x) & 7 ))) & 1 ) 2 | #define SETQRBIT(x,y) qrframe[((x)>>3) + (y) * WDB] |= 0x80 >> ((x) & 7) 3 | #define TOGQRBIT(x,y) qrframe[((x)>>3) + (y) * WDB] ^= 0x80 >> ((x) & 7) 4 | -------------------------------------------------------------------------------- /qrenc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "qrencode.h" 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int x, y; 10 | int ret; 11 | 12 | x = 1; 13 | if( argc > 2 ) 14 | x = atoi(argv[2]); 15 | y = 6; 16 | if( argc > 1 ) 17 | y = atoi(argv[1]); 18 | 19 | y = initecc(x,y); 20 | // if size is known, pick frame, 21 | //iiteccsize( ecc, strlen(s) ); 22 | 23 | ret = fread(strinbuf, 1, y, stdin); 24 | strinbuf[ret] = '\0'; 25 | 26 | initframe(); 27 | qrencode(); 28 | 29 | 30 | /* data */ 31 | #ifdef PAD 32 | printf("P1\n%d %d\n", WD + 8, WD + 8); 33 | for (y = 0; y < 4; y++) { 34 | for (x = 0; x < WD + 8; x++) 35 | printf("0 "); 36 | printf("\n"); 37 | } 38 | #else 39 | printf("P1\n%d %d\n", WD, WD); 40 | #endif 41 | for (y = 0; y < WD; y++) { 42 | #ifdef PAD 43 | for (x = 0; x < 4; x++) 44 | printf("0 "); 45 | #endif 46 | for (x = 0; x < WD; x++) 47 | printf("%d ", QRBIT(x,y) ); 48 | #ifdef PAD 49 | for (x = 0; x < 4; x++) 50 | printf("0 "); 51 | #endif 52 | printf("\n"); 53 | } 54 | #ifdef PAD 55 | for (y = 0; y < 4; y++) { 56 | for (x = 0; x < WD + 8; x++) 57 | printf("0 "); 58 | printf("\n"); 59 | } 60 | #endif 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /qrencode.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qrencode.h" 4 | 5 | extern unsigned char neccblk1; 6 | extern unsigned char neccblk2; 7 | extern unsigned char datablkw; 8 | extern unsigned char eccblkwid; 9 | extern unsigned char VERSION; 10 | extern unsigned char ECCLEVEL; 11 | extern unsigned char WD, WDB; 12 | #ifndef USEPRECALC 13 | // These are malloced by initframe 14 | extern unsigned char *rlens; 15 | extern unsigned char *framebase; 16 | extern unsigned char *framask; 17 | #else 18 | extern unsigned char rlens[]; 19 | extern unsigned char framebase[] PROGMEM; 20 | extern unsigned char framask[] PROGMEM; 21 | #endif 22 | 23 | //======================================================================== 24 | // Reed Solomon error correction 25 | static unsigned modnn(unsigned x) 26 | { 27 | while (x >= 255) { 28 | x -= 255; 29 | x = (x >> 8) + (x & 255); 30 | } 31 | return x; 32 | } 33 | 34 | #ifndef RTGENEXPLOG 35 | static const unsigned char g0log[256] PROGMEM = { 36 | 0xff,0x00,0x01,0x19,0x02,0x32,0x1a,0xc6,0x03,0xdf,0x33,0xee,0x1b,0x68,0xc7,0x4b, 37 | 0x04,0x64,0xe0,0x0e,0x34,0x8d,0xef,0x81,0x1c,0xc1,0x69,0xf8,0xc8,0x08,0x4c,0x71, 38 | 0x05,0x8a,0x65,0x2f,0xe1,0x24,0x0f,0x21,0x35,0x93,0x8e,0xda,0xf0,0x12,0x82,0x45, 39 | 0x1d,0xb5,0xc2,0x7d,0x6a,0x27,0xf9,0xb9,0xc9,0x9a,0x09,0x78,0x4d,0xe4,0x72,0xa6, 40 | 0x06,0xbf,0x8b,0x62,0x66,0xdd,0x30,0xfd,0xe2,0x98,0x25,0xb3,0x10,0x91,0x22,0x88, 41 | 0x36,0xd0,0x94,0xce,0x8f,0x96,0xdb,0xbd,0xf1,0xd2,0x13,0x5c,0x83,0x38,0x46,0x40, 42 | 0x1e,0x42,0xb6,0xa3,0xc3,0x48,0x7e,0x6e,0x6b,0x3a,0x28,0x54,0xfa,0x85,0xba,0x3d, 43 | 0xca,0x5e,0x9b,0x9f,0x0a,0x15,0x79,0x2b,0x4e,0xd4,0xe5,0xac,0x73,0xf3,0xa7,0x57, 44 | 0x07,0x70,0xc0,0xf7,0x8c,0x80,0x63,0x0d,0x67,0x4a,0xde,0xed,0x31,0xc5,0xfe,0x18, 45 | 0xe3,0xa5,0x99,0x77,0x26,0xb8,0xb4,0x7c,0x11,0x44,0x92,0xd9,0x23,0x20,0x89,0x2e, 46 | 0x37,0x3f,0xd1,0x5b,0x95,0xbc,0xcf,0xcd,0x90,0x87,0x97,0xb2,0xdc,0xfc,0xbe,0x61, 47 | 0xf2,0x56,0xd3,0xab,0x14,0x2a,0x5d,0x9e,0x84,0x3c,0x39,0x53,0x47,0x6d,0x41,0xa2, 48 | 0x1f,0x2d,0x43,0xd8,0xb7,0x7b,0xa4,0x76,0xc4,0x17,0x49,0xec,0x7f,0x0c,0x6f,0xf6, 49 | 0x6c,0xa1,0x3b,0x52,0x29,0x9d,0x55,0xaa,0xfb,0x60,0x86,0xb1,0xbb,0xcc,0x3e,0x5a, 50 | 0xcb,0x59,0x5f,0xb0,0x9c,0xa9,0xa0,0x51,0x0b,0xf5,0x16,0xeb,0x7a,0x75,0x2c,0xd7, 51 | 0x4f,0xae,0xd5,0xe9,0xe6,0xe7,0xad,0xe8,0x74,0xd6,0xf4,0xea,0xa8,0x50,0x58,0xaf, 52 | }; 53 | 54 | static const unsigned char g0exp[256] PROGMEM = { 55 | 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1d,0x3a,0x74,0xe8,0xcd,0x87,0x13,0x26, 56 | 0x4c,0x98,0x2d,0x5a,0xb4,0x75,0xea,0xc9,0x8f,0x03,0x06,0x0c,0x18,0x30,0x60,0xc0, 57 | 0x9d,0x27,0x4e,0x9c,0x25,0x4a,0x94,0x35,0x6a,0xd4,0xb5,0x77,0xee,0xc1,0x9f,0x23, 58 | 0x46,0x8c,0x05,0x0a,0x14,0x28,0x50,0xa0,0x5d,0xba,0x69,0xd2,0xb9,0x6f,0xde,0xa1, 59 | 0x5f,0xbe,0x61,0xc2,0x99,0x2f,0x5e,0xbc,0x65,0xca,0x89,0x0f,0x1e,0x3c,0x78,0xf0, 60 | 0xfd,0xe7,0xd3,0xbb,0x6b,0xd6,0xb1,0x7f,0xfe,0xe1,0xdf,0xa3,0x5b,0xb6,0x71,0xe2, 61 | 0xd9,0xaf,0x43,0x86,0x11,0x22,0x44,0x88,0x0d,0x1a,0x34,0x68,0xd0,0xbd,0x67,0xce, 62 | 0x81,0x1f,0x3e,0x7c,0xf8,0xed,0xc7,0x93,0x3b,0x76,0xec,0xc5,0x97,0x33,0x66,0xcc, 63 | 0x85,0x17,0x2e,0x5c,0xb8,0x6d,0xda,0xa9,0x4f,0x9e,0x21,0x42,0x84,0x15,0x2a,0x54, 64 | 0xa8,0x4d,0x9a,0x29,0x52,0xa4,0x55,0xaa,0x49,0x92,0x39,0x72,0xe4,0xd5,0xb7,0x73, 65 | 0xe6,0xd1,0xbf,0x63,0xc6,0x91,0x3f,0x7e,0xfc,0xe5,0xd7,0xb3,0x7b,0xf6,0xf1,0xff, 66 | 0xe3,0xdb,0xab,0x4b,0x96,0x31,0x62,0xc4,0x95,0x37,0x6e,0xdc,0xa5,0x57,0xae,0x41, 67 | 0x82,0x19,0x32,0x64,0xc8,0x8d,0x07,0x0e,0x1c,0x38,0x70,0xe0,0xdd,0xa7,0x53,0xa6, 68 | 0x51,0xa2,0x59,0xb2,0x79,0xf2,0xf9,0xef,0xc3,0x9b,0x2b,0x56,0xac,0x45,0x8a,0x09, 69 | 0x12,0x24,0x48,0x90,0x3d,0x7a,0xf4,0xf5,0xf7,0xf3,0xfb,0xeb,0xcb,0x8b,0x0b,0x16, 70 | 0x2c,0x58,0xb0,0x7d,0xfa,0xe9,0xcf,0x83,0x1b,0x36,0x6c,0xd8,0xad,0x47,0x8e,0x00, 71 | }; 72 | #define glog(x) __LPM(&g0log[x]) 73 | #define gexp(x) __LPM(&g0exp[x]) 74 | 75 | #else // generate the log and exp tables - some CPU, much less flash, +512 bytes ram which can be shared 76 | 77 | unsigned char g0log[256],g0exp[256]; 78 | #define glog(x) (g0log[x]) 79 | #define gexp(x) (g0exp[x]) 80 | static void gentables() { 81 | #define GFPOLY (0x11d) 82 | unsigned char i,j; 83 | g0log[0] = 255; 84 | g0exp[255] = 0; 85 | j = 1; 86 | for (i = 0; i < 255; i++) { 87 | g0log[j] = i; 88 | g0exp[i] = j; 89 | j <<= 1; 90 | if (j & 256) 91 | j ^= GFPOLY; 92 | j &= 255; 93 | } 94 | } 95 | #endif 96 | 97 | static void initrspoly(unsigned char eclen, unsigned char *genpoly) 98 | { 99 | unsigned char i, j; 100 | 101 | #ifdef RTGENEXPLOG 102 | gentables(); 103 | #endif 104 | 105 | genpoly[0] = 1; 106 | for (i = 0; i < eclen; i++) { 107 | genpoly[i + 1] = 1; 108 | for (j = i; j > 0; j--) 109 | genpoly[j] = genpoly[j] 110 | ? genpoly[j - 1] ^ gexp(modnn(glog(genpoly[j]) + i)) : genpoly[j - 1]; 111 | genpoly[0] = gexp(modnn(glog(genpoly[0]) + i)); 112 | } 113 | for (i = 0; i <= eclen; i++) 114 | genpoly[i] = glog(genpoly[i]); // use logs for genpoly[] 115 | } 116 | 117 | static void appendrs(unsigned char *data, unsigned char dlen, 118 | unsigned char *ecbuf, unsigned char eclen, unsigned char *genpoly) 119 | { 120 | unsigned char i, j, fb; 121 | 122 | memset(ecbuf, 0, eclen); 123 | for (i = 0; i < dlen; i++) { 124 | fb = glog(data[i] ^ ecbuf[0]); 125 | if (fb != 255) /* fb term is non-zero */ 126 | for (j = 1; j < eclen; j++) 127 | ecbuf[j-1] = ecbuf[j] ^ gexp(modnn(fb + genpoly[eclen - j])); 128 | else 129 | memmove(ecbuf, ecbuf + 1, eclen - 1); 130 | ecbuf[eclen - 1] = fb == 255 ? 0 : gexp(modnn(fb + genpoly[0])); 131 | } 132 | } 133 | 134 | //======================================================================== 135 | // 8 bit data to QR-coded 8 bit data 136 | static void stringtoqr(void) 137 | { 138 | unsigned i; 139 | unsigned size, max; 140 | size = strlen((char *) strinbuf); 141 | 142 | max = datablkw * (neccblk1 + neccblk2) + neccblk2; 143 | if (size >= max - 2) { 144 | size = max - 2; 145 | if (VERSION > 9) 146 | size--; 147 | } 148 | 149 | i = size; 150 | if (VERSION > 9) { 151 | strinbuf[i + 2] = 0; 152 | while (i--) { 153 | strinbuf[i + 3] |= strinbuf[i] << 4; 154 | strinbuf[i + 2] = strinbuf[i] >> 4; 155 | } 156 | strinbuf[2] |= size << 4; 157 | strinbuf[1] = size >> 4; 158 | strinbuf[0] = 0x40 | (size >> 12); 159 | } else { 160 | strinbuf[i + 1] = 0; 161 | while (i--) { 162 | strinbuf[i + 2] |= strinbuf[i] << 4; 163 | strinbuf[i + 1] = strinbuf[i] >> 4; 164 | } 165 | strinbuf[1] |= size << 4; 166 | strinbuf[0] = 0x40 | (size >> 4); 167 | } 168 | i = size + 3 - (VERSION < 10); 169 | while (i < max) { 170 | strinbuf[i++] = 0xec; 171 | // buffer has room if (i == max) break; 172 | strinbuf[i++] = 0x11; 173 | } 174 | 175 | // calculate and append ECC 176 | unsigned char *ecc = &strinbuf[max]; 177 | unsigned char *dat = strinbuf; 178 | initrspoly(eccblkwid,qrframe); 179 | 180 | for (i = 0; i < neccblk1; i++) { 181 | appendrs(dat, datablkw, ecc, eccblkwid, qrframe); 182 | dat += datablkw; 183 | ecc += eccblkwid; 184 | } 185 | for (i = 0; i < neccblk2; i++) { 186 | appendrs(dat, datablkw + 1, ecc, eccblkwid, qrframe); 187 | dat += datablkw + 1; 188 | ecc += eccblkwid; 189 | } 190 | unsigned j; 191 | dat = qrframe; 192 | for (i = 0; i < datablkw; i++) { 193 | for (j = 0; j < neccblk1; j++) 194 | *dat++ = strinbuf[i + j * datablkw]; 195 | for (j = 0; j < neccblk2; j++) 196 | *dat++ = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))]; 197 | } 198 | for (j = 0; j < neccblk2; j++) 199 | *dat++ = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))]; 200 | for (i = 0; i < eccblkwid; i++) 201 | for (j = 0; j < neccblk1 + neccblk2; j++) 202 | *dat++ = strinbuf[max + i + j * eccblkwid]; 203 | memcpy(strinbuf, qrframe, max + eccblkwid * (neccblk1 + neccblk2)); 204 | 205 | } 206 | 207 | //======================================================================== 208 | // Frame data insert following the path rules 209 | static unsigned char ismasked(unsigned char x, unsigned char y) 210 | { 211 | unsigned bt; 212 | if (x > y) { 213 | bt = x; 214 | x = y; 215 | y = bt; 216 | } 217 | bt = y; 218 | bt += y * y; 219 | #if 0 220 | // bt += y*y; 221 | unsigned s = 1; 222 | while (y--) { 223 | bt += s; 224 | s += 2; 225 | } 226 | #endif 227 | bt >>= 1; 228 | bt += x; 229 | return (__LPM(&framask[bt >> 3]) >> (7 - (bt & 7))) & 1; 230 | } 231 | 232 | static void fillframe(void) 233 | { 234 | unsigned i; 235 | unsigned char d, j; 236 | unsigned char x, y, ffdecy, ffgohv; 237 | 238 | memcpy_P(qrframe, framebase, WDB * WD); 239 | x = y = WD - 1; 240 | ffdecy = 1; // up, minus 241 | ffgohv = 1; 242 | 243 | /* inteleaved data and ecc codes */ 244 | for (i = 0; i < ((datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2); i++) { 245 | d = strinbuf[i]; 246 | for (j = 0; j < 8; j++, d <<= 1) { 247 | if( i || j ) 248 | do { // find next fill position 249 | if (ffgohv) 250 | x--; 251 | else { 252 | x++; 253 | if (ffdecy) { 254 | if (y != 0) 255 | y--; 256 | else { 257 | x -= 2; 258 | ffdecy = !ffdecy; 259 | if (x == 6) { 260 | x--; 261 | y = 9; 262 | } 263 | } 264 | } else { 265 | if (y != WD - 1) 266 | y++; 267 | else { 268 | x -= 2; 269 | ffdecy = !ffdecy; 270 | if (x == 6) { 271 | x--; 272 | y -= 8; 273 | } 274 | } 275 | } 276 | } 277 | ffgohv = !ffgohv; 278 | } while (ismasked(x, y)); 279 | if (0x80 & d) 280 | SETQRBIT(x, y); 281 | } 282 | } 283 | 284 | } 285 | 286 | //======================================================================== 287 | // Masking 288 | static void applymask(unsigned char m) 289 | { 290 | unsigned char x, y, r3x, r3y; 291 | 292 | switch (m) { 293 | case 0: 294 | for (y = 0; y < WD; y++) 295 | for (x = 0; x < WD; x++) 296 | if (!((x + y) & 1) && !ismasked(x, y)) 297 | TOGQRBIT(x, y); 298 | break; 299 | case 1: 300 | for (y = 0; y < WD; y++) 301 | for (x = 0; x < WD; x++) 302 | if (!(y & 1) && !ismasked(x, y)) 303 | TOGQRBIT(x, y); 304 | break; 305 | case 2: 306 | for (y = 0; y < WD; y++) 307 | for (r3x = 0, x = 0; x < WD; x++, r3x++) { 308 | if (r3x == 3) 309 | r3x = 0; 310 | if (!r3x && !ismasked(x, y)) 311 | TOGQRBIT(x, y); 312 | } 313 | break; 314 | case 3: 315 | for (r3y = 0, y = 0; y < WD; y++, r3y++) { 316 | if (r3y == 3) 317 | r3y = 0; 318 | for (r3x = r3y, x = 0; x < WD; x++, r3x++) { 319 | if (r3x == 3) 320 | r3x = 0; 321 | if (!r3x && !ismasked(x, y)) 322 | TOGQRBIT(x, y); 323 | } 324 | } 325 | break; 326 | case 4: 327 | for (y = 0; y < WD; y++) 328 | for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < WD; x++, r3x++) { 329 | if (r3x == 3) { 330 | r3x = 0; 331 | r3y = !r3y; 332 | } 333 | if (!r3y && !ismasked(x, y)) 334 | TOGQRBIT(x, y); 335 | } 336 | break; 337 | case 5: 338 | for (r3y = 0, y = 0; y < WD; y++, r3y++) { 339 | if (r3y == 3) 340 | r3y = 0; 341 | for (r3x = 0, x = 0; x < WD; x++, r3x++) { 342 | if (r3x == 3) 343 | r3x = 0; 344 | if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y)) 345 | TOGQRBIT(x, y); 346 | } 347 | } 348 | break; 349 | case 6: 350 | for (r3y = 0, y = 0; y < WD; y++, r3y++) { 351 | if (r3y == 3) 352 | r3y = 0; 353 | for (r3x = 0, x = 0; x < WD; x++, r3x++) { 354 | if (r3x == 3) 355 | r3x = 0; 356 | if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y)) 357 | TOGQRBIT(x, y); 358 | } 359 | } 360 | break; 361 | case 7: 362 | for (r3y = 0, y = 0; y < WD; y++, r3y++) { 363 | if (r3y == 3) 364 | r3y = 0; 365 | for (r3x = 0, x = 0; x < WD; x++, r3x++) { 366 | if (r3x == 3) 367 | r3x = 0; 368 | if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y)) 369 | TOGQRBIT(x, y); 370 | } 371 | } 372 | break; 373 | } 374 | return; 375 | } 376 | 377 | // Badness coefficients. 378 | static const unsigned char N1 = 3; 379 | static const unsigned char N2 = 3; 380 | static const unsigned char N3 = 40; 381 | static const unsigned char N4 = 10; 382 | 383 | static unsigned badruns(unsigned char length) 384 | { 385 | unsigned char i; 386 | unsigned runsbad = 0; 387 | for (i = 0; i <= length; i++) 388 | if (rlens[i] >= 5) 389 | runsbad += N1 + rlens[i] - 5; 390 | // BwBBBwB 391 | for (i = 3; i < length - 1; i += 2) 392 | if (rlens[i - 2] == rlens[i + 2] 393 | && rlens[i + 2] == rlens[i - 1] 394 | && rlens[i - 1] == rlens[i + 1] 395 | && rlens[i - 1] * 3 == rlens[i] 396 | // white around the black pattern? Not part of spec 397 | && (rlens[i - 3] == 0 // beginning 398 | || i + 3 > length // end 399 | || rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4) 400 | ) 401 | runsbad += N3; 402 | return runsbad; 403 | } 404 | 405 | static int badcheck() 406 | { 407 | unsigned char x, y, h, b, b1; 408 | unsigned thisbad = 0; 409 | int bw = 0; 410 | 411 | // blocks of same color. 412 | for (y = 0; y < WD - 1; y++) 413 | for (x = 0; x < WD - 1; x++) 414 | if ((QRBIT(x, y) && QRBIT(x + 1, y) && QRBIT(x, y + 1) && QRBIT(x + 1, y + 1)) // all black 415 | || !(QRBIT(x, y) || QRBIT(x + 1, y) || QRBIT(x, y + 1) || QRBIT(x + 1, y + 1))) // all white 416 | thisbad += N2; 417 | 418 | // X runs 419 | for (y = 0; y < WD; y++) { 420 | rlens[0] = 0; 421 | for (h = b = x = 0; x < WD; x++) { 422 | if ((b1 = QRBIT(x, y)) == b) 423 | rlens[h]++; 424 | else 425 | rlens[++h] = 1; 426 | b = b1; 427 | bw += b ? 1 : -1; 428 | } 429 | thisbad += badruns(h); 430 | } 431 | 432 | // black/white imbalance 433 | if (bw < 0) 434 | bw = -bw; 435 | 436 | unsigned long big = bw; 437 | unsigned count = 0; 438 | big += big << 2; 439 | big <<= 1; 440 | while (big > WD * WD) 441 | big -= WD * WD, count++; 442 | thisbad += count * N4; 443 | 444 | // Y runs 445 | for (x = 0; x < WD; x++) { 446 | rlens[0] = 0; 447 | for (h = b = y = 0; y < WD; y++) { 448 | if ((b1 = QRBIT(x, y)) == b) 449 | rlens[h]++; 450 | else 451 | rlens[++h] = 1; 452 | b = b1; 453 | } 454 | thisbad += badruns(h); 455 | } 456 | return thisbad; 457 | } 458 | 459 | // final format bits with mask 460 | // level << 3 | mask 461 | static const unsigned fmtword[] PROGMEM = { 462 | 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L 463 | 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M 464 | 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q 465 | 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, //H 466 | }; 467 | 468 | static void addfmt(unsigned char masknum) 469 | { 470 | unsigned fmtbits; 471 | unsigned char i, lvl = ECCLEVEL - 1; 472 | 473 | fmtbits = pgm_read_word(&fmtword[masknum + (lvl << 3)]); 474 | // low byte 475 | for (i = 0; i < 8; i++, fmtbits >>= 1) 476 | if (fmtbits & 1) { 477 | SETQRBIT(WD - 1 - i, 8); 478 | if (i < 6) 479 | SETQRBIT(8, i); 480 | else 481 | SETQRBIT(8, i + 1); 482 | } 483 | // high byte 484 | for (i = 0; i < 7; i++, fmtbits >>= 1) 485 | if (fmtbits & 1) { 486 | SETQRBIT(8, WD - 7 + i); 487 | if (i) 488 | SETQRBIT(6 - i, 8); 489 | else 490 | SETQRBIT(7, 8); 491 | } 492 | } 493 | 494 | void qrencode() 495 | { 496 | unsigned mindem = 30000; 497 | unsigned char best = 0; 498 | unsigned char i; 499 | unsigned badness; 500 | 501 | stringtoqr(); 502 | fillframe(); // Inisde loop to avoid having separate mask buffer 503 | memcpy(strinbuf, qrframe, WD * WDB); 504 | for (i = 0; i < 8; i++) { 505 | applymask(i); // returns black-white imbalance 506 | badness = badcheck(); 507 | #if 0 //ndef PUREBAD 508 | if (badness < WD * WD * 5 / 4) { // good enough - masks grow in compute complexity 509 | best = i; 510 | break; 511 | } 512 | #endif 513 | if (badness < mindem) { 514 | mindem = badness; 515 | best = i; 516 | } 517 | if (best == 7) 518 | break; // don't increment i to avoid redoing mask 519 | memcpy(qrframe, strinbuf, WD * WDB); // reset filled frame 520 | } 521 | if (best != i) // redo best mask - none good enough, last wasn't best 522 | applymask(best); 523 | addfmt(best); // add in final format bytes 524 | } 525 | -------------------------------------------------------------------------------- /qrencode.h: -------------------------------------------------------------------------------- 1 | #ifndef __AVR__ 2 | #define PROGMEM 3 | #define memcpy_P memcpy 4 | #define __LPM(x) *x 5 | #define pgm_read_word(x) *x 6 | #else 7 | #include 8 | #define USEPRECALC 9 | #endif 10 | 11 | #ifndef USEPRECALC 12 | // malloc-ed by initframe, free manually 13 | extern unsigned char *strinbuf; // string iput buffer 14 | extern unsigned char *qrframe; 15 | // setup the base frame structure - can be reused 16 | void initframe(void); 17 | // free the basic frame malloced structures 18 | void freeframe(void); 19 | // these resturn maximum string size to send in 20 | unsigned initeccsize(unsigned char ecc, unsigned size); 21 | unsigned initecc(unsigned char level,unsigned char version); 22 | #else // precalc-ed arrays 23 | extern unsigned char strinbuf[]; 24 | extern unsigned char qrframe[]; 25 | #endif 26 | 27 | extern unsigned char WD, WDB; 28 | #include "qrbits.h" 29 | 30 | // strinbuf in, qrframe out 31 | void qrencode(void); 32 | 33 | 34 | -------------------------------------------------------------------------------- /qrframe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifndef __AVR__ 5 | #define PROGMEM 6 | #define memcpy_P memcpy 7 | #define __LPM(x) *x 8 | #define pgm_read_word(x) *x 9 | #else 10 | #include 11 | #endif 12 | 13 | unsigned char *framebase; 14 | unsigned char *framask; 15 | unsigned char *rlens; 16 | unsigned char VERSION; 17 | unsigned char WD, WDB; // filled in from verison by initframe 18 | 19 | #define QRBIT(x,y) ( ( framebase[((x)>>3) + (y) * WDB] >> (7-((x) & 7 ))) & 1 ) 20 | #define SETQRBIT(x,y) framebase[((x)>>3) + (y) * WDB] |= 0x80 >> ((x) & 7) 21 | 22 | static void setmask(unsigned char x, unsigned char y) 23 | { 24 | unsigned bt; 25 | if (x > y) { 26 | bt = x; 27 | x = y; 28 | y = bt; 29 | } 30 | // y*y = 1+3+5... 31 | bt = y; 32 | bt *= y; 33 | bt += y; 34 | bt >>= 1; 35 | bt += x; 36 | framask[bt >> 3] |= 0x80 >> (bt & 7); 37 | } 38 | 39 | static void putfind() 40 | { 41 | unsigned char j, i, k, t; 42 | for (t = 0; t < 3; t++) { 43 | k = 0; 44 | i = 0; 45 | if (t == 1) 46 | k = (WD - 7); 47 | if (t == 2) 48 | i = (WD - 7); 49 | SETQRBIT(i + 3, k + 3); 50 | for (j = 0; j < 6; j++) { 51 | SETQRBIT(i + j, k); 52 | SETQRBIT(i, k + j + 1); 53 | SETQRBIT(i + 6, k + j); 54 | SETQRBIT(i + j + 1, k + 6); 55 | } 56 | for (j = 1; j < 5; j++) { 57 | setmask(i + j, k + 1); 58 | setmask(i + 1, k + j + 1); 59 | setmask(i + 5, k + j); 60 | setmask(i + j + 1, k + 5); 61 | } 62 | for (j = 2; j < 4; j++) { 63 | SETQRBIT(i + j, k + 2); 64 | SETQRBIT(i + 2, k + j + 1); 65 | SETQRBIT(i + 4, k + j); 66 | SETQRBIT(i + j + 1, k + 4); 67 | } 68 | } 69 | } 70 | 71 | static void putalign(int x, int y) 72 | { 73 | int j; 74 | 75 | SETQRBIT(x, y); 76 | for (j = -2; j < 2; j++) { 77 | SETQRBIT(x + j, y - 2); 78 | SETQRBIT(x - 2, y + j + 1); 79 | SETQRBIT(x + 2, y + j); 80 | SETQRBIT(x + j + 1, y + 2); 81 | } 82 | for (j = 0; j < 2; j++) { 83 | setmask(x - 1, y + j); 84 | setmask(x + 1, y - j); 85 | setmask(x - j, y - 1); 86 | setmask(x + j, y + 1); 87 | } 88 | } 89 | 90 | static const unsigned char adelta[41] PROGMEM = { 91 | 0, 11, 15, 19, 23, 27, 31, // force 1 pat 92 | 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, 93 | 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28, 94 | }; 95 | 96 | static void doaligns(void) 97 | { 98 | unsigned char delta, x, y; 99 | if (VERSION < 2) 100 | return; 101 | delta = __LPM(&adelta[VERSION]); 102 | y = WD - 7; 103 | for (;;) { 104 | x = WD - 7; 105 | while (x > delta - 3U) { 106 | putalign(x, y); 107 | if (x < delta) 108 | break; 109 | x -= delta; 110 | } 111 | if (y <= delta + 9U) 112 | break; 113 | y -= delta; 114 | putalign(6, y); 115 | putalign(y, 6); 116 | } 117 | } 118 | 119 | static const unsigned vpat[] PROGMEM = { 120 | 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 121 | 0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9, 122 | 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 123 | 0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 124 | 0x541, 0xc69 125 | }; 126 | 127 | static void putvpat(void) 128 | { 129 | unsigned char vers = VERSION; 130 | unsigned char x, y, bc; 131 | unsigned verinfo; 132 | if (vers < 7) 133 | return; 134 | verinfo = pgm_read_word(&vpat[vers - 7]); 135 | 136 | bc = 17; 137 | for (x = 0; x < 6; x++) 138 | for (y = 0; y < 3; y++, bc--) 139 | if (1 & (bc > 11 ? vers >> (bc - 12) : verinfo >> bc)) { 140 | SETQRBIT(5 - x, 2 - y + WD - 11); 141 | SETQRBIT(2 - y + WD - 11, 5 - x); 142 | } else { 143 | setmask(5 - x, 2 - y + WD - 11); 144 | setmask(2 - y + WD - 11, 5 - x); 145 | } 146 | } 147 | 148 | void initframe() 149 | { 150 | unsigned x, y; 151 | 152 | framebase = calloc(WDB * WD, 1); 153 | framask = calloc(((WD * (WD + 1) / 2) + 7) / 8, 1); 154 | rlens = malloc(WD + 1); 155 | // finders 156 | putfind(); 157 | // alignment blocks 158 | doaligns(); 159 | // single black 160 | SETQRBIT(8, WD - 8); 161 | // timing gap - masks only 162 | for (y = 0; y < 7; y++) { 163 | setmask(7, y); 164 | setmask(WD - 8, y); 165 | setmask(7, y + WD - 7); 166 | } 167 | for (x = 0; x < 8; x++) { 168 | setmask(x, 7); 169 | setmask(x + WD - 8, 7); 170 | setmask(x, WD - 8); 171 | } 172 | // reserve mask-format area 173 | for (x = 0; x < 9; x++) 174 | setmask(x, 8); 175 | for (x = 0; x < 8; x++) { 176 | setmask(x + WD - 8, 8); 177 | setmask(8, x); 178 | } 179 | for (y = 0; y < 7; y++) 180 | setmask(8, y + WD - 7); 181 | // timing 182 | for (x = 0; x < WD - 14; x++) 183 | if (x & 1) { 184 | setmask(8 + x, 6); 185 | setmask(6, 8 + x); 186 | } else { 187 | SETQRBIT(8 + x, 6); 188 | SETQRBIT(6, 8 + x); 189 | } 190 | 191 | // version block 192 | putvpat(); 193 | for (y = 0; y < WD; y++) 194 | for (x = 0; x <= y; x++) 195 | if (QRBIT(x, y)) 196 | setmask(x, y); 197 | } 198 | 199 | void freeframe() { 200 | free( framebase ); 201 | free( framask ); 202 | free( rlens ); 203 | } 204 | 205 | unsigned char *strinbuf; 206 | unsigned char *qrframe; 207 | unsigned char ECCLEVEL; 208 | unsigned char neccblk1; 209 | unsigned char neccblk2; 210 | unsigned char datablkw; 211 | unsigned char eccblkwid; 212 | 213 | #ifndef __AVR__ 214 | #define PROGMEM 215 | #define memcpy_P memcpy 216 | #define __LPM(x) *x 217 | #else 218 | #include 219 | #endif 220 | 221 | #include "ecctable.h" 222 | 223 | unsigned initecc(unsigned char ecc, unsigned char vers) 224 | { 225 | VERSION = vers; 226 | WD = 17 + 4 * vers; 227 | WDB = (WD + 7) / 8; 228 | 229 | unsigned fsz = WD * WDB; 230 | if (fsz < 768) // for ECC math buffers 231 | fsz = 768; 232 | qrframe = malloc(fsz); 233 | 234 | ECCLEVEL = ecc; 235 | unsigned eccindex = (ecc - 1) * 4 + (vers - 1) * 16; 236 | 237 | neccblk1 = eccblocks[eccindex++]; 238 | neccblk2 = eccblocks[eccindex++]; 239 | datablkw = eccblocks[eccindex++]; 240 | eccblkwid = eccblocks[eccindex++]; 241 | 242 | if (fsz < datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2) 243 | fsz = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2; 244 | strinbuf = malloc(fsz); 245 | return datablkw * (neccblk1 + neccblk2) + neccblk2 - 3; //-2 if vers <= 9! 246 | } 247 | 248 | unsigned initeccsize(unsigned char ecc, unsigned size) 249 | { 250 | unsigned eccindex; 251 | unsigned char vers; 252 | for( vers = 1 ; vers < 40; vers++ ) { 253 | eccindex = (ecc - 1) * 4 + (vers - 1) * 16; 254 | neccblk1 = eccblocks[eccindex++]; 255 | neccblk2 = eccblocks[eccindex++]; 256 | datablkw = eccblocks[eccindex++]; 257 | if( size < datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 ) 258 | break; 259 | } 260 | return initecc( ecc, vers ); 261 | } 262 | -------------------------------------------------------------------------------- /qrjpeg.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned char jpeg0[] = { 4 | 0xff, 0xd8, 5 | 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 6 | 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 7 | 8 | 0xFF, 0xDB, 0x00, 0x43, 0x00, 9 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 10 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 11 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 12 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 13 | 14 | 0xff, 0xc1, 0x00, 0x0b, 0x08, 15 | // address 0x5e 16 | 0x00, 0x80, // height 17 | 0x00, 0x80, // width 18 | 0x01, 0x01, 0x11, 0x00, 19 | // DC table 20 | 0xff, 0xc4, 0x00, 0x15, 0x00, 21 | 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 | 6, 0, 23 | // AC Table 24 | 0xff, 0xc4, 0x00, 0x14, 0x10, 25 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | 0, 27 | // Image scan header 28 | 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00 29 | }; 30 | 31 | #include "qrencode.h" 32 | 33 | #include 34 | #include 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | unsigned char x, y, v = 0, l = 1; 39 | char *c; 40 | unsigned width, height, j, k; 41 | int argp = 0; 42 | 43 | if( argc < 2 ) { 44 | printf( "Usage:\n\nqrjpeg [-v VERS_1_40] [-l ECCLVL_1_4] \"text to encode\" >output.jpg\n" ); 45 | printf( "version defaults to auto, same as \"-v 0\"\necc level defaults to 1\n" ); 46 | return 1; 47 | } 48 | c = "Test Message"; 49 | 50 | while( ++argp < argc ) { 51 | if( argv[argp][0] == '-' ) { 52 | if( argv[argp][1] == 'v' ) 53 | v = atoi( argv[++argp]); 54 | else if( argv[argp][1] == 'l' ) 55 | l = atoi( argv[++argp]); 56 | else { 57 | printf( "Usage:\n\nqrjpeg [-v VERS_1_40] [-l ECCLVL_1_4] \"text to encode\" >output.jpg\n" ); 58 | printf( "version defaults to auto, same as \"-v 0\"\necc level defaults to 1\n" ); 59 | return 1; 60 | } 61 | } 62 | else 63 | c = argv[argp]; 64 | } 65 | if( v > 40 ) { 66 | fprintf( stderr, "Bad version (size) parameter (should be 0 (auto) to 40)\n" ); 67 | return -1; 68 | } 69 | if( l < 1 || l > 4 ) { 70 | fprintf( stderr, "Bad ECC level parameter (should be 1 to 4)\n" ); 71 | return -1; 72 | } 73 | 74 | if( v ) 75 | k = initecc(l, v); 76 | else 77 | k = initeccsize( l, strlen(c)); 78 | 79 | initframe(); 80 | strcpy((char *)strinbuf, c ); 81 | qrencode(); 82 | 83 | width = height = WD+8; 84 | // set height and width in header 85 | jpeg0[0x5e] = width >> 5; 86 | jpeg0[0x5f] = width << 3; 87 | jpeg0[0x60] = width >> 5; 88 | jpeg0[0x61] = width << 3; 89 | // write out header 90 | fwrite(jpeg0, 1, sizeof(jpeg0), stdout); 91 | // put half full scale, 3e for white, 40 for black 92 | putchar(0x40); 93 | for (j = 0; j < width * 4 + 3; j++) 94 | putchar(0x80); 95 | for (y = 0; y < WD; y++) { 96 | k = 0; 97 | for (x = 0; x < WD; x++) { 98 | j = QRBIT(x, y); 99 | if (k == j) { 100 | putchar(0x80); // code for no change 101 | continue; 102 | } 103 | putchar(j ? 0 : 0x7e); // full scale flip 104 | k = j; 105 | } 106 | if (k != 0) 107 | putchar(0x7e); 108 | else 109 | putchar(0x80); 110 | for (j = 0; j < 7; j++) 111 | putchar(0x80); 112 | } 113 | for (j = 0; j < width * 4 - 4; j++) 114 | putchar(0x80); 115 | putchar(0x80); // one last for EOF 116 | putchar(0xFF); // end marker 117 | putchar(0xd9); 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /regtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | make 3 | #for i in 1 2 3 4 5 6 7 8 9 10 11 12; do 4 | i=1; 5 | while [ $i -ne 41 ]; do 6 | #for i in 9 10 11 12; do 7 | for j in 1 2 3 4; do 8 | echo $i $j 9 | echo "Hello" | ./qrencode $i $j >Hello$i$j.pbm 10 | diff -q Hello$i$j.pbm regout/ 11 | done 12 | i=$[$i+1] 13 | done 14 | echo 15 | #md5sum Hello??.pbm base/Hello??.pbm | sort | uniq -c -w32 | sort -nr 16 | --------------------------------------------------------------------------------