├── 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 |
--------------------------------------------------------------------------------