summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING674
-rw-r--r--README46
-rw-r--r--exifilm.glade552
-rw-r--r--exifilm.gladep8
-rw-r--r--exifilm.py383
-rw-r--r--lfrecord.ps781
-rw-r--r--lfrecord.py863
-rw-r--r--printrecord.py187
8 files changed, 3494 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
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
11software and other kinds of works.
12
13 The licenses for most software and other practical works are designed
14to take away your freedom to share and change the works. By contrast,
15the GNU General Public License is intended to guarantee your freedom to
16share and change all versions of a program--to make sure it remains free
17software for all its users. We, the Free Software Foundation, use the
18GNU General Public License for most of our software; it applies also to
19any other work released this way by its authors. You can apply it to
20your programs, too.
21
22 When we speak of free software, we are referring to freedom, not
23price. Our General Public Licenses are designed to make sure that you
24have the freedom to distribute copies of free software (and charge for
25them if you wish), that you receive source code or can get it if you
26want it, that you can change the software or use pieces of it in new
27free programs, and that you know you can do these things.
28
29 To protect your rights, we need to prevent others from denying you
30these rights or asking you to surrender the rights. Therefore, you have
31certain responsibilities if you distribute copies of the software, or if
32you modify it: responsibilities to respect the freedom of others.
33
34 For example, if you distribute copies of such a program, whether
35gratis or for a fee, you must pass on to the recipients the same
36freedoms that you received. You must make sure that they, too, receive
37or can get the source code. And you must show them these terms so they
38know 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
42giving you legal permission to copy, distribute and/or modify it.
43
44 For the developers' and authors' protection, the GPL clearly explains
45that there is no warranty for this free software. For both users' and
46authors' sake, the GPL requires that modified versions be marked as
47changed, so that their problems will not be attributed erroneously to
48authors of previous versions.
49
50 Some devices are designed to deny users access to install or run
51modified versions of the software inside them, although the manufacturer
52can do so. This is fundamentally incompatible with the aim of
53protecting users' freedom to change the software. The systematic
54pattern of such abuse occurs in the area of products for individuals to
55use, which is precisely where it is most unacceptable. Therefore, we
56have designed this version of the GPL to prohibit the practice for those
57products. If such problems arise substantially in other domains, we
58stand ready to extend this provision to those domains in future versions
59of the GPL, as needed to protect the freedom of users.
60
61 Finally, every program is threatened constantly by software patents.
62States should not allow patents to restrict development and use of
63software on general-purpose computers, but in those that do, we wish to
64avoid the special danger that patents applied to a free program could
65make it effectively proprietary. To prevent this, the GPL assures that
66patents cannot be used to render the program non-free.
67
68 The precise terms and conditions for copying, distribution and
69modification 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
78works, such as semiconductor masks.
79
80 "The Program" refers to any copyrightable work licensed under this
81License. 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
85in a fashion requiring copyright permission, other than the making of an
86exact copy. The resulting work is called a "modified version" of the
87earlier work or a work "based on" the earlier work.
88
89 A "covered work" means either the unmodified Program or a work based
90on the Program.
91
92 To "propagate" a work means to do anything with it that, without
93permission, would make you directly or secondarily liable for
94infringement under applicable copyright law, except executing it on a
95computer or modifying a private copy. Propagation includes copying,
96distribution (with or without modification), making available to the
97public, and in some countries other activities as well.
98
99 To "convey" a work means any kind of propagation that enables other
100parties to make or receive copies. Mere interaction with a user through
101a computer network, with no transfer of a copy, is not conveying.
102
103 An interactive user interface displays "Appropriate Legal Notices"
104to the extent that it includes a convenient and prominently visible
105feature that (1) displays an appropriate copyright notice, and (2)
106tells the user that there is no warranty for the work (except to the
107extent that warranties are provided), that licensees may convey the
108work under this License, and how to view a copy of this License. If
109the interface presents a list of user commands or options, such as a
110menu, 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
115for making modifications to it. "Object code" means any non-source
116form of a work.
117
118 A "Standard Interface" means an interface that either is an official
119standard defined by a recognized standards body, or, in the case of
120interfaces specified for a particular programming language, one that
121is widely used among developers working in that language.
122
123 The "System Libraries" of an executable work include anything, other
124than the work as a whole, that (a) is included in the normal form of
125packaging a Major Component, but which is not part of that Major
126Component, and (b) serves only to enable use of the work with that
127Major Component, or to implement a Standard Interface for which an
128implementation 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
132produce 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
135the source code needed to generate, install, and (for an executable
136work) run the object code and to modify the work, including scripts to
137control those activities. However, it does not include the work's
138System Libraries, or general-purpose tools or generally available free
139programs which are used unmodified in performing those activities but
140which are not part of the work. For example, Corresponding Source
141includes interface definition files associated with source files for
142the work, and the source code for shared libraries and dynamically
143linked subprograms that the work is specifically designed to require,
144such as by intimate data communication or control flow between those
145subprograms and other parts of the work.
146
147 The Corresponding Source need not include anything that users
148can regenerate automatically from other parts of the Corresponding
149Source.
150
151 The Corresponding Source for a work in source code form is that
152same work.
153
154 2. Basic Permissions.
155
156 All rights granted under this License are granted for the term of
157copyright on the Program, and are irrevocable provided the stated
158conditions are met. This License explicitly affirms your unlimited
159permission to run the unmodified Program. The output from running a
160covered work is covered by this License only if the output, given its
161content, constitutes a covered work. This License acknowledges your
162rights 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
165convey, without conditions so long as your license otherwise remains
166in force. You may convey covered works to others for the sole purpose
167of having them make modifications exclusively for you, or provide you
168with facilities for running those works, provided that you comply with
169the terms of this License in conveying all material for which you do
170not control copyright. Those thus making or running the covered works
171for you must do so exclusively on your behalf, under your direction
172and control, on terms that prohibit them from making any copies of
173your copyrighted material outside their relationship with you.
174
175 Conveying under any other circumstances is permitted solely under
176the conditions stated below. Sublicensing is not allowed; section 10
177makes 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
182measure under any applicable law fulfilling obligations under article
18311 of the WIPO copyright treaty adopted on 20 December 1996, or
184similar laws prohibiting or restricting circumvention of such
185measures.
186
187 When you convey a covered work, you waive any legal power to forbid
188circumvention of technological measures to the extent such circumvention
189is effected by exercising rights under this License with respect to
190the covered work, and you disclaim any intention to limit operation or
191modification of the work as a means of enforcing, against the work's
192users, your or third parties' legal rights to forbid circumvention of
193technological measures.
194
195 4. Conveying Verbatim Copies.
196
197 You may convey verbatim copies of the Program's source code as you
198receive it, in any medium, provided that you conspicuously and
199appropriately publish on each copy an appropriate copyright notice;
200keep intact all notices stating that this License and any
201non-permissive terms added in accord with section 7 apply to the code;
202keep intact all notices of the absence of any warranty; and give all
203recipients 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,
206and 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
211produce it from the Program, in the form of source code under the
212terms 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
236works, which are not by their nature extensions of the covered work,
237and which are not combined with it such as to form a larger program,
238in or on a volume of a storage or distribution medium, is called an
239"aggregate" if the compilation and its resulting copyright are not
240used to limit the access or legal rights of the compilation's users
241beyond what the individual works permit. Inclusion of a covered work
242in an aggregate does not cause this License to apply to the other
243parts 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
248of sections 4 and 5, provided that you also convey the
249machine-readable Corresponding Source under the terms of this License,
250in 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
294from the Corresponding Source as a System Library, need not be
295included in conveying the object code work.
296
297 A "User Product" is either (1) a "consumer product", which means any
298tangible personal property which is normally used for personal, family,
299or household purposes, or (2) anything designed or sold for incorporation
300into a dwelling. In determining whether a product is a consumer product,
301doubtful cases shall be resolved in favor of coverage. For a particular
302product received by a particular user, "normally used" refers to a
303typical or common use of that class of product, regardless of the status
304of the particular user or of the way in which the particular user
305actually uses, or expects or is expected to use, the product. A product
306is a consumer product regardless of whether the product has substantial
307commercial, industrial or non-consumer uses, unless such uses represent
308the only significant mode of use of the product.
309
310 "Installation Information" for a User Product means any methods,
311procedures, authorization keys, or other information required to install
312and execute modified versions of a covered work in that User Product from
313a modified version of its Corresponding Source. The information must
314suffice to ensure that the continued functioning of the modified object
315code is in no case prevented or interfered with solely because
316modification has been made.
317
318 If you convey an object code work under this section in, or with, or
319specifically for use in, a User Product, and the conveying occurs as
320part of a transaction in which the right of possession and use of the
321User Product is transferred to the recipient in perpetuity or for a
322fixed term (regardless of how the transaction is characterized), the
323Corresponding Source conveyed under this section must be accompanied
324by the Installation Information. But this requirement does not apply
325if neither you nor any third party retains the ability to install
326modified object code on the User Product (for example, the work has
327been installed in ROM).
328
329 The requirement to provide Installation Information does not include a
330requirement to continue to provide support service, warranty, or updates
331for a work that has been modified or installed by the recipient, or for
332the User Product in which it has been modified or installed. Access to a
333network may be denied when the modification itself materially and
334adversely affects the operation of the network or violates the rules and
335protocols for communication across the network.
336
337 Corresponding Source conveyed, and Installation Information provided,
338in accord with this section must be in a format that is publicly
339documented (and with an implementation available to the public in
340source code form), and must require no special password or key for
341unpacking, reading or copying.
342
343 7. Additional Terms.
344
345 "Additional permissions" are terms that supplement the terms of this
346License by making exceptions from one or more of its conditions.
347Additional permissions that are applicable to the entire Program shall
348be treated as though they were included in this License, to the extent
349that they are valid under applicable law. If additional permissions
350apply only to part of the Program, that part may be used separately
351under those permissions, but the entire Program remains governed by
352this License without regard to the additional permissions.
353
354 When you convey a copy of a covered work, you may at your option
355remove any additional permissions from that copy, or from any part of
356it. (Additional permissions may be written to require their own
357removal in certain cases when you modify the work.) You may place
358additional permissions on material, added by you to a covered work,
359for which you have or can give appropriate copyright permission.
360
361 Notwithstanding any other provision of this License, for material you
362add to a covered work, you may (if authorized by the copyright holders of
363that 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
389restrictions" within the meaning of section 10. If the Program as you
390received it, or any part of it, contains a notice stating that it is
391governed by this License along with a term that is a further
392restriction, you may remove that term. If a license document contains
393a further restriction but permits relicensing or conveying under this
394License, you may add to a covered work material governed by the terms
395of that license document, provided that the further restriction does
396not survive such relicensing or conveying.
397
398 If you add terms to a covered work in accord with this section, you
399must place, in the relevant source files, a statement of the
400additional terms that apply to those files, or a notice indicating
401where to find the applicable terms.
402
403 Additional terms, permissive or non-permissive, may be stated in the
404form of a separately written license, or stated as exceptions;
405the above requirements apply either way.
406
407 8. Termination.
408
409 You may not propagate or modify a covered work except as expressly
410provided under this License. Any attempt otherwise to propagate or
411modify it is void, and will automatically terminate your rights under
412this License (including any patent licenses granted under the third
413paragraph of section 11).
414
415 However, if you cease all violation of this License, then your
416license from a particular copyright holder is reinstated (a)
417provisionally, unless and until the copyright holder explicitly and
418finally terminates your license, and (b) permanently, if the copyright
419holder fails to notify you of the violation by some reasonable means
420prior to 60 days after the cessation.
421
422 Moreover, your license from a particular copyright holder is
423reinstated permanently if the copyright holder notifies you of the
424violation by some reasonable means, this is the first time you have
425received notice of violation of this License (for any work) from that
426copyright holder, and you cure the violation prior to 30 days after
427your receipt of the notice.
428
429 Termination of your rights under this section does not terminate the
430licenses of parties who have received copies or rights from you under
431this License. If your rights have been terminated and not permanently
432reinstated, you do not qualify to receive new licenses for the same
433material 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
438run a copy of the Program. Ancillary propagation of a covered work
439occurring solely as a consequence of using peer-to-peer transmission
440to receive a copy likewise does not require acceptance. However,
441nothing other than this License grants you permission to propagate or
442modify any covered work. These actions infringe copyright if you do
443not accept this License. Therefore, by modifying or propagating a
444covered 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
449receives a license from the original licensors, to run, modify and
450propagate that work, subject to this License. You are not responsible
451for enforcing compliance by third parties with this License.
452
453 An "entity transaction" is a transaction transferring control of an
454organization, or substantially all assets of one, or subdividing an
455organization, or merging organizations. If propagation of a covered
456work results from an entity transaction, each party to that
457transaction who receives a copy of the work also receives whatever
458licenses to the work the party's predecessor in interest had or could
459give under the previous paragraph, plus a right to possession of the
460Corresponding Source of the work from the predecessor in interest, if
461the predecessor has it or can get it with reasonable efforts.
462
463 You may not impose any further restrictions on the exercise of the
464rights granted or affirmed under this License. For example, you may
465not impose a license fee, royalty, or other charge for exercise of
466rights granted under this License, and you may not initiate litigation
467(including a cross-claim or counterclaim in a lawsuit) alleging that
468any patent claim is infringed by making, using, selling, offering for
469sale, 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
474License of the Program or a work on which the Program is based. The
475work thus licensed is called the contributor's "contributor version".
476
477 A contributor's "essential patent claims" are all patent claims
478owned or controlled by the contributor, whether already acquired or
479hereafter acquired, that would be infringed by some manner, permitted
480by this License, of making, using, or selling its contributor version,
481but do not include claims that would be infringed only as a
482consequence of further modification of the contributor version. For
483purposes of this definition, "control" includes the right to grant
484patent sublicenses in a manner consistent with the requirements of
485this License.
486
487 Each contributor grants you a non-exclusive, worldwide, royalty-free
488patent license under the contributor's essential patent claims, to
489make, use, sell, offer for sale, import and otherwise run, modify and
490propagate the contents of its contributor version.
491
492 In the following three paragraphs, a "patent license" is any express
493agreement or commitment, however denominated, not to enforce a patent
494(such as an express permission to practice a patent or covenant not to
495sue for patent infringement). To "grant" such a patent license to a
496party means to make such an agreement or commitment not to enforce a
497patent against the party.
498
499 If you convey a covered work, knowingly relying on a patent license,
500and the Corresponding Source of the work is not available for anyone
501to copy, free of charge and under the terms of this License, through a
502publicly available network server or other readily accessible means,
503then you must either (1) cause the Corresponding Source to be so
504available, or (2) arrange to deprive yourself of the benefit of the
505patent license for this particular work, or (3) arrange, in a manner
506consistent with the requirements of this License, to extend the patent
507license to downstream recipients. "Knowingly relying" means you have
508actual knowledge that, but for the patent license, your conveying the
509covered work in a country, or your recipient's use of the covered work
510in a country, would infringe one or more identifiable patents in that
511country that you have reason to believe are valid.
512
513 If, pursuant to or in connection with a single transaction or
514arrangement, you convey, or propagate by procuring conveyance of, a
515covered work, and grant a patent license to some of the parties
516receiving the covered work authorizing them to use, propagate, modify
517or convey a specific copy of the covered work, then the patent license
518you grant is automatically extended to all recipients of the covered
519work and works based on it.
520
521 A patent license is "discriminatory" if it does not include within
522the scope of its coverage, prohibits the exercise of, or is
523conditioned on the non-exercise of one or more of the rights that are
524specifically granted under this License. You may not convey a covered
525work if you are a party to an arrangement with a third party that is
526in the business of distributing software, under which you make payment
527to the third party based on the extent of your activity of conveying
528the work, and under which the third party grants, to any of the
529parties who would receive the covered work from you, a discriminatory
530patent license (a) in connection with copies of the covered work
531conveyed by you (or copies made from those copies), or (b) primarily
532for and in connection with specific products or compilations that
533contain the covered work, unless you entered into that arrangement,
534or that patent license was granted, prior to 28 March 2007.
535
536 Nothing in this License shall be construed as excluding or limiting
537any implied license or other defenses to infringement that may
538otherwise 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
543otherwise) that contradict the conditions of this License, they do not
544excuse you from the conditions of this License. If you cannot convey a
545covered work so as to satisfy simultaneously your obligations under this
546License and any other pertinent obligations, then as a consequence you may
547not convey it at all. For example, if you agree to terms that obligate you
548to collect a royalty for further conveying from those to whom you convey
549the Program, the only way you could satisfy both those terms and this
550License 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
555permission to link or combine any covered work with a work licensed
556under version 3 of the GNU Affero General Public License into a single
557combined work, and to convey the resulting work. The terms of this
558License will continue to apply to the part which is the covered work,
559but the special requirements of the GNU Affero General Public License,
560section 13, concerning interaction through a network will apply to the
561combination as such.
562
563 14. Revised Versions of this License.
564
565 The Free Software Foundation may publish revised and/or new versions of
566the GNU General Public License from time to time. Such new versions will
567be similar in spirit to the present version, but may differ in detail to
568address new problems or concerns.
569
570 Each version is given a distinguishing version number. If the
571Program specifies that a certain numbered version of the GNU General
572Public License "or any later version" applies to it, you have the
573option of following the terms and conditions either of that numbered
574version or of any later version published by the Free Software
575Foundation. If the Program does not specify a version number of the
576GNU General Public License, you may choose any version ever published
577by the Free Software Foundation.
578
579 If the Program specifies that a proxy can decide which future
580versions of the GNU General Public License can be used, that proxy's
581public statement of acceptance of a version permanently authorizes you
582to choose that version for the Program.
583
584 Later license versions may give you additional or different
585permissions. However, no additional obligations are imposed on any
586author or copyright holder as a result of your choosing to follow a
587later version.
588
589 15. Disclaimer of Warranty.
590
591 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598ALL 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
603WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610SUCH DAMAGES.
611
612 17. Interpretation of Sections 15 and 16.
613
614 If the disclaimer of warranty and limitation of liability provided
615above cannot be given local legal effect according to their terms,
616reviewing courts shall apply local law that most closely approximates
617an absolute waiver of all civil liability in connection with the
618Program, unless a warranty or assumption of liability accompanies a
619copy 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
626possible use to the public, the best way to achieve this is to make it
627free 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
630to attach them to the start of each source file to most effectively
631state the exclusion of warranty; and each file should have at least
632the "copyright" line and a pointer to where the full notice is found.
633
634 <one line to give the program's name and a brief idea of what it does.>
635 Copyright (C) <year> <name of author>
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 <http://www.gnu.org/licenses/>.
649
650Also 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
653notice like this when it starts in an interactive mode:
654
655 <program> Copyright (C) <year> <name of author>
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
660The hypothetical commands `show w' and `show c' should show the appropriate
661parts of the General Public License. Of course, your program's commands
662might 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,
665if any, to sign a "copyright disclaimer" for the program, if necessary.
666For more information on this, and how to apply and follow the GNU GPL, see
667<http://www.gnu.org/licenses/>.
668
669 The GNU General Public License does not permit incorporating your program
670into proprietary programs. If your program is a subroutine library, you
671may consider it more useful to permit linking proprietary applications with
672the library. If this is what you want to do, use the GNU Lesser General
673Public License instead of this License. But first, please read
674<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/README b/README
new file mode 100644
index 0000000..0da7aa4
--- /dev/null
+++ b/README
@@ -0,0 +1,46 @@
1INTRODUCTION:
2
3ExiFilm is a suite of programs that can be used to annotate digital
4images with information about the film exposure used to create them.
5In particular, it is designed for use with large format film cameras
6where the photographer may then scan the film to create a digital copy
7for a library or for digital processing.
8
9By storing the exposure metadata in EXIF tags of scanned images, the
10photographer can have electronic access to the same information
11contained in the written record from the field from within an image
12viewer. Further processing of the data can be done without the need
13to store the metadata in a separate database.
14
15THE PROGRAMS:
16
17The file "lfrecord.ps" is a PostScript file that can be printed on US
18letter paper (or other sizes). It is a single page of four exposure
19record forms design for large format photography. The author trims
20the four forms and binds them together as a notepad to take into the
21field. The PostScript program is hand-written and can be altered
22fairly easily.
23
24The Python program "exifilm.py" provides a data entry screen similar
25to the form in "lfrecord.ps". It takes an optional argument of a path
26to a directory with JPEG image files. It will provide a drop-down
27list of JPEG files in the directory, and selecting one of the files
28will load the EXIF information from that file. In this way it allows
29the user to quickly enter metadata for a number of scanned film
30images. The metadata are saved immediately upon loading a new file or
31exiting the program.
32
33The Python program "printrecord.py" loads the metadata previously
34entered with "exifilm.py" and produces pages similar to those in
35"lfrecord.ps" with the metadata typeset into the fields. The
36resulting file may then be printed and bound into a photo archive with
37the original film. Example usage:
38
39 python printrecord.py /path/to/images 1 16 | lpr
40
41Produces four pages of output including the metadata for image IDs 1
42through 16.
43
44
45James E. Blair <corvus@gnu.org>
46October, 2009
diff --git a/exifilm.glade b/exifilm.glade
new file mode 100644
index 0000000..7ae4660
--- /dev/null
+++ b/exifilm.glade
@@ -0,0 +1,552 @@
1<?xml version="1.0"?>
2<glade-interface>
3 <!-- interface-requires gtk+ 2.16 -->
4 <!-- interface-naming-policy toplevel-contextual -->
5 <widget class="GtkWindow" id="main_window">
6 <property name="visible">True</property>
7 <property name="title" translatable="yes">ExiFilm</property>
8 <property name="default_width">400</property>
9 <property name="default_height">500</property>
10 <signal name="destroy" handler="on_main_window_destroy"/>
11 <signal name="key_press_event" handler="on_main_window_key_press_event"/>
12 <child>
13 <widget class="GtkVBox" id="vbox1">
14 <property name="visible">True</property>
15 <child>
16 <widget class="GtkHBox" id="hbox1">
17 <property name="visible">True</property>
18 <property name="border_width">5</property>
19 <property name="spacing">5</property>
20 <child>
21 <widget class="GtkLabel" id="label10">
22 <property name="visible">True</property>
23 <property name="label" translatable="yes">File:</property>
24 </widget>
25 <packing>
26 <property name="expand">False</property>
27 <property name="fill">False</property>
28 <property name="position">0</property>
29 </packing>
30 </child>
31 <child>
32 <widget class="GtkComboBox" id="file">
33 <property name="visible">True</property>
34 <signal name="changed" handler="on_file_changed"/>
35 </widget>
36 <packing>
37 <property name="position">1</property>
38 </packing>
39 </child>
40 </widget>
41 <packing>
42 <property name="expand">False</property>
43 <property name="fill">False</property>
44 <property name="position">0</property>
45 </packing>
46 </child>
47 <child>
48 <widget class="GtkHSeparator" id="hseparator1">
49 <property name="visible">True</property>
50 </widget>
51 <packing>
52 <property name="expand">False</property>
53 <property name="fill">False</property>
54 <property name="position">1</property>
55 </packing>
56 </child>
57 <child>
58 <widget class="GtkTable" id="table1">
59 <property name="visible">True</property>
60 <property name="border_width">5</property>
61 <property name="n_rows">4</property>
62 <property name="n_columns">6</property>
63 <property name="column_spacing">5</property>
64 <property name="row_spacing">5</property>
65 <child>
66 <widget class="GtkEntry" id="film">
67 <property name="visible">True</property>
68 <property name="can_focus">True</property>
69 <property name="invisible_char">&#x25CF;</property>
70 <property name="width_chars">6</property>
71 </widget>
72 <packing>
73 <property name="left_attach">1</property>
74 <property name="right_attach">2</property>
75 <property name="top_attach">1</property>
76 <property name="bottom_attach">2</property>
77 <property name="y_options"></property>
78 </packing>
79 </child>
80 <child>
81 <widget class="GtkEntry" id="aperture">
82 <property name="visible">True</property>
83 <property name="can_focus">True</property>
84 <property name="invisible_char">&#x25CF;</property>
85 <property name="width_chars">6</property>
86 </widget>
87 <packing>
88 <property name="left_attach">1</property>
89 <property name="right_attach">3</property>
90 <property name="top_attach">3</property>
91 <property name="bottom_attach">4</property>
92 <property name="y_options"></property>
93 </packing>
94 </child>
95 <child>
96 <widget class="GtkEntry" id="shutter">
97 <property name="visible">True</property>
98 <property name="can_focus">True</property>
99 <property name="invisible_char">&#x25CF;</property>
100 <property name="width_chars">6</property>
101 </widget>
102 <packing>
103 <property name="left_attach">3</property>
104 <property name="right_attach">5</property>
105 <property name="top_attach">3</property>
106 <property name="bottom_attach">4</property>
107 <property name="y_options"></property>
108 </packing>
109 </child>
110 <child>
111 <widget class="GtkEntry" id="carrier">
112 <property name="visible">True</property>
113 <property name="can_focus">True</property>
114 <property name="invisible_char">&#x25CF;</property>
115 <property name="width_chars">4</property>
116 </widget>
117 <packing>
118 <property name="left_attach">2</property>
119 <property name="right_attach">4</property>
120 <property name="top_attach">1</property>
121 <property name="bottom_attach">2</property>
122 <property name="y_options"></property>
123 </packing>
124 </child>
125 <child>
126 <widget class="GtkEntry" id="process">
127 <property name="visible">True</property>
128 <property name="can_focus">True</property>
129 <property name="invisible_char">&#x25CF;</property>
130 <property name="width_chars">4</property>
131 </widget>
132 <packing>
133 <property name="left_attach">4</property>
134 <property name="right_attach">5</property>
135 <property name="top_attach">1</property>
136 <property name="bottom_attach">2</property>
137 <property name="y_options"></property>
138 </packing>
139 </child>
140 <child>
141 <widget class="GtkLabel" id="label1">
142 <property name="visible">True</property>
143 <property name="label" translatable="yes">ID</property>
144 </widget>
145 <packing>
146 <property name="x_options">GTK_FILL</property>
147 <property name="y_options"></property>
148 </packing>
149 </child>
150 <child>
151 <widget class="GtkLabel" id="label2">
152 <property name="visible">True</property>
153 <property name="label" translatable="yes">Film</property>
154 </widget>
155 <packing>
156 <property name="left_attach">1</property>
157 <property name="right_attach">2</property>
158 <property name="x_options">GTK_FILL</property>
159 <property name="y_options"></property>
160 </packing>
161 </child>
162 <child>
163 <widget class="GtkLabel" id="label3">
164 <property name="visible">True</property>
165 <property name="label" translatable="yes">Carrier</property>
166 </widget>
167 <packing>
168 <property name="left_attach">2</property>
169 <property name="right_attach">4</property>
170 <property name="x_options">GTK_FILL</property>
171 <property name="y_options"></property>
172 </packing>
173 </child>
174 <child>
175 <widget class="GtkLabel" id="label4">
176 <property name="visible">True</property>
177 <property name="label" translatable="yes">Process</property>
178 </widget>
179 <packing>
180 <property name="left_attach">4</property>
181 <property name="right_attach">5</property>
182 <property name="x_options">GTK_FILL</property>
183 <property name="y_options"></property>
184 </packing>
185 </child>
186 <child>
187 <widget class="GtkLabel" id="label5">
188 <property name="visible">True</property>
189 <property name="label" translatable="yes">Front Movement</property>
190 </widget>
191 <packing>
192 <property name="left_attach">5</property>
193 <property name="right_attach">6</property>
194 <property name="x_options">GTK_FILL</property>
195 <property name="y_options"></property>
196 </packing>
197 </child>
198 <child>
199 <widget class="GtkLabel" id="label6">
200 <property name="visible">True</property>
201 <property name="label" translatable="yes">Rear Movement</property>
202 </widget>
203 <packing>
204 <property name="left_attach">5</property>
205 <property name="right_attach">6</property>
206 <property name="top_attach">2</property>
207 <property name="bottom_attach">3</property>
208 <property name="x_options">GTK_FILL</property>
209 <property name="y_options"></property>
210 </packing>
211 </child>
212 <child>
213 <widget class="GtkLabel" id="label7">
214 <property name="visible">True</property>
215 <property name="label" translatable="yes">Lens</property>
216 </widget>
217 <packing>
218 <property name="top_attach">2</property>
219 <property name="bottom_attach">3</property>
220 <property name="x_options">GTK_FILL</property>
221 <property name="y_options"></property>
222 </packing>
223 </child>
224 <child>
225 <widget class="GtkLabel" id="label8">
226 <property name="visible">True</property>
227 <property name="label" translatable="yes">Aperture</property>
228 </widget>
229 <packing>
230 <property name="left_attach">1</property>
231 <property name="right_attach">3</property>
232 <property name="top_attach">2</property>
233 <property name="bottom_attach">3</property>
234 <property name="x_options">GTK_FILL</property>
235 <property name="y_options"></property>
236 </packing>
237 </child>
238 <child>
239 <widget class="GtkLabel" id="label9">
240 <property name="visible">True</property>
241 <property name="label" translatable="yes">Shutter</property>
242 </widget>
243 <packing>
244 <property name="left_attach">3</property>
245 <property name="right_attach">5</property>
246 <property name="top_attach">2</property>
247 <property name="bottom_attach">3</property>
248 <property name="x_options">GTK_FILL</property>
249 <property name="y_options"></property>
250 </packing>
251 </child>
252 <child>
253 <widget class="GtkEntry" id="id">
254 <property name="visible">True</property>
255 <property name="can_focus">True</property>
256 <property name="invisible_char">&#x25CF;</property>
257 <property name="width_chars">4</property>
258 </widget>
259 <packing>
260 <property name="top_attach">1</property>
261 <property name="bottom_attach">2</property>
262 <property name="y_options"></property>
263 </packing>
264 </child>
265 <child>
266 <widget class="GtkEntry" id="lens">
267 <property name="visible">True</property>
268 <property name="can_focus">True</property>
269 <property name="invisible_char">&#x25CF;</property>
270 <property name="width_chars">4</property>
271 </widget>
272 <packing>
273 <property name="top_attach">3</property>
274 <property name="bottom_attach">4</property>
275 <property name="y_options"></property>
276 </packing>
277 </child>
278 <child>
279 <widget class="GtkButton" id="front">
280 <property name="label" translatable="yes">None</property>
281 <property name="visible">True</property>
282 <property name="can_focus">True</property>
283 <property name="receives_default">True</property>
284 <signal name="clicked" handler="on_front_clicked"/>
285 </widget>
286 <packing>
287 <property name="left_attach">5</property>
288 <property name="right_attach">6</property>
289 <property name="top_attach">1</property>
290 <property name="bottom_attach">2</property>
291 </packing>
292 </child>
293 <child>
294 <widget class="GtkButton" id="rear">
295 <property name="label" translatable="yes">None</property>
296 <property name="visible">True</property>
297 <property name="can_focus">True</property>
298 <property name="receives_default">True</property>
299 <signal name="clicked" handler="on_rear_clicked"/>
300 </widget>
301 <packing>
302 <property name="left_attach">5</property>
303 <property name="right_attach">6</property>
304 <property name="top_attach">3</property>
305 <property name="bottom_attach">4</property>
306 </packing>
307 </child>
308 </widget>
309 <packing>
310 <property name="expand">False</property>
311 <property name="fill">False</property>
312 <property name="position">2</property>
313 </packing>
314 </child>
315 <child>
316 <widget class="GtkHSeparator" id="hseparator2">
317 <property name="visible">True</property>
318 </widget>
319 <packing>
320 <property name="expand">False</property>
321 <property name="position">3</property>
322 </packing>
323 </child>
324 <child>
325 <widget class="GtkTable" id="table2">
326 <property name="visible">True</property>
327 <property name="border_width">5</property>
328 <property name="n_rows">2</property>
329 <property name="n_columns">2</property>
330 <property name="column_spacing">5</property>
331 <property name="row_spacing">5</property>
332 <child>
333 <widget class="GtkLabel" id="label11">
334 <property name="visible">True</property>
335 <property name="xalign">0</property>
336 <property name="label" translatable="yes">Description:</property>
337 </widget>
338 <packing>
339 <property name="x_options">GTK_FILL</property>
340 </packing>
341 </child>
342 <child>
343 <widget class="GtkLabel" id="label12">
344 <property name="visible">True</property>
345 <property name="xalign">0</property>
346 <property name="label" translatable="yes">Date:</property>
347 </widget>
348 <packing>
349 <property name="top_attach">1</property>
350 <property name="bottom_attach">2</property>
351 <property name="x_options">GTK_FILL</property>
352 </packing>
353 </child>
354 <child>
355 <widget class="GtkEntry" id="description">
356 <property name="visible">True</property>
357 <property name="can_focus">True</property>
358 <property name="invisible_char">&#x25CF;</property>
359 </widget>
360 <packing>
361 <property name="left_attach">1</property>
362 <property name="right_attach">2</property>
363 </packing>
364 </child>
365 <child>
366 <widget class="GtkHButtonBox" id="hbuttonbox1">
367 <property name="visible">True</property>
368 <property name="layout_style">start</property>
369 <child>
370 <widget class="GtkButton" id="date">
371 <property name="visible">True</property>
372 <property name="can_focus">True</property>
373 <property name="receives_default">True</property>
374 <signal name="clicked" handler="on_date_clicked"/>
375 </widget>
376 <packing>
377 <property name="expand">False</property>
378 <property name="fill">False</property>
379 <property name="position">0</property>
380 </packing>
381 </child>
382 </widget>
383 <packing>
384 <property name="left_attach">1</property>
385 <property name="right_attach">2</property>
386 <property name="top_attach">1</property>
387 <property name="bottom_attach">2</property>
388 </packing>
389 </child>
390 </widget>
391 <packing>
392 <property name="expand">False</property>
393 <property name="fill">False</property>
394 <property name="position">4</property>
395 </packing>
396 </child>
397 <child>
398 <widget class="GtkHSeparator" id="hseparator3">
399 <property name="visible">True</property>
400 </widget>
401 <packing>
402 <property name="expand">False</property>
403 <property name="position">5</property>
404 </packing>
405 </child>
406 <child>
407 <widget class="GtkScrolledWindow" id="scrolledwindow1">
408 <property name="visible">True</property>
409 <property name="can_focus">True</property>
410 <property name="border_width">5</property>
411 <property name="hscrollbar_policy">automatic</property>
412 <property name="vscrollbar_policy">automatic</property>
413 <child>
414 <widget class="GtkTextView" id="comments">
415 <property name="visible">True</property>
416 <property name="can_focus">True</property>
417 </widget>
418 </child>
419 </widget>
420 <packing>
421 <property name="position">6</property>
422 </packing>
423 </child>
424 </widget>
425 </child>
426 </widget>
427 <widget class="GtkDialog" id="calendar_dialog">
428 <property name="border_width">5</property>
429 <property name="type_hint">normal</property>
430 <property name="has_separator">False</property>
431 <child internal-child="vbox">
432 <widget class="GtkVBox" id="dialog-vbox1">
433 <property name="visible">True</property>
434 <property name="orientation">vertical</property>
435 <property name="spacing">2</property>
436 <child>
437 <widget class="GtkCalendar" id="calendar">
438 <property name="visible">True</property>
439 <property name="can_focus">True</property>
440 <property name="year">2009</property>
441 <property name="month">4</property>
442 <property name="day">27</property>
443 </widget>
444 <packing>
445 <property name="position">1</property>
446 </packing>
447 </child>
448 <child internal-child="action_area">
449 <widget class="GtkHButtonBox" id="dialog-action_area1">
450 <property name="visible">True</property>
451 <property name="layout_style">end</property>
452 <child>
453 <widget class="GtkButton" id="cancel">
454 <property name="label" translatable="yes">gtk-cancel</property>
455 <property name="visible">True</property>
456 <property name="can_focus">True</property>
457 <property name="receives_default">True</property>
458 <property name="use_stock">True</property>
459 </widget>
460 <packing>
461 <property name="expand">False</property>
462 <property name="fill">False</property>
463 <property name="position">0</property>
464 </packing>
465 </child>
466 <child>
467 <widget class="GtkButton" id="ok">
468 <property name="label" translatable="yes">gtk-ok</property>
469 <property name="response_id">1</property>
470 <property name="visible">True</property>
471 <property name="can_focus">True</property>
472 <property name="receives_default">True</property>
473 <property name="use_stock">True</property>
474 </widget>
475 <packing>
476 <property name="expand">False</property>
477 <property name="fill">False</property>
478 <property name="position">1</property>
479 </packing>
480 </child>
481 </widget>
482 <packing>
483 <property name="expand">False</property>
484 <property name="pack_type">end</property>
485 <property name="position">0</property>
486 </packing>
487 </child>
488 </widget>
489 </child>
490 </widget>
491 <widget class="GtkDialog" id="movement_dialog">
492 <property name="border_width">5</property>
493 <property name="type_hint">normal</property>
494 <property name="has_separator">False</property>
495 <child internal-child="vbox">
496 <widget class="GtkVBox" id="dialog-vbox2">
497 <property name="visible">True</property>
498 <property name="orientation">vertical</property>
499 <property name="spacing">2</property>
500 <child>
501 <widget class="GtkTreeView" id="movements">
502 <property name="visible">True</property>
503 <property name="can_focus">True</property>
504 </widget>
505 <packing>
506 <property name="position">1</property>
507 </packing>
508 </child>
509 <child internal-child="action_area">
510 <widget class="GtkHButtonBox" id="dialog-action_area2">
511 <property name="visible">True</property>
512 <property name="layout_style">end</property>
513 <child>
514 <widget class="GtkButton" id="cancel">
515 <property name="label" translatable="yes">gtk-cancel</property>
516 <property name="visible">True</property>
517 <property name="can_focus">True</property>
518 <property name="receives_default">True</property>
519 <property name="use_stock">True</property>
520 </widget>
521 <packing>
522 <property name="expand">False</property>
523 <property name="fill">False</property>
524 <property name="position">0</property>
525 </packing>
526 </child>
527 <child>
528 <widget class="GtkButton" id="ok">
529 <property name="label" translatable="yes">gtk-ok</property>
530 <property name="response_id">1</property>
531 <property name="visible">True</property>
532 <property name="can_focus">True</property>
533 <property name="receives_default">True</property>
534 <property name="use_stock">True</property>
535 </widget>
536 <packing>
537 <property name="expand">False</property>
538 <property name="fill">False</property>
539 <property name="position">1</property>
540 </packing>
541 </child>
542 </widget>
543 <packing>
544 <property name="expand">False</property>
545 <property name="pack_type">end</property>
546 <property name="position">0</property>
547 </packing>
548 </child>
549 </widget>
550 </child>
551 </widget>
552</glade-interface>
diff --git a/exifilm.gladep b/exifilm.gladep
new file mode 100644
index 0000000..407c797
--- /dev/null
+++ b/exifilm.gladep
@@ -0,0 +1,8 @@
1<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
2<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
3
4<glade-project>
5 <name>Exifilm</name>
6 <program_name>exifilm</program_name>
7 <gnome_support>FALSE</gnome_support>
8</glade-project>
diff --git a/exifilm.py b/exifilm.py
new file mode 100644
index 0000000..17db62d
--- /dev/null
+++ b/exifilm.py
@@ -0,0 +1,383 @@
1#!/usr/bin/python
2
3# ExiFilm -- Add film exposure metadata to EXIF tags of digital images
4# Copyright (C) 2009 James E. Blair <corvus@gnu.org>
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19import pygtk
20pygtk.require('2.0')
21import gtk, gobject
22import gtk.glade
23import gtk.keysyms
24from gtk import gdk
25
26import os, sys
27import pyexiv2
28import datetime
29import decimal, fractions
30import re
31
32HALF_STOP_SCALE = ['1', '1.2', '1.4', '1.7', '2', '2.4', '2.8', '3.3', '4', '4.8',
33 '5.6', '6.7', '8', '9.5', '11', '13', '16', '19', '22', '27',
34 '32', '38', '45', '54', '64', '76', '91']
35
36
37THIRD_STOP_SCALE = ['1', '1.1', '1.2', '1.4', '1.6', '1.8', '2', '2.2', '2.5',
38 '2.8', '3.2', '3.5', '4', '4.5', '5.0', '5.6', '6.3', '7.1',
39 '8', '9', '10', '11', '13', '14', '16', '18', '20', '22',
40 '25', '29', '32', '36', '40', '45', '51', '57', '64', '72',
41 '81', '91']
42
43CAMERA_MOVEMENTS = [
44 'rising',
45 'falling',
46 'forward tilt',
47 'backward tilt',
48 'left shift',
49 'right shift',
50 'left swing',
51 'right swing',
52 ]
53
54ID = 'ID'
55FILM = 'Film'
56CARRIER = 'Carrier'
57PROCESS = 'Process'
58FRONT_MOVEMENTS = 'Front movements'
59REAR_MOVEMENTS = 'Rear movements'
60
61PRIVATE_KEYS = [
62 ID,
63 FILM,
64 CARRIER,
65 PROCESS,
66 FRONT_MOVEMENTS,
67 REAR_MOVEMENTS,
68 ]
69
70ISO_RE = re.compile(r'\d\d+')
71
72def to_rational(v):
73 if '/' in v:
74 n,d = v.split('/')
75 else:
76 n,d = (v,1)
77 return pyexiv2.Rational(int(n), int(d))
78
79def from_rational(v):
80 if not v: return v
81 n,d = str(v).split('/')
82 if d == '1':
83 return str(n)
84 return str(v)
85
86def from_fstop(v):
87 if '/' in v:
88 whole, frac = v.split(' ')
89 n,d = frac.split('/')
90 if d == '2': scale = HALF_STOP_SCALE
91 if d == '3': scale = THIRD_STOP_SCALE
92 i = scale.index(whole)
93 i += int(n)
94 f = fractions.Fraction.from_decimal(decimal.Decimal(str(scale[i])))
95 return str(f)
96 f = fractions.Fraction.from_decimal(decimal.Decimal(v))
97 return str(f)
98
99def to_fstop(v):
100 if '/' in v:
101 n,d = v.split('/')
102 return str(float(n)/float(d))
103 return v
104
105def encode_comments(d, comments):
106 ret = ''
107 for k in PRIVATE_KEYS:
108 if k in d.keys():
109 ret += '%s: %s\n' % (k, d[k])
110 ret += '\n'+comments
111 return ret
112
113def decode_comments(comments):
114 d = {}
115 ret = ''
116 lines = comments.split('\n')
117 while lines:
118 line = lines.pop(0).strip()
119 if not line: break
120 if ':' in line:
121 k,v = line.split(':', 1)
122 d[k.strip()] = v.strip()
123 else:
124 ret += line+'\n'
125 break
126 return d, ret+'\n'.join(lines)
127
128class ExiFilm(object):
129
130 def __init__(self):
131 self.image = None
132 self.xml = gtk.glade.XML('exifilm.glade', 'main_window')
133
134 self.file_combo = self.xml.get_widget('file')
135
136 self.id_entry = self.xml.get_widget('id')
137 self.film_entry = self.xml.get_widget('film')
138 self.carrier_entry = self.xml.get_widget('carrier')
139 self.process_entry = self.xml.get_widget('process')
140 self.lens_entry = self.xml.get_widget('lens')
141 self.aperture_entry = self.xml.get_widget('aperture')
142 self.shutter_entry = self.xml.get_widget('shutter')
143
144 self.front_button = self.xml.get_widget('front')
145 self.rear_button = self.xml.get_widget('rear')
146
147 self.description_entry = self.xml.get_widget('description')
148 self.date_button = self.xml.get_widget('date')
149
150 self.comments_text = self.xml.get_widget('comments')
151 self.comments_buffer = gtk.TextBuffer()
152 self.comments_text.set_buffer(self.comments_buffer)
153
154 # Keep the last selected date to provide a sane default
155 self.lastdate = None
156
157 dic = {
158 'on_main_window_destroy': self.window_closed,
159 'on_main_window_key_press_event': self.key_press,
160 'on_date_clicked': self.date_clicked,
161 'on_front_clicked': self.front_clicked,
162 'on_rear_clicked': self.rear_clicked,
163 'on_file_changed': self.file_changed,
164 }
165
166 self.xml.signal_autoconnect (dic)
167
168 self.file_store = gtk.ListStore(gobject.TYPE_STRING)
169 cell = gtk.CellRendererText()
170 self.file_combo.pack_start(cell, True)
171 self.file_combo.add_attribute(cell, 'text', 0)
172 self.file_combo.set_model(self.file_store)
173
174 self.filename = None
175 first = None
176 self.directory = '.'
177 if len(sys.argv)>1:
178 self.directory = sys.argv[1]
179 files = os.listdir(self.directory)
180 files.sort()
181 for fn in files:
182 if not (fn.lower().endswith('.jpeg') or
183 fn.lower().endswith('.jpg')):
184 continue
185 if not first: first = fn
186 self.file_store.append((fn,))
187 if first:
188 self.file_combo.set_active(0)
189
190 def file_changed(self, widget, data=None):
191 if self.filename:
192 self.save()
193 i = self.file_combo.get_active()
194 fn = self.file_store[i][0]
195 self.load(fn)
196 self.id_entry.grab_focus()
197
198 def key_press(self, widget, data=None):
199 if data.keyval == gtk.keysyms.Page_Up:
200 i = self.file_combo.get_active()
201 if i>0:
202 self.file_combo.set_active(i-1)
203 return True
204
205 if data.keyval == gtk.keysyms.Page_Down:
206 i = self.file_combo.get_active()
207 if i<len(self.file_store)-1:
208 self.file_combo.set_active(i+1)
209 return True
210
211 def load(self, fn):
212 fn = os.path.join(self.directory, fn)
213 self.filename = fn
214
215 image = pyexiv2.Image(fn)
216 image.readMetadata()
217 keys = image.exifKeys()
218 self.image = image
219
220 def get(key, default=''):
221 if key in keys:
222 return image[key]
223 return default
224
225 self.date = get('Exif.Photo.DateTimeOriginal', None)
226 if self.date:
227 self.date_button.set_label(str(self.date.date()))
228 else:
229 self.date_button.set_label('Set')
230
231 self.shutter_entry.set_text(from_rational(get('Exif.Photo.ExposureTime')))
232 self.aperture_entry.set_text(to_fstop(from_rational(get('Exif.Photo.FNumber'))))
233 self.lens_entry.set_text(from_rational(get('Exif.Photo.FocalLength')))
234
235 self.description_entry.set_text(get('Exif.Image.ImageDescription'))
236 extras, comments = decode_comments(get('Exif.Photo.UserComment'))
237 self.comments_buffer.set_text(comments)
238
239 self.id_entry.set_text(extras.get(ID, ''))
240 self.film_entry.set_text(extras.get(FILM, ''))
241 self.carrier_entry.set_text(extras.get(CARRIER, ''))
242 self.process_entry.set_text(extras.get(PROCESS, ''))
243
244 self.front_movements = extras.get(FRONT_MOVEMENTS, '')
245 if self.front_movements:
246 self.front_button.set_label(self.front_movements)
247 else:
248 self.front_button.set_label('None')
249
250 self.rear_movements = extras.get(REAR_MOVEMENTS, '')
251 if self.rear_movements:
252 self.rear_button.set_label(self.rear_movements)
253 else:
254 self.rear_button.set_label('None')
255
256 def save(self):
257 if self.date:
258 self.image['Exif.Photo.DateTimeOriginal'] = self.date
259 v = self.shutter_entry.get_text()
260 if v: self.image['Exif.Photo.ExposureTime'] = to_rational(v)
261 v = self.aperture_entry.get_text()
262 if v: self.image['Exif.Photo.FNumber'] = to_rational(from_fstop(v))
263 v = self.lens_entry.get_text()
264 if v: self.image['Exif.Photo.FocalLength'] = to_rational(v)
265 v = self.description_entry.get_text()
266 if v: self.image['Exif.Image.ImageDescription'] = v
267
268 extras = {}
269
270 v = self.id_entry.get_text()
271 if v: extras[ID] = v
272 v = self.film_entry.get_text()
273 if v:
274 extras[FILM] = v
275 m = ISO_RE.search(v)
276 if m:
277 iso = int(m.group(0))
278 self.image['Exif.Photo.ISOSpeedRatings'] = iso
279 v = self.carrier_entry.get_text()
280 if v: extras[CARRIER] = v
281 v = self.process_entry.get_text()
282 if v: extras[PROCESS] = v
283 if self.front_movements:
284 extras[FRONT_MOVEMENTS] = self.front_movements
285 if self.rear_movements:
286 extras[REAR_MOVEMENTS] = self.rear_movements
287
288 bounds = self.comments_buffer.get_bounds()
289 v = self.comments_buffer.get_text(bounds[0], bounds[1])
290 if v or extras:
291 self.image['Exif.Photo.UserComment'] = encode_comments(extras, v)
292
293 self.image.writeMetadata()
294
295 def window_closed(self, widget, data=None):
296 if self.image:
297 self.save()
298 gtk.main_quit()
299
300 def date_clicked(self, widget, data=None):
301 xml = gtk.glade.XML('exifilm.glade', 'calendar_dialog')
302 calendar_dialog = xml.get_widget('calendar_dialog')
303 calendar = xml.get_widget('calendar')
304 if self.date:
305 date = self.date
306 else:
307 if self.lastdate:
308 date = self.lastdate
309 else:
310 date = datetime.datetime.now()
311 calendar.select_month(date.month-1, date.year)
312 calendar.select_day(date.day)
313 r = calendar_dialog.run()
314 if r:
315 date = calendar.get_date()
316 self.date = datetime.datetime(date[0], date[1]+1, date[2])
317 self.lastdate = self.date
318 self.date_button.set_label(str(self.date.date()))
319 calendar_dialog.destroy()
320
321 def front_clicked(self, widget, data=None):
322 moves = self.front_movements.split('/')
323 moves = self.get_movements(moves)
324 self.front_movements = '/'.join(moves)
325 if self.front_movements:
326 self.front_button.set_label(self.front_movements)
327 else:
328 self.front_button.set_label('None')
329
330 def rear_clicked(self, widget, data=None):
331 moves = self.rear_movements.split('/')
332 moves = self.get_movements(moves)
333 self.rear_movements = '/'.join(moves)
334 if self.rear_movements:
335 self.rear_button.set_label(self.rear_movements)
336 else:
337 self.rear_button.set_label('None')
338
339 def get_movements(self, orig_movements):
340 xml = gtk.glade.XML('exifilm.glade', 'movement_dialog')
341 dialog = xml.get_widget('movement_dialog')
342 tree_view = xml.get_widget('movements')
343
344 column = gtk.TreeViewColumn("Movements")
345 renderer=gtk.CellRendererText()
346 column.pack_start(renderer,0)
347 column.add_attribute(renderer, 'text', 0)
348 tree_view.append_column(column)
349
350 tree_store = gtk.TreeStore(str)
351 tree_view.set_model(tree_store)
352 tree_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
353 for i,m in enumerate(CAMERA_MOVEMENTS):
354 tree_store.append(None, (m,))
355 if m in orig_movements:
356 tree_view.get_selection().select_path((i,))
357
358 r = dialog.run()
359 if r:
360 store, rows = tree_view.get_selection().get_selected_rows()
361 ret = []
362 for row in rows:
363 ret.append(tree_store.get_value(tree_store.get_iter(row), 0))
364 else:
365 ret = orig_movements
366 dialog.destroy()
367 return ret
368
369def main():
370 gdk.threads_init()
371 gdk.threads_enter()
372 ExiFilm()
373 gtk.main()
374 gdk.threads_leave()
375
376if __name__=='__main__':
377 if len(sys.argv)>1 and sys.argv[1][0]=='-':
378 print "Usage: %s [PATH]" % sys.argv[0]
379 print
380 print " PATH is a directory with JPEG files to edit."
381 print " PATH defaults to the current directory."
382 else:
383 main()
diff --git a/lfrecord.ps b/lfrecord.ps
new file mode 100644
index 0000000..23153c1
--- /dev/null
+++ b/lfrecord.ps
@@ -0,0 +1,781 @@
1%!PS-Adobe-3.0
2%%Pages: 1
3%%BoundingBox: 0 0 612 792
4%%EndComments
5%%Page: 1 1
6
7% ExiFilm -- Add film exposure metadata to EXIF tags of digital images
8% Copyright (C) 2009 James E. Blair <corvus@gnu.org>
9%
10% This program is free software: you can redistribute it and/or modify
11% it under the terms of the GNU General Public License as published by
12% the Free Software Foundation, either version 3 of the License, or
13% (at your option) any later version.
14%
15% This program is distributed in the hope that it will be useful,
16% but WITHOUT ANY WARRANTY; without even the implied warranty of
17% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18% GNU General Public License for more details.
19%
20% You should have received a copy of the GNU General Public License
21% along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23% User servicable:
24
25/in { 72 mul } def
26
27/cellheight 12.75 def
28/plantop 9.75 in def % 8.5 - .5 in at top
29/planleft 7 32 div in def
30/planwidth 3 in 15 16 div in add def
31
32% 3 15/16 in wide
33% 5 in high
34
35/normalfont {/Times-Roman 10 selectfont} def
36/smallfont {/Times-Roman 8 selectfont} def
37
38/baselineskip 12 def
391 setlinewidth
40
41% Less user servicable:
42
43/planheight 21 cellheight mul def
44/condtop plantop planheight sub def
45/condleft planleft def
46/condheight 11 cellheight mul def
47
48/cell {/cury curx cury wd cellht box def} def
49/cell1 {curx cury wd1 cellht box pop} def
50/cell2cr {/cury curx wd1 add cury wd2 cellht box def} def
51/cell3cr {/cury curx wd1 add wd2 add cury wd3 cellht box def} def
52/cell2 {curx wd1 add cury wd2 cellht box pop} def
53/cell3 {curx wd1 add wd2 add cury wd3 cellht box pop} def
54/triangle {newpath curx cury moveto 6 0 cellht 2 div sub rlineto
55 -6 0 cellht 2 div sub rlineto closepath fill} def
56
57
58/toppic
59{
600 18 translate
610.8 -0.8 scale
620 0 0 setrgbcolor
63[] 0 setdash
641 setlinewidth
650 setlinejoin
660 setlinecap
67gsave [1 0 0 1 0 0] concat
680 0 0 setrgbcolor
69[] 0 setdash
700.625 setlinewidth
711 setlinejoin
721 setlinecap
73newpath
7417.465566 7.6270604 moveto
7517.34201 7.4607341 17.023642 7.1667431 16.801411 7.0511098 curveto
7616.503644 6.896187 16.307292 6.8516095 16.026569 6.7055509 curveto
7715.791517 6.5832505 15.419851 6.5327667 15.14103 6.5327667 curveto
7814.851109 6.5327667 14.510791 6.4751688 14.200137 6.4751688 curveto
7913.906717 6.4751688 13.544314 6.6414571 13.314598 6.8207372 curveto
8013.068846 7.0125432 12.874548 7.2361726 12.595099 7.4542762 curveto
8112.344743 7.6496678 12.125565 7.8753705 11.930944 8.1454035 curveto
8211.751845 8.3938944 11.61173 8.7253772 11.543518 9.0093151 curveto
8311.483134 9.2606497 11.432821 9.6008921 11.432821 9.9308246 curveto
8411.432821 10.284991 11.481859 10.646709 11.543518 10.96752 curveto
8511.606347 11.294419 11.689348 11.459357 11.764903 11.773844 curveto
8611.826229 12.029125 12.085382 12.337715 12.207673 12.464971 curveto
8712.411225 12.676797 12.681981 12.913342 12.927172 13.040921 curveto
8813.208038 13.187056 13.356056 13.321654 13.591326 13.444078 curveto
8913.894704 13.60193 14.210656 13.770986 14.532219 13.904833 curveto
9014.799874 14.016243 15.064115 14.020019 15.362414 14.020019 curveto
9115.668037 14.020019 15.886968 14.041942 16.1926 13.962421 curveto
9216.488636 13.885412 16.686938 13.733028 16.912108 13.674451 curveto
9317.175607 13.605906 17.382184 13.372271 17.576263 13.271294 curveto
9417.802565 13.15354 17.966257 13.038239 18.12972 12.868137 curveto
9518.33059 12.659107 18.448373 12.636072 18.517146 12.349785 curveto
9618.58201 12.07978 18.683187 12.005006 18.683187 11.658657 curveto
9718.683187 11.370687 18.683187 11.082707 18.683187 10.794746 curveto
9818.683187 10.482732 18.689036 10.243133 18.627843 9.9884225 curveto
9918.56315 9.7191599 18.57249 9.4050915 18.57249 9.1245109 curveto
10018.57249 8.8389752 18.46301 8.6086787 18.351105 8.3757857 curveto
10118.246685 8.158462 18.001799 8.0698776 17.852991 7.9150309 curveto
10217.675889 7.730729 17.748724 7.7007222 17.465566 7.6270604 curveto
103closepath
104stroke
1050 0 0 setrgbcolor
106[] 0 setdash
1070.625 setlinewidth
1081 setlinejoin
1091 setlinecap
110newpath
11118.908969 9.1187484 moveto
11219.132586 9.2148318 19.670178 9.5204546 19.889559 9.6723899 curveto
11320.225854 9.9053021 20.525329 9.9224118 20.835946 10.076851 curveto
11421.210027 10.262847 21.490107 10.364636 21.849811 10.465301 curveto
11522.38606 10.615383 21.920523 10.684453 21.563764 10.76915 curveto
11621.276372 10.837386 20.927903 10.920113 20.619207 10.993399 curveto
11720.270784 11.076118 19.970536 11.147404 19.607192 11.233666 curveto
11819.449759 11.271042 19.292336 11.308417 19.134913 11.345791 curveto
119stroke
1200 0 0 setrgbcolor
121[] 0 setdash
1220.625 setlinewidth
1231 setlinejoin
1241 setlinecap
125newpath
12612.479003 7.3178906 moveto
12712.297483 7.2051594 10.437915 6.743884 10.199405 6.6961819 curveto
1289.9461844 6.6455378 8.2389814 6.412102 8.4897064 6.4371367 curveto
1298.9210134 6.4802021 7.6023054 6.3853275 7.3499064 6.3853275 curveto
1307.1865764 6.3853275 6.6748094 6.3424179 6.2101074 6.3853275 curveto
1315.9802984 6.4065477 4.6730454 6.5580544 4.3967904 6.6961819 curveto
1324.1597714 6.8146914 3.9322444 6.8766459 3.6714644 7.0070363 curveto
1333.3812444 7.1521462 3.1878204 7.2920552 2.9461374 7.4733178 curveto
1342.7386724 7.6289163 2.4671594 7.8455027 2.2726194 7.9914084 curveto
1352.0299164 8.1734353 1.8916084 8.3206101 1.7027194 8.5094989 curveto
1361.5052674 8.706951 1.4151344 8.8256235 1.2882464 9.0793985 curveto
1371.1595274 9.3368386 1.0339524 9.4843697 0.92558337 9.7011073 curveto
1380.78229837 9.9876779 0.64040737 10.116486 0.56292037 10.426434 curveto
1390.50396737 10.662246 0.51591437 10.873501 0.45930237 11.099952 curveto
1400.39136637 11.371693 0.56233537 11.565062 0.66653837 11.77347 curveto
1410.76972037 11.979834 1.0569594 12.231766 1.1846294 12.395178 curveto
1421.4171204 12.692756 1.6462124 12.974507 1.9099554 13.172314 curveto
1432.2042814 13.393059 2.9527384 13.952751 3.2569914 14.104877 curveto
1444.1361764 14.565305 4.7738594 14.88324 5.7438264 14.985631 curveto
1456.1202154 15.079729 7.3525084 15.363749 8.8005604 15.192867 curveto
1469.8815834 15.065298 10.824802 14.750645 11.494631 14.260304 curveto
14712.29744 13.766723 12.403624 13.534597 12.789858 13.120505 curveto
148stroke
149grestore
150} def
151
152/sidepic
153{
1540 18 translate
1550.8 -0.8 scale
1560 0 0 setrgbcolor
157[] 0 setdash
1581 setlinewidth
1590 setlinejoin
1600 setlinecap
161gsave [1 0 0 1 0 0] concat
1620 0 0 setrgbcolor
163[] 0 setdash
1640.625 setlinewidth
1651 setlinejoin
1661 setlinecap
167newpath
16817.41745 3.3235764 moveto
16917.28754 3.1486964 16.9528 2.8395864 16.71914 2.7180064 curveto
17016.40606 2.5551164 16.19961 2.5082464 15.90445 2.3546764 curveto
17115.65731 2.2260864 15.26653 2.1730064 14.97337 2.1730064 curveto
17214.66854 2.1730064 14.31072 2.1124464 13.98409 2.1124464 curveto
17313.67558 2.1124464 13.29454 2.2872864 13.05301 2.4757864 curveto
17412.79462 2.6774564 12.59033 2.9125864 12.296511 3.1419064 curveto
17512.033281 3.3473464 11.802831 3.5846564 11.598201 3.8685764 curveto
17611.409891 4.1298464 11.262571 4.4783764 11.190851 4.7769164 curveto
17711.127361 5.0411764 11.074461 5.3989164 11.074461 5.7458164 curveto
17811.074461 6.1181964 11.126021 6.4985164 11.190851 6.8358264 curveto
17911.256911 7.1795364 11.344181 7.3529564 11.423621 7.6836164 curveto
18011.488101 7.9520264 11.760581 8.2764864 11.889161 8.4102864 curveto
18112.103181 8.6330064 12.387861 8.8817164 12.64566 9.0158564 curveto
18212.94097 9.1695064 13.0966 9.3110264 13.34397 9.4397464 curveto
18313.66295 9.6057164 13.99515 9.7834664 14.33325 9.9241964 curveto
18414.61467 10.041336 14.8925 10.045306 15.20614 10.045306 curveto
18515.52748 10.045306 15.75767 10.068356 16.07902 9.9847464 curveto
18616.39028 9.9037764 16.59878 9.7435564 16.83553 9.6819664 curveto
18717.11258 9.6098964 17.32978 9.3642464 17.53384 9.2580764 curveto
18817.77178 9.1342664 17.94389 9.0130364 18.11576 8.8341864 curveto
18918.32696 8.6144064 18.4508 8.5901864 18.52311 8.2891764 curveto
19018.59131 8.0052864 18.69769 7.9266664 18.69769 7.5625064 curveto
19118.69769 7.2597264 18.69769 6.9569364 18.69769 6.6541664 curveto
19218.69769 6.3261064 18.70384 6.0741864 18.6395 5.8063764 curveto
19318.57148 5.5232664 18.5813 5.1930464 18.5813 4.8980364 curveto
19418.5813 4.5978164 18.46619 4.3556764 18.34853 4.1108064 curveto
19518.23874 3.8823064 17.98126 3.7891664 17.8248 3.6263564 curveto
19617.63859 3.4325764 17.71517 3.4010264 17.41745 3.3235764 curveto
197closepath
198stroke
1990 0 0 setrgbcolor
200[] 0 setdash
2010.625 setlinewidth
2021 setlinejoin
2031 setlinecap
204newpath
20518.94656 5.9379964 moveto
20619.1584 6.0815564 19.65288 6.5037464 19.84927 6.7041364 curveto
20720.15032 7.0113264 20.45615 7.0883864 20.74625 7.3094564 curveto
20821.09562 7.5756964 21.36463 7.7363464 21.716081 7.9116264 curveto
20922.240021 8.1729464 21.745631 8.1519364 21.36046 8.1686364 curveto
21021.05018 8.1820964 20.67396 8.1984064 20.34068 8.2128564 curveto
21119.96451 8.2291664 19.64035 8.2432264 19.24807 8.2602364 curveto
21219.0781 8.2676064 18.90814 8.2749764 18.73818 8.2823464 curveto
213stroke
2140 0 0 setrgbcolor
215[] 0 setdash
2160.625 setlinewidth
2171 setlinejoin
2181 setlinecap
219newpath
22011.058081 6.3609964 moveto
22110.898991 6.3609964 10.297991 6.3609964 9.9236506 6.3609964 curveto
2229.6528706 6.3609964 9.2296906 6.4606964 9.0019306 6.5275864 curveto
2238.6792106 6.6223764 8.3901106 6.6031664 8.0802106 6.6941864 curveto
2247.7549906 6.7896964 7.3425006 6.8692064 7.0875806 6.9440764 curveto
2256.7203606 7.0519264 6.3784006 7.1731864 6.0240506 7.2772664 curveto
2265.6876206 7.3760764 5.4495006 7.5314764 5.1732306 7.6937564 curveto
2274.8089906 7.9077164 4.5570206 8.1390264 4.1806106 8.3601364 curveto
2283.8315206 8.5651864 3.5054206 9.0700664 3.2588806 9.3597064 curveto
2292.9162706 9.7622164 2.6772606 10.143226 2.4789706 10.609166 curveto
2302.2757806 11.086586 2.1067606 11.567026 1.9117506 12.025216 curveto
2311.7229306 12.468886 1.5183906 12.957456 1.4154406 13.441276 curveto
2321.3145406 13.915446 1.0273606 14.353136 0.84822058 14.774036 curveto
2330.65579058 15.226186 0.63552058 15.643266 0.63552058 15.773606 curveto
234stroke
2350 0 0 setrgbcolor
236[] 0 setdash
2370.625 setlinewidth
2381 setlinejoin
2391 setlinecap
240newpath
24114.33933 10.302876 moveto
24214.20693 10.595156 14.14423 11.072806 13.90194 11.429396 curveto
24313.70442 11.720106 13.37015 12.016406 13.17297 12.234056 curveto
24412.88897 12.547546 12.59356 12.873636 12.298201 13.199656 curveto
24512.020021 13.506716 11.823431 13.804186 11.496341 14.165246 curveto
24611.169801 14.525686 10.912571 14.749106 10.548671 15.050376 curveto
24710.232431 15.312176 9.7936806 15.426826 9.4552106 15.613636 curveto
2489.1243106 15.796266 8.5739906 15.756236 8.2159606 15.855036 curveto
2497.8258106 15.962696 7.3481706 15.832996 6.9767106 15.935496 curveto
2506.5954506 16.040716 6.0587306 15.935496 5.6645506 15.935496 curveto
2515.2171706 15.935496 4.8659706 16.015966 4.4253006 16.015966 curveto
2524.0136906 16.015966 3.5635006 15.935496 3.1131506 15.935496 curveto
2532.7207406 15.935496 2.2370206 15.733586 2.0196906 15.613636 curveto
2541.7663706 15.473826 1.1338906 15.325916 1.0720306 15.291776 curveto
255stroke
2560 0 0 setrgbcolor
257[] 0 setdash
2580.63630593 setlinewidth
2591 setlinejoin
2601 setlinecap
261newpath
2629.9264619 15.524615 moveto
2639.601864 15.336485 9.9988871 16.363201 9.9988871 16.783897 curveto
2649.9988871 17.343824 9.8991612 17.884929 9.9988871 18.462927 curveto
26510.104136 19.072974 9.9702746 19.353219 10.288574 19.722199 curveto
26610.538501 20.011916 10.948726 20.272725 11.157634 20.393812 curveto
26711.29979 20.476203 11.505777 20.474522 11.519735 20.477757 curveto
268stroke
2690 0 0 setrgbcolor
270[] 0 setdash
2710.625 setlinewidth
2721 setlinejoin
2731 setlinecap
274newpath
27510.213238 19.68757 moveto
27610.382008 19.78072 9.6081369 20.54456 9.4113669 20.65317 curveto
2779.2846369 20.72311 9.1736069 20.82462 9.0468769 20.89457 curveto
278stroke
2790 0 0 setrgbcolor
280[] 0 setdash
2810.625 setlinewidth
2821 setlinejoin
2831 setlinecap
284newpath
2856.5393206 16.015966 moveto
2866.2133206 16.195896 6.5393206 16.820626 6.5393206 17.222956 curveto
2876.5393206 17.627916 6.5393206 17.996046 6.5393206 18.429956 curveto
2886.5393206 18.885926 6.5393206 19.341896 6.5393206 19.797876 curveto
2896.5393206 19.821846 7.2722806 20.242636 7.3411906 20.280676 curveto
2907.3483106 20.418036 7.4383906 20.334316 7.4869906 20.361136 curveto
291stroke
2920 0 0 setrgbcolor
293[] 0 setdash
2940.625 setlinewidth
2951 setlinejoin
2961 setlinecap
297newpath
2986.5393206 19.797876 moveto
2996.8774206 19.984476 6.0047406 20.387956 5.7374506 20.683006 curveto
3005.6645606 20.763466 5.5916606 20.843936 5.5187606 20.924396 curveto
301stroke
302gsave
3030 0 0 setrgbcolor
304newpath
30516.59914 4.9921064 moveto
30616.75393 5.5208564 16.53852 5.6023764 16.16176 5.3944364 curveto
30715.78595 5.1870264 16.27681 4.8497864 16.59914 4.9921064 curveto
308closepath
309fill
310grestore
3110 0 0 setrgbcolor
312[] 0 setdash
3130.625 setlinewidth
3141 setlinejoin
3151 setlinecap
316newpath
31716.59914 4.9921064 moveto
31816.75393 5.5208564 16.53852 5.6023764 16.16176 5.3944364 curveto
31915.78595 5.1870264 16.27681 4.8497864 16.59914 4.9921064 curveto
320closepath
321stroke
322grestore
323} def
324
325/greybox
326 {
327 /height exch def
328 /width exch def
329 /top exch def
330 /left exch def
331
332 /bottom top height sub def
333
334 .8 .8 .8 setrgbcolor
335 left bottom width height rectfill
336 0 0 0 setrgbcolor
337 left bottom width height rectstroke
338 bottom
339 } def
340
341/blackbox
342 {
343 /height exch def
344 /width exch def
345 /top exch def
346 /left exch def
347
348 /bottom top height sub def
349
350 0 0 0 setrgbcolor
351 left bottom width height rectfill
352 left bottom width height rectstroke
353 bottom
354 } def
355
356/box
357 {
358 /height exch def
359 /width exch def
360 /top exch def
361 /left exch def
362
363 /bottom top height sub def
364
365 0 0 0 setrgbcolor
366 left bottom width height rectstroke
367 bottom
368 } def
369
370/writingline
371 {
372 /height exch def
373 /width exch def
374 /top exch def
375 /left exch def
376
377 /bottom top height sub def
378
379 .125 setlinewidth
380 left bottom moveto width 0 rlineto stroke
381 1 setlinewidth
382 bottom
383 } def
384
385
386/centertext
387 {
388 /s exch def
389 /x2 exch def
390 /x1 exch def
391 /y exch def
392
393 x2 x1 sub 2 div x1 add % midpoint
394 s stringwidth pop 2 div % half the string width
395 sub % move left to start
396
397 y baselineskip sub moveto s show
398 y baselineskip sub
399 } def
400
401/righttext
402 {
403 /s exch def
404 /x2 exch def
405 /x1 exch def
406 /y exch def
407
408 x2
409 s stringwidth pop
410 sub 1 sub
411
412 y baselineskip sub moveto s show
413 y baselineskip sub
414 } def
415
416/lefttext
417 {
418 /s exch def
419 /x2 exch def
420 /x1 exch def
421 /y exch def
422
423 x1 1 add
424
425 y baselineskip sub moveto s show
426 y baselineskip sub
427 } def
428
429
430/picid
431 {
432 /cury exch def
433 /curx exch def
434 /wd 42 def
435 /headht 1 cellheight mul def
436 /cellht 2 cellheight mul def
437
438 curx cury wd headht greybox
439
440 cury 2 add
441 curx curx wd add (ID) centertext
442 pop
443
444 /cury exch def % add height change from box
445
446 cell
447
448 xpos wd add
449 } def
450
451/aperture
452 {
453 /cury exch def
454 /curx exch def
455 /wd 68 def
456 /headht 1 cellheight mul def
457 /cellht 2 cellheight mul def
458
459 curx cury wd headht greybox
460
461 cury 2 add
462 curx curx wd add (Aperture (f/x)) centertext
463 pop
464
465 /cury exch def % add height change from box
466
467 cell
468
469 xpos wd add
470 } def
471
472/shutter
473 {
474 /cury exch def
475 /curx exch def
476 /wd 68 def
477 /headht 1 cellheight mul def
478 /cellht 2 cellheight mul def
479
480 curx cury wd headht greybox
481
482 cury 2 add
483 curx curx wd add (Shutter (sec)) centertext
484 pop
485
486 /cury exch def % add height change from box
487
488 cell
489
490 xpos wd add
491 } def
492
493/geometry
494 {
495 /cury exch def
496 /curx exch def
497 /wd 74 def
498 /headht 1 cellheight mul def
499 /cellht 2.5 cellheight mul def
500
501 curx cury wd headht greybox
502
503 cury 2 add
504 curx curx wd add (Geometry) centertext
505 pop
506
507 /cury exch def % add height change from box
508
509 cell
510
511 gsave curx 3 add cury 6 add translate toppic grestore
512
513 cell
514
515 gsave curx 3 add cury 6 add translate sidepic grestore
516
517 xpos wd add
518 } def
519
520/film
521 {
522 /cury exch def
523 /curx exch def
524 /wd 52 def
525 /headht 1 cellheight mul def
526 /cellht 2 cellheight mul def
527
528 curx cury wd headht greybox
529
530 cury 2 add
531 curx curx wd add (Film) centertext
532 pop
533
534 /cury exch def % add height change from box
535
536 cell
537
538 xpos wd add
539 } def
540
541/carrier
542 {
543 /cury exch def
544 /curx exch def
545 /wd 42 def
546 /headht 1 cellheight mul def
547 /cellht 2 cellheight mul def
548
549 curx cury wd headht greybox
550
551 cury 2 add
552 curx curx wd add (Carrier) centertext
553 pop
554
555 /cury exch def % add height change from box
556
557 cell
558
559 xpos wd add
560 } def
561
562/lens
563 {
564 /cury exch def
565 /curx exch def
566 /wd 42 def
567 /headht 1 cellheight mul def
568 /cellht 2 cellheight mul def
569
570 curx cury wd headht greybox
571
572 cury 2 add
573 curx curx wd add (Lens) centertext
574 pop
575
576 /cury exch def % add height change from box
577
578 cell
579
580 xpos wd add
581 } def
582
583/process
584 {
585 /cury exch def
586 /curx exch def
587 /wd 42 def
588 /headht 1 cellheight mul def
589 /cellht 2 cellheight mul def
590
591 curx cury wd headht greybox
592
593 cury 2 add
594 curx curx wd add (Process) centertext
595 pop
596
597 /cury exch def % add height change from box
598
599 cell
600
601 xpos wd add
602 } def
603
604/date
605 {
606 /cury exch def
607 /curx exch def
608
609 /wd 252 108 sub def
610 /cellht 1.5 cellheight mul def
611
612 curx cury wd 2 cellht mul box pop
613
614 /cury curx cury wd cellht writingline def
615 /cury curx cury wd cellht writingline def
616
617 /cury cury 2 cellht mul add def
618 /curx curx wd add def
619
620 /wd 108 def
621 /headht 1 cellheight mul def
622 /cellht 2 cellheight mul def
623
624 curx cury wd headht greybox
625
626 cury 2 add
627 curx curx wd add (Date) centertext
628 pop
629
630 /cury exch def % add height change from box
631
632 cell
633
634 % draw the writing lines
635
636 xpos
637 } def
638
639/notes
640 {
641 /cury exch def
642 /curx exch def
643 /wd 252 def
644 %/headht 1 cellheight mul def
645 /cellht 1.5 cellheight mul def
646 /boxht 4.5 in 6 cellheight mul sub def % 5in - header so far
647
648 %curx cury wd headht greybox
649
650 %cury 2 add
651 %curx curx wd add (Process) centertext
652 %pop
653
654 %/cury exch def % add height change from box
655
656 curx cury wd boxht box pop
657
658 %/cury curx 10 add cury wd 20 sub cellht writingline def
659
660 /cury curx cury wd cellht writingline def
661 /cury curx cury wd cellht writingline def
662 /cury curx cury wd cellht writingline def
663 /cury curx cury wd cellht writingline def
664 /cury curx cury wd cellht writingline def
665 /cury curx cury wd cellht writingline def
666 /cury curx cury wd cellht writingline def
667 /cury curx cury wd cellht writingline def
668 /cury curx cury wd cellht writingline def
669 /cury curx cury wd cellht writingline def
670 /cury curx cury wd cellht writingline def
671 /cury curx cury wd cellht writingline def
672
673 xpos
674 } def
675
676/record
677 {
678 /rtop exch def
679 /rleft exch def
680
681 /xpos rleft def
682 /ypos rtop def
683 normalfont
684 /xpos xpos ypos picid def
685 /xpos xpos ypos film def
686 /xpos xpos ypos carrier def
687 /xpos xpos ypos process def
688 /xpos xpos ypos geometry def
689
690 /ypos ypos 3 cellheight mul sub def
691 /xpos rleft def
692
693 /xpos xpos ypos lens def
694 /xpos xpos ypos aperture def
695 /xpos xpos ypos shutter def
696
697 /ypos ypos 3 cellheight mul sub def
698 /xpos rleft def
699
700 %/xpos xpos ypos date def
701 %/ypos ypos 3 cellheight mul sub def
702 %/xpos rleft def
703
704 /xpos xpos ypos notes def
705 }
706def
707
708/xpos planleft def
709/ypos plantop def
710
711planleft plantop record
712planleft planwidth add plantop record
713planleft plantop 5 in sub record
714planleft planwidth add plantop 5 in sub record
715
716%/xpos planleft def
717%/ypos ypos 3 cellheight mul sub def
718%/xpos xpos ypos picid def
719%/xpos xpos ypos aperture def
720%/xpos xpos ypos shutter def
721%/xpos xpos ypos geometry def
722
723%/xpos xpos plantop vor def
724%/totalleft xpos def
725%/xpos xpos plantop course def
726%/xpos xpos plantop altitude def
727%/xpos xpos plantop wind def
728%/xpos xpos plantop airspeed def
729%/xpos xpos plantop tc def
730%/xpos xpos plantop th def
731%/xpos xpos plantop mh def
732%/xpos xpos plantop ch def
733%/xpos xpos plantop dist def
734%/xpos xpos plantop gs def
735%/totalright xpos def
736%/xpos xpos plantop time def
737%/xpos xpos plantop gph def
738%/planright xpos def
739%totalleft totalright plantop planheight cellheight sub sub total
740
741%/xpos condleft def
742%normalfont
743%/xpos xpos condtop frequencies 1 add def
744%/xpos xpos condtop atis 1 add def
745%/xpos xpos condtop planright condheight layout def
746
747/crop
748{
749 gsave
750 .2 setlinewidth
751 .7 .7 .7 setrgbcolor
752
753 /bottom plantop 8.5 72 mul sub 36 add def
754
755 planleft 4.5 sub plantop 36 add moveto
756 gsave
757 0 -8 rmoveto 0 16 rlineto stroke
758 grestore
759 -8 0 rmoveto 16 0 rlineto stroke
760
761 planright 4.5 add plantop 36 add moveto
762 gsave
763 0 -8 rmoveto 0 16 rlineto stroke
764 grestore
765 -8 0 rmoveto 16 0 rlineto stroke
766
767
768 planleft 4.5 sub bottom moveto
769 0 -8 rmoveto 0 16 rlineto stroke
770
771 planright 4.5 add bottom moveto
772 0 -8 rmoveto 0 16 rlineto stroke
773
774 grestore
775} def
776
777%crop
778
779showpage
780
781%%EOF \ No newline at end of file
diff --git a/lfrecord.py b/lfrecord.py
new file mode 100644
index 0000000..b869033
--- /dev/null
+++ b/lfrecord.py
@@ -0,0 +1,863 @@
1# ExiFilm -- Add film exposure metadata to EXIF tags of digital images
2# Copyright (C) 2009 James E. Blair <corvus@gnu.org>
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17program = """%%!PS-Adobe-3.0
18%%%%Pages: %(pages)s
19%%%%BoundingBox: 0 0 612 792
20%%%%EndComments
21
22%% User servicable:
23
24/in { 72 mul } def
25
26/cellheight 12.75 def
27%%/plantop 9.75 in def %% 8.5 - .5 in at top
28%%/planleft 7 32 div in def
29/plantop 10.25 in def %% 8.5 - .5 in at top
30/planleft .75 in def
31/planwidth 3 in 15 16 div in add def
32
33%% 3 15/16 in wide
34%% 5 in high
35
36/bigfont {/Times-Roman 14 selectfont} def
37/normalfont {/Times-Roman 12 selectfont} def
38/smallfont {/Times-Roman 10 selectfont} def
39
40/baselineskip 12 def
411 setlinewidth
42
43%% Less so:
44
45/planheight 21 cellheight mul def
46/condtop plantop planheight sub def
47/condleft planleft def
48/condheight 11 cellheight mul def
49
50/cell {/cury curx cury wd cellht box def} def
51/cell1 {curx cury wd1 cellht box pop} def
52/cell2cr {/cury curx wd1 add cury wd2 cellht box def} def
53/cell3cr {/cury curx wd1 add wd2 add cury wd3 cellht box def} def
54/cell2 {curx wd1 add cury wd2 cellht box pop} def
55/cell3 {curx wd1 add wd2 add cury wd3 cellht box pop} def
56/triangle {newpath curx cury moveto 6 0 cellht 2 div sub rlineto
57 -6 0 cellht 2 div sub rlineto closepath fill} def
58
59
60/toppic
61{
620 18 translate
630.8 -0.8 scale
640 0 0 setrgbcolor
65[] 0 setdash
661 setlinewidth
670 setlinejoin
680 setlinecap
69gsave [1 0 0 1 0 0] concat
700 0 0 setrgbcolor
71[] 0 setdash
720.625 setlinewidth
731 setlinejoin
741 setlinecap
75newpath
7617.465566 7.6270604 moveto
7717.34201 7.4607341 17.023642 7.1667431 16.801411 7.0511098 curveto
7816.503644 6.896187 16.307292 6.8516095 16.026569 6.7055509 curveto
7915.791517 6.5832505 15.419851 6.5327667 15.14103 6.5327667 curveto
8014.851109 6.5327667 14.510791 6.4751688 14.200137 6.4751688 curveto
8113.906717 6.4751688 13.544314 6.6414571 13.314598 6.8207372 curveto
8213.068846 7.0125432 12.874548 7.2361726 12.595099 7.4542762 curveto
8312.344743 7.6496678 12.125565 7.8753705 11.930944 8.1454035 curveto
8411.751845 8.3938944 11.61173 8.7253772 11.543518 9.0093151 curveto
8511.483134 9.2606497 11.432821 9.6008921 11.432821 9.9308246 curveto
8611.432821 10.284991 11.481859 10.646709 11.543518 10.96752 curveto
8711.606347 11.294419 11.689348 11.459357 11.764903 11.773844 curveto
8811.826229 12.029125 12.085382 12.337715 12.207673 12.464971 curveto
8912.411225 12.676797 12.681981 12.913342 12.927172 13.040921 curveto
9013.208038 13.187056 13.356056 13.321654 13.591326 13.444078 curveto
9113.894704 13.60193 14.210656 13.770986 14.532219 13.904833 curveto
9214.799874 14.016243 15.064115 14.020019 15.362414 14.020019 curveto
9315.668037 14.020019 15.886968 14.041942 16.1926 13.962421 curveto
9416.488636 13.885412 16.686938 13.733028 16.912108 13.674451 curveto
9517.175607 13.605906 17.382184 13.372271 17.576263 13.271294 curveto
9617.802565 13.15354 17.966257 13.038239 18.12972 12.868137 curveto
9718.33059 12.659107 18.448373 12.636072 18.517146 12.349785 curveto
9818.58201 12.07978 18.683187 12.005006 18.683187 11.658657 curveto
9918.683187 11.370687 18.683187 11.082707 18.683187 10.794746 curveto
10018.683187 10.482732 18.689036 10.243133 18.627843 9.9884225 curveto
10118.56315 9.7191599 18.57249 9.4050915 18.57249 9.1245109 curveto
10218.57249 8.8389752 18.46301 8.6086787 18.351105 8.3757857 curveto
10318.246685 8.158462 18.001799 8.0698776 17.852991 7.9150309 curveto
10417.675889 7.730729 17.748724 7.7007222 17.465566 7.6270604 curveto
105closepath
106stroke
1070 0 0 setrgbcolor
108[] 0 setdash
1090.625 setlinewidth
1101 setlinejoin
1111 setlinecap
112newpath
11318.908969 9.1187484 moveto
11419.132586 9.2148318 19.670178 9.5204546 19.889559 9.6723899 curveto
11520.225854 9.9053021 20.525329 9.9224118 20.835946 10.076851 curveto
11621.210027 10.262847 21.490107 10.364636 21.849811 10.465301 curveto
11722.38606 10.615383 21.920523 10.684453 21.563764 10.76915 curveto
11821.276372 10.837386 20.927903 10.920113 20.619207 10.993399 curveto
11920.270784 11.076118 19.970536 11.147404 19.607192 11.233666 curveto
12019.449759 11.271042 19.292336 11.308417 19.134913 11.345791 curveto
121stroke
1220 0 0 setrgbcolor
123[] 0 setdash
1240.625 setlinewidth
1251 setlinejoin
1261 setlinecap
127newpath
12812.479003 7.3178906 moveto
12912.297483 7.2051594 10.437915 6.743884 10.199405 6.6961819 curveto
1309.9461844 6.6455378 8.2389814 6.412102 8.4897064 6.4371367 curveto
1318.9210134 6.4802021 7.6023054 6.3853275 7.3499064 6.3853275 curveto
1327.1865764 6.3853275 6.6748094 6.3424179 6.2101074 6.3853275 curveto
1335.9802984 6.4065477 4.6730454 6.5580544 4.3967904 6.6961819 curveto
1344.1597714 6.8146914 3.9322444 6.8766459 3.6714644 7.0070363 curveto
1353.3812444 7.1521462 3.1878204 7.2920552 2.9461374 7.4733178 curveto
1362.7386724 7.6289163 2.4671594 7.8455027 2.2726194 7.9914084 curveto
1372.0299164 8.1734353 1.8916084 8.3206101 1.7027194 8.5094989 curveto
1381.5052674 8.706951 1.4151344 8.8256235 1.2882464 9.0793985 curveto
1391.1595274 9.3368386 1.0339524 9.4843697 0.92558337 9.7011073 curveto
1400.78229837 9.9876779 0.64040737 10.116486 0.56292037 10.426434 curveto
1410.50396737 10.662246 0.51591437 10.873501 0.45930237 11.099952 curveto
1420.39136637 11.371693 0.56233537 11.565062 0.66653837 11.77347 curveto
1430.76972037 11.979834 1.0569594 12.231766 1.1846294 12.395178 curveto
1441.4171204 12.692756 1.6462124 12.974507 1.9099554 13.172314 curveto
1452.2042814 13.393059 2.9527384 13.952751 3.2569914 14.104877 curveto
1464.1361764 14.565305 4.7738594 14.88324 5.7438264 14.985631 curveto
1476.1202154 15.079729 7.3525084 15.363749 8.8005604 15.192867 curveto
1489.8815834 15.065298 10.824802 14.750645 11.494631 14.260304 curveto
14912.29744 13.766723 12.403624 13.534597 12.789858 13.120505 curveto
150stroke
151grestore
152} def
153
154/sidepic
155{
1560 18 translate
1570.8 -0.8 scale
1580 0 0 setrgbcolor
159[] 0 setdash
1601 setlinewidth
1610 setlinejoin
1620 setlinecap
163gsave [1 0 0 1 0 0] concat
1640 0 0 setrgbcolor
165[] 0 setdash
1660.625 setlinewidth
1671 setlinejoin
1681 setlinecap
169newpath
17017.41745 3.3235764 moveto
17117.28754 3.1486964 16.9528 2.8395864 16.71914 2.7180064 curveto
17216.40606 2.5551164 16.19961 2.5082464 15.90445 2.3546764 curveto
17315.65731 2.2260864 15.26653 2.1730064 14.97337 2.1730064 curveto
17414.66854 2.1730064 14.31072 2.1124464 13.98409 2.1124464 curveto
17513.67558 2.1124464 13.29454 2.2872864 13.05301 2.4757864 curveto
17612.79462 2.6774564 12.59033 2.9125864 12.296511 3.1419064 curveto
17712.033281 3.3473464 11.802831 3.5846564 11.598201 3.8685764 curveto
17811.409891 4.1298464 11.262571 4.4783764 11.190851 4.7769164 curveto
17911.127361 5.0411764 11.074461 5.3989164 11.074461 5.7458164 curveto
18011.074461 6.1181964 11.126021 6.4985164 11.190851 6.8358264 curveto
18111.256911 7.1795364 11.344181 7.3529564 11.423621 7.6836164 curveto
18211.488101 7.9520264 11.760581 8.2764864 11.889161 8.4102864 curveto
18312.103181 8.6330064 12.387861 8.8817164 12.64566 9.0158564 curveto
18412.94097 9.1695064 13.0966 9.3110264 13.34397 9.4397464 curveto
18513.66295 9.6057164 13.99515 9.7834664 14.33325 9.9241964 curveto
18614.61467 10.041336 14.8925 10.045306 15.20614 10.045306 curveto
18715.52748 10.045306 15.75767 10.068356 16.07902 9.9847464 curveto
18816.39028 9.9037764 16.59878 9.7435564 16.83553 9.6819664 curveto
18917.11258 9.6098964 17.32978 9.3642464 17.53384 9.2580764 curveto
19017.77178 9.1342664 17.94389 9.0130364 18.11576 8.8341864 curveto
19118.32696 8.6144064 18.4508 8.5901864 18.52311 8.2891764 curveto
19218.59131 8.0052864 18.69769 7.9266664 18.69769 7.5625064 curveto
19318.69769 7.2597264 18.69769 6.9569364 18.69769 6.6541664 curveto
19418.69769 6.3261064 18.70384 6.0741864 18.6395 5.8063764 curveto
19518.57148 5.5232664 18.5813 5.1930464 18.5813 4.8980364 curveto
19618.5813 4.5978164 18.46619 4.3556764 18.34853 4.1108064 curveto
19718.23874 3.8823064 17.98126 3.7891664 17.8248 3.6263564 curveto
19817.63859 3.4325764 17.71517 3.4010264 17.41745 3.3235764 curveto
199closepath
200stroke
2010 0 0 setrgbcolor
202[] 0 setdash
2030.625 setlinewidth
2041 setlinejoin
2051 setlinecap
206newpath
20718.94656 5.9379964 moveto
20819.1584 6.0815564 19.65288 6.5037464 19.84927 6.7041364 curveto
20920.15032 7.0113264 20.45615 7.0883864 20.74625 7.3094564 curveto
21021.09562 7.5756964 21.36463 7.7363464 21.716081 7.9116264 curveto
21122.240021 8.1729464 21.745631 8.1519364 21.36046 8.1686364 curveto
21221.05018 8.1820964 20.67396 8.1984064 20.34068 8.2128564 curveto
21319.96451 8.2291664 19.64035 8.2432264 19.24807 8.2602364 curveto
21419.0781 8.2676064 18.90814 8.2749764 18.73818 8.2823464 curveto
215stroke
2160 0 0 setrgbcolor
217[] 0 setdash
2180.625 setlinewidth
2191 setlinejoin
2201 setlinecap
221newpath
22211.058081 6.3609964 moveto
22310.898991 6.3609964 10.297991 6.3609964 9.9236506 6.3609964 curveto
2249.6528706 6.3609964 9.2296906 6.4606964 9.0019306 6.5275864 curveto
2258.6792106 6.6223764 8.3901106 6.6031664 8.0802106 6.6941864 curveto
2267.7549906 6.7896964 7.3425006 6.8692064 7.0875806 6.9440764 curveto
2276.7203606 7.0519264 6.3784006 7.1731864 6.0240506 7.2772664 curveto
2285.6876206 7.3760764 5.4495006 7.5314764 5.1732306 7.6937564 curveto
2294.8089906 7.9077164 4.5570206 8.1390264 4.1806106 8.3601364 curveto
2303.8315206 8.5651864 3.5054206 9.0700664 3.2588806 9.3597064 curveto
2312.9162706 9.7622164 2.6772606 10.143226 2.4789706 10.609166 curveto
2322.2757806 11.086586 2.1067606 11.567026 1.9117506 12.025216 curveto
2331.7229306 12.468886 1.5183906 12.957456 1.4154406 13.441276 curveto
2341.3145406 13.915446 1.0273606 14.353136 0.84822058 14.774036 curveto
2350.65579058 15.226186 0.63552058 15.643266 0.63552058 15.773606 curveto
236stroke
2370 0 0 setrgbcolor
238[] 0 setdash
2390.625 setlinewidth
2401 setlinejoin
2411 setlinecap
242newpath
24314.33933 10.302876 moveto
24414.20693 10.595156 14.14423 11.072806 13.90194 11.429396 curveto
24513.70442 11.720106 13.37015 12.016406 13.17297 12.234056 curveto
24612.88897 12.547546 12.59356 12.873636 12.298201 13.199656 curveto
24712.020021 13.506716 11.823431 13.804186 11.496341 14.165246 curveto
24811.169801 14.525686 10.912571 14.749106 10.548671 15.050376 curveto
24910.232431 15.312176 9.7936806 15.426826 9.4552106 15.613636 curveto
2509.1243106 15.796266 8.5739906 15.756236 8.2159606 15.855036 curveto
2517.8258106 15.962696 7.3481706 15.832996 6.9767106 15.935496 curveto
2526.5954506 16.040716 6.0587306 15.935496 5.6645506 15.935496 curveto
2535.2171706 15.935496 4.8659706 16.015966 4.4253006 16.015966 curveto
2544.0136906 16.015966 3.5635006 15.935496 3.1131506 15.935496 curveto
2552.7207406 15.935496 2.2370206 15.733586 2.0196906 15.613636 curveto
2561.7663706 15.473826 1.1338906 15.325916 1.0720306 15.291776 curveto
257stroke
2580 0 0 setrgbcolor
259[] 0 setdash
2600.63630593 setlinewidth
2611 setlinejoin
2621 setlinecap
263newpath
2649.9264619 15.524615 moveto
2659.601864 15.336485 9.9988871 16.363201 9.9988871 16.783897 curveto
2669.9988871 17.343824 9.8991612 17.884929 9.9988871 18.462927 curveto
26710.104136 19.072974 9.9702746 19.353219 10.288574 19.722199 curveto
26810.538501 20.011916 10.948726 20.272725 11.157634 20.393812 curveto
26911.29979 20.476203 11.505777 20.474522 11.519735 20.477757 curveto
270stroke
2710 0 0 setrgbcolor
272[] 0 setdash
2730.625 setlinewidth
2741 setlinejoin
2751 setlinecap
276newpath
27710.213238 19.68757 moveto
27810.382008 19.78072 9.6081369 20.54456 9.4113669 20.65317 curveto
2799.2846369 20.72311 9.1736069 20.82462 9.0468769 20.89457 curveto
280stroke
2810 0 0 setrgbcolor
282[] 0 setdash
2830.625 setlinewidth
2841 setlinejoin
2851 setlinecap
286newpath
2876.5393206 16.015966 moveto
2886.2133206 16.195896 6.5393206 16.820626 6.5393206 17.222956 curveto
2896.5393206 17.627916 6.5393206 17.996046 6.5393206 18.429956 curveto
2906.5393206 18.885926 6.5393206 19.341896 6.5393206 19.797876 curveto
2916.5393206 19.821846 7.2722806 20.242636 7.3411906 20.280676 curveto
2927.3483106 20.418036 7.4383906 20.334316 7.4869906 20.361136 curveto
293stroke
2940 0 0 setrgbcolor
295[] 0 setdash
2960.625 setlinewidth
2971 setlinejoin
2981 setlinecap
299newpath
3006.5393206 19.797876 moveto
3016.8774206 19.984476 6.0047406 20.387956 5.7374506 20.683006 curveto
3025.6645606 20.763466 5.5916606 20.843936 5.5187606 20.924396 curveto
303stroke
304gsave
3050 0 0 setrgbcolor
306newpath
30716.59914 4.9921064 moveto
30816.75393 5.5208564 16.53852 5.6023764 16.16176 5.3944364 curveto
30915.78595 5.1870264 16.27681 4.8497864 16.59914 4.9921064 curveto
310closepath
311fill
312grestore
3130 0 0 setrgbcolor
314[] 0 setdash
3150.625 setlinewidth
3161 setlinejoin
3171 setlinecap
318newpath
31916.59914 4.9921064 moveto
32016.75393 5.5208564 16.53852 5.6023764 16.16176 5.3944364 curveto
32115.78595 5.1870264 16.27681 4.8497864 16.59914 4.9921064 curveto
322closepath
323stroke
324grestore
325} def
326
327/cameraview
328 {
329 /crtilt exch def %%or swing
330 /crrise exch def %%or shift
331
332 /cftilt exch def %%or swing
333 /cfrise exch def %%or shift
334
335 30 10 translate
336 -4 0 moveto 28 0 rlineto stroke
337
338 /ftopx -2.5 cftilt mul def
339 /ftopy 5 cfrise mul 5 add def
340 /fbotx 2.5 cftilt mul def
341 /fboty 5 cfrise mul -5 add def
342
343 /rtopx 20 -2.5 crtilt mul add def
344 /rtopy 5 crrise mul 5 add def
345 /rbotx 20 2.5 crtilt mul add def
346 /rboty 5 crrise mul -5 add def
347
348 ftopx ftopy moveto
349 fbotx fboty lineto
350 rbotx rboty lineto
351 rtopx rtopy lineto
352 ftopx ftopy lineto
353 stroke
354
355 } def
356
357/greybox
358 {
359 /height exch def
360 /width exch def
361 /top exch def
362 /left exch def
363
364 /bottom top height sub def
365
366 .8 .8 .8 setrgbcolor
367 left bottom width height rectfill
368 0 0 0 setrgbcolor
369 left bottom width height rectstroke
370 bottom
371 } def
372
373/blackbox
374 {
375 /height exch def
376 /width exch def
377 /top exch def
378 /left exch def
379
380 /bottom top height sub def
381
382 0 0 0 setrgbcolor
383 left bottom width height rectfill
384 left bottom width height rectstroke
385 bottom
386 } def
387
388/box
389 {
390 /height exch def
391 /width exch def
392 /top exch def
393 /left exch def
394
395 /bottom top height sub def
396
397 0 0 0 setrgbcolor
398 left bottom width height rectstroke
399 bottom
400 } def
401
402/writingline
403 {
404 /height exch def
405 /width exch def
406 /top exch def
407 /left exch def
408
409 /bottom top height sub def
410
411 .125 setlinewidth
412 left bottom moveto width 0 rlineto stroke
413 1 setlinewidth
414 bottom
415 } def
416
417
418/centertext
419 {
420 /s exch def
421 /x2 exch def
422 /x1 exch def
423 /y exch def
424
425 x2 x1 sub 2 div x1 add %% midpoint
426 s stringwidth pop 2 div %% half the string width
427 sub %% move left to start
428
429 y baselineskip sub moveto s show
430 y baselineskip sub
431 } def
432
433/righttext
434 {
435 /s exch def
436 /x2 exch def
437 /x1 exch def
438 /y exch def
439
440 x2
441 s stringwidth pop
442 sub 1 sub
443
444 y baselineskip sub moveto s show
445 y baselineskip sub
446 } def
447
448/lefttext
449 {
450 /s exch def
451 /x2 exch def
452 /x1 exch def
453 /y exch def
454
455 x1 1 add
456
457 y baselineskip sub moveto s show
458 y baselineskip sub
459 } def
460
461
462/picid
463 {
464 /cury exch def
465 /curx exch def
466 /wd 42 def
467 /headht 1 cellheight mul def
468 /cellht 2 cellheight mul def
469
470 curx cury wd headht greybox
471
472 cury 2 add
473 curx curx wd add (ID) centertext
474 pop
475
476 /cury exch def %% add height change from box
477
478 cell
479
480 bigfont
481 cury 20 add curx curx wd add idtext centertext pop
482 smallfont
483
484 xpos wd add
485 } def
486
487/aperture
488 {
489 /cury exch def
490 /curx exch def
491 /wd 68 def
492 /headht 1 cellheight mul def
493 /cellht 2 cellheight mul def
494
495 curx cury wd headht greybox
496
497 cury 2 add
498 curx curx wd add (Aperture (f/x)) centertext
499 pop
500
501 /cury exch def %% add height change from box
502
503 cell
504
505 bigfont
506 cury 20 add curx curx wd add aperturetext centertext pop
507 smallfont
508
509 xpos wd add
510 } def
511
512/shutter
513 {
514 /cury exch def
515 /curx exch def
516 /wd 68 def
517 /headht 1 cellheight mul def
518 /cellht 2 cellheight mul def
519
520 curx cury wd headht greybox
521
522 cury 2 add
523 curx curx wd add (Shutter (sec)) centertext
524 pop
525
526 /cury exch def %% add height change from box
527
528 cell
529
530 bigfont
531 cury 20 add curx curx wd add shuttertext centertext pop
532 smallfont
533
534 xpos wd add
535 } def
536
537/geometry
538 {
539 /rrise exch def
540 /rtilt exch def
541 /rswing exch def
542 /rshift exch def
543
544 /frise exch def
545 /ftilt exch def
546 /fswing exch def
547 /fshift exch def
548
549 /cury exch def
550 /curx exch def
551 /wd 74 def
552 /headht 1 cellheight mul def
553 /cellht 2.5 cellheight mul def
554
555 curx cury wd headht greybox
556
557 cury 2 add
558 curx curx wd add (Geometry) centertext
559 pop
560
561 /cury exch def %% add height change from box
562
563 cell
564
565 gsave
566 curx 3 add cury 6 add translate toppic
567 grestore
568 gsave
569 curx 3 add cury 6 add translate
570 fshift fswing rshift rswing cameraview
571 grestore
572
573 cell
574
575 gsave
576 curx 3 add cury 6 add translate sidepic
577 grestore
578 gsave
579 curx 3 add cury 6 add translate
580 frise ftilt rrise rtilt cameraview
581 grestore
582
583 xpos wd add
584 } def
585
586/film
587 {
588 /cury exch def
589 /curx exch def
590 /wd 52 def
591 /headht 1 cellheight mul def
592 /cellht 2 cellheight mul def
593
594 curx cury wd headht greybox
595
596 cury 2 add
597 curx curx wd add (Film) centertext
598 pop
599
600 /cury exch def %% add height change from box
601
602 cell
603
604 bigfont
605 cury 20 add curx curx wd add filmtext centertext pop
606 smallfont
607
608 xpos wd add
609 } def
610
611/carrier
612 {
613 /cury exch def
614 /curx exch def
615 /wd 42 def
616 /headht 1 cellheight mul def
617 /cellht 2 cellheight mul def
618
619 curx cury wd headht greybox
620
621 cury 2 add
622 curx curx wd add (Carrier) centertext
623 pop
624
625 /cury exch def %% add height change from box
626
627 cell
628
629 bigfont
630 cury 20 add curx curx wd add carriertext centertext pop
631 smallfont
632
633 xpos wd add
634 } def
635
636/lens
637 {
638 /cury exch def
639 /curx exch def
640 /wd 42 def
641 /headht 1 cellheight mul def
642 /cellht 2 cellheight mul def
643
644 curx cury wd headht greybox
645
646 cury 2 add
647 curx curx wd add (Lens) centertext
648 pop
649
650 /cury exch def %% add height change from box
651
652 cell
653
654 bigfont
655 cury 20 add curx curx wd add lenstext centertext pop
656 smallfont
657
658 xpos wd add
659 } def
660
661/process
662 {
663 /cury exch def
664 /curx exch def
665 /wd 42 def
666 /headht 1 cellheight mul def
667 /cellht 2 cellheight mul def
668
669 curx cury wd headht greybox
670
671 cury 2 add
672 curx curx wd add (Process) centertext
673 pop
674
675 /cury exch def %% add height change from box
676
677 cell
678
679 bigfont
680 cury 20 add curx curx wd add processtext centertext pop
681 smallfont
682
683 xpos wd add
684 } def
685
686/date
687 {
688 /cury exch def
689 /curx exch def
690
691 /wd 252 108 sub def
692 /cellht 1.5 cellheight mul def
693
694 curx cury wd 2 cellht mul box pop
695
696 /cury curx cury wd cellht writingline def
697 /cury curx cury wd cellht writingline def
698
699 /cury cury 2 cellht mul add def
700 /curx curx wd add def
701
702 /wd 108 def
703 /headht 1 cellheight mul def
704 /cellht 2 cellheight mul def
705
706 curx cury wd headht greybox
707
708 cury 2 add
709 curx curx wd add (Date) centertext
710 pop
711
712 /cury exch def %% add height change from box
713
714 cell
715
716 %% draw the writing lines
717
718 xpos
719 } def
720
721/notes
722 {
723 /cury exch def
724 /curx exch def
725
726 /wd 252 def
727 %%/headht 1 cellheight mul def
728 /cellht 1.5 cellheight mul def
729 /boxht 4.5 in 6 cellheight mul sub def %% 5in - header so far
730
731 %%curx cury wd headht greybox
732
733 %%cury 2 add
734 %%curx curx wd add (Process) centertext
735 %%pop
736
737 %%/cury exch def %% add height change from box
738
739 curx cury wd boxht box pop
740
741 %%/cury curx 10 add cury wd 20 sub cellht writingline def
742
743 curx cury %% save for returning to print text
744 /cury curx cury wd cellht writingline def
745 /cury curx cury wd cellht writingline def
746 /cury curx cury wd cellht writingline def
747 /cury curx cury wd cellht writingline def
748 /cury curx cury wd cellht writingline def
749 /cury curx cury wd cellht writingline def
750 /cury curx cury wd cellht writingline def
751 /cury curx cury wd cellht writingline def
752 /cury curx cury wd cellht writingline def
753 /cury curx cury wd cellht writingline def
754 /cury curx cury wd cellht writingline def
755 /cury curx cury wd cellht writingline def
756
757 moveto %% saved starting point
758 normalfont
759 notelines
760 {
761 0 0 cellht sub rmoveto
762 currentpoint
763 2 2 rmoveto
764 3 -1 roll show
765 moveto
766 } forall
767 smallfont
768
769 xpos
770 } def
771
772/record
773 {
774 /notelines exch def
775
776 /rrise exch def
777 /rtilt exch def
778 /rswing exch def
779 /rshift exch def
780
781 /frise exch def
782 /ftilt exch def
783 /fswing exch def
784 /fshift exch def
785
786 /shuttertext exch def
787 /aperturetext exch def
788 /lenstext exch def
789
790 /processtext exch def
791 /carriertext exch def
792 /filmtext exch def
793 /idtext exch def
794
795 /rtop exch def
796 /rleft exch def
797
798 /xpos rleft def
799 /ypos rtop def
800 smallfont
801 /xpos xpos ypos picid def
802 /xpos xpos ypos film def
803 /xpos xpos ypos carrier def
804 /xpos xpos ypos process def
805 /xpos xpos ypos
806 frise ftilt fswing fshift
807 rrise rtilt rswing rshift
808 geometry def
809
810 /ypos ypos 3 cellheight mul sub def
811 /xpos rleft def
812
813 /xpos xpos ypos lens def
814 /xpos xpos ypos aperture def
815 /xpos xpos ypos shutter def
816
817 /ypos ypos 3 cellheight mul sub def
818 /xpos rleft def
819
820 %%/xpos xpos ypos date def
821 %%/ypos ypos 3 cellheight mul sub def
822 %%/xpos rleft def
823
824 /xpos xpos ypos notes def
825 }
826def
827
828%(code)s
829
830/crop
831{
832 gsave
833 .2 setlinewidth
834 .7 .7 .7 setrgbcolor
835
836 /bottom plantop 8.5 72 mul sub 36 add def
837
838 planleft 4.5 sub plantop 36 add moveto
839 gsave
840 0 -8 rmoveto 0 16 rlineto stroke
841 grestore
842 -8 0 rmoveto 16 0 rlineto stroke
843
844 planright 4.5 add plantop 36 add moveto
845 gsave
846 0 -8 rmoveto 0 16 rlineto stroke
847 grestore
848 -8 0 rmoveto 16 0 rlineto stroke
849
850
851 planleft 4.5 sub bottom moveto
852 0 -8 rmoveto 0 16 rlineto stroke
853
854 planright 4.5 add bottom moveto
855 0 -8 rmoveto 0 16 rlineto stroke
856
857 grestore
858} def
859
860%%crop
861
862%%%%EOF
863"""
diff --git a/printrecord.py b/printrecord.py
new file mode 100644
index 0000000..65dc48a
--- /dev/null
+++ b/printrecord.py
@@ -0,0 +1,187 @@
1#!/usr/bin/python
2
3# ExiFilm -- Add film exposure metadata to EXIF tags of digital images
4# Copyright (C) 2009 James E. Blair <corvus@gnu.org>
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19import os, sys
20import pyexiv2
21import datetime
22import decimal, fractions
23import re
24
25from exifilm import *
26import lfrecord
27
28class MyImage(object):
29 def __init__(self, fn):
30 if fn:
31 image = pyexiv2.Image(fn)
32 image.readMetadata()
33 keys = image.exifKeys()
34 self.image = image
35 else:
36 keys = []
37
38 def get(key, default=''):
39 if key in keys:
40 return image[key]
41 return default
42
43 self.date = get('Exif.Photo.DateTimeOriginal', '')
44
45 self.shutter=from_rational(get('Exif.Photo.ExposureTime'))
46 self.aperture=to_fstop(from_rational(get('Exif.Photo.FNumber')))
47 self.lens=from_rational(get('Exif.Photo.FocalLength'))
48
49 self.description=get('Exif.Image.ImageDescription')
50 extras, comments = decode_comments(get('Exif.Photo.UserComment'))
51 self.comments=comments
52
53 self.id = extras.get(ID, '')
54 self.film = extras.get(FILM, '')
55 self.carrier = extras.get(CARRIER, '')
56 self.process = extras.get(PROCESS, '')
57
58 self.front_movements = extras.get(FRONT_MOVEMENTS, '').split('/')
59 self.rear_movements = extras.get(REAR_MOVEMENTS, '').split('/')
60
61 def render(self):
62 r = ' (%s) (%s) (%s) (%s)\n' % (self.id, self.film, self.carrier, self.process)
63 r += ' (%s) (%s) (%s)\n' % (self.lens, self.aperture, self.shutter)
64 r += ' '
65
66 if 'rising' in self.front_movements: r += '1 '
67 elif 'falling' in self.front_movements: r += '-1 '
68 else: r += '0 '
69
70 if 'forward tilt' in self.front_movements: r += '1 '
71 elif 'backward tilt' in self.front_movements: r += '-1 '
72 else: r += '0 '
73
74 if 'left swing' in self.front_movements: r += '1 '
75 elif 'right swing' in self.front_movements: r += '-1 '
76 else: r += '0 '
77
78 if 'left shift' in self.front_movements: r += '1 '
79 elif 'right shift' in self.front_movements: r += '-1 '
80 else: r += '0 '
81
82 r += ' '
83
84 if 'rising' in self.rear_movements: r += '1 '
85 elif 'falling' in self.rear_movements: r += '-1 '
86 else: r += '0 '
87
88 if 'forward tilt' in self.rear_movements: r += '1 '
89 elif 'backward tilt' in self.rear_movements: r += '-1 '
90 else: r += '0 '
91
92 if 'left swing' in self.rear_movements: r += '1 '
93 elif 'right swing' in self.rear_movements: r += '-1 '
94 else: r += '0 '
95
96 if 'left shift' in self.rear_movements: r += '1'
97 elif 'right shift' in self.rear_movements: r += '-1'
98 else: r += '0'
99
100 r += '\n'
101
102 notes = []
103 if self.description:
104 notes.append(self.description)
105 if self.date:
106 notes.append(str(self.date.date()))
107 if self.description or self.date:
108 notes.append('')
109 notes += self.comments.split('\n')
110
111 r += ' [ '
112 for note in notes:
113 r += '('+note+') '
114 r += ']\n'
115 r += 'record\n'
116 return r
117
118def main():
119 directory = sys.argv[1]
120 start = int(sys.argv[2])
121 end = int(sys.argv[3])
122 end += end%4
123
124 files = os.listdir(directory)
125 files.sort()
126 images = {}
127 for fn in files:
128 if not (fn.lower().endswith('.jpeg') or
129 fn.lower().endswith('.jpg')):
130 continue
131 i = MyImage(os.path.join(directory,fn))
132 if i.id:
133 images[int(i.id)] = i
134
135 code = ''
136 page = 0
137 i = start
138 while i<end:
139 page += 1
140 code += '%%%%Page: %s %s\n' % (page, page)
141 code += '/xpos planleft def\n'
142 code += '/ypos plantop def\n'
143
144 code += 'planleft plantop\n'
145 if images.has_key(i): image = images[i]
146 else: image = MyImage(None)
147 code += image.render()
148 i += 1
149
150 code += 'planleft planwidth add plantop\n'
151 if images.has_key(i): image = images[i]
152 else: image = MyImage(None)
153 code += image.render()
154 i += 1
155
156 code += 'planleft plantop 5 in sub\n'
157 if images.has_key(i): image = images[i]
158 else: image = MyImage(None)
159 code += image.render()
160 i += 1
161
162 code += 'planleft planwidth add plantop 5 in sub\n'
163 if images.has_key(i): image = images[i]
164 else: image = MyImage(None)
165 code += image.render()
166 i += 1
167
168 code += 'showpage\n'
169
170 print lfrecord.program % dict(pages=page, code=code)
171
172if __name__=='__main__':
173 if len(sys.argv) != 4:
174 print "Usage: %s PATH START END" % sys.argv[0]
175 print
176 print "Produce a sheet of four ExiFilm image records."
177 print
178 print " PATH is a directory with JPEG files to edit."
179 print
180 print " START and END are image IDs as set by ExiFilm. A series"
181 print " of PostScript pages will be generated that contain the"
182 print " images ranging from START to END."
183 print
184 print "Output goes to standard out."
185 else:
186 main()
187