Import Upstream version 2.1

This commit is contained in:
openKylinBot 2022-05-14 00:26:25 +08:00
commit 5452c32bf3
50 changed files with 11633 additions and 0 deletions

172
ANNOUNCE Normal file
View File

@ -0,0 +1,172 @@
JBIG-KIT lossless image compression library
-------------------------------------------
by Markus Kuhn
The latest release of JBIG-KIT can be downloaded from
http://www.cl.cam.ac.uk/~mgk25/jbigkit/
JBIG-KIT implements a highly effective data compression algorithm for
bi-level high-resolution images such as fax pages or scanned
documents.
JBIG-KIT provides two variants of a portable library of compression
and decompression functions with a documented interface. You can very
easily include into your image or document processing software. In
addition, JBIG-KIT provides ready-to-use compression and decompression
programs with a simple command line interface (similar to the
converters found in Jef Poskanzer's PBM graphics file conversion
package).
JBIG-KIT implements the specification
International Standard ISO/IEC 11544:1993 and ITU-T Recommendation
T.82(1993), "Information technology - Coded representation of picture
and audio information - progressive bi-level image compression",
<http://www.itu.int/rec/T-REC-T.82>,
which is commonly referred to as the "JBIG1 standard". JBIG (Joint
Bi-level Image experts Group) is the committee which developed this
international standard for the lossless compression of images using
arithmetic coding. Like the well-known compression algorithms JPEG and
MPEG, JBIG has also been developed and published by the International
Organization for Standardization (ISO) and the International
Telecommunication Union (ITU). See also
http://www.jpeg.org/jbig/
http://www.iso.ch/
http://www.itu.int/
The JBIG compression algorithm offers the following features:
- Close to state-of-the-art lossless compression ratio for high
resolution bi-level images.
- About 1.1 to 1.5 times better compression ratio on typical
scanned documents compared to G4 fax compression (ITU-T T.6),
which has been the best compression algorithm for scanned
documents available prior to JBIG.
- Up to 30 times better compression of scanned images with dithered
images compared to G4 fax compression.
- About 2 times better compression on typical 300 dpi documents
compared to 'gzip -9' on raw bitmaps.
- About 3-4 times better compression than GIF on typical 300 dpi
documents.
- Even much better competitive compression results on computer
generated images which are free of scanning distortions.
- JBIG supports hierarchical "progressive" encoding, that means it is
possible to encode a low resolution image first, followed by
resolution enhancement data. This allows, for instance, a document
browser to display already a good 75 dpi low resolution version of
an image, while the data necessary to reconstruct the full 300 dpi
version for laser printer reproduction is still arriving (say
over a slow network link or mass storage medium).
- The various resolution layers of a JBIG image in progressive
encoding mode together require not much more space than a
normal non-progressive mode encoded image (which JBIG also
supports).
- The progressive encoding mode utilizes a quite sophisticated
resolution reduction algorithm which offers high quality low
resolution versions that preserve the shape of characters as well
as the integrity of thin lines and dithered images.
- JBIG supports multiple bit planes and can this way also be used
for grayscale and color images, although the main field of
application is compression of bi-level images, i.e. images with
only two different pixel values. For grayscale images with up to
6 bit per pixel, JBIG performs superior to JPEG's lossless
mode.
JBIG-KIT can be used as free software under the GNU General Public
License. Other license arrangements more suitable for commercial
applications are available as well, please contact the author for
details. JBIG-KIT provides two portable libraries implemented in
ANSI/ISO C for encoding and decoding JBIG data streams, along with
documentation. The first library, jbig.c, implements nearly all of the
options that the JBIG standard provides, but keeps the entire
uncompressed image in memory. The second library, jbig85.c, implements
only the ITU-R T.85 subset of the standard that black/white fax
machines use (single bit per pixel, no "progressive" encoding), and
keeps only three lines of the uncompressed image in memory, making it
particularly attractive for low-memory embedded applications.
The libraries are not intended for 8-bit or 16-bit machine
architectures (e.g., old MS-DOS C compilers). For maximum performance,
a 32-bit processor is required (64-bit systems work too, of course).
On architectures with 16-bit pointer arithmetic, the full-featured
jbig.c library can process only very small images.
Special features of the full-featured jbig.c variant:
- Fully reentrant multithread-capable design (no global or static
variables, isolated malloc()/free() calls, etc.)
- Capable of handling incomplete and growing JBIG data streams in
order to allow earliest display of low resolution versions
- Capable of handling several incoming data streams simultaneously
in one single process and thread
- Especially designed with applications in mind that want to display
incoming data as early as possible (e.g., similar to the way in
which Netscape Navigator handles incoming GIF images)
- Implements all JBIG features and options including progressive and
sequential encoding, multiple bit planes, user specified
resolution reduction and deterministic prediction tables, adaptive
template changes for optimal performance on half-tone images,
deterministic prediction, typical prediction in lowest and
differential layers, various stripe orderings, etc; only the SEQ
and HITOLO options are currently not supported by the decoder
(they are normally never required, but could be added later in
case of user requirements)
- Suitable for fax applications, satisfies ITU-T T.85 profile
- Efficient code, optimized utilization of 32-bit processor
registers
- Very easy to use documented C library interface
- Included Gray code conversion routines for efficient encoding
of grayscale images
- Ready-to-use pbmtojbg and jbgtopbm converters.
Special features of the light-weight jbig85.c variant:
- Suitable for low-memory embedded applications
- Implements only the JBIG1 subset defined in the ITU-T T.85
profile (single bit plane, no differential layers)
- Requires only three pixel rows of the uncompressed image to be
kept in memory
- Handles all NEWLEN modes of operation required by ITU-T T.85 with
just a single pass over the data, automatically performing the
necessary lookahead after the last stripe
- Codec buffers only a few bytes of arithmetic-codec data and outputs
resulting bytes or lines as soon as they are available.
I will try to provide free support and maintenance for this software
for the foreseeable future, depending on my available time.
Happy compressing ...
Markus Kuhn
--
Markus Kuhn, Computer Laboratory, University of Cambridge
http://www.cl.cam.ac.uk/~mgk25/ || CB3 0FD, Great Britain

237
CHANGES Normal file
View File

@ -0,0 +1,237 @@
JBIG-KIT revision history
-------------------------
Changes in version 2.1 (2014-04-08)
This is a security-critical bug-fix release that remains API and ABI
backwards compatible to version 2.0. Users who process BIE data from
untrusted sources should upgrade.
- fixed a buffer-overflow vulnerability in the jbig.c decoder,
reported by Florian Weimer (Red Hat): CVE-2013-6369
- fixed ability of corrupted input data to force jbig85.c decoder
into an end-less loop
- fixed a bug in the processing of private deterministic-prediction
tables (DPPRIV=1) in jbig.c decoder
- fixed integer-type mismatches in printf arguments on 64-bit systems
- fuzz-testing script added
Changes in version 2.0 (2008-08-30)
Main new features of release 2.0:
- This release adds a separate lightweight "T.85" version of the
encoder and decoder library (jbig85.c, jbig85.h). This new T.85
library is optimized for embedded low-memory applications, such as
printers and fax machines. It implements only the subset of the
JBIG standard that is required by the ITU-T T.85 fax profile,
namely only a single bit plane (P = 1) and no differential layers
(DL = D = HITOLO = SEQ = ILEAVE = SMID = TPDON = DPON = DPON =
DPLAST = 0) and some other restrictions (MY = 0, MX < 128).
The T.85 library requires only three pixel rows of the
uncompressed image to reside in memory at any time. This 3-line
buffer has to be allocated by the calling application, therefore
the T.85 library will not call any heap management functions such
as malloc() or free() itself.
- There are also two new example applications pbmtojbg85 and
jbgtopbm85 included that provide command-line access to the new
T.85 library. (Note to distribution maintainers: there is probably
little point in adding pbmtojbg85 and jbgtopbm85 to precompiled
JBIG-KIT packages for workstation operating systems, as these two
programs do not really provide the end user much additional
functionality beyond what pbmtojbg and jbgtopbm already do, which
use the full library instead.)
Changes to the original full jbig.c library from version 1.6:
- the arithmetic codec routines are now located in a separate source
file (they are now used by both the full library jbig.c and the new
T.85 library jbig85.c, and might also be of use to other applications)
- arithmetic decoder behaviour slightly changed to enable the
lookahead needed to handle T.85-style NEWLEN after the final
stripe
- added encoder support for adding comment marker segment
- added encoder option for using SDRST marker instead of SDNORM
(only useful to make encoder able to generate a wider range
of test data)
- added pbmtojbg options -C and -r, which provide command-line
access to the previous two extensions
- slightly improved diagnostic output of jbgtopbm option -d
- non-English translations of error messages are now provided
in a separate PO file (e.g., for use with GNU gettext),
jbg_strerror() no longer has a language attribute and the
JBG_EN, JBG_DE_8859_1, JBG_DE_UTF_8 constants no longer exist
- jbg_dec_in() return values changed; the least significant bits of
the error codes now provide more information about what caused the
error, beyond what the more general error text messages returned by
jbg_strerror() reveal
- pbmtojbg has a new option -f as a shortcut for all the options
needed to make the output comply to the basic ITU-T T.85 fax
profile
- jbg_dec_getwidth(), jbg_dec_getheight(), jbg_dec_getsize(), and
jbg_dec_getsize_merged() return now an unsigned long value
(was: long), and return 0 (was: -1) if no image is available yet
- jbgtopbm now outputs image dimensions in header padded to 10
digits fixed width, for consistency with jbgtopbm85
to allow for later in-place update of height due to NEWLEN
- macro JBG_LICENCE can be changed from the default value "GPL" to a
licence agreement reference code to if the library is used under a
commercial licence, to clarify under which exact licence the
library is used in a particular application
Changes in version 1.6 (2004-06-11)
- various small changes to reduce the risk of 32-bit unsigned
integer overflows when dealing with extremely large images
- robuster treatment of L0 = 0xffffffff
- minor API modification in jbg_enc_options(): parameter l0 changed
from type long to unsigned long; previous value now remains
unchanged when l0 == 0 (was: l0 < 0)
- lots of type casts added such that the C source code is now
also compilable as C++
Changes in version 1.5 (2003-06-11)
- fixed two minor memory leaks (special thanks to Davide Pizzolato
<ing.davide.pizzolato@libero.it> for locating one of these)
- jbgtopbm does not attempt any more to parse multiple concatenated
BIEs (options -m must be used now to enable this feature explicitly),
in order to handle BIEs with data after the last expected SDE gracefully
- various extensions to improve support of JBIG fax applications
(ITU-T T.85 profile):
o support for maximum adaptive template pixel offset increased
to MX=127 in both encoder and decoder
o encoder now has a hook for producing BIEs with a NEWLEN marker
segment and VLENGTH=1, in order to assist in testing decoders
for T.85 conformance (see also new pbmtojbg option -Y)
o a new function jbg_newlen() can be used to scan an
entire in-memory BIE for NEWLEN marker segments and update the
YD value in the BIE header, which can be applied to BIE data
before passing it to the decoder for T.85 compliance
(Background: the incremental design of the JBIG-KIT decoder
makes it infeasible to look ahead for NEWLEN marker segments
that occur after the SDE with the last image line, therefore
this second pass is necessary to handle the old-style fax
applications permitted by T.85 in which the low-RAM encoder
doesn't know the height of the image at the start of
transmission)
Changes in version 1.4 (2002-04-09)
- typo fixed in stripe number calculation, which caused encoder and
decoder to fail on certain image sizes (special thanks to Koen Denecker
<denecker@elis.rug.ac.be> for locating this one)
Changes in version 1.3 (2002-03-23):
- bugs fixed in jbg_split_planes(), jbg_dec_merge_planes() that
caused a failure for more than eight planes per pixel
- example converters now can handle PGM files with up to 32 bits
per pixel
Changes in version 1.2 (2000-04-08):
- bug in the decoder fixed, which caused the rest of the input file
to be skipped whenever a comment marker was encountered (special
thanks to Ben Rudiak-Gould <benrg@math.berkeley.edu> for
reporting this one)
Changes in version 1.1 (1999-11-16):
- serious bug in the encoder fixed, which for a very small
percentage of images has caused an unterminated linked list to be
created internally that could have been responsible for
segmentation violations or non-terminating encoders
(special thanks to Hisashi Saiga <saiga@itl.tnr.sharp.co.jp> for
tracking that one down)
- minor bug in the "jbgtopbm -d" diagnostic output fixed
Changes in version 1.0 (1998-04-11):
- two bugs fixed that caused the encoder and decoder to fail
under certain modes of operation with several bit planes
- added new functions jbg_split_planes(), jbg_dec_merge_planes(),
and jbg_dec_getsize_merged() for easy handling of grayscale
images
- added support for compressing grayscale PGM files to pbmtojbg
and jbgtopbm
- more changes to avoid paranoid compiler warnings
Changes in version 0.9 (1996-01-09):
- encoder won't break any more on input bitmap data with incorrect
zero padding
- pbmtojbg displays a warning if input file has incorrect zero
padding
- various minor improvements suggested by Stefan Willer
<Stefan.Willer@unnet.wupper.DE>
- many minor changes in order to avoid warnings from paranoid
compilers
Changes in version 0.8 (1995-09-20):
- namespace cleared up, all names externally visible from the library
start now with jbg_ or JBG_
- minor non-critical bug fixed which caused library to fail compatibility
test and showed up especially on DEC Alpha systems
- jbg_dec_gethight() is now called jbg_dec_getheight()
- filenames conform now to MS-DOS limits
- Bug in pbmtojbg fixed (handling of ASCII PBM files)
Changes in version 0.7 (1995-06-10):
- more problems on 16-bit int systems and on Macintosh systems fixed
(special thanks to Jean-Pierre Gachen <jpg11@calvanet.calvacom.fr>)
- global Makefile
Changes in version 0.6 (1995-06-08):
- memory leak fixed
- should now also work on systems where int is only 16-bit large
- changes of the JBIG "Technical Corrigendum 1" included (special
thanks to Dr. Sebestyen from Siemens AG for sending me a copy
of the draft)
First release: version 0.5 (1995-05-28)

339
COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

163
INSTALL Normal file
View File

@ -0,0 +1,163 @@
Getting started with JBIG-KIT
-----------------------------
Markus Kuhn -- 2014-03-27
JBIG-KIT is a portable C library that should work on any platform with
an ANSI/ISO C compiler, such as GNU gcc.
To get started, compile the demonstration software in pbmtools/ and
test it with some of the provided example files.
On a Unix system, check Makefile to suit your compiler, then start
"make". If libjbig.a and/or libjbig85.a have been produced correctly,
then activate the automatic library test suite with "make test", or
just start libjbig/tstcodec and libjbig/tstcodec85. If these tests
fail, please do let me know.
On other operating systems, just link libjbig/jbig.c and
libjbig/jbig_ar.c together with any application in which you want to
use the full JBIG-KIT library. Likewise, just link libjbig/jbig85.c
and libjbig/jbig_ar.c together with any application in which you want
to use the simpler variant optimized for fax applications.
In subdirectory pbmtools/, you will find the programs pbmtojbg and
jbgtopbm. These are two file converters, serving as examples for
applications that use the full JBIG-KIT library (jbig.c). After
testing them on some of the example JBIG files, you can move these
executable files together with their respective man pages (in a UNIX
style environment) to the appropriate directories. Options -h and
--help will give you short command-line usage summaries. The programs
pbmtojbg85 and jbgtopbm85 are very similar, but demonstrate use of the
simpler jbig85.c library instead.
The subdirectory examples/ contains a few files as raw JBIG data
streams (called bi-level image entities (BIE) in the standard).
Try
jbgtopbm ccitt1.jbg ccitt1.pbm
to decompress CCITT test letter #1 into a portable bitmap file, which
you can then further convert using Jef Poskanzer's PBM tools
<http://www.acme.com/software/pbmplus/>, or view with many popular
image file viewers, such as the "display" command from ImageMagick.
The ccitt1.jbg image is 1728 x 2376 pixels large and may not fit onto
your display screen. However, fortunately, I have stored it in JBIG's
"progressive mode" with the following resolution layers:
layer 0: 216 x 297 pixel
layer 1: 432 x 594 pixel
layer 2: 864 x 1188 pixel
layer 3: 1728 x 2376 pixel
In progressive mode, each layer has twice the resolution of the
previous one. Resolution layer 0 encodes all its pixels independent
from any other data; all other resolution layers encode only the
difference between the previous and the new resolution layer, which
requires much less space than encoding resolution layers without
referring to the lower layer. By default, the BIE files produced by
pbmtojbg will all start with a lowest resolution layer 0 that fits
onto a 640 x 480 screen.
In order to tell jbgtopbm that you do not want to decode higher
resolution layers if they will not fit onto your (say) 1024 x 768
pixel display, simply use
jbgtopbm -x 1024 -y 768 ccitt1.jbg ccitt1.pbm
You will get a 4 times smaller image, the highest resolution layer
that still fits onto your screen. You can also directly pipe the image
to another application using standard output, by removing the second
file name, e.g.
jbgtopbm -x 1024 -y 768 ccitt1.jbg | display
In fact, the data in the first quarter of the input file is sufficient
to decode the requested resolution:
head --bytes=4000 ccitt1.jbg | ../pbmtools/jbgtopbm -x 1024 -y 768 | display
Now let's do some compression. With
jbgtopbm ccitt1.jbg ccitt1.pbm
followed by
pbmtojbg ccitt1.pbm test.jbg
you produce again the same data stream as ccitt1.jbg. However if you
want that the lowest resolution layer is not larger than 70 x 100
pixels ("thumb nail" image), then use
pbmtojbg -v -x 100 -y 150 ccitt1.pbm test.jbg
Option -v will output some technical data, and will tell you that five
incremental resolution layers have been created, in addition to the
lowest 54 x 75 pixel large layer 0. Look at the lowest resolution
layer in test.jbg with
jbgtopbm -x 100 test.jbg | display
and you will still be able to clearly recognize the layout and line
structure of the page, which the implemented bi-level
resolution-reduction algorithm tried to preserve. With
pbmtojbg -q ccitt1.pbm test.jbg
you can enforce a single resolution layer, which usually requires a
slightly less space than progressive encoding.
OK, another small exercise. Assume you want to build a document
database in which you want to store scanned images in two resolution
layers, one for screen previewing and one for laser-printer output.
However, you do not want your decision to store images in two
resolutions to cause too much additional storage requirement. You
decide that 3 resolution layers in JBIG fit your requirement and you
want to store
layer 0: 432 x 594 pixels
in the first file test-low.jbg and the two layers
layer 1: 864 x 1188 pixels
layer 2: 1728 x 2376 pixels
in the second file test-high.jbg. No problem, just call
pbmtojbg -d 2 -l 0 -h 0 ccitt1.pbm test-low.jbg
pbmtojbg -d 2 -l 1 -h 2 ccitt1.pbm test-high.jbg
where option -d specifies the total number of layers and -l/-h select
the range of layers written to the output file. You will see that the
low and high resolution file together are only 1.6 kB larger than if
you had stored only the high-res version directly without progressive
mode (option -q). Progressive mode has reduced the additional storage
requirement by 50% compared to storing the 3.2 kB low-resolution
version independently of the high resolution image.
In order to view only the screen version, use
jbgtopbm test-low.jbg | display
and in order to send the full version to the printer, just concatenate
both BIE files like in
cat test-low.jbg test-high.jbg | jbgtopbm -m | ....
All this functionality, and more, are available as functions in the
libjbig C library, which you can link into your application. Just copy
the relevant files from libjbig/ into your own source-code directory
and adapt your Makefile. In libjbig/jbig.txt, you will find
documentation about how to use the full library, while
libjbig/jbig85.txt documents the fax variant of the library. The
latter lacks progressive encoding, but can instead deal better with
images where the height is not yet known at the start of a
transmission.
Markus

44
Makefile Normal file
View File

@ -0,0 +1,44 @@
# Unix makefile for JBIG-KIT
# Select an ANSI/ISO C compiler here, GNU gcc is recommended
CC = gcc
# Options for the compiler: A high optimization level is suggested
CFLAGS = -O2 -W -Wno-unused-result
# CFLAGS = -O -g -W -Wall -Wno-unused-result -ansi -pedantic # -DDEBUG
export CC CFLAGS
VERSION=2.1
all: lib pbm
@echo "Enter 'make test' in order to start some automatic tests."
lib:
cd libjbig && $(MAKE) -e
pbm: lib
cd pbmtools && $(MAKE) -e
test: lib pbm
cd libjbig && $(MAKE) test
cd pbmtools && $(MAKE) test
analyze:
cd libjbig && $(MAKE) analyze
cd pbmtools && $(MAKE) analyze
clean:
rm -f *~ core
cd libjbig && $(MAKE) clean
cd pbmtools && $(MAKE) clean
distribution:
rm -rf jbigkit-$(VERSION)
git archive v$(VERSION) --prefix jbigkit-$(VERSION)/ | tar xvf -
make -C jbigkit-$(VERSION)/pbmtools txt
tar cvaf jbigkit-$(VERSION).tar.gz jbigkit-$(VERSION)
release:
rsync -t jbigkit-$(VERSION).tar.gz $(HOME)/public_html/download/
rsync -t jbigkit-$(VERSION)/CHANGES $(HOME)/public_html/jbigkit/

51
TODO Normal file
View File

@ -0,0 +1,51 @@
Features that may appear in some future release regarding jbig.c:
- function to prepare incompletely decoded images for display by Xlib
- use a more efficient resolution-reduction method suggested by
Dr. Klaus Bartz <bartzkau@kou3.ina.de>
- investigate whether there is a standard way of embedding JBIG
into TIFF and implement it (see also RFC 2301)
- test for and eliminate warning messages from compilers
other than GCC
- multichannel (e.g., RGB) support, PPM support
- add dynamic library target to Makefile (patch by David Woodhouse),
for the benefit of Linux packagers
The NEWLEN handling in jbig.c remains less than ideal. There is no
easy fix as NEWLEN is inherently incompatible with many of the other
options that jbig.c supports. The whole point of the VLENGTH bit may
have been to allow recipients to choose between a jbig.c (VLENGTH=0)
and jbig85.c (VLENGTH=1) style of decoder implementation. The cleanest
option would really be to remove NEWLEN support entirely from jbig.c
and to urge users who need it to use jbig85.c instead. Short of that,
the new NEWLEN look-ahead architecture from jbig85.c could be
backported to jbig.c, but this would only only slightly increase the
number of cases where the jbig.c decoder could deal with a NEWLEN
marker without a prior invocation of the jbg_newlen() pre-processing
pass.
The following past feature requests for jbig.c probably have become
less important since the release of jbig85.c:
- compile-time option to remove progressive encoding and
resolution-reduction support (in the interest of reducing code size)
- investigate how to best deal with broken BIEs that contain
multiple NEWLEN marker segments, which are not permitted by ITU-T
T.85, but which have been observed coming from some fax machines;
possible options for jbg_newlen(): use first, last, or minimum
value
- version of jbg_newlen() for dealing with BIEs that are split
into several blocks
- call-back function for progress meter
Features that may appear in some future release regarding jbig85.c:
- man pages for pbmtojbg85 and jbgtopbm85

16
contrib/INDEX Normal file
View File

@ -0,0 +1,16 @@
Here are some files which users of JBIG-KIT have contributed and which
I have included into the package in the hope that you might find them
useful. If you have questions with regard to these files, better
contact the respective contributors directly.
---------------------------------------------------------------------------
atariprj.tar
From: Stefan Willer <Stefan.Willer@unnet.wupper.DE>
These are four hierarchical project files for use with the Atari ST
Pure-C development environment. With these files, installing
JBIG-KIT should be child's play for Atari ST users (except the
necessary line end changes in all text files).

BIN
contrib/atariprj.tar Normal file

Binary file not shown.

8
examples/README Normal file
View File

@ -0,0 +1,8 @@
The files in this directory are a few sample images and documents
stored as raw bi-level image entities (BIE) (the data stream specified
by the JBIG standard).
The source data for the test examples ccitt* and lena.bie is available from
ftp://ftp.funet.fi/pub/graphics/misc/test-images/

BIN
examples/ccitt1.jbg Normal file

Binary file not shown.

BIN
examples/ccitt2.jbg Normal file

Binary file not shown.

BIN
examples/ccitt3.jbg Normal file

Binary file not shown.

BIN
examples/ccitt4.jbg Normal file

Binary file not shown.

BIN
examples/ccitt5.jbg Normal file

Binary file not shown.

BIN
examples/ccitt6.jbg Normal file

Binary file not shown.

BIN
examples/ccitt7.jbg Normal file

Binary file not shown.

BIN
examples/ccitt8.jbg Normal file

Binary file not shown.

10
examples/jbgtests.m Normal file
View File

@ -0,0 +1,10 @@
% MATLAB code to generate test files that exercise a JBIG codec
width = 1200;
img = [];
for y=1:650;
mx = ceil(y / 5);
line = uint8(repmat(round(rand(1,mx)),1,ceil(width/mx))) == 1;
img = [img ; line(1:width)];
end
imwrite(img, 'mx.png', 'PNG');

5
examples/multi.pgm Normal file
View File

@ -0,0 +1,5 @@
P5
2
2
4294967295
abcdABCD9876WXYZ

BIN
examples/mx.jbg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
examples/sandra.pgm Normal file

Binary file not shown.

BIN
examples/xvlogo.jbg Normal file

Binary file not shown.

55
libjbig/Makefile Normal file
View File

@ -0,0 +1,55 @@
# Unix makefile for the JBIG-KIT library
# Select an ANSI/ISO C compiler here, GNU gcc is recommended
CC = gcc
# Options for the compiler: A high optimization level is suggested
CFLAGS = -g -O -W -Wall -ansi -pedantic # --coverage
all: libjbig.a libjbig85.a tstcodec tstcodec85
tstcodec: tstcodec.o jbig.o jbig_ar.o
$(CC) $(CFLAGS) -o tstcodec tstcodec.o jbig.o jbig_ar.o
tstcodec85: tstcodec85.o jbig85.o jbig_ar.o
$(CC) $(CFLAGS) -o tstcodec85 tstcodec85.o jbig85.o jbig_ar.o
libjbig.a: jbig.o jbig_ar.o
rm -f libjbig.a
ar rc libjbig.a jbig.o jbig_ar.o
-ranlib libjbig.a
libjbig85.a: jbig85.o jbig_ar.o
rm -f libjbig85.a
ar rc libjbig85.a jbig85.o jbig_ar.o
-ranlib libjbig85.a
jbig.o: jbig.c jbig.h jbig_ar.h
jbig85.o: jbig85.c jbig85.h jbig_ar.h
jbig_ar.o: jbig_ar.c jbig_ar.h
tstcodec.o: tstcodec.c jbig.h
tstcodec85.o: tstcodec85.c jbig85.h
update-po: jbig.c jbig85.c Makefile
xgettext -ojbig.pot -k_ \
--copyright-holder='Markus Kuhn' \
--msgid-bugs-address='http://www.cl.cam.ac.uk/~mgk25/jbigkit/' \
--package-name jbigkit \
jbig.c jbig85.c
cd po && for po in *.po ; do \
msgmerge --update $$po ../jbig.pot ; done
analyze:
clang --analyze *.c
test: tstcodec tstcodec85
./tstcodec
./tstcodec85
t82test.pbm: tstcodec
./tstcodec $@
clean:
rm -f *.o *.gcda *.gcno *.gcov *.plist *~ core gmon.out dbg_d\=??.pbm
rm -f t82test.pbm
rm -f tstcodec tstcodec85

3285
libjbig/jbig.c Normal file

File diff suppressed because it is too large Load Diff

233
libjbig/jbig.h Normal file
View File

@ -0,0 +1,233 @@
/*
* Header file for the portable JBIG compression library
*
* Copyright 1995-2014 -- Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/
*/
#ifndef JBG_H
#define JBG_H
#include <stddef.h>
#include "jbig_ar.h"
/*
* JBIG-KIT version number
*/
#define JBG_VERSION "2.1"
#define JBG_VERSION_MAJOR 2
#define JBG_VERSION_MINOR 1
/*
* JBIG-KIT licence agreement reference code:
* If you use JBIG-KIT under a commercial licence, please replace
* below the letters GPL with the reference code that you received
* with your licence agreement. (This code is typically a letter "A"
* followed by four decimal digits, e.g. "A1234".)
*/
#define JBG_LICENCE "GPL"
/*
* Buffer block for SDEs which are temporarily stored by encoder
*/
#define JBG_BUFSIZE 4000
struct jbg_buf {
unsigned char d[JBG_BUFSIZE]; /* one block of a buffer list */
int len; /* length of the data in this block */
struct jbg_buf *next; /* pointer to next block */
struct jbg_buf *previous; /* pointer to previous block *
* (unused in freelist) */
struct jbg_buf *last; /* only used in list head: final block of list */
struct jbg_buf **free_list; /* pointer to pointer to head of free list */
};
/*
* Maximum number of ATMOVEs per stripe that decoder can handle
*/
#define JBG_ATMOVES_MAX 64
/*
* Option and order flags
*/
#define JBG_HITOLO 0x08
#define JBG_SEQ 0x04
#define JBG_ILEAVE 0x02
#define JBG_SMID 0x01
#define JBG_LRLTWO 0x40
#define JBG_VLENGTH 0x20
#define JBG_TPDON 0x10
#define JBG_TPBON 0x08
#define JBG_DPON 0x04
#define JBG_DPPRIV 0x02
#define JBG_DPLAST 0x01
/* encoding options that will not be indicated in the header */
#define JBG_DELAY_AT 0x100 /* Delay ATMOVE until the first line of the next
* stripe. Option available for compatibility
* with conformance test example in clause 7.2. */
#define JBG_SDRST 0x200 /* Use SDRST instead of SDNORM. This option is
* there for anyone who needs to generate
* test data that covers the SDRST cases. */
/*
* Possible error code return values
*/
#define JBG_EOK (0 << 4)
#define JBG_EOK_INTR (1 << 4)
#define JBG_EAGAIN (2 << 4)
#define JBG_ENOMEM (3 << 4)
#define JBG_EABORT (4 << 4)
#define JBG_EMARKER (5 << 4)
#define JBG_EINVAL (6 << 4)
#define JBG_EIMPL (7 << 4)
#define JBG_ENOCONT (8 << 4)
/*
* Status of a JBIG encoder
*/
struct jbg_enc_state {
int d; /* resolution layer of the input image */
unsigned long xd, yd; /* size of the input image (resolution layer d) */
unsigned long yd1; /* BIH announced height of image, use yd1 != yd to
emulate T.85-style NEWLEN height updates for tests */
int planes; /* number of different bitmap planes */
int dl; /* lowest resolution layer in the next BIE */
int dh; /* highest resolution layer in the next BIE */
unsigned long l0; /* number of lines per stripe at lowest *
* resolution layer 0 */
unsigned long stripes; /* number of stripes required (determ. by l0) */
unsigned char **lhp[2]; /* pointers to lower/higher resolution images */
int *highres; /* index [plane] of highres image in lhp[] */
int order; /* SDE ordering parameters */
int options; /* encoding parameters */
unsigned mx, my; /* maximum ATMOVE window size */
int *tx; /* array [plane] with x-offset of adaptive template pixel */
char *dppriv; /* optional private deterministic prediction table */
char *res_tab; /* table for the resolution reduction algorithm */
struct jbg_buf ****sde; /* array [stripe][layer][plane] pointers to *
* buffers for stored SDEs */
struct jbg_arenc_state *s; /* array [planes] for arithm. encoder status */
struct jbg_buf *free_list; /* list of currently unused SDE block buffers */
void (*data_out)(unsigned char *start, size_t len, void *file);
/* data write callback */
void *file; /* parameter passed to data_out() */
char *tp; /* buffer for temp. values used by diff. typical prediction */
unsigned char *comment; /* content of comment marker segment to be added
at next opportunity (will be reset to NULL
as soon as comment has been written) */
unsigned long comment_len; /* length of data pointed to by comment */
};
/*
* Status of a JBIG decoder
*/
struct jbg_dec_state {
/* data from BIH */
int d; /* resolution layer of the full image */
int dl; /* first resolution layer in this BIE */
unsigned long xd, yd; /* size of the full image (resolution layer d) */
int planes; /* number of different bitmap planes */
unsigned long l0; /* number of lines per stripe at lowest *
* resolution layer 0 */
unsigned long stripes; /* number of stripes required (determ. by l0) */
int order; /* SDE ordering parameters */
int options; /* encoding parameters */
int mx, my; /* maximum ATMOVE window size */
char *dppriv; /* optional private deterministic prediction table */
/* loop variables */
unsigned long ii[3]; /* current stripe, layer, plane (outer loop first) */
/*
* Pointers to array [planes] of lower/higher resolution images.
* lhp[d & 1] contains image of layer d.
*/
unsigned char **lhp[2];
/* status information */
int **tx, **ty; /* array [plane][layer-dl] with x,y-offset of AT pixel */
struct jbg_ardec_state **s; /* array [plane][layer-dl] for arithmetic *
* decoder status */
int **reset; /* array [plane][layer-dl] remembers if previous stripe *
* in that plane/resolution ended with SDRST. */
unsigned long bie_len; /* number of bytes read so far */
unsigned char buffer[20]; /* used to store BIH or marker segments fragm. */
int buf_len; /* number of bytes in buffer */
unsigned long comment_skip; /* remaining bytes of a COMMENT segment */
unsigned long x; /* x position of next pixel in current SDE */
unsigned long i; /* line in current SDE (first line of each stripe is 0) */
int at_moves; /* number of AT moves in the current stripe */
unsigned long at_line[JBG_ATMOVES_MAX]; /* lines at which an *
* AT move will happen */
int at_tx[JBG_ATMOVES_MAX], at_ty[JBG_ATMOVES_MAX]; /* ATMOVE offsets in *
* current stripe */
unsigned long line_h1, line_h2, line_h3; /* variables of decode_pscd */
unsigned long line_l1, line_l2, line_l3;
int pseudo; /* flag for TPBON/TPDON: next pixel is pseudo pixel */
int **lntp; /* flag [plane][layer-dl] for TP: line is not typical */
unsigned long xmax, ymax; /* if possible abort before image gets *
* larger than this size */
int dmax; /* abort after this layer */
};
/* some macros (too trivial for a function) */
#define jbg_dec_getplanes(s) ((s)->planes)
/* function prototypes */
void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y,
int planes, unsigned char **p,
void (*data_out)(unsigned char *start, size_t len,
void *file),
void *file);
int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth,
unsigned long mheight);
void jbg_enc_layers(struct jbg_enc_state *s, int d);
int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh);
void jbg_enc_options(struct jbg_enc_state *s, int order, int options,
unsigned long l0, int mx, int my);
void jbg_enc_out(struct jbg_enc_state *s);
void jbg_enc_free(struct jbg_enc_state *s);
void jbg_dec_init(struct jbg_dec_state *s);
void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax,
unsigned long ymax);
int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len,
size_t *cnt);
unsigned long jbg_dec_getwidth(const struct jbg_dec_state *s);
unsigned long jbg_dec_getheight(const struct jbg_dec_state *s);
unsigned char *jbg_dec_getimage(const struct jbg_dec_state *s, int plane);
unsigned long jbg_dec_getsize(const struct jbg_dec_state *s);
void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode,
void (*data_out)(unsigned char *start, size_t len,
void *file), void *file);
unsigned long jbg_dec_getsize_merged(const struct jbg_dec_state *s);
void jbg_dec_free(struct jbg_dec_state *s);
const char *jbg_strerror(int errnum);
void jbg_int2dppriv(unsigned char *dptable, const char *internal);
void jbg_dppriv2int(char *internal, const unsigned char *dptable);
unsigned long jbg_ceil_half(unsigned long x, int n);
void jbg_split_planes(unsigned long x, unsigned long y, int has_planes,
int encode_planes,
const unsigned char *src, unsigned char **dest,
int use_graycode);
int jbg_newlen(unsigned char *bie, size_t len);
#endif /* JBG_H */

810
libjbig/jbig.txt Normal file
View File

@ -0,0 +1,810 @@
Using the JBIG-KIT library
--------------------------
Markus Kuhn -- 2013-09-10
This text explains how to use the functions provided by the JBIG-KIT
portable image compression library jbig.c in your application
software. The jbig.c library is a full-featured implementation of the
JBIG1 standard aimed at applications that can hold the entire
uncompressed and compressed image in RAM.
[For applications that require only the single-bit-per-pixel "fax
subset" of the JBIG1 standard defined in ITU-T Recommendation T.85
<http://www.itu.int/rec/T-REC-T.85/en>, the alternative implementation
found in jbig85.c may be preferable. It keeps not more than three
lines of the uncompressed image in RAM, which makes it particularly
suitable for embedded applications. For information on how to use
jbig85.c, please refer to the separate documentation file jbig85.txt.]
1 Introduction to JBIG
We start with a short introduction to JBIG1. More detailed information
is provided in the "Introduction and overview" section of the JBIG1
standard. Information on how to obtain a copy of the standard is
available from <http://www.itu.int/rec/T-REC-T.82/en> or
<http://www.iso.ch/>.
Image data encoded with the JBIG algorithm is separated into planes,
layers, and stripes. Each plane contains one bit per pixel. The number
of planes stored in a JBIG data stream is the number of bits per
pixel. Resolution layers are numbered from 0 to D with 0 being the
layer with the lowest resolution and D the one with the highest. Each
next higher resolution layer has twice the number of rows and columns.
Layer 0 is encoded independently of any other data, all other
resolution layers are encoded as only the difference between the next
lower and the current layer. For applications that require very quick
access to parts of an image, it is possible to divide an image into
several horizontal stripes. All stripes of one resolution layer have
equal size, except perhaps the final one. The number of stripes of an
image is equal in all resolution layers and in all bit planes.
The compressed data stream specified by the JBIG standard is called a
bi-level image entity (BIE). A BIE consists of a 20-byte header,
followed by an optional 1728-byte table (usually not present, except
in special applications) followed by a sequence of stripe data
entities (SDE). Each SDE encodes the content of one single stripe in
one plane of one resolution layer. Between the SDEs, other information
blocks (called floating marker segments) can also be present. They are
used to change certain parameters of the algorithm in the middle of an
image or contain additional application specific information. A BIE
looks like this:
+------------------------------------------------+
| |
| 20-byte header (with image size, #planes, |
| #layers, stripe size, first layer, options, |
| SDE ordering, ...) |
| |
+------------------------------------------------+
| |
| optional 1728-byte table |
| |
+------------------------------------------------+
| |
| optional floating marker segments |
| |
+------------------------------------------------+
| |
| stripe data entity |
| |
+------------------------------------------------+
| |
| optional floating marker segments |
| |
+------------------------------------------------+
| |
| stripe data entity |
| |
+------------------------------------------------+
...
+------------------------------------------------+
| |
| stripe data entity |
| |
+------------------------------------------------+
One BIE can contain all resolution layers of an image, but it is also
possible to store various resolution layers in several BIEs. The BIE
header contains the number of the first and the last resolution layer
stored in this BIE, as well as the size of the highest resolution
layer stored in this BIE. Progressive coding is deactivated by simply
storing the image in one single resolution layer.
Different applications might have different requirements for the order
in which the SDEs for stripes of various planes and layers are stored
in the BIE, so all possible sensible orderings are allowed by the
standard and indicated by four bits in the header.
It is possible to use the raw BIE data stream as specified by the JBIG
standard directly as the format of a file used for storing images.
This is what the pbmtojbg, jbgtopbm, pbmtojbg85, and jbgtopbm85
conversion tools do that are provided in this package as demonstration
applications. However, as the BIE format has been designed for a large
number of very different applications, and to allow efficient direct
processing by special JBIG hardware chip implementations, the BIE
header contains only the minimum amount of information absolutely
required by the decompression algorithm. Many features expected from a
good file format are missing in the BIE data stream:
- no "magic code" in the first few bytes to allow identification
of the file format on a typeless file system and to allow
automatic distinction from other compression algorithms
- no standardized way to encode additional information such as a
textual description, information about the meaning of various bit
planes, the physical size and resolution of the document, etc.
- a checksum to ensure image integrity
- encryption and signature mechanisms
- many things more
Raw BIE data streams alone may therefore not be a suitable format for
document archiving and exchange. A standard format for this purpose
would typically combine a BIE representing the image data with an
additional header providing auxiliary information into one file.
Existing established multi-purpose file formats with a rich set of
auxiliary information attributes like TIFF could be extended easily to
also hold JBIG compressed data.
On the other hand, in e.g. database applications, a BIE might be
stored directly in a binary variable-length field. Auxiliary
information would then be stored in other fields of the same record,
to simplify search operations.
2 Compressing an image
2.1 Format of the source image
To be processed by the jbig.c encoder, the image has to be present in
memory as separate bitmap planes. Each byte of a bitmap contains eight
pixels, where the most significant bit represents the leftmost of
these. Each line of a bitmap has to be stored in an integral number of
bytes. If the image width is not an integral multiple of eight, then
the final byte has to be padded with zero bits.
For example the 23x5 pixels large single plane image:
.XXXXX..XXX...X...XXX..
.....X..X..X..X..X.....
.....X..XXX...X..X.XXX.
.X...X..X..X..X..X...X.
..XXX...XXX...X...XXX..
is represented by the 15 bytes
01111100 11100010 00111000
00000100 10010010 01000000
00000100 11100010 01011100
01000100 10010010 01000100
00111000 11100010 00111000
or in hexadecimal notation
7c e2 38 04 92 40 04 e2 5c 44 92 44 38 e2 38
This is the format used in binary PBM files and it can also be handled
directly by the Xlib library of the X Window System.
As JBIG can also handle images with multiple bit planes, the jbig.c
library functions accept and return always arrays of pointers to
bitmaps with one pointer per plane.
For single-plane images, the standard recommends that a 0 pixel
represents the background and a 1 pixel represents the foreground
colour of an image, in other words, 0 is white and 1 is black for
scanned paper documents. For images with several bits per pixel, the
JBIG standard makes no recommendations about how various colours should
be encoded.
For grey-scale images, by using a Gray code instead of a simple binary
weighted representation of the pixel intensity, some increase in
coding efficiency can be reached.
A Gray code is also a binary representation of integer numbers, but it
has the property that the representations of the integer numbers i and
(i+1) always differ in exactly one bit. For example, the numbers 0 to
7 can be represented in normal binary code and Gray code as in the
following table:
normal
number binary code Gray code
---------------------------------------
0 000 000
1 001 001
2 010 011
3 011 010
4 100 110
5 101 111
6 110 101
7 111 100
The form of Gray code shown above has the property that the second
half of the code (numbers 4 - 7) is simply the mirrored first half
(numbers 3 - 0) with the first bit set to one. This way, arbitrarily
large Gray codes can be generated quickly by mirroring the above
example and prefixing the first half with zeros and the second half
with ones as often as required. In grey-scale images, it is common
practise to use the all-0 code for black and the all-1 code for white.
No matter whether a Gray code or a binary code is used for encoding a
pixel intensity in several bit planes, it always makes sense to store
the most significant (leftmost) bit in plane 0, which is transmitted
first. This way, a decoder could increase the precision of the
displayed pixel intensities while data is still being received and the
basic structure of the image will become visible as early as possible
during the transmission.
2.2 A simple compression application
In order to use jbig.c in your application, just link libjbig.a to
your executable (on Unix systems just add -ljbig and -L. to the
command line options of your compiler, on other systems you will have
to write a new Makefile anyway), copy the file jbig.h into your source
directory and put the line
#include "jbig.h"
into your source code.
The library interface follows object-oriented programming principles.
You have to declare a variable (object)
struct jbg_enc_state s;
which contains the current status of an encoder. Then you initialize
the encoder by calling the constructor function
void jbg_enc_init(struct jbg_enc_state *s, unsigned long x, unsigned long y,
int pl, unsigned char **p,
void (*data_out)(unsigned char *start, size_t len,
void *file),
void *file);
The parameters have the following meaning:
s A pointer to the jbg_enc_state structure that you want
to initialize.
x The width of your image in pixels.
y The height of your image in pixels (lines).
pl the number of bitmap planes you want to encode.
p A pointer to an array of pl pointers, where each is again
pointing to the first byte of a bitmap as described in
section 2.1.
data_out This is a call-back function that the encoder will
call during the compression process by in order to
deliver the BIE data to your application. The
parameters of the function data_out are a pointer
start to the new block of data being delivered, as
well as the number len of delivered bytes. The pointer
file is transparently delivered to data_out, as
specified in jbg_enc_init(). Typically, data_out will
write the BIE portion to a file, send it to a network
connection, or append it to some memory buffer.
file A pointer parameter that is passed on to data_out()
and can be used, for instance, to allow data_out() to
distinguish by which compression task it has been
called in multi-threaded applications.
In the simplest case, the compression is then started by calling the
function
void jbg_enc_out(struct jbg_enc_state *s);
which will deliver the complete BIE to data_out() in several calls.
After jbg_enc_out has returned, a call to the destructor function
void jbg_enc_free(struct jbg_enc_state *s);
will release any heap memory allocated by the previous functions.
A minimal example application, which sends the BIE of the above bitmap
to stdout, looks like this:
---------------------------------------------------------------------------
/* A sample JBIG encoding application */
#include <stdio.h>
#include "jbig.h"
void output_bie(unsigned char *start, size_t len, void *file)
{
fwrite(start, 1, len, (FILE *) file);
return;
}
int main()
{
unsigned char bitmap[15] = {
/* 23 x 5 pixels, "JBIG" */
0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2,
0x5c, 0x44, 0x92, 0x44, 0x38, 0xe2, 0x38
};
unsigned char *bitmaps[1] = { bitmap };
struct jbg_enc_state se;
jbg_enc_init(&se, 23, 5, 1, bitmaps,
output_bie, stdout); /* initialize encoder */
jbg_enc_out(&se); /* encode image */
jbg_enc_free(&se); /* release allocated resources */
return 0;
}
---------------------------------------------------------------------------
This software produces a 42 byte long BIE. (JBIG is not very good at
compressing extremely small images like in this example, because the
arithmetic encoder requires some startup data in order to generate
reasonable statistics which influence the compression process and
because there is some header overhead.)
2.3 More about compression
If jbg_enc_out() is called directly after jbg_enc_init(), the
following default values are used for various compression parameters:
- Only one single resolution layer is used, i.e. no progressive
mode.
- The number of lines per stripe is selected so that approximately
35 stripes per image are used (as recommended in annex C of the
standard together with the suggested adaptive template change
algorithm). However, not less than 2 and not more than 128 lines
are used in order to stay within the suggested minimum parameter
support range specified in annex A of the standard).
- All optional parts of the JBIG algorithm are activated (TPBON,
TPDON and DPON).
- The default resolution reduction table and the default deterministic
prediction table are used
- The maximal vertical offset of the adaptive template pixel is 0
and the maximal horizontal offset is 8 (mx = 8, my = 0).
In order to change any of these default parameters, additional
functions have to be called between jbg_enc_init() and jbg_enc_out().
In order to activate progressive encoding, it is possible to specify
with
void jbg_enc_layers(struct jbg_enc_state *s, int d);
the number d of differential resolution layers which shall be encoded
in addition to the lowest resolution layer 0. For example, if a
document with 60-micrometer pixels has to be stored, and the lowest
resolution layer shall have 240-micrometer pixels, so that a screen
previewer can directly decompress only the required resolution, then a
call
jbg_enc_layers(&se, 2);
will cause three layers with 240, 120 and 60 micrometers resolution to
be generated.
If the application does not know what typical resolutions are used and
simply wants to ensure that the lowest resolution layer will fit into
a given maximal window size, then as an alternative, a call to
int jbg_enc_lrlmax(struct jbg_enc_state *s, unsigned long mwidth,
unsigned long mheight);
will cause the library to automatically determine the suitable number
of resolutions so that the lowest resolution layer 0 will not be
larger than mwidth x mheight pixels. E.g. if one wants to ensure that
systems with a 640 x 480 pixel large screen can decode the required
resolution directly, then call
jbg_enc_lrlmax(&se, 640, 480);
The return value is the number of differential layers selected.
After the number of resolution layers has been specified by calls to
jbg_enc_layers() or jbg_enc_lrlmax(), by default, all these layers
will be written into the BIE. This can be changed with a call to
int jbg_enc_lrange(struct jbg_enc_state *s, int dl, int dh);
Parameter dl specifies the lowest resolution layer and dh the highest
resolution layer that will appear in the BIE. For instance, if layer 0
shall be written to the first BIE and layer 1 and 2 shall be written
to a second one, then before writing the first BIE, call
jbg_enc_lrange(&se, 0, 0);
and before writing the second BIE with jbg_enc_out(), call
jbg_enc_lrange(&se, 1, 2);
If any of the parameters is negative, it will be ignored. The return
value is the total number of differential layers that will represent
the input image. This way, jbg_enc_lrange(&se, -1, -1) can be used to
query the layer of the full image resolution.
A number of other more exotic options of the JBIG algorithm can be
modified by calling
void jbg_enc_options(struct jbg_enc_state *s, int order, int options,
long l0, int mx, int my);
before calling jbg_enc_out().
The order parameter can be a combination of the bits JBG_HITOLO,
JBG_SEQ, JBG_ILEAVE and JBG_SMID and it determines in which order
the SDEs are stored in the BIE. The bits have the following meaning:
JBG_HITOLO Usually, the lower resolution layers are stored before
the higher resolution layers, so that a decoder can
already start to display a low resolution version of
the full image once a prefix of the BIE has been
received. When this bit is set, however, the BIE will
contain the higher layers before the lower layers. This
avoids additional buffer memory in the encoder and is
intended for applications where the encoder is connected
to a database which can easily reorder the SDEs before
sending them to a decoder. Warning: JBIG decoders are
not expected to support the HITOLO option (e.g. the
jbig.c decoder currently does not) so you should
normally not use it.
JBG_SEQ Usually, at first all stripes of one resolution layer
are written to the BIE and then all stripes of the next
layer, and so on. When the SEQ bit is set however, then
all layers of the first stripe will be written,
followed by all layers of the second stripe, etc. This
option also should normally never be required and is
not supported by the current jbig.c decoder.
JBG_SMID In case there exist several bit planes, then the order of
the stripes is determined by three loops over all stripes,
all planes and all layers. When SMID is set, the loop
over all stripes is the middle loop.
JBG_ILEAVE If this bit is set, then at first all layers of one
plane are written before the encoder starts with the next
plane.
The above description may be somewhat confusing, but the following
table (see also Table 11 in ITU-T T.82) clarifies how the three bits
JBG_SEQ, JBIG_ILEAVE and JBG_SMID influence the ordering of the loops
over all stripes, planes and layers:
Loops:
JBG_SEQ JBG_ILEAVE JBG_SMID | Outer Middle Inner
------------------------------------+---------------------------
0 0 0 | p d s
0 1 0 | d p s
0 1 1 | d s p
1 0 0 | s p d
1 0 1 | p s d
1 1 0 | s d p
p: plane, s: stripe, d: layer
By default, the order combination JBG_ILEAVE | JBG_SMID is used.
The options value can contain the following bits, which activate
some of the optional algorithms defined by JBIG:
JBG_LRLTWO Normally, in the lowest resolution layer, pixels
from three lines around the next pixel are used
in order to determine the context in which the next
pixel is encoded. Some people in the JBIG committee
seem to have argued that using only 2 lines will
make software implementations a little bit faster,
however others have argued that using only two lines
will decrease compression efficiency by around 5%.
As you might expect from a committee, now both
alternatives are allowed and if JBG_LRLTWO is set,
the slightly faster but 5% less well compressing two
line alternative is selected. God bless the committees.
Although probably nobody will ever need this option,
it has been implemented in jbig.c and is off by
default.
JBG_TPDON This activates the "typical prediction" algorithm
for differential layers which avoids that large
areas of equal colour have to be encoded at all.
This is on by default and there is no good reason to
switch it off except for debugging or preparing data
for cheap JBIG hardware that might not support this
option.
JBG_TPBON Like JBG_TPDON this activates the "typical prediction"
algorithm in the lowest resolution layer. Also activated
by default.
JBG_DPON This bit activates for the differential resolution
layers the "deterministic prediction" algorithm,
which avoids that higher resolution layer pixels are
encoded when their value can already be determined
with the knowledge of the neighbour pixels, the
corresponding lower resolution pixels and the
resolution reduction algorithm. This is also
activated by default and one reason for deactivating
it would be if the default resolution reduction
algorithm were replaced by another one.
JBG_DELAY_AT Use a slightly less efficient algorithm to determine
when an adaptive template change is necessary. With
this bit set, the encoder output is compatible to the
conformance test examples in cause 7.2 of ITU-T T.82.
Then all adaptive template changes are delayed until
the first line of the next stripe. This option is by
default deactivated and is only required for passing a
special compatibility test suite.
In addition, parameter l0 in jbg_enc_options() allows you to specify
the number of lines per stripe in resolution layer 0. The parameters
mx and my change the maximal offset allowed for the adaptive template
pixel. JBIG-KIT now supports the full range of possible mx values up
to 127 in the encoder and decoder, but my is at the moment ignored and
always set to 0. As the standard requires of all decoder
implementations only to support maximum values mx = 16 and my = 0,
higher values should normally be avoided in order to guarantee
interoperability. The ITU-T T.85 profile for JBIG in fax machines
requires support for mx = 127 and my = 0. Default is mx = 8 and my =
0. If any of the parameters order, options, mx or my is negative, or
l0 is zero, then the corresponding current value remains unmodified.
The resolution reduction and deterministic prediction tables can also
be replaced. However as these options are anyway only for experts,
please have a look at the source code of jbg_enc_out() and the struct
members dppriv and res_tab of struct jbg_enc_state for the details of
how to do this, in case you really need it. The functions
jbg_int2dppriv and jbg_dppriv2int are provided in order to convert the
DPTABLE data from the format used in the standard into the more
efficient format used internally by JBIG-KIT.
If you want to encode a grey-scale image, you can use the library
function
void jbg_split_planes(unsigned long x, unsigned long y, int has_planes,
int encode_planes,
const unsigned char *src, unsigned char **dest,
int use_graycode);
It separates an image in which each pixel is represented by one or
more bytes into separate bit planes. The dest array of pointers to
these bit planes can then be handed over to jbg_enc_init(). The
variables x and y specify the width and height of the image in pixels,
and has_planes specifies how many bits per pixel are used. As each
pixel is represented by an integral number of consecutive bytes, of
which each contains up to eight bits, the total length of the input
image array src[] will therefore be x * y * ((has_planes + 7) / 8)
bytes. The pixels are stored as usually in English reading order, and
for each pixel the integer value is stored with the most significant
byte coming first (Bigendian). This is exactly the format used in raw
PGM files. In encode_planes, the number of bit planes that shall be
extracted can be specified. This allows for instance to extract only
the most significant 8 bits of a 12-bit image, where each pixel is
represented by two bytes, by specifying has_planes = 12 and
encode_planes = 8. If use_graycode is zero, then the binary code of
the pixel integer values will be used instead of the Gray code. Plane
0 contains always the most significant bit.
3 Decompressing an image
Like with the compression functions, if you want to use the jbig.c
library, you have to put the line
#include "jbig.h"
into your source code and link your executable with libjbig.a.
The state of a JBIG decoder is stored completely in a struct and you
will have to define a variable like
struct jbg_dec_state sd;
which is initialized by a call to
void jbg_dec_init(struct jbg_dec_state *s);
After this, you can directly start to pass data from the BIE to the decoder
by calling the function
int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len,
size_t *cnt);
The pointer data points to the first byte of a data block with length
len, which contains bytes from a BIE. It is not necessary to pass a
whole BIE at once to jbg_dec_in(), it can arrive fragmented in any way
by calling jbg_dec_in() several times. It is also possible to send
several BIEs concatenated to jbg_dec_in(), however these then have to
fit together. If you send several BIEs to the decoder, the lowest
resolution layer in each following BIE has to be the highest
resolution layer in the previous BIE plus one and the image sizes and
number of planes also have to fit together, otherwise jbg_dec_in()
will return the error JBG_ENOCONT after the header of the new BIE has
been received completely.
If pointer cnt is not NULL, then the number of bytes actually read
from the data block will be stored there. In case the data block did
not contain the end of the BIE, then the value JBG_EAGAIN will be
returned and *cnt equals len.
Once the end of a BIE has been reached, the return value of
jbg_dec_in() will be JBG_EOK. After this has happened, the functions
and macros
unsigned long jbg_dec_getwidth(struct jbg_dec_state *s);
unsigned long jbg_dec_getheight(struct jbg_dec_state *s);
int jbg_dec_getplanes(struct jbg_dec_state *s);
unsigned char *jbg_dec_getimage(struct jbg_dec_state *s, int plane);
unsigned long jbg_dec_getsize(struct jbg_dec_state *s);
can be used to query the dimensions of the now completely decoded
image and to get a pointer to all bitmap planes. The bitmaps are
stored as described in section 2.1. The function jbg_dec_getsize()
calculates the number of bytes which one bitmap requires.
The function
void jbg_dec_merge_planes(const struct jbg_dec_state *s, int use_graycode,
void (*data_out)(unsigned char *start, size_t len,
void *file), void *file);
allows you to merge the bit planes that can be accessed individually
with jbg_dec_getimage() into an array with one or more bytes per pixel
(i.e., the format provided to jbg_split_planes()). If use_graycode is
zero, then a binary encoding will be used. The output array will be
delivered via the callback function data_out, exactly in the same way
in which the encoder provides the BIE. The function
unsigned long jbg_dec_getsize_merged(const struct jbg_dec_state *s);
determines how long the data array delivered by jbg_dec_merge_planes()
is going to be.
Before calling jbg_dec_in() the first time, it is possible to specify with
a call to
void jbg_dec_maxsize(struct jbg_dec_state *s, unsigned long xmax,
unsigned long ymax);
an abort criterion for progressively encoded images. For instance if an
application will display a whole document on a screen which is 1024 x
768 pixels large, then this application should call
jbg_dec_maxsize(&sd, 1024, 768);
before the decoding process starts. If the image has been encoded in
progressive mode (i.e. with several resolution layers), then the
decoder will stop with a return value JBG_EOK_INTR after the largest
resolution layer that is still smaller than 1024 x 768. However this
is no guarantee that the image which can then be read out using
jbg_dec_getimage(), etc. is really not larger than the specified
maximal size. The application will have to check the size of the
image, because the decoder does not automatically apply a resolution
reduction if no suitable resolution layer is available in the BIE.
If jbg_dec_in() returned JBG_EOK_INTR or JBG_EOK, then it is possible
to continue calling jbg_dec_in() with the remaining data in order to
either decode the remaining resolution layers of the current BIE or in
order to add another BIE with additional resolution layers. In both
cases, after jbg_dec_in() returned JBG_EOK_INTR or JBG_EOK, *cnt is
probably not equal to len and the remainder of the data block which
has not yet been processed by the decoder has to be delivered to
jbg_dec_in() again.
If any other return value than JBG_EOK, JBG_EOK_INTR or JBG_EAGAIN
has been returned by jbg_dec_in(), then an error has occurred and
void jbg_dec_free(struct jbg_dec_state *s);
should be called in order to release any allocated memory. The
destructor jbg_dec_free() should of course also be called, once the
decoded bitmap returned by jbg_dec_getimage() is no longer required
and the memory can be released.
The function
const char *jbg_strerror(int errnum);
returns a pointer to a short single line test message that explains
the return value of jbg_dec_in(). This message can be used in order to
provide the user a brief informative message about what when wrong
while decompressing a JBIG image. The po/ subdirectory contains *.po
files that translate the English ASCII strings returned by
jbg_strerror() into other languages (e.g., for use with GNU gettext).
The four least-significant bits of the return value of jbg_dec_in()
may contain additional detailed technical information about the exact
test that spotted the error condition (see source code for details),
i.e. more than the text message returned by jbg_strerror() reveals.
Therefore it may be useful to display the return value itself as a
hexadecimal number, in addition to the string returned by
jbg_strerror().
The current implementation of the jbig.c decoder has the following
limitations:
- The maximal vertical offset MY of the adaptive template pixel
must be zero.
- HITOLO and SEQ bits must not be set in the order value.
- Not more than JBG_ATMOVES_MAX (currently set to 64) ATMOVE
marker segments can be handled per stripe.
- the number D of differential layers must be less than 32
None of the above limitations can be exceeded by a JBIG data stream
that conforms to the ITU-T T.85 application profile for the use of
JBIG1 in fax machines.
The current implementation of the jbig.c decoder does not impose any
limits on the image size that it will process, as long as malloc() is
able to allocate enough heap space for the resulting bitmaps. The only
exception is that jbg_dec_in() will return "Input data stream uses
unimplemented JBIG features" (JBG_EIMPL | 1) if Y_D equals 0xffffffff,
which is an extreme value commonly used to encode images according to
ITU-T T.85 where the height was unknown when the BIH was emitted.
After jbg_dec_in() received the 20-byte long BIH at the start of the
BIE, it will malloc() to allocate enough memory to hold the requested
image planes and layers. If you want to defend your application
against excessive image-size parameters in a received BIH, then do
make sure that you check X_D, Y_D, and P against appropriate safety
limits before handing over the BIH to jbg_dec_in().
There are two more limitations of the current implementation of the
jbig.c decoder that might cause problems with processing JBIG data
stream that conform to ITU-T T.85:
- The jbig.c decoder was designed to operate incrementally.
Each received byte is processed immediately as soon as it arrives.
As a result, it does not look beyond the SDRST/SDNORM at the end
of all stripes for any immediately following NEWLEN marker that
might reduce the number of lines encoded by the current stripe.
However section 6.2.6.2 of ITU-T T.82 says that a NEWLEN marker
segment "could refer to a line in the immediately preceding stripe
due to an unexpected termination of the image or the use of only
such stripe", and ITU-T.85 explicitly suggests the use of this
for fax machines that start transmission before having encountered
the end of the page.
- The image size initially indicated in the BIE header is used to
allocate memory for a bitmap of this size. This means that BIEs
that set initially Y_D = 0xffffffff (as suggested in ITU-T T.85
for fax machines that do not know the height of the page at the
start of the transmission) cannot be decoded directly by this
version.
For both issues, there is a workaround available:
If you encounter a BIE that has in the header the VLENGTH=1 option bit
set, then first wait until you have received the entire BIE and stored
it in memory. Then call the function
int jbg_newlen(unsigned char *bie, size_t len);
where bie is a pointer to the first byte of the BIE and len its length
in bytes. This function will scan the entire BIE for the first NEWLEN
marker segment. It will then take the updated image-height value YD
from it and use it to overwrite the YD value in the BIE header. The
jbg_newlen() can return some of the same error codes as jbg_dec_in(),
namely JBG_EOK if everything went fine, JBG_EAGAIN is the data
provided is too short to be a valid BIE, JBG_EINVAL if a format error
was encountered, and JBG_EABORT if an ABORT marker segment was found.
After having patched the image-height value in the BIE using
jbg_newlen(), simply hand over the BIE as usual to jbg_dec_in().
In general, for applications where NEWLEN markers can appear, in
particular fax reception, you should consider using the jbig85.c
decoder instead, as it can process BIEs with NEWLEN markers in a
single pass.
A more detailed description of the JBIG-KIT implementation is
Markus Kuhn: Effiziente Kompression von bi-level Bilddaten durch
kontextsensitive arithmetische Codierung. Studienarbeit, Lehrstuhl
für Betriebssysteme, IMMD IV, Universität Erlangen-Nürnberg,
Erlangen, July 1995. (German, 62 pages)
<http://www.cl.cam.ac.uk/~mgk25/kuhn-sta.pdf>
Please quote the above if you use JBIG-KIT in your research project.
*** Happy compressing ***
[end]

1091
libjbig/jbig85.c Normal file

File diff suppressed because it is too large Load Diff

173
libjbig/jbig85.h Normal file
View File

@ -0,0 +1,173 @@
/*
* Header file for the T.85 "light" version of the portable
* JBIG image compression library
*
* Copyright 1995-2014 -- Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/
*/
#ifndef JBG85_H
#define JBG85_H
#include <stddef.h>
#include "jbig_ar.h"
/*
* JBIG-KIT version number
*/
#define JBG85_VERSION "2.1"
#define JBG85_VERSION_MAJOR 2
#define JBG85_VERSION_MINOR 1
/*
* JBIG-KIT licence agreement reference code:
* If you use JBIG-KIT under a commercial licence, please replace
* below the letters GPL with the reference code that you received
* with your licence agreement. (This code is typically a letter "A"
* followed by four decimal digits, e.g. "A1234".)
*/
#define JBG85_LICENCE "GPL"
/*
* Maximum number of ATMOVEs per stripe that decoder can handle
*/
#define JBG85_ATMOVES_MAX 1
#ifndef JBG_LRLTWO
/*
* Option and order flags
*/
#define JBG_LRLTWO 0x40
#define JBG_VLENGTH 0x20
#define JBG_TPBON 0x08
/*
* Possible error code return values
*/
#define JBG_EOK (0 << 4)
#define JBG_EOK_INTR (1 << 4)
#define JBG_EAGAIN (2 << 4)
#define JBG_ENOMEM (3 << 4)
#define JBG_EABORT (4 << 4)
#define JBG_EMARKER (5 << 4)
#define JBG_EINVAL (6 << 4)
#define JBG_EIMPL (7 << 4)
#endif
/*
* Status of a JBIG encoder
*/
struct jbg85_enc_state {
unsigned long x0, y0; /* size of the input image */
unsigned long l0; /* number of lines per stripe */
int options; /* encoding parameters */
int newlen; /* 0 = jbg85_enc_newlen() has not yet been called
1 = jbg85_enc_newlen() has updated y0, NEWLEN pending
2 = NEWLEN has already been output */
unsigned mx; /* maximum ATMOVE window size */
unsigned long y; /* next line number to be encoded */
unsigned long i; /* next per-stripe line number to be encoded */
int tx; /* x-offset of adaptive template pixel */
unsigned long c_all, c[128]; /* adaptive template algorithm variables */
int new_tx; /* -1 = no ATMOVE pending, otherwise new TX value */
int ltp_old; /* true if line y-1 was "typical" */
struct jbg_arenc_state s; /* arithmetic encoder status */
void (*data_out)(unsigned char *start, size_t len, void *file);
/* data write callback */
void *file; /* parameter passed to data_out() */
unsigned char *comment; /* content of comment marker segment to be added
at next opportunity (will be reset to NULL
as soon as comment has been written) */
unsigned long comment_len; /* length of data pointed to by comment */
};
/*
* Status of a JBIG decoder
*/
struct jbg85_dec_state {
/* data from BIH */
unsigned long x0, y0; /* size of the full image */
unsigned long l0; /* number of lines per stripe */
int options; /* encoding parameters */
int mx; /* maximum ATMOVE window size */
/* image data */
int p[3]; /* curr. line starts at linebuf+bpl*p[0], prev. line starts
* at linebuf+bpl*p[1], its predecessor at linebuf+bpl*p[2] */
unsigned char *linebuf; /* buffer region provided by caller */
size_t linebuf_len;
size_t bpl; /* bytes per line */
/* status information */
int tx; /* x-offset of AT pixel */
struct jbg_ardec_state s; /* arithmetic decoder status */
unsigned long bie_len; /* number of bytes read so far */
unsigned char buffer[20]; /* used to store BIH or marker segments fragm. */
int buf_len; /* number of bytes in buffer */
unsigned long comment_skip; /* remaining bytes of a COMMENT segment */
unsigned long x; /* x position of next pixel */
unsigned long stripe; /* current stripe */
unsigned long y; /* line in image (first line is 0) */
unsigned long i; /* line in current stripe (first line of stripe is 0) */
int at_moves; /* number of AT moves in the current stripe */
unsigned long at_line[JBG85_ATMOVES_MAX]; /* lines at which an *
* AT move will happen */
int at_tx[JBG85_ATMOVES_MAX]; /* ATMOVE x-offsets in current stripe */
unsigned long line_h1, line_h2, line_h3; /* variables of decode_pscd */
int pseudo; /* flag for TPBON/TPDON: next pixel is pseudo pixel */
int lntp; /* flag for TP: line is not typical */
int (*line_out)(const struct jbg85_dec_state *s,
unsigned char *start, size_t len,
unsigned long y, void *file);
/* data write callback */
void *file; /* parameter passed to data_out() */
int intr; /* flag that line_out requested interrupt */
int end_of_bie; /* flag that the end of the BIE has been signalled */
};
/* function prototypes */
void jbg85_enc_init(struct jbg85_enc_state *s,
unsigned long x0, unsigned long y0,
void (*data_out)(unsigned char *start, size_t len,
void *file),
void *file);
void jbg85_enc_options(struct jbg85_enc_state *s, int options,
unsigned long l0, int mx);
void jbg85_enc_lineout(struct jbg85_enc_state *s, unsigned char *line,
unsigned char *prevline, unsigned char *prevprevline);
void jbg85_enc_newlen(struct jbg85_enc_state *s, unsigned long y0);
void jbg85_enc_abort(struct jbg85_enc_state *s);
void jbg85_dec_init(struct jbg85_dec_state *s,
unsigned char *buf, size_t buflen,
int (*line_out)(const struct jbg85_dec_state *s,
unsigned char *start, size_t len,
unsigned long y, void *file),
void *file);
int jbg85_dec_in(struct jbg85_dec_state *s, unsigned char *data, size_t len,
size_t *cnt);
int jbg85_dec_end(struct jbg85_dec_state *s);
const char *jbg85_strerror(int errnum);
/* some macros for examining decoder state */
#define jbg85_dec_finished(s) ((s)->bie_len == 20 && (s)->y >= (s)->y0)
/* enquire about image size */
#define jbg85_dec_getwidth(s) ((s)->x0)
#define jbg85_dec_getheight(s) ((s)->y0)
/* enquire about validity of image-size results */
#define jbg85_dec_validwidth(s) ((s)->bie_len == 20)
#define jbg85_dec_finalheight(s) ((s)->bie_len == 20 && \
((((s)->options & JBG_VLENGHT) == 0) || \
((s)->y >= (s)->y0)))
#endif /* JBG85_H */

617
libjbig/jbig85.txt Normal file
View File

@ -0,0 +1,617 @@
Using the T.85 "light" version of the JBIG-KIT library
------------------------------------------------------
Markus Kuhn -- 2008-08-30
This text explains how to use the functions provided by the JBIG-KIT
portable image compression library jbig85.c in your application
software.
1 Distinguishing features
The jbig85.c library implements only the "single-progression
sequential coding" subset of the JBIG1 standard, which is defined in
ITU-T Recommendation T.85 <http://www.itu.int/rec/T-REC-T.85/en>, also
known as the "facsimile application profile". This means that the
JBIG1 data streams that the jbig85.c library can process can have
- no progressive encoding, i.e. the image is always encoded in a
single resolution layer (and not as a sequence of layers of a
resolution pyramid);
- only a single plane, i.e. the raw data are black/white images with
only one bit per pixel information.
The jbig85.c library is not suitable for continuous-tone (colour or
grey-scale) image applications, including the fax method described in
ITU-R Recommendation T.43. For these applications, use the full jbig.c
library instead.
The T.85 restrictions are sufficient for black/white fax transmission
and several other common bi-level image applications (printer drivers,
document archiving, etc.). They simplify the design of the encoder and
decoder and allow the jbig85.c library to provide several advantages
over the full-featured jbig.c:
- Only the last three lines of the uncompressed image need to be
kept in RAM at any time.
- All memory allocation is done outside the jbig85.c library, which
performs no calls to malloc(), free(), etc.
- The implementation can handle images whose height (number of pixel
rows) is not yet known before the last line has been encoded or
decoded.
- All usage modes of the NEWLEN marker segment are supported,
including a NEWLEN occurring after the final stripe, as required by
ITU-T Recommendation T.85, using only a single pass over the data.
- The code is smaller and there is no need to store tables related
to the resolution-reduction algorithms.
This makes the jbig85.c library particularly suited for very small
embedded applications, e.g. low-end fax machines, along with the fact
that the library is non-recursive and requires only a very small stack
(typically just a bit over 100 bytes on a 32-bit system). The jbig85.c
library may also be a good choice where very large black/white images
are processed.
The jbig85.c and jbig.c libraries both can be linked simultaneously
with the same application if you #include jbig85.h after jbig.h into
your source code.
2 Introduction to JBIG (T.85 subset)
We start with a short introduction to the T.85 subset of JBIG1. More
detailed information is provided in the "Introduction and overview"
section of the JBIG1 standard. Information on how to obtain a copy of
the standard is available from <http://www.itu.int/rec/T-REC-T.82/en>
or <http://www.iso.ch/>.
The JBIG1 standard allows the encoder to divide an image into several
horizontal stripes. All stripes have equal size, except perhaps the
final one.
The compressed data stream specified by the JBIG standard is called a
bi-level image entity (BIE). A BIE consists of a 20-byte header,
followed by a sequence of stripe data entities (SDE). Each SDE encodes
the content of one single stripe in one plane of one resolution layer.
Between the SDEs, other information blocks (called floating marker
segments) can also be present. They are used to change certain
parameters of the algorithm in the middle of an image or contain
additional application specific information. A BIE looks like this:
+------------------------------------------------+
| |
| 20-byte header (specifying image size, stripe |
| size, and options) |
| |
+------------------------------------------------+
| |
| optional floating marker segments |
| |
+------------------------------------------------+
| |
| stripe data entity |
| |
+------------------------------------------------+
| |
| optional floating marker segments |
| |
+------------------------------------------------+
| |
| stripe data entity |
| |
+------------------------------------------------+
...
+------------------------------------------------+
| |
| stripe data entity |
| |
+------------------------------------------------+
It is possible to use the raw BIE data stream as specified by the JBIG
standard directly as the format of a file used for storing images.
This is what the pbmtojbg, jbgtopbm, pbmtojbg85, and jbgtopbm85
conversion tools do that are provided in this package as demonstration
applications. However, as the BIE format has been designed for a large
number of very different applications, and to allow efficient direct
processing by special JBIG hardware chip implementations, the BIE
header contains only the minimum amount of information absolutely
required by the decompression algorithm. Many features expected from a
good file format are missing in the BIE data stream:
- no "magic code" in the first few bytes to allow identification
of the file format on a typeless file system and to allow
automatic distinction from other compression algorithms
- no standardized way to encode additional information such as a
textual description, the physical size and resolution of the
document, etc.
- a checksum to ensure image integrity
- encryption and signature mechanisms
- many things more
Raw BIE data streams alone may therefore not be a suitable format for
document archiving and exchange. A standard format for this purpose
would typically combine a BIE representing the image data with an
additional header providing auxiliary information into one file.
Existing established multi-purpose file formats with a rich set of
auxiliary information attributes like TIFF could be extended easily to
also hold JBIG compressed data.
On the other hand, in e.g. database applications, a BIE might be
stored directly in a binary variable-length field. Auxiliary
information would then be stored in other fields of the same record,
to simplify search operations.
2 Compressing an image
2.1 Format of the source image
To be processed by the jbig85.c encoder, the image has to be present
in memory a bitmap. Each byte of a bitmap contains eight pixels, where
the most significant bit represents the leftmost of these. Each line
of a bitmap has to be stored in an integral number of bytes. If the
image width is not an integral multiple of eight, then the final byte
has to be padded with zero bits.
For example the 23x5 pixels large single plane image:
.XXXXX..XXX...X...XXX..
.....X..X..X..X..X.....
.....X..XXX...X..X.XXX.
.X...X..X..X..X..X...X.
..XXX...XXX...X...XXX..
is represented by the 15 bytes
01111100 11100010 00111000
00000100 10010010 01000000
00000100 11100010 01011100
01000100 10010010 01000100
00111000 11100010 00111000
or in hexadecimal notation
7c e2 38 04 92 40 04 e2 5c 44 92 44 38 e2 38
This is the format used in binary PBM files and it can also be handled
directly by the Xlib library of the X Window System.
The standard recommends that a 0 pixel represents the background and a
1 pixel represents the foreground colour of an image, in other words, 0
is white and 1 is black for scanned paper documents.
2.2 A simple compression application
In order to use the library in your application, just link libjbig85.a
to your executable (on Unix systems just add -ljbig85 and -L. to the
command line options of your compiler, on other systems you will have
to write a new Makefile anyway), copy the file jbig85.h into your
source directory and put the line
#include "jbig85.h"
into your source code.
The library interface follows object-oriented programming principles.
You have to declare a variable (object)
struct jbg85_enc_state s;
which contains the current status of an encoder. Then you initialize
the encoder by calling
void jbg85_enc_init(struct jbg85_enc_state *s,
unsigned long x, unsigned long y,
void (*data_out)(unsigned char *start, size_t len,
void *file),
void *file);
The parameters have the following meaning:
s A pointer to the jbg85_enc_state structure that you want
to initialize.
x The width of your image in pixels.
y The height of your image in pixels (lines). This can be
a larger value than the actual height of the image, or
even 2^32-1 (or equally -1), if the height of the
image is not yet known. In that case, leave the
JBG_VLENGTH option set (see below) and call
jbg85_enc_newlen() as soon as the actual image height
is known.
data_out This is a call-back function that the encoder will
call during the compression process in order to
deliver the BIE data to your application. The
parameters of the function data_out are a pointer
start to the new block of data being delivered, as
well as the number len of delivered bytes. The pointer
file is transparently delivered to data_out, as
specified in jbg85_enc_init(). Typically, data_out
will write the BIE portion to a file, send it to a
network connection, or append it to some memory
buffer.
file A pointer parameter that is passed on to data_out()
and can be used, for instance, to allow data_out() to
distinguish by which compression task it has been
called in multi-threaded applications.
The compression can then be started by calling the function
void jbg85_enc_lineout(struct jbg85_enc_state *s, unsigned char *line,
unsigned char *prevline, unsigned char *prevprevline);
successively for each line of the image, top to bottom. The parameters
are:
line A pointer to the first byte of the line to be encoded.
prevline A pointer to the data that the line parameter pointed
to in the previous call. The value will be ignored
if this is the first call.
prevprevline A pointer to the data that the prevline parameter pointed
to in the previous call. The value will be ignored
if this is the first or second call.
After jbg85_enc_lineout() has been called for all lines of the image,
the complete BIE will have been delivered via several callbacks to
data_out(). These BIE bytes are delivered as soon as possible, as the
encoder cannot buffer more than a few bytes internally.
A minimal example application, which sends the BIE of the above bitmap
to stdout, looks like this:
---------------------------------------------------------------------------
/* A sample JBIG T.85 encoding application */
#include <stdio.h>
#include "jbig85.h"
void output_bie(unsigned char *start, size_t len, void *file)
{
fwrite(start, 1, len, (FILE *) file);
return;
}
int main()
{
unsigned char bitmap[15] = {
/* 23 x 5 pixels, "JBIG" */
0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2,
0x5c, 0x44, 0x92, 0x44, 0x38, 0xe2, 0x38
};
struct jbg85_enc_state se;
int i;
jbg85_enc_init(&se, 23, 5, output_bie, stdout); /* initialize encoder */
jbg85_enc_options(&se, JBG_TPBON, 0, -1); /* clear JBG_VLENGTH option */
for (i = 0; i < 5; i++) {
/* encode line */
jbg85_enc_lineout(&se, bitmap+i*3, bitmap+(i-1)*3, bitmap+(i-2)*3);
}
return 0;
}
---------------------------------------------------------------------------
This software produces a 37 byte long BIE. (JBIG is not very good at
compressing extremely small images like in this example, because the
arithmetic encoder requires some startup data in order to generate
reasonable statistics which influence the compression process and
because there is some header overhead.)
2.3 More about compression
If jbg85_enc_lineout() is called directly after jbg85_enc_init(), the
following default values are used for various compression parameters:
- The number of lines per stripe (l0) is set to 128, which is the
T.85 BASIC setting.
- The typical-prediction (TPBON) and variable-length (VLENGTH) options
are activated, but the two-line template (LRLTWO) option is not.
- The maximal horizontal offset of the adaptive template pixel is 127
(mx = 127, my = 0).
In order to change any of these default parameters, an additional
function has to be called between jbg85_enc_init() and the first
jbg85_enc_lineout():
void jbg85_enc_options(struct jbg85_enc_state *s, int options,
unsigned long l0, int mx)
The options value can contain the following bits, which activate some
of the optional algorithms defined by JBIG:
JBG_LRLTWO This option bit changes the JBIG algorithm such that the
context in which the probability of a pixel is
estimated includes only the previous line (two-line
template), rather than the previous two lines
(three-line template). This option is off by default
and the author cannot think of a good reason to set it.
[Some people in the JBIG committee seem to have
argued that using a two-line template will make
software implementations a little bit faster, while
others have argued that using only two lines will
decrease compression efficiency by around 5%. As you
might expect from a committee, now both alternatives
are allowed (and add to the implementation and testing
complexity of every decoder).]
JBG_TPBON This bit activates the "typical prediction" algorithm. It
is set by default. Typical prediction means that JBIG
prefixes each line to be encoded with a "pseudopixel"
that indicates if the line is identical to the
previous line, and skips encoding the line if it is.
This helps to encode empty parts of a page very
efficiently in just a few bytes, therefore this
option should be left on. (The only reason the author
could think of for ever deactivating this option is
if you know in advance that there will never be two
identical lines follow each other in the image to be
encoded, in which case deactivating this option might
provide a tiny performance improvement.)
JBG_VLENGTH This bit indicates that the image height y provided
to jbg85_enc_init() was only an estimate and may
be lowered sometimes during the encoding process
using a call to jbg85_enc_newlen(). This feature
is intended for fax machines that start transmitting
a page while still scanning it and without knowing
how long the page is going to be.
Value -1 for options keeps the current setting, the default is
JBG_TPBON | JBG_VLENGTH.
The other parameters are:
l0 Sets the number of lines per stripe (valid range:
1 to 2^32-1, default 128, value 0 keeps the current
setting).
mx Changes the maximal offset allowed for the adaptive
template pixel (valid range: 0 to 127, default 127,
value -1 keeps the current setting).
If the JBG_VLENGTH option was set, then you can call at any time the
function
void jbg85_enc_newlen(struct jbg85_enc_state *s, unsigned long newlen)
in order to announce the actual height of the image. You can call this
function only once per image, and the provided new height value newlen
must not be larger than the estimate y originally provided. It is good
practice to call jbg85_enc_newlen() as soon as the height of the image
is known. However, it is even possible to call it after the last line
has already been encoded using jbg85_enc_lineout(). The latter case
will result in a somewhat odd BIE, where an additional empty stripe
has to be appended just to announce the new length. This is not pretty
and was not described in great detail in the original JBIG1 standard,
but decoders are required by ITU-T T.85 to understand even this
extremely late announcement of the end of the image.
If the image height y initially given to jbg85_enc_init() is already
the correct final value and you will therefore never call
jbg85_enc_newlen(), then it is good practice to clear the JBG_VLENGTH
option bit, which is set by default, e.g. by calling
jbg85_enc_options(&s, JBG_TPBON, 0, -1);
between jbg85_enc_init() and jbg85_enc_lineout().
The JBIG standard also has a provision for aborting a BIE with a
special abort marker segment, and calling
void jbg85_enc_abort(struct jbg85_enc_state *s);
does that. This is probably only needed if there is no other way
(e.g., end-of-file) of telling the decoder that no further data bytes
will be coming.
3 Decompressing an image
Like with the compression functions, if you want to use the jbig85.c
library, you have to put the line
#include "jbig85.h"
into your source code and link your executable with libjbig85.a.
The state of a JBIG decoder is stored completely in a struct and you
will have to define a variable like
struct jbg85_dec_state s;
which is initialized by a call to
void jbg85_dec_init(struct jbg85_dec_state *s,
unsigned char *buf, size_t buflen,
int (*line_out)(const struct jbg85_dec_state *s,
unsigned char *start, size_t len,
unsigned long y, void *file),
void *file);
The parameters are:
buf A memory buffer that is long enough to store up to
three lines of the image. This buffer will be used
by the decoder to temporarily store decoded lines.
If the decoded image uses the LRLTWO option, the buffer
has to be only sufficient for two uncompressed
image lines.
buflen The length in bytes of the buffer area to which buf
points. Knowing this value prevents accidental buffer
overflows and allows the decoder to abort with
JBG_ENOMEM if the provided buffer was too small, once
it knows the width of the image to be decoded from
parsing its 20-byte header. If xmax is the expected
maximum width of the image in pixels, then buflen
should be at least ((xmax >> 3) + !!(xmax & 7)) * 3
bytes. [If only BIEs with option LRLTWO set will be
received, then ((xmax >> 3) + !!(xmax & 7)) * 2
bytes will be sufficient.]
line_out This call-back function will be used whenever the decoder
has completed another line. The start parameter will
point to the location in buf where the len bytes of
the just decoded line reside. The line_out() function
has to read (and copy or output) this line, but it is
not allowed to modify it in-place, as the decoder will
also need to access it while decoding the following
two lines. The parameter y is just the line number
(starting from 0) and file is the jbg85_dec_init()
parameter of the same name passed on. The normal
return value of line_out is zero; a non-zero value
can be returned to request an interrupt of the decoding
process (see discussion of JBG_EOK_INTR below).
file A pointer parameter that is passed on to line_out()
and can be used, for instance, to allow line_out() to
distinguish by which compression task it has been
called in multi-threaded applications.
After this, you can directly start to pass data from the BIE to the decoder
by calling the function
int jbg85_dec_in(struct jbg85_dec_state *s, unsigned char *data, size_t len,
size_t *cnt);
The pointer data points to the first byte of a data block with length
len, which contains bytes from a BIE. It is not necessary to pass a
whole BIE at once to jbg85_dec_in(), it can arrive fragmented in any
way by calling jbg85_dec_in() several times. Only a single BIE can be
delivered via jbg85_dec_in() calls and the decoder has to be
reinitialized with jbg85_dec_init() before it is ready to accept
another BIE.
If pointer cnt is not NULL, then the number of bytes actually read
from the data block will be stored there. In case the decoder did not
recognize the end of the BIE in the data block, then the value
JBG_EAGAIN will be returned and *cnt equals len.
Once the end of a BIE has been reached, the return value of
jbg85_dec_in() will be JBG_EOK.
The decoder can recognize the end of a BIE only if either the VLENGTH
option is not set, or if there has been a NEWLEN marker segment before
the start of the last stripe. Otherwise, the decoder cannot know
whether there is or is not a NEWLEN marker segment following the last
stripe. For this reason, jbg85_dec_in() can return JBG_EAGAIN even
though you have already given it the last byte of the BIE. In this
case, call
int jbg85_dec_end(struct jbg85_dec_state *s);
to explicitely signal to the decoder that it has already received all
bytes of the BIE. This function will then output any remaining lines
and return JBG_EOK if no problem has occurred.
The macros
unsigned long jbg85_dec_getwidth(struct jbg85_dec_state *s);
unsigned long jbg85_dec_getheight(struct jbg85_dec_state *s);
can be used to query the dimensions of the image. The width will be
known already after the first 20 bytes of the BIE have been provided,
and also during the first callback to line_out(). But the height might
not have reached its final value before jbg85_dec_in() has returned
JBG_EOK. The additional boolean macros
int jbg85_dec_validwidth(struct jbg85_dec_state *s);
int jbg85_dec_finalheight(struct jbg85_dec_state *s);
int jbg85_dec_finished(struct jbg85_dec_state *s);
tell, whether the width and final height are already known, and
whether the decoder has finished outputting all lines.
If one of the callbacks to line_out() provides a non-zero return
value, then the decoder will interrupt the decoding process and
jbg85_dec_in() or jbg85_dec_end() will return JBG_EOK_INTR. This
feature might be useful to stop the decoding process temporarily, e.g.
to load a new sheet of paper, where performing this task is
inconvenient to complete inside line_out(). It is then possible to
continue calling jbg85_dec_in() with the remaining data (or
jbg85_dec_end() if there isn't any left) in order to decode the
remaining lines of the BIE. After jbg85_dec_in() returned
JBG_EOK_INTR, *cnt is probably not equal to len and the remainder of
the data block which has not yet been processed by the decoder has to
be delivered to jbg85_dec_in() again. Any line that has already been
delivered to line_out() will not be delivered again.
If any other return value than JBG_EOK, JBG_EOK_INTR or JBG_EAGAIN has
been returned by jbg85_dec_in() or jbg85_dec_end(), then an error has
occurred and the decoding process has been aborted. The function
const char *jbg85_strerror(int errnum);
returns a pointer to a short single-line test message that explains
the return value of jbg85_dec_in() or jbg85_dec_end(). This message
can be used in order to provide the user a brief informative message
about what when wrong while decompressing a JBIG image. The po/
subdirectory contains *.po files that translate the English ASCII
strings returned by jbg85_strerror() into other languages (e.g., for
use with GNU gettext). The four least-significant bits of the return
value of jbg85_dec_in() or jbg85_dec_end() may contain additional
detailed technical information about the exact test that spotted the
error condition (see source code for details), i.e. more than the text
message returned by jbg85_strerror() reveals. Therefore it may be
useful to display the return value itself as a hexadecimal number, in
addition to the string returned by jbg85_strerror().
4 Additional notes
The following remarks will not affect the normal user of the library
but might be of interest to some users who have to deal with exotic
cases, in particular dealing with broken non-JBIG-KIT encoders out
there:
- There has been one report about malformed BIEs produced by another
JBIG implementation that violates the standard by containing
several NEWLEN marker segments in the same BIE. The jbig85.c
decoder will normally abort with JBG_EINVALID when it encounters
such an illegal BIE. The compile-time option
JBG85_TOLERATE_MULTIPLE_NEWLEN can be used to make the decoder
more tolerant to this type of syntax error.
- Even though the T.85 standard prescribes all-zero values for the
order bits HITOLO, SEQ, ILEAVE, SMID, the jbig85.c decoder will
not complain about any other values of these bits, as they do not
affect the decoding process when there is only a single plane and
resolution layer (the only case supported by this decoder). The
compile-time option JBG85_STRICT_ORDER_BITS will make the decoder
less tolerant and abort with JBG_EIMPL if the received order bits
do not comply with the T.85 "single-progression sequential coding"
requirements.
- The T.85 standard allows only a single ATMOVE marker segment per
SDE, and the jbig85.c decoder enforces this limit by default. This
limit can be increased by setting JBG85_ATMOVES_MAX in jbig85.h to
the desired value. The encoder will never output more than a
single ATMOVE marker segment per stripe.
*** Happy decompressing ***
[end]

417
libjbig/jbig_ar.c Normal file
View File

@ -0,0 +1,417 @@
/*
* Arithmetic encoder and decoder of the portable JBIG
* compression library
*
* Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/jbigkit/
*
* This module implements a portable standard C arithmetic encoder
* and decoder used by the JBIG lossless bi-level image compression
* algorithm as specified in International Standard ISO 11544:1993
* and ITU-T Recommendation T.82.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* If you want to use this program under different license conditions,
* then contact the author for an arrangement.
*/
#include <assert.h>
#include "jbig_ar.h"
/*
* Probability estimation tables for the arithmetic encoder/decoder
* given by ITU T.82 Table 24.
*/
static short lsztab[113] = {
0x5a1d, 0x2586, 0x1114, 0x080b, 0x03d8, 0x01da, 0x00e5, 0x006f,
0x0036, 0x001a, 0x000d, 0x0006, 0x0003, 0x0001, 0x5a7f, 0x3f25,
0x2cf2, 0x207c, 0x17b9, 0x1182, 0x0cef, 0x09a1, 0x072f, 0x055c,
0x0406, 0x0303, 0x0240, 0x01b1, 0x0144, 0x00f5, 0x00b7, 0x008a,
0x0068, 0x004e, 0x003b, 0x002c, 0x5ae1, 0x484c, 0x3a0d, 0x2ef1,
0x261f, 0x1f33, 0x19a8, 0x1518, 0x1177, 0x0e74, 0x0bfb, 0x09f8,
0x0861, 0x0706, 0x05cd, 0x04de, 0x040f, 0x0363, 0x02d4, 0x025c,
0x01f8, 0x01a4, 0x0160, 0x0125, 0x00f6, 0x00cb, 0x00ab, 0x008f,
0x5b12, 0x4d04, 0x412c, 0x37d8, 0x2fe8, 0x293c, 0x2379, 0x1edf,
0x1aa9, 0x174e, 0x1424, 0x119c, 0x0f6b, 0x0d51, 0x0bb6, 0x0a40,
0x5832, 0x4d1c, 0x438e, 0x3bdd, 0x34ee, 0x2eae, 0x299a, 0x2516,
0x5570, 0x4ca9, 0x44d9, 0x3e22, 0x3824, 0x32b4, 0x2e17, 0x56a8,
0x4f46, 0x47e5, 0x41cf, 0x3c3d, 0x375e, 0x5231, 0x4c0f, 0x4639,
0x415e, 0x5627, 0x50e7, 0x4b85, 0x5597, 0x504f, 0x5a10, 0x5522,
0x59eb
};
static unsigned char nmpstab[113] = {
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 13, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 9, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 32,
65, 66, 67, 68, 69, 70, 71, 72,
73, 74, 75, 76, 77, 78, 79, 48,
81, 82, 83, 84, 85, 86, 87, 71,
89, 90, 91, 92, 93, 94, 86, 96,
97, 98, 99, 100, 93, 102, 103, 104,
99, 106, 107, 103, 109, 107, 111, 109,
111
};
/*
* least significant 7 bits (mask 0x7f) of nlpstab[] contain NLPS value,
* most significant bit (mask 0x80) contains SWTCH bit
*/
static unsigned char nlpstab[113] = {
129, 14, 16, 18, 20, 23, 25, 28,
30, 33, 35, 9, 10, 12, 143, 36,
38, 39, 40, 42, 43, 45, 46, 48,
49, 51, 52, 54, 56, 57, 59, 60,
62, 63, 32, 33, 165, 64, 65, 67,
68, 69, 70, 72, 73, 74, 75, 77,
78, 79, 48, 50, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 61, 61,
193, 80, 81, 82, 83, 84, 86, 87,
87, 72, 72, 74, 74, 75, 77, 77,
208, 88, 89, 90, 91, 92, 93, 86,
216, 95, 96, 97, 99, 99, 93, 223,
101, 102, 103, 104, 99, 105, 106, 107,
103, 233, 108, 109, 110, 111, 238, 112,
240
};
/*
* The next functions implement the arithmedic encoder and decoder
* required for JBIG. The same algorithm is also used in the arithmetic
* variant of JPEG.
*/
/* marker codes */
#define MARKER_STUFF 0x00
#define MARKER_ESC 0xff
void arith_encode_init(struct jbg_arenc_state *s, int reuse_st)
{
int i;
if (!reuse_st)
for (i = 0; i < 4096; s->st[i++] = 0) ;
s->c = 0;
s->a = 0x10000L;
s->sc = 0;
s->ct = 11;
s->buffer = -1; /* empty */
return;
}
void arith_encode_flush(struct jbg_arenc_state *s)
{
unsigned long temp;
/* find the s->c in the coding interval with the largest
* number of trailing zero bits */
if ((temp = (s->a - 1 + s->c) & 0xffff0000L) < s->c)
s->c = temp + 0x8000;
else
s->c = temp;
/* send remaining bytes to output */
s->c <<= s->ct;
if (s->c & 0xf8000000L) {
/* one final overflow has to be handled */
if (s->buffer >= 0) {
s->byte_out(s->buffer + 1, s->file);
if (s->buffer + 1 == MARKER_ESC)
s->byte_out(MARKER_STUFF, s->file);
}
/* output 0x00 bytes only when more non-0x00 will follow */
if (s->c & 0x7fff800L)
for (; s->sc; --s->sc)
s->byte_out(0x00, s->file);
} else {
if (s->buffer >= 0)
s->byte_out(s->buffer, s->file);
/* T.82 figure 30 says buffer+1 for the above line! Typo? */
for (; s->sc; --s->sc) {
s->byte_out(0xff, s->file);
s->byte_out(MARKER_STUFF, s->file);
}
}
/* output final bytes only if they are not 0x00 */
if (s->c & 0x7fff800L) {
s->byte_out((s->c >> 19) & 0xff, s->file);
if (((s->c >> 19) & 0xff) == MARKER_ESC)
s->byte_out(MARKER_STUFF, s->file);
if (s->c & 0x7f800L) {
s->byte_out((s->c >> 11) & 0xff, s->file);
if (((s->c >> 11) & 0xff) == MARKER_ESC)
s->byte_out(MARKER_STUFF, s->file);
}
}
return;
}
void arith_encode(struct jbg_arenc_state *s, int cx, int pix)
{
register unsigned lsz, ss;
register unsigned char *st;
long temp;
assert(cx >= 0 && cx < 4096);
st = s->st + cx;
ss = *st & 0x7f;
assert(ss < 113);
lsz = lsztab[ss];
#if 0
fprintf(stderr, "pix = %d, cx = %d, mps = %d, st = %3d, lsz = 0x%04x, "
"a = 0x%05lx, c = 0x%08lx, ct = %2d, buf = 0x%02x\n",
pix, cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct,
s->buffer);
#endif
if (((pix << 7) ^ s->st[cx]) & 0x80) {
/* encode the less probable symbol */
if ((s->a -= lsz) >= lsz) {
/* If the interval size (lsz) for the less probable symbol (LPS)
* is larger than the interval size for the MPS, then exchange
* the two symbols for coding efficiency, otherwise code the LPS
* as usual: */
s->c += s->a;
s->a = lsz;
}
/* Check whether MPS/LPS exchange is necessary
* and chose next probability estimator status */
*st &= 0x80;
*st ^= nlpstab[ss];
} else {
/* encode the more probable symbol */
if ((s->a -= lsz) & 0xffff8000L)
return; /* A >= 0x8000 -> ready, no renormalization required */
if (s->a < lsz) {
/* If the interval size (lsz) for the less probable symbol (LPS)
* is larger than the interval size for the MPS, then exchange
* the two symbols for coding efficiency: */
s->c += s->a;
s->a = lsz;
}
/* chose next probability estimator status */
*st &= 0x80;
*st |= nmpstab[ss];
}
/* renormalization of coding interval */
do {
s->a <<= 1;
s->c <<= 1;
--s->ct;
if (s->ct == 0) {
/* another byte is ready for output */
temp = s->c >> 19;
if (temp & 0xffffff00L) {
/* handle overflow over all buffered 0xff bytes */
if (s->buffer >= 0) {
++s->buffer;
s->byte_out(s->buffer, s->file);
if (s->buffer == MARKER_ESC)
s->byte_out(MARKER_STUFF, s->file);
}
for (; s->sc; --s->sc)
s->byte_out(0x00, s->file);
s->buffer = temp & 0xff; /* new output byte, might overflow later */
assert(s->buffer != 0xff);
/* can s->buffer really never become 0xff here? */
} else if (temp == 0xff) {
/* buffer 0xff byte (which might overflow later) */
++s->sc;
} else {
/* output all buffered 0xff bytes, they will not overflow any more */
if (s->buffer >= 0)
s->byte_out(s->buffer, s->file);
for (; s->sc; --s->sc) {
s->byte_out(0xff, s->file);
s->byte_out(MARKER_STUFF, s->file);
}
s->buffer = temp; /* buffer new output byte (can still overflow) */
}
s->c &= 0x7ffffL;
s->ct = 8;
}
} while (s->a < 0x8000);
return;
}
void arith_decode_init(struct jbg_ardec_state *s, int reuse_st)
{
int i;
if (!reuse_st)
for (i = 0; i < 4096; s->st[i++] = 0) ;
s->c = 0;
s->a = 1;
s->ct = 0;
s->startup = 1;
s->nopadding = 0;
return;
}
/*
* Decode and return one symbol from the provided PSCD byte stream
* that starts in s->pscd_ptr and ends in the byte before s->pscd_end.
* The context cx is a 12-bit integer in the range 0..4095. This
* function will advance s->pscd_ptr each time it has consumed all
* information from that PSCD byte.
*
* If a symbol has been decoded successfully, the return value will be
* 0 or 1 (depending on the symbol).
*
* If the decoder was not able to decode a symbol from the provided
* PSCD, then the return value will be -1, and two cases can be
* distinguished:
*
* s->pscd_ptr == s->pscd_end:
*
* The decoder has used up all information in the provided PSCD
* bytes. Further PSCD bytes have to be provided (via new values of
* s->pscd_ptr and/or s->pscd_end) before another symbol can be
* decoded.
*
* s->pscd_ptr == s->pscd_end - 1:
*
* The decoder has used up all provided PSCD bytes except for the
* very last byte, because that has the value 0xff. The decoder can
* at this point not yet tell whether this 0xff belongs to a
* MARKER_STUFF sequence or marks the end of the PSCD. Further PSCD
* bytes have to be provided (via new values of s->pscd_ptr and/or
* s->pscd_end), including the not yet processed 0xff byte, before
* another symbol can be decoded successfully.
*
* If s->nopadding != 0, the decoder will return -2 when it reaches
* the first two bytes of the marker segment that follows (and
* terminates) the PSCD, but before decoding the first symbol that
* depends on a bit in the input data that could have been the result
* of zero padding, and might, therefore, never have been encoded.
* This gives the caller the opportunity to lookahead early enough
* beyond a terminating SDNORM/SDRST for a trailing NEWLEN (as
* required by T.85) before decoding remaining symbols. Call the
* decoder again afterwards as often as necessary (leaving s->pscd_ptr
* pointing to the start of the marker segment) to retrieve any
* required remaining symbols that might depend on padding.
*
* [Note that each PSCD can be decoded into an infinitely long
* sequence of symbols, because the encoder might have truncated away
* an arbitrarily long sequence of trailing 0x00 bytes, which the
* decoder will append automatically as needed when it reaches the end
* of the PSCD. Therefore, the decoder cannot report any end of the
* symbol sequence and other means (external to the PSCD and
* arithmetic decoding process) are needed to determine that.]
*/
int arith_decode(struct jbg_ardec_state *s, int cx)
{
register unsigned lsz, ss;
register unsigned char *st;
int pix;
/* renormalization */
while (s->a < 0x8000 || s->startup) {
while (s->ct <= 8 && s->ct >= 0) {
/* first we can move a new byte into s->c */
if (s->pscd_ptr >= s->pscd_end) {
return -1; /* more bytes needed */
}
if (*s->pscd_ptr == 0xff)
if (s->pscd_ptr + 1 >= s->pscd_end) {
return -1; /* final 0xff byte not processed */
} else {
if (*(s->pscd_ptr + 1) == MARKER_STUFF) {
s->c |= 0xffL << (8 - s->ct);
s->ct += 8;
s->pscd_ptr += 2;
} else {
s->ct = -1; /* start padding with zero bytes */
if (s->nopadding) {
s->nopadding = 0;
return -2; /* subsequent symbols might depend on zero padding */
}
}
}
else {
s->c |= (long)*(s->pscd_ptr++) << (8 - s->ct);
s->ct += 8;
}
}
s->c <<= 1;
s->a <<= 1;
if (s->ct >= 0) s->ct--;
if (s->a == 0x10000L)
s->startup = 0;
}
st = s->st + cx;
ss = *st & 0x7f;
assert(ss < 113);
lsz = lsztab[ss];
#if 0
fprintf(stderr, "cx = %d, mps = %d, st = %3d, lsz = 0x%04x, a = 0x%05lx, "
"c = 0x%08lx, ct = %2d\n",
cx, !!(s->st[cx] & 0x80), ss, lsz, s->a, s->c, s->ct);
#endif
if ((s->c >> 16) < (s->a -= lsz))
if (s->a & 0xffff8000L)
return *st >> 7;
else {
/* MPS_EXCHANGE */
if (s->a < lsz) {
pix = 1 - (*st >> 7);
/* Check whether MPS/LPS exchange is necessary
* and chose next probability estimator status */
*st &= 0x80;
*st ^= nlpstab[ss];
} else {
pix = *st >> 7;
*st &= 0x80;
*st |= nmpstab[ss];
}
}
else {
/* LPS_EXCHANGE */
if (s->a < lsz) {
s->c -= s->a << 16;
s->a = lsz;
pix = *st >> 7;
*st &= 0x80;
*st |= nmpstab[ss];
} else {
s->c -= s->a << 16;
s->a = lsz;
pix = 1 - (*st >> 7);
/* Check whether MPS/LPS exchange is necessary
* and chose next probability estimator status */
*st &= 0x80;
*st ^= nlpstab[ss];
}
}
return pix;
}

53
libjbig/jbig_ar.h Normal file
View File

@ -0,0 +1,53 @@
/*
* Header file for the arithmetic encoder and decoder of
* the portable JBIG compression library
*
* Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/jbigkit/
*/
#ifndef JBG_AR_H
#define JBG_AR_H
/*
* Status of arithmetic encoder
*/
struct jbg_arenc_state {
unsigned char st[4096]; /* probability status for contexts, MSB = MPS */
unsigned long c; /* register C: base of coding intervall, *
* layout as in Table 23 */
unsigned long a; /* register A: normalized size of coding interval */
long sc; /* number of buffered 0xff values that might still overflow */
int ct; /* bit shift counter, determines when next byte will be written */
int buffer; /* buffer for most recent output byte != 0xff */
void (*byte_out)(int, void *); /* function that receives all PSCD bytes */
void *file; /* parameter passed to byte_out */
};
/*
* Status of arithmetic decoder
*/
struct jbg_ardec_state {
unsigned char st[4096]; /* probability status for contexts, MSB = MPS */
unsigned long c; /* register C: base of coding intervall, *
* layout as in Table 25 */
unsigned long a; /* register A: normalized size of coding interval */
unsigned char *pscd_ptr; /* pointer to next PSCD data byte */
unsigned char *pscd_end; /* pointer to byte after PSCD */
int ct; /* bit-shift counter, determines when next byte will be read;
* special value -1 signals that zero-padding has started */
int startup; /* boolean flag that controls initial fill of s->c */
int nopadding; /* boolean flag that triggers return -2 between
* reaching PSCD end and decoding the first symbol
* that might never have been encoded in the first
* place */
};
void arith_encode_init(struct jbg_arenc_state *s, int reuse_st);
void arith_encode_flush(struct jbg_arenc_state *s);
void arith_encode(struct jbg_arenc_state *s, int cx, int pix);
void arith_decode_init(struct jbg_ardec_state *s, int reuse_st);
int arith_decode(struct jbg_ardec_state *s, int cx);
#endif /* JBG_AR_H */

20
libjbig/po/README.txt Normal file
View File

@ -0,0 +1,20 @@
Older versions of jbig.c contained a list of human-readable
result/error messages in both English and German.
These messages are highly technical and unlikely to be of much use to
end users who are not familiar with the JBIG1 standard (which has only
been published in English, Spanish and French). Therefore, in the
interest of simplicity, since release 2.0 the source code contains in
errmsg[] now only the English version of these messages.
The German version is preserved here in the form of a PO translation
file, as used by the GNU gettext package, just in case anyone still
finds it of use.
See http://www.gnu.org/software/gettext/manual/gettext.html for
information on the PO file format and tools for creating and using
them.
JBIG-KIT itself does not use gettext, but the included po files might
help users of the library to translate the strings returned by
jbg_strerror() or jbg85_strerror() into other languages.

52
libjbig/po/de.po Normal file
View File

@ -0,0 +1,52 @@
# German translations for jbigkit package
# Copyright (C) 2008 Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
# This file is distributed under the same license as the jbigkit package.
#
msgid ""
msgstr ""
"Project-Id-Version: jbigkit 2.0\n"
"Report-Msgid-Bugs-To: http://www.cl.cam.ac.uk/~mgk25/jbigkit/\n"
"POT-Creation-Date: 2014-03-24 15:35+0000\n"
"PO-Revision-Date: 2008-08-27 20:16+0100\n"
"Last-Translator: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: jbig.c:98 jbig85.c:69
msgid "All OK"
msgstr "Kein Problem"
#: jbig.c:99 jbig85.c:70
msgid "Reached specified image size"
msgstr "Angeforderte Bildgröße erreicht"
#: jbig.c:100 jbig85.c:71
msgid "Unexpected end of input data stream"
msgstr "Unerwartetes Ende des Eingabedatenstroms"
#: jbig.c:101 jbig85.c:72
msgid "Not enough memory available"
msgstr "Nicht genügend Speicher vorhanden"
#: jbig.c:102 jbig85.c:73
msgid "ABORT marker segment encountered"
msgstr "Es wurde eine Abbruch-Sequenz gefunden"
#: jbig.c:103 jbig85.c:74
msgid "Unknown marker segment encountered"
msgstr "Es wurde eine unbekannte Marker-Sequenz gefunden"
#: jbig.c:104 jbig85.c:75
msgid "Input data stream contains invalid data"
msgstr "Es wurden ungültige Daten gefunden"
#: jbig.c:105 jbig85.c:76
msgid "Input data stream uses unimplemented JBIG features"
msgstr "Eingabedatenstrom benutzt nicht implementierte JBIG Optionen"
#: jbig.c:106
msgid "Incremental BIE does not continue previous one"
msgstr "Neue Bilddaten passen nicht zu vorangegangenen"

53
libjbig/po/ru.po Normal file
View File

@ -0,0 +1,53 @@
# Russian translations for jbigkit package.
# This file is distributed under the same license as the jbigkit package.
# Russian translation by ghostmansd@gmil.com,
# with some changes by Sergei Skorobogatov.
#
msgid ""
msgstr ""
"Project-Id-Version: jbigkit 2.1\n"
"Report-Msgid-Bugs-To: http://www.cl.cam.ac.uk/~mgk25/jbigkit/\n"
"POT-Creation-Date: 2014-03-24 15:35+0000\n"
"PO-Revision-Date: 2014-03-21 18:06+0000\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: jbig.c:98 jbig85.c:69
msgid "All OK"
msgstr "Успешное завершение"
#: jbig.c:99 jbig85.c:70
msgid "Reached specified image size"
msgstr "Указанный размер достигнут"
#: jbig.c:100 jbig85.c:71
msgid "Unexpected end of input data stream"
msgstr "Неожиданный конец входного потока"
#: jbig.c:101 jbig85.c:72
msgid "Not enough memory available"
msgstr "Недостаточно памяти"
#: jbig.c:102 jbig85.c:73
msgid "ABORT marker segment encountered"
msgstr "Обнаружен сегмент прерывания"
#: jbig.c:103 jbig85.c:74
msgid "Unknown marker segment encountered"
msgstr "Обнаружен неизвестный сегмент"
#: jbig.c:104 jbig85.c:75
msgid "Input data stream contains invalid data"
msgstr "Входной поток содержит неверные данные"
#: jbig.c:105 jbig85.c:76
msgid "Input data stream uses unimplemented JBIG features"
msgstr "Входной поток использует нереализованные функции"
#: jbig.c:106
msgid "Incremental BIE does not continue previous one"
msgstr "Следующий тип данных BIE не продолжает предыдущий"

550
libjbig/tstcodec.c Normal file
View File

@ -0,0 +1,550 @@
/*
* A sequence of test procedures for this JBIG implementation
*
* Run this test sequence after each modification on the JBIG library.
*
* Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "jbig.h"
#define TESTBUF_SIZE 400000L
#define TESTPIC_SIZE 477995L
#define FAILED "F\bFA\bAI\bIL\bLE\bED\bD"
#define PASSED "PASSED"
unsigned char *testbuf;
unsigned char *testpic;
long testbuf_len;
static void *checkedmalloc(size_t n)
{
void *p;
if ((p = malloc(n)) == NULL) {
fprintf(stderr, "Sorry, not enough memory available!\n");
exit(1);
}
return p;
}
static void testbuf_write(int v, void *dummy)
{
if (testbuf_len < TESTBUF_SIZE)
testbuf[testbuf_len++] = v;
(void) dummy;
return;
}
static void testbuf_writel(unsigned char *start, size_t len, void *dummy)
{
if (testbuf_len < TESTBUF_SIZE) {
if (testbuf_len + len < TESTBUF_SIZE)
memcpy(testbuf + testbuf_len, start, len);
else
memcpy(testbuf + testbuf_len, start, TESTBUF_SIZE - testbuf_len);
}
testbuf_len += len;
#ifdef DEBUG
{
unsigned char *p;
unsigned sum = 0;
for (p = start; p - start < (ptrdiff_t) len; sum = (sum ^ *p++) << 1);
printf(" testbuf_writel: %4lu bytes, checksum %04x\n",
(unsigned long) len, sum & 0xffff);
}
#endif
(void) dummy;
return;
}
/*
* Store the artificial test image defined in T.82, clause 7.2.1 at
* pic. The image requires 477995 bytes of memory, is 1960 x 1951 pixels
* large and has one plane.
*/
static void testimage(unsigned char *pic)
{
unsigned long i, j, sum;
unsigned int prsg, repeat[8];
unsigned char *p;
memset(pic, 0, TESTPIC_SIZE);
p = pic;
prsg = 1;
for (j = 0; j < 1951; j++)
for (i = 0; i < 1960; i++) {
if (j >= 192) {
if (j < 1023 || ((i >> 3) & 3) == 0) {
sum = (prsg & 1) + ((prsg >> 2) & 1) + ((prsg >> 11) & 1) +
((prsg >> 15) & 1);
prsg = (prsg << 1) + (sum & 1);
if ((prsg & 3) == 0) {
*p |= 1 << (7 - (i & 7));
repeat[i & 7] = 1;
} else {
repeat[i & 7] = 0;
}
} else {
if (repeat[i & 7])
*p |= 1 << (7 - (i & 7));
}
}
if ((i & 7) == 7) ++p;
}
/* verify test image */
sum = 0;
for (i = 0; i < TESTPIC_SIZE; i++)
for (j = 0; j < 8; j++)
sum += (pic[i] >> j) & 1;
if (sum != 861965L)
printf("WARNING: Artificial test image has %lu (not 861965) "
"foreground pixels!\n", sum);
return;
}
/*
* Perform a full test cycle with one set of parameters. Encode an image
* and compare the length of the result with correct_length. Then decode
* the image again both in one single chunk or byte by byte and compare
* the results with the original input image.
*/
static int test_cycle(unsigned char **orig_image, int width, int height,
int options, int order, int layers, int planes,
unsigned long l0, int mx, long correct_length,
const char *test_id)
{
struct jbg_enc_state sje;
struct jbg_dec_state sjd;
int trouble = 0;
long l;
size_t plane_size;
int i, result;
unsigned char **image;
plane_size = ((width + 7) / 8) * height;
image = (unsigned char **) checkedmalloc(planes * sizeof(unsigned char *));
for (i = 0; i < planes; i++) {
image[i] = (unsigned char *) checkedmalloc(plane_size);
memcpy(image[i], orig_image[i], plane_size);
}
printf("\nTest %s.1: Encoding ...\n", test_id);
testbuf_len = 0;
jbg_enc_init(&sje, width, height, planes, image, testbuf_writel, NULL);
jbg_enc_layers(&sje, layers);
jbg_enc_options(&sje, order, options, l0, mx, 0);
jbg_enc_out(&sje);
jbg_enc_free(&sje);
for (i = 0; i < planes; i++)
free(image[i]);
free(image);
printf("Encoded BIE has %6ld bytes: ", testbuf_len);
if (correct_length >= 0)
if (testbuf_len == correct_length)
puts(PASSED);
else {
trouble++;
printf(FAILED ", correct would have been %ld\n", correct_length);
}
else
puts("");
printf("Test %s.2: Decoding whole chunk ...\n", test_id);
jbg_dec_init(&sjd);
result = jbg_dec_in(&sjd, testbuf, testbuf_len, NULL);
if (result != JBG_EOK) {
printf("Decoder complained with return value %d: " FAILED "\n"
"Cause: '%s'\n", result, jbg_strerror(result));
trouble++;
} else {
printf("Image comparison: ");
result = 1;
for (i = 0; i < planes; i++) {
if (memcmp(orig_image[i], sjd.lhp[layers & 1][i],
((width + 7) / 8) * height)) {
result = 0;
trouble++;
printf(FAILED " for plane %d\n", i);
}
}
if (result)
puts(PASSED);
}
jbg_dec_free(&sjd);
printf("Test %s.3: Decoding with single-byte feed ...\n", test_id);
jbg_dec_init(&sjd);
result = JBG_EAGAIN;
for (l = 0; l < testbuf_len; l++) {
result = jbg_dec_in(&sjd, testbuf + l, 1, NULL);
if (l < testbuf_len - 1 && result != JBG_EAGAIN) {
printf("Decoder complained with return value %d at byte %ld: " FAILED
"\nCause: '%s'\n", result, l, jbg_strerror(result));
trouble++;
break;
}
}
if (l == testbuf_len) {
if (result != JBG_EOK) {
printf("Decoder complained with return value %d at final byte: " FAILED
"\nCause: '%s'\n", result, jbg_strerror(result));
trouble++;
} else {
printf("Image comparison: ");
result = 1;
for (i = 0; i < planes; i++) {
if (memcmp(orig_image[i], sjd.lhp[layers & 1][i],
((width + 7) / 8) * height)) {
result = 0;
trouble++;
printf(FAILED " for plane %d\n", i);
}
}
if (result)
puts(PASSED);
}
}
jbg_dec_free(&sjd);
puts("");
return trouble != 0;
}
int main(int argc, char **argv)
{
int trouble, problems = 0;
struct jbg_arenc_state *se;
struct jbg_ardec_state *sd;
long i;
int pix, order, layers;
char test[10];
size_t st;
unsigned char *pp;
unsigned char *ppp[4];
int t82pix[16] = {
0x05e0, 0x0000, 0x8b00, 0x01c4, 0x1700, 0x0034, 0x7fff, 0x1a3f,
0x951b, 0x05d8, 0x1d17, 0xe770, 0x0000, 0x0000, 0x0656, 0x0e6a
};
int t82cx[16] = {
0x0fe0, 0x0000, 0x0f00, 0x00f0, 0xff00, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};
unsigned char t82sde[32] = {
0x69, 0x89, 0x99, 0x5c, 0x32, 0xea, 0xfa, 0xa0,
0xd5, 0xff, 0x00, 0x52, 0x7f, 0xff, 0x00, 0xff,
0x00, 0xff, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x3f,
0xff, 0x00, 0x2d, 0x20, 0x82, 0x91, 0xff, 0x02
};
/* three 23x5 pixel test images with the letters JBIG */
unsigned char jbig_normal[15*4] = {
0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2, 0x5c, 0x44,
0x92, 0x44, 0x38, 0xe2, 0x38,
0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2, 0x5c, 0x44,
0x92, 0x44, 0x38, 0xe2, 0x38,
0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2, 0x5c, 0x44,
0x92, 0x44, 0x38, 0xe2, 0x38,
0x7c, 0xe2, 0x38, 0x04, 0x92, 0x40, 0x04, 0xe2, 0x5c, 0x44,
0x92, 0x44, 0x38, 0xe2, 0x38
};
unsigned char jbig_upsidedown[15*4] = {
0x38, 0xe2, 0x38, 0x44, 0x92, 0x44, 0x04, 0xe2, 0x5c, 0x04,
0x92, 0x40, 0x7c, 0xe2, 0x38,
0x38, 0xe2, 0x38, 0x44, 0x92, 0x44, 0x04, 0xe2, 0x5c, 0x04,
0x92, 0x40, 0x7c, 0xe2, 0x38,
0x38, 0xe2, 0x38, 0x44, 0x92, 0x44, 0x04, 0xe2, 0x5c, 0x04,
0x92, 0x40, 0x7c, 0xe2, 0x38,
0x38, 0xe2, 0x38, 0x44, 0x92, 0x44, 0x04, 0xe2, 0x5c, 0x04,
0x92, 0x40, 0x7c, 0xe2, 0x38
};
unsigned char jbig_inverse[15*4] = {
0xff^0x7c, 0xff^0xe2, 0xfe^0x38, 0xff^0x04, 0xff^0x92,
0xfe^0x40, 0xff^0x04, 0xff^0xe2, 0xfe^0x5c, 0xff^0x44,
0xff^0x92, 0xfe^0x44, 0xff^0x38, 0xff^0xe2, 0xfe^0x38,
0xff^0x7c, 0xff^0xe2, 0xfe^0x38, 0xff^0x04, 0xff^0x92,
0xfe^0x40, 0xff^0x04, 0xff^0xe2, 0xfe^0x5c, 0xff^0x44,
0xff^0x92, 0xfe^0x44, 0xff^0x38, 0xff^0xe2, 0xfe^0x38,
0xff^0x7c, 0xff^0xe2, 0xfe^0x38, 0xff^0x04, 0xff^0x92,
0xfe^0x40, 0xff^0x04, 0xff^0xe2, 0xfe^0x5c, 0xff^0x44,
0xff^0x92, 0xfe^0x44, 0xff^0x38, 0xff^0xe2, 0xfe^0x38,
0xff^0x7c, 0xff^0xe2, 0xfe^0x38, 0xff^0x04, 0xff^0x92,
0xfe^0x40, 0xff^0x04, 0xff^0xe2, 0xfe^0x5c, 0xff^0x44,
0xff^0x92, 0xfe^0x44, 0xff^0x38, 0xff^0xe2, 0xfe^0x38
};
int orders[] = {
0,
JBG_ILEAVE,
JBG_ILEAVE | JBG_SMID,
#if 0
JBG_SEQ,
JBG_SEQ | JBG_SMID,
JBG_SEQ | JBG_ILEAVE,
JBG_HITOLO,
JBG_HITOLO | JBG_ILEAVE,
JBG_HITOLO | JBG_ILEAVE | JBG_SMID,
JBG_HITOLO | JBG_SEQ,
JBG_HITOLO | JBG_SEQ | JBG_SMID,
JBG_HITOLO | JBG_SEQ | JBG_ILEAVE
#endif
};
printf("\nAutomatic JBIG Compatibility Test Suite\n"
"---------------------------------------\n\n"
"JBIG-KIT Version " JBG_VERSION
" -- This test may take a few minutes.\n\n\n");
/* allocate test buffer memory */
testbuf = (unsigned char *) checkedmalloc(TESTBUF_SIZE);
testpic = (unsigned char *) checkedmalloc(TESTPIC_SIZE);
se = (struct jbg_arenc_state *) checkedmalloc(sizeof(struct jbg_arenc_state));
sd = (struct jbg_ardec_state *) checkedmalloc(sizeof(struct jbg_ardec_state));
/* test a few properties of the machine architecture */
testbuf[0] = 42;
testbuf[0x10000L] = 0x42;
st = 1 << 16;
testbuf[st]++;
pp = testbuf + 0x4000;
pp += 0x4000;
pp += 0x4000;
pp += 0x4000;
if (testbuf[0] != 42 || *pp != 0x43) {
printf("Porting error detected:\n\n"
"Pointer arithmetic with this compiler has not at least 32 bits!\n"
"Are you sure, you have not compiled this program on an 8-bit\n"
"or 16-bit architecture? This compiler mode can obviously not\n"
"handle arrays with a size of more than 65536 bytes. With this\n"
"memory model, JBIG-KIT can only handle very small images and\n"
"not even this compatibility test suite will run. :-(\n\n");
exit(1);
}
/* only supported command line option:
* output file name for exporting test image */
if (argc > 1) {
FILE *f;
puts("Generating test image ...");
testimage(testpic);
printf("Storing in '%s' ...\n", argv[1]);
/* write out test image as PBM file */
f = fopen(argv[1], "wb");
if (!f) abort();
fprintf(f, "P4\n");
#if 0
fprintf(f, "# Test image as defined in ITU-T T.82, clause 7.2.1\n");
#endif
fprintf(f, "%10lu\n%10lu\n", 1960LU, 1951LU);
fwrite(testpic, 1, TESTPIC_SIZE, f);
fclose(f);
exit(0);
}
#if 1
puts("1) Arithmetic encoder test sequence from ITU-T T.82, clause 7.1\n"
"---------------------------------------------------------------\n");
arith_encode_init(se, 0);
testbuf_len = 0;
se->byte_out = testbuf_write;
for (i = 0; i < 16 * 16; i++)
arith_encode(se, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1,
(t82pix[i >> 4] >> ((15 - i) & 15)) & 1);
arith_encode_flush(se);
printf("result of encoder:\n ");
for (i = 0; i < testbuf_len && i < TESTBUF_SIZE; i++)
printf("%02x", testbuf[i]);
printf("\nexpected result:\n ");
for (i = 0; i < 30; i++)
printf("%02x", t82sde[i]);
printf("\n\nTest 1: ");
if (testbuf_len != 30 || memcmp(testbuf, t82sde, 30)) {
problems++;
printf(FAILED);
} else
printf(PASSED);
printf("\n\n");
puts("2) Arithmetic decoder test sequence from ITU-T T.82, clause 7.1\n"
"---------------------------------------------------------------\n");
printf("Test 2.1: Decoding whole chunk ...\n");
arith_decode_init(sd, 0);
sd->pscd_ptr = t82sde;
sd->pscd_end = t82sde + 32;
trouble = 0;
for (i = 0; i < 16 * 16 && !trouble; i++) {
pix = arith_decode(sd, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1);
if (pix < 0) {
printf("Problem at pixel %ld, byte %ld.\n\n",
i+1, (long) (sd->pscd_ptr - sd->pscd_end));
trouble++;
break;
}
if (pix != ((t82pix[i >> 4] >> ((15 - i) & 15)) & 1)) {
printf("Wrong PIX answer (%d) at pixel %ld.\n\n", pix, i+1);
trouble++;
break;
}
}
if (!trouble && sd->pscd_ptr != sd->pscd_end - 2) {
printf("%ld bytes left after decoder finished.\n\n",
(long) (sd->pscd_end - sd->pscd_ptr - 2));
trouble++;
}
printf("Test result: ");
if (trouble) {
problems++;
puts(FAILED);
} else
puts(PASSED);
printf("\n");
printf("Test 2.2: Decoding with single byte feed ...\n");
arith_decode_init(sd, 0);
pp = t82sde;
sd->pscd_ptr = pp;
sd->pscd_end = pp + 1;
trouble = 0;
for (i = 0; i < 16 * 16 && !trouble; i++) {
pix = arith_decode(sd, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1);
while (pix < 0 && sd->pscd_end < t82sde + 32) {
pp++;
if (sd->pscd_ptr != pp - 1)
sd->pscd_ptr = pp;
sd->pscd_end = pp + 1;
pix = arith_decode(sd, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1);
}
if (pix < 0) {
printf("Problem at pixel %ld, byte %ld.\n\n",
i+1, (long) (sd->pscd_ptr - sd->pscd_end));
trouble++;
break;
}
if (pix != ((t82pix[i >> 4] >> ((15 - i) & 15)) & 1)) {
printf("Wrong PIX answer (%d) at pixel %ld.\n\n", pix, i+1);
trouble++;
break;
}
}
if (!trouble && sd->pscd_ptr != sd->pscd_end - 2) {
printf("%ld bytes left after decoder finished.\n\n",
(long) (sd->pscd_end - sd->pscd_ptr - 2));
trouble++;
}
printf("Test result: ");
if (trouble) {
problems++;
puts(FAILED);
} else
puts(PASSED);
printf("\n");
puts("3) Parametric algorithm test sequence from ITU-T T.82, clause 7.2\n"
"-----------------------------------------------------------------\n");
puts("Generating test image ...");
testimage(testpic);
putchar('\n');
pp = testpic;
puts("Test 3.1: TPBON=0, Mx=0, LRLTWO=0, L0=1951, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_DELAY_AT,
0, 0, 1, 1951, 0, 317384L, "3.1");
puts("Test 3.2: TPBON=0, Mx=0, LRLTWO=1, L0=1951, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_DELAY_AT | JBG_LRLTWO,
0, 0, 1, 1951, 0, 317132L, "3.2");
puts("Test 3.3: TPBON=1, Mx=8, LRLTWO=0, L0=128, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_DELAY_AT | JBG_TPBON,
0, 0, 1, 128, 8, 253653L, "3.3");
puts("Test 3.4: TPBON=1, DPON=1, TPDON=1, Mx=8, LRLTWO=0, L0=2, 6 layers");
problems += test_cycle(&pp, 1960, 1951,
JBG_DELAY_AT | JBG_TPBON | JBG_TPDON | JBG_DPON,
0, 6, 1, 2, 8, 279314L, "3.4");
puts("Test 3.5: as Test 3.4 but with DPPRIV=1");
problems += test_cycle(&pp, 1960, 1951,
JBG_DELAY_AT | JBG_TPBON | JBG_TPDON | JBG_DPON |
JBG_DPPRIV,
0, 6, 1, 2, 8, 279314L + 1728, "3.5");
#if 0 /* Note: option SEQ is currently not supported by the decoder */
puts("Test 3.6: as Test 3.4 but with order bit SEQ set");
problems += test_cycle(&pp, 1960, 1951,
JBG_DELAY_AT | JBG_TPBON | JBG_TPDON | JBG_DPON,
JBG_SEQ, 6, 1, 2, 8, 279314L, "3.6");
#endif
#endif
puts("4) Same T.82 tests with SDRST instead of SDNORM\n"
"-----------------------------------------------\n");
puts("Test 4.0: TPBON=1, Mx=8, LRLTWO=0, L0=128, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_SDRST | JBG_TPBON,
0, 0, 1, 128, 8, -1, "4.0");
puts("Test 4.1: TPBON=0, Mx=0, LRLTWO=0, L0=1951, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_SDRST,
0, 0, 1, 1951, 0, -1, "4.1");
puts("Test 4.2: TPBON=0, Mx=0, LRLTWO=1, L0=1951, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_LRLTWO | JBG_SDRST,
0, 0, 1, 1951, 0, -1, "4.2");
puts("Test 4.3: TPBON=1, Mx=8, LRLTWO=0, L0=128, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_TPBON | JBG_SDRST,
0, 0, 1, 128, 8, -1, "4.3");
puts("Test 4.4: TPBON=1, DPON=1, TPDON=1, Mx=8, LRLTWO=0, L0=2, 6 layers");
problems += test_cycle(&pp, 1960, 1951,
JBG_TPBON | JBG_TPDON |
JBG_DPON | JBG_SDRST,
0, 6, 1, 2, 8, -1, "4.4");
puts("5) Small test image, 0-3 layers, 4 planes, different orders\n"
"-----------------------------------------------------------\n");
/* test a simple multi-plane image */
ppp[0] = jbig_normal;
ppp[1] = jbig_upsidedown;
ppp[2] = jbig_inverse;
ppp[3] = jbig_inverse;
i = 0;
for (layers = 0; layers <= 3; layers++)
for (order = 0; order < (int) (sizeof(orders)/sizeof(int)); order++) {
sprintf(test, "5.%ld", ++i);
printf("Test %s: order=%d, %d layers, 4 planes", test, orders[order],
layers);
problems += test_cycle(ppp, 23, 5*4, JBG_TPBON | JBG_TPDON | JBG_DPON,
orders[order], layers, 4, 2, 8, -1, test);
}
printf("\nTest result summary: the library has %s the test suite.\n\n",
problems ? FAILED : PASSED);
if (problems)
puts("This is bad. If you cannot identify the problem yourself, please "
"send\nthis output plus a detailed description of your "
"compile environment\n(OS, compiler, version, options, etc.) to "
"Markus Kuhn\n<http://www.cl.cam.ac.uk/~mgk25/>.");
else
puts("Congratulations, everything is fine.\n");
return problems != 0;
}

450
libjbig/tstcodec85.c Normal file
View File

@ -0,0 +1,450 @@
/*
* A sequence of test procedures for this JBIG implementation
*
* Run this test sequence after each modification on the JBIG library.
*
* Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "jbig85.h"
#define TESTBUF_SIZE 400000L
#define TESTPIC_SIZE 477995L
#define FAILED "F\bFA\bAI\bIL\bLE\bED\bD"
#define PASSED "PASSED"
unsigned char *testbuf;
unsigned char *testpic;
long testbuf_len;
static void *checkedmalloc(size_t n)
{
void *p;
if ((p = calloc(1, n)) == NULL) {
fprintf(stderr, "Sorry, not enough memory available!\n");
exit(1);
}
return p;
}
static void testbuf_write(int v, void *dummy)
{
if (testbuf_len < TESTBUF_SIZE)
testbuf[testbuf_len++] = v;
(void) dummy;
return;
}
static void testbuf_writel(unsigned char *start, size_t len, void *dummy)
{
if (testbuf_len < TESTBUF_SIZE) {
if (testbuf_len + len < TESTBUF_SIZE)
memcpy(testbuf + testbuf_len, start, len);
else
memcpy(testbuf + testbuf_len, start, TESTBUF_SIZE - testbuf_len);
}
testbuf_len += len;
#ifdef DEBUG
{
unsigned char *p;
unsigned sum = 0;
for (p = start; p - start < (ptrdiff_t) len; sum = (sum ^ *p++) << 1);
printf(" testbuf_writel: %4lu bytes, checksum %04x\n",
(unsigned long) len, sum & 0xffff);
}
#endif
(void) dummy;
return;
}
static int line_out(const struct jbg85_dec_state *s,
unsigned char *start, size_t len,
unsigned long y, void *bitmap)
{
assert(jbg85_dec_validwidth(s));
assert(len == (jbg85_dec_getwidth(s) >> 3) + !!(jbg85_dec_getwidth(s) & 7));
assert(y < jbg85_dec_getheight(s));
memcpy((unsigned char *) bitmap + len * y, start, len);
return 0;
}
/*
* Store the artificial test image defined in T.82, clause 7.2.1 at
* pic. The image requires 477995 bytes of memory, is 1960 x 1951 pixels
* large and has one plane.
*/
static void testimage(unsigned char *pic)
{
unsigned long i, j, sum;
unsigned int prsg, repeat[8];
unsigned char *p;
memset(pic, 0, TESTPIC_SIZE);
p = pic;
prsg = 1;
for (j = 0; j < 1951; j++)
for (i = 0; i < 1960; i++) {
if (j >= 192) {
if (j < 1023 || ((i >> 3) & 3) == 0) {
sum = (prsg & 1) + ((prsg >> 2) & 1) + ((prsg >> 11) & 1) +
((prsg >> 15) & 1);
prsg = (prsg << 1) + (sum & 1);
if ((prsg & 3) == 0) {
*p |= 1 << (7 - (i & 7));
repeat[i & 7] = 1;
} else {
repeat[i & 7] = 0;
}
} else {
if (repeat[i & 7])
*p |= 1 << (7 - (i & 7));
}
}
if ((i & 7) == 7) ++p;
}
/* verify test image */
sum = 0;
for (i = 0; i < TESTPIC_SIZE; i++)
for (j = 0; j < 8; j++)
sum += (pic[i] >> j) & 1;
if (sum != 861965L)
printf("WARNING: Artificial test image has %lu (not 861965) "
"foreground pixels!\n", sum);
return;
}
/*
* Perform a full test cycle with one set of parameters. Encode an image
* and compare the length of the result with correct_length. Then decode
* the image again both in one single chunk or byte by byte and compare
* the results with the original input image.
*/
static int test_cycle(unsigned char *orig_image, int width, int height,
int options, unsigned long l0, int mx,
long correct_length, const char *test_id)
{
struct jbg85_enc_state sje;
struct jbg85_dec_state sjd;
int trouble = 0;
long l;
size_t plane_size, buffer_len;
int i, result;
unsigned char *image, *buffer;
size_t bpl;
size_t cnt;
bpl = (width + 7) / 8;
plane_size = bpl * height;
image = (unsigned char *) checkedmalloc(plane_size);
memcpy(image, orig_image, plane_size);
printf("\nTest-85 %s.1: Encoding ...\n", test_id);
testbuf_len = 0;
jbg85_enc_init(&sje, width, height, testbuf_writel, NULL);
jbg85_enc_options(&sje, options, l0, mx);
for (i = 0; i < height; i++)
jbg85_enc_lineout(&sje,
image + i * bpl,
image + (i-1) * bpl,
image + (i-2) * bpl);
free(image);
printf("Encoded BIE has %6ld bytes: ", testbuf_len);
if (correct_length >= 0)
if (testbuf_len == correct_length)
puts(PASSED);
else {
trouble++;
printf(FAILED ", correct would have been %ld\n", correct_length);
}
else
puts("");
#if 1
buffer_len = ((width >> 3) + !!(width & 7)) * 3;
buffer = (unsigned char *) checkedmalloc(buffer_len);
image = (unsigned char *) checkedmalloc(plane_size);
printf("Test-85 %s.2: Decoding whole chunk ...\n", test_id);
jbg85_dec_init(&sjd, buffer, buffer_len, line_out, image);
result = jbg85_dec_in(&sjd, testbuf, testbuf_len, &cnt);
if (result != JBG_EOK) {
printf("Decoder complained with return value 0x%02x: "
FAILED "\nCause: '%s'\n", result, jbg85_strerror(result));
printf("%ld bytes of BIE read, %lu lines decoded.\n",
(long) cnt, sjd.y);
trouble++;
} else {
printf("Image comparison: ");
result = 1;
if (memcmp(orig_image, image, plane_size)) {
result = 0;
trouble++;
printf(FAILED);
}
if (result)
puts(PASSED);
}
free(image);
image = (unsigned char *) checkedmalloc(plane_size);
printf("Test-85 %s.3: Decoding with single-byte feed ...\n", test_id);
jbg85_dec_init(&sjd, buffer, buffer_len, line_out, image);
result = JBG_EAGAIN;
for (l = 0; l < testbuf_len; l++) {
result = jbg85_dec_in(&sjd, testbuf + l, 1, NULL);
if (l < testbuf_len - 1 && result != JBG_EAGAIN) {
printf("Decoder complained with return value 0x%02x at byte %ld: "
FAILED "\nCause: '%s'\n", result, l, jbg85_strerror(result));
trouble++;
break;
}
}
if (l == testbuf_len) {
if (result != JBG_EOK) {
printf("Decoder complained with return value 0x%02x at final byte: "
FAILED "\nCause: '%s'\n", result, jbg85_strerror(result));
trouble++;
} else {
printf("Image comparison: ");
result = 1;
if (memcmp(orig_image, image, plane_size)) {
result = 0;
trouble++;
printf(FAILED);
}
if (result)
puts(PASSED);
}
}
free(image);
#endif
puts("");
return trouble != 0;
}
int main(int argc, char **argv)
{
int trouble, problems = 0;
struct jbg_arenc_state *se;
struct jbg_ardec_state *sd;
long i;
int pix;
unsigned char *pp;
int t82pix[16] = {
0x05e0, 0x0000, 0x8b00, 0x01c4, 0x1700, 0x0034, 0x7fff, 0x1a3f,
0x951b, 0x05d8, 0x1d17, 0xe770, 0x0000, 0x0000, 0x0656, 0x0e6a
};
int t82cx[16] = {
0x0fe0, 0x0000, 0x0f00, 0x00f0, 0xff00, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};
unsigned char t82sde[32] = {
0x69, 0x89, 0x99, 0x5c, 0x32, 0xea, 0xfa, 0xa0,
0xd5, 0xff, 0x00, 0x52, 0x7f, 0xff, 0x00, 0xff,
0x00, 0xff, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x3f,
0xff, 0x00, 0x2d, 0x20, 0x82, 0x91, 0xff, 0x02
};
printf("\nAutomatic JBIG Compatibility Test Suite\n"
"---------------------------------------\n\n"
"JBIG-KIT Version " JBG85_VERSION " (T.85 version)"
" -- This test may take a few minutes.\n\n\n");
/* allocate test buffer memory */
testbuf = (unsigned char *) checkedmalloc(TESTBUF_SIZE);
testpic = (unsigned char *) checkedmalloc(TESTPIC_SIZE);
se = (struct jbg_arenc_state *) checkedmalloc(sizeof(struct jbg_arenc_state));
sd = (struct jbg_ardec_state *) checkedmalloc(sizeof(struct jbg_ardec_state));
/* only supported command line option:
* output file name for exporting test image */
if (argc > 1) {
FILE *f;
puts("Generating test image ...");
testimage(testpic);
printf("Storing in '%s' ...\n", argv[1]);
/* write out test image as PBM file */
f = fopen(argv[1], "wb");
if (!f) abort();
fprintf(f, "P4\n");
#if 0
fprintf(f, "# Test image as defined in ITU-T T.82, clause 7.2.1\n");
#endif
fprintf(f, "1960 1951\n");
fwrite(testpic, 1, TESTPIC_SIZE, f);
fclose(f);
exit(0);
}
#if 1
puts("1) Arithmetic encoder test sequence from ITU-T T.82, clause 7.1\n"
"---------------------------------------------------------------\n");
arith_encode_init(se, 0);
testbuf_len = 0;
se->byte_out = testbuf_write;
for (i = 0; i < 16 * 16; i++)
arith_encode(se, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1,
(t82pix[i >> 4] >> ((15 - i) & 15)) & 1);
arith_encode_flush(se);
printf("result of encoder:\n ");
for (i = 0; i < testbuf_len && i < TESTBUF_SIZE; i++)
printf("%02x", testbuf[i]);
printf("\nexpected result:\n ");
for (i = 0; i < 30; i++)
printf("%02x", t82sde[i]);
printf("\n\nTest 1: ");
if (testbuf_len != 30 || memcmp(testbuf, t82sde, 30)) {
problems++;
printf(FAILED);
} else
printf(PASSED);
printf("\n\n");
puts("2) Arithmetic decoder test sequence from ITU-T T.82, clause 7.1\n"
"---------------------------------------------------------------\n");
printf("Test 2.1: Decoding whole chunk ...\n");
arith_decode_init(sd, 0);
sd->pscd_ptr = t82sde;
sd->pscd_end = t82sde + 32;
trouble = 0;
for (i = 0; i < 16 * 16 && !trouble; i++) {
pix = arith_decode(sd, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1);
if (pix < 0) {
printf("Problem at pixel %ld, byte %ld.\n\n",
i+1, (long) (sd->pscd_ptr - sd->pscd_end));
trouble++;
break;
}
if (pix != ((t82pix[i >> 4] >> ((15 - i) & 15)) & 1)) {
printf("Wrong PIX answer (%d) at pixel %ld.\n\n", pix, i+1);
trouble++;
break;
}
}
if (!trouble && sd->pscd_ptr != sd->pscd_end - 2) {
printf("%ld bytes left after decoder finished.\n\n",
(long) (sd->pscd_end - sd->pscd_ptr - 2));
trouble++;
}
printf("Test result: ");
if (trouble) {
problems++;
puts(FAILED);
} else
puts(PASSED);
printf("\n");
printf("Test 2.2: Decoding with single byte feed ...\n");
arith_decode_init(sd, 0);
pp = t82sde;
sd->pscd_ptr = pp;
sd->pscd_end = pp + 1;
trouble = 0;
for (i = 0; i < 16 * 16 && !trouble; i++) {
pix = arith_decode(sd, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1);
while (pix < 0 && sd->pscd_end < t82sde + 32) {
pp++;
if (sd->pscd_ptr != pp - 1)
sd->pscd_ptr = pp;
sd->pscd_end = pp + 1;
pix = arith_decode(sd, (t82cx[i >> 4] >> ((15 - i) & 15)) & 1);
}
if (pix < 0) {
printf("Problem at pixel %ld, byte %ld.\n\n",
i+1, (long) (sd->pscd_ptr - sd->pscd_end));
trouble++;
break;
}
if (pix != ((t82pix[i >> 4] >> ((15 - i) & 15)) & 1)) {
printf("Wrong PIX answer (%d) at pixel %ld.\n\n", pix, i+1);
trouble++;
break;
}
}
if (!trouble && sd->pscd_ptr != sd->pscd_end - 2) {
printf("%ld bytes left after decoder finished.\n\n",
(long) (sd->pscd_end - sd->pscd_ptr - 2));
trouble++;
}
printf("Test result: ");
if (trouble) {
problems++;
puts(FAILED);
} else
puts(PASSED);
printf("\n");
puts("3) Parametric algorithm test sequence from ITU-T T.82, clause 7.2\n"
"-----------------------------------------------------------------\n");
puts("Generating test image ...");
testimage(testpic);
putchar('\n');
puts("Test-85 3.1: TPBON=0, Mx=0, LRLTWO=0, L0=1951, 0 layers");
problems += test_cycle(testpic, 1960, 1951, 0,
1951, 0, 317384L, "3.1");
puts("Test-85 3.2: TPBON=0, Mx=0, LRLTWO=1, L0=1951, 0 layers");
problems += test_cycle(testpic, 1960, 1951, JBG_LRLTWO,
1951, 0, 317132L, "3.2");
puts("Test-85 3.3: TPBON=1, Mx=8, LRLTWO=0, L0=128, 0 layers");
problems += test_cycle(testpic, 1960, 1951, JBG_TPBON,
128, 8, 253653L, "3.3");
#endif
#if 0
puts("4) Same T.82 tests with SDRST instead of SDNORM\n"
"-----------------------------------------------\n");
puts("Test-85 4.0: TPBON=1, Mx=8, LRLTWO=0, L0=128, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_SDRST | JBG_TPBON,
128, 8, -1, "4.0");
puts("Test-85 4.1: TPBON=0, Mx=0, LRLTWO=0, L0=1951, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_SDRST,
1951, 0, -1, "4.1");
puts("Test-85 4.2: TPBON=0, Mx=0, LRLTWO=1, L0=1951, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_LRLTWO | JBG_SDRST,
1951, 0, -1, "4.2");
puts("Test-85 4.3: TPBON=1, Mx=8, LRLTWO=0, L0=128, 0 layers");
problems += test_cycle(&pp, 1960, 1951, JBG_TPBON | JBG_SDRST,
128, 8, -1, "4.3");
#endif
printf("\nTest result summary: the T.85 library has %s the test suite.\n\n",
problems ? FAILED : PASSED);
if (problems)
puts("This is bad. If you cannot identify the problem yourself, please "
"send\nthis output plus a detailed description of your "
"compile environment\n(OS, compiler, version, options, etc.) to "
"Markus Kuhn\n<http://www.cl.cam.ac.uk/~mgk25/>.");
else
puts("Congratulations, everything is fine.\n");
return problems != 0;
}

166
pbmtools/Makefile Normal file
View File

@ -0,0 +1,166 @@
# Unix makefile for the JBIG-KIT PBM tools
# Select an ANSI/ISO C compiler here, e.g. GNU gcc is recommended
CC = gcc
# Options for the compiler
CFLAGS = -g -O -W -Wall -Wno-unused-result -ansi -pedantic # --coverage
CPPFLAGS = -I../libjbig
.SUFFIXES: .1 .5 .txt $(SUFFIXES)
.PHONY: txt test test82 test85 clean
all: pbmtojbg jbgtopbm pbmtojbg85 jbgtopbm85 txt
txt: pbmtojbg.txt jbgtopbm.txt pbm.txt pgm.txt
pbmtojbg: pbmtojbg.o ../libjbig/libjbig.a
$(CC) $(CFLAGS) -o pbmtojbg pbmtojbg.o -L../libjbig -ljbig
jbgtopbm: jbgtopbm.o ../libjbig/libjbig.a
$(CC) $(CFLAGS) -o jbgtopbm jbgtopbm.o -L../libjbig -ljbig
pbmtojbg85: pbmtojbg85.o ../libjbig/libjbig85.a
$(CC) $(CFLAGS) -o pbmtojbg85 pbmtojbg85.o -L../libjbig -ljbig85
jbgtopbm85: jbgtopbm85.o ../libjbig/libjbig85.a
$(CC) $(CFLAGS) -o jbgtopbm85 jbgtopbm85.o -L../libjbig -ljbig85
jbgtopbm.o: jbgtopbm.c ../libjbig/jbig.h
pbmtojbg.o: pbmtojbg.c ../libjbig/jbig.h
jbgtopbm85.o: jbgtopbm85.c ../libjbig/jbig85.h
pbmtojbg85.o: pbmtojbg85.c ../libjbig/jbig85.h
../libjbig/libjbig.a: ../libjbig/jbig.c ../libjbig/jbig.h \
../libjbig/jbig_ar.c ../libjbig/jbig_ar.h
make -C ../libjbig libjbig.a
../libjbig/libjbig85.a: ../libjbig/jbig85.c ../libjbig/jbig85.h \
../libjbig/jbig_ar.c ../libjbig/jbig_ar.h
make -C ../libjbig libjbig85.a
analyze:
clang $(CPPFLAGS) --analyze *.c
test: test82 test85
test82: pbmtojbg jbgtopbm
make IMG=ccitt1 OPTIONSP= dotest1
make IMG=ccitt2 OPTIONSP= dotest1
make IMG=ccitt3 OPTIONSP= dotest1
make IMG=xvlogo "OPTIONSP=-d 3" dotest1
make IMG=sandra OPTIONSP= OPTIONSJ= dotest2g
make IMG=sandra OPTIONSP=-b OPTIONSJ=-b dotest2g
make IMG=sandra OPTIONSP=-q OPTIONSJ= dotest2g
make IMG=sandra "OPTIONSP=-o 0" OPTIONSJ= dotest2g
make IMG=sandra "OPTIONSP=-o 2" OPTIONSJ= dotest2g
make IMG=multi OPTIONSP= OPTIONSJ= dotest2g
make IMG=multi OPTIONSP=-b OPTIONSJ=-b dotest2g
make IMG=mx "OPTIONSP=-q -s 3 -m 128" dotest1
make IMG=mx "OPTIONSP=-q -s 3 -m 128" dotest2b
make IMG=mx "OPTIONSP=-q -s 3 -m 128 -p 92" dotest2b
make IMG=mx "OPTIONSP=-q -Y -1" dotest2b
make IMG=mx "OPTIONSP=-Y -1" dotest2b
rm -f test-*.jbg test-*.pbm test-*.pgm
./jbgtopbm ../examples/ccitt1.jbg | ./pbmtojbg > test-ccitt1.jbg
cmp ../examples/ccitt1.jbg test-ccitt1.jbg
rm -f test-*.jbg test-*.pbm test-*.pgm
./jbgtopbm < ../examples/ccitt1.jbg | ./pbmtojbg - test-ccitt1.jbg
cmp ../examples/ccitt1.jbg test-ccitt1.jbg
rm -f test-*.jbg test-*.pbm test-*.pgm
./jbgtopbm < ../examples/ccitt1.jbg - test-ccitt1.pbm ; \
./pbmtojbg test-ccitt1.pbm test-ccitt1.jbg
cmp ../examples/ccitt1.jbg test-ccitt1.jbg
rm -f test-*.jbg test-*.pbm test-*.pgm
./jbgtopbm ../examples/ccitt1.jbg test-ccitt1.pbm ; \
./pbmtojbg test-ccitt1.pbm >test-ccitt1.jbg
cmp ../examples/ccitt1.jbg test-ccitt1.jbg
rm -f test-*.jbg test-*.pbm test-*.pgm
@echo
@echo "The pbmtools have PASSED the functional tests. Good!"
@echo
dotest1:
./jbgtopbm ../examples/$(IMG).jbg test-$(IMG).pbm
./pbmtojbg $(OPTIONSP) test-$(IMG).pbm test-$(IMG).jbg
cmp test-$(IMG).jbg ../examples/$(IMG).jbg
dotest2b:
./pbmtojbg $(OPTIONSP) test-$(IMG).pbm test-$(IMG).jbg
./jbgtopbm $(OPTIONSJ) test-$(IMG).jbg test-$(IMG)-2.pbm
cmp test-$(IMG).pbm test-$(IMG)-2.pbm
dotest2g:
./pbmtojbg $(OPTIONSP) ../examples/$(IMG).pgm test-$(IMG).jbg
./jbgtopbm $(OPTIONSJ) test-$(IMG).jbg test-$(IMG).pgm
cmp test-$(IMG).pgm ../examples/$(IMG).pgm
test85: pbmtojbg jbgtopbm pbmtojbg85 jbgtopbm85 test-t82.pbm
make IMG=t82 "OPTIONSP=-p 0" dotest85
make IMG=t82 "OPTIONSP=-p 8" dotest85
make IMG=t82 "OPTIONSP=-p 8 -r" dotest85b
make IMG=t82 "OPTIONSP=-p 64" dotest85
make IMG=t82 "OPTIONSP=-p 72" dotest85
make IMG=t82 "OPTIONSP=-s 2 -C c" dotest85
make IMG=t82 "OPTIONSP=-s 99999" dotest85
make IMG=t82 "OPTIONSP=-Y 9999 0" dotest85
make IMG=t82 "OPTIONSP=-Y 1951 0" dotest85
make IMG=t82 "OPTIONSP=-Y -1 127" dotest85
make IMG=t82 "OPTIONSP=-Y -1 128" dotest85
make IMG=t82 "OPTIONSP=-Y -1 1919" dotest85
make IMG=t82 "OPTIONSP=-Y -1 1920" dotest85
make IMG=t82 "OPTIONSP=-Y -1 1949" dotest85
make IMG=t82 "OPTIONSP=-Y -1 1950" dotest85
make IMG=ccitt1 dotest85
make IMG=ccitt2 dotest85
make IMG=ccitt3 dotest85
rm -f test-*.jbg test-*.jbg85 test-*.pbm
@echo
@echo "The T.85 pbmtools have PASSED the functional tests. Good!"
@echo
dotest85: test-$(IMG).pbm
./pbmtojbg85 $(OPTIONSP) test-$(IMG).pbm test-$(IMG).jbg85
ls -l test-$(IMG).jbg85
./jbgtopbm test-$(IMG).jbg85 test-$(IMG).pbm85
cmp test-$(IMG).pbm test-$(IMG).pbm85
rm test-$(IMG).pbm85
./jbgtopbm85 test-$(IMG).jbg85 test-$(IMG).pbm85
cmp test-$(IMG).pbm test-$(IMG).pbm85
rm test-$(IMG).pbm85
./jbgtopbm85 -B 1 test-$(IMG).jbg85 test-$(IMG).pbm85
cmp test-$(IMG).pbm test-$(IMG).pbm85
dotest85b: test-$(IMG).pbm
./pbmtojbg -f $(OPTIONSP) test-$(IMG).pbm test-$(IMG).jbg85
ls -l test-$(IMG).jbg85
./jbgtopbm test-$(IMG).jbg85 test-$(IMG).pbm85
cmp test-$(IMG).pbm test-$(IMG).pbm85
rm test-$(IMG).pbm85
./jbgtopbm85 test-$(IMG).jbg85 test-$(IMG).pbm85
cmp test-$(IMG).pbm test-$(IMG).pbm85
rm test-$(IMG).pbm85
./jbgtopbm85 -B 1 test-$(IMG).jbg85 test-$(IMG).pbm85
cmp test-$(IMG).pbm test-$(IMG).pbm85
test-%.pbm: ../examples/%.jbg
./jbgtopbm $< $@
test-t82.pbm:
make -C ../libjbig tstcodec
../libjbig/tstcodec $@
FOPT=-c 1000 -p 300000 -m 3
fuzz: test-t82.pbm
while \
./pbmtojbg -f test-t82.pbm | ./jbgfuzz.pl $(FOPT) && \
./pbmtojbg test-t82.pbm | ./jbgfuzz.pl $(FOPT) -d jbgtopbm ; \
do true; done
.1.txt .5.txt:
groff -man -Tascii -P -c -P -b -P -u $< >$@
clean:
rm -f *.o *~ core pbmtojbg jbgtopbm pbmtojbg85 jbgtopbm85
rm -f test-*.jbg test-*.pbm test-*.pgm test-*.jbg85 test-*.pbm85
rm -f *.gcda *.gcno *.plist

105
pbmtools/jbgfuzz.pl Executable file
View File

@ -0,0 +1,105 @@
#!/usr/bin/perl
# Simple fuzz tester for JBIG-KIT decoder -- Markus Kuhn
#
# Usage example:
#
# $ ../libjbig/tstcodec t.pbm
# $ ./pbmtojbg -f t.pbm | ./jbgfuzz.pl
use strict;
my $fntst = '/tmp/test.jbg'; # fuzz testing file to be generated
my $fntmp = $fntst . '~'; # temporary file (for atomic update)
my $fnvalid = '-'; # valid example BIE file
my $pbmtools = '.'; # location of jbgtopbm and jbgtopbm85
my $count = "inf"; # how many times shall we try?
my @decoders;
my $prefix_len = 2000;
my $rnd_suffix_len = 2000;
my $mutation_rate = 10; # percentage of bytes substituted in prefix
while ($_ = shift @ARGV) {
if ($_ eq '-c') {
$count = shift @ARGV;
} elsif ($_ eq '-m') {
$mutation_rate = shift @ARGV;
} elsif ($_ eq '-p') {
$prefix_len = shift @ARGV;
} elsif ($_ eq '-r') {
$rnd_suffix_len = shift @ARGV;
} elsif ($_ eq '-d') {
push @decoders, shift @ARGV;
} elsif ($_ eq '-t') {
$pbmtools = shift @ARGV;
} else {
$fnvalid = $_;
}
}
@decoders = ('jbgtopbm', 'jbgtopbm85') unless @decoders;
# read some bytes from a valid BIE
my $valid_prefix;
my $in;
open($in, "<$fnvalid") || die("$fnvalid: $!\n");
read $in, $valid_prefix, $prefix_len;
close $in || die("$fnvalid: $!\n");
# open a source of random bytes
my $fn_rnd = '/dev/urandom';
my $rnd;
open($rnd, '<', $fn_rnd) || die;
for (my $i = 0; $i < $count; $i++) {
my $out;
open($out, '>', $fntmp) || die("$fntmp: $!\n");
my $prefix;
# randomly substitute some prefix bytes with random bytes
$prefix = $valid_prefix;
if (length($prefix) != $prefix_len) {
warn("Truncating requested $prefix_len byte prefix to available ".
length($prefix)." bytes.\n");
$prefix_len = length($prefix);
}
#print "\nB: ".join(',', unpack('C4N3C4', substr($prefix, 0, 20)))."\n";
for (my $p = 0; $p < $prefix_len; $p++) {
if (rand(100) < $mutation_rate) {
substr($prefix, $p, 1) = chr(int(rand(256)));
}
}
#print "A: ".join(',', unpack('C4N3C4', substr($prefix, 0, 20)))."\n";
# constrain header
my ($dl,$d,$p,$res,$xd,$yd,$l0,$mx,$my,$order,$options,$rest) =
unpack('C4N3C4a*', $prefix);
redo if $xd * $yd > 1e9; # eliminate excessive image sizes
$prefix = pack('C4N3C4a*', $dl,$d,$p,$res,$xd,$yd,$l0,$mx,$my,
$order,$options,$rest);
print $out $prefix;
# append random suffix
my $data;
read $rnd, $data, $rnd_suffix_len;
print $out $data;
close($out) || die("$fntmp: $!\n");
rename($fntmp, $fntst) || die("mv $fntmp $fntst: $!\n");
# now feed fuzz input into decoder(s)
for my $jbgtopbm (@decoders) {
printf "%5d: ", $i;
$_ = `$pbmtools/$jbgtopbm $fntst /dev/null 2>&1`;
my $r = $?;
if ($r == 0) {
print "no error encountered\n";
next;
} elsif ($r == 256) {
my $err;
if (/(\(error code.*\))/) {
$err = $1;
print $err, "\n";
} else {
die("$_\nno error code found\n");
}
} else {
die("$_\nreturn value: $r\n");
}
}
}

118
pbmtools/jbgtopbm.1 Normal file
View File

@ -0,0 +1,118 @@
.TH JBGTOPBM 1 "2003-06-04"
.SH NAME
jbgtopbm \- JBIG1 to portable bitmap file converter
.SH SYNOPSIS
.B jbgtopbm
[
.I options
]
[
.I input-file
| \- [
.I output-file
]]
.br
.SH DESCRIPTION
Reads in a
.I JBIG1
bi-level image entity (BIE) from a file or standard
input, decompresses it, and outputs a portable bitmap (PBM) file.
.I JBIG1
is a highly effective lossless compression algorithm for
bi-level images (one bit per pixel), which is particularly suitable
for scanned document pages.
A
.I JBIG1
encoded image can be stored in several resolutions in one or several
BIEs. All resolution layers except the lowest one are stored
efficiently as differences to the next lower resolution layer. Options
.BI -x
and
.BI -y
can be used to stop the decompression at a specified maximal output
image size. With option
.BI -m
the input file can consist of multiple concatenated BIEs
which contain different increasing resolution layers of the same
image.
If more than one bit per pixel is stored in the JBIG1 file, then a PGM
file will be produced.
.SH OPTIONS
.TP 14
.BI \-
A single hyphen instead of an input file name will cause
.I jbgtopbm
to read the data from standard input instead from a file.
.TP
.BI \-x " number"
Decode only up to the largest resolution layer which is still not
more than
.I number
pixels wide. If no such resolution layer exists, then use the smallest
one available.
.TP
.BI \-y " number"
Decode only up to the largest resolution layer which is still not
more than
.I number
pixels high. If no such resolution layer exists, then use the smallest
one available. Options
.BI \-x
and
.BI \-y
can also be used together in which case the largest layer that satisfies
both limits will be selected.
.TP
.BI \-m
Process multiple concatenated BIEs. If there are bytes left after the
final SDE in the first BIE, then with this option
.I jbgtopbm
will attempt to decode these as the start of another BIE that may
contain higher resolution data. Normally, any remaining bytes will
generate a warning message.
.TP
.BI \-b
Use binary values instead of Gray code words in order to decode pixel
values from multiple bitplanes. This option has only an effect if the
input has more than one bitplane and a PGM output file is produced.
Note that the decoder has to be used in the same mode as the encoder
and cannot determine from the BIE, whether Gray or binary code words
were used by the encoder.
.TP
.BI \-d
Diagnose a single BIE. With this option,
.I jbgtopbm
will print a summary of the header information found in the input
file, followed by a list of all PSCD and ESC marker sequences
encountered until the end of the file is reached.
.TP
.BI \-p " number"
If the input contains multiple bitplanes, then extract only the
specified single plane as a PBM file. The first plane has number 0.
.SH BUGS
Using standard input and standard output for binary data works only on
systems where there is no difference between binary and text streams
(e.g., Unix). On other systems (e.g., MS-DOS), using standard input or
standard output may cause control characters like CR or LF to be
inserted or deleted and this will damage the binary data.
.SH STANDARDS
This program implements the
.I JBIG1
image coding algorithm as specified in ISO/IEC 11544:1993 and
ITU-T T.82(1993).
.SH AUTHOR
The
.I jbgtopbm
program is part of the
.I JBIG-KIT
package, which has been developed by Markus Kuhn.
The most recent version of this
portable
.I JBIG1
library and tools set is available from
<http://www.cl.cam.ac.uk/~mgk25/jbigkit/>.
.SH SEE ALSO
pbm(5), pgm(5), pbmtojbg(1)

481
pbmtools/jbgtopbm.c Normal file
View File

@ -0,0 +1,481 @@
/*
* jbgtopbm - JBIG to Portable Bitmap converter
*
* Markus Kuhn - http://www.cl.cam.ac.uk/~mgk25/jbigkit/
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include "jbig.h"
char *progname; /* global pointer to argv[0] */
/*
* Print usage message and abort
*/
static void usage(void)
{
fprintf(stderr, "JBIGtoPBM converter " JBG_VERSION " -- "
"reads a bi-level image entity (BIE) as input file\n\n"
"usage: %s [<options>] [<input-file> | - [<output-file>]]\n\n"
"options:\n\n", progname);
fprintf(stderr,
" -x number\tif possible decode only up to a resolution layer not\n"
"\t\twider than the given number of pixels\n"
" -y number\tif possible decode only up to a resolution layer not\n"
"\t\thigher than the given number of pixels\n"
" -m\t\tdecode a progressive sequence of multiple concatenated BIEs\n"
" -b\t\tuse binary code for multiple bit planes (default: Gray code)\n"
" -d\t\tdiagnose single BIE, print header, list marker sequences\n"
" -p number\tdecode only one single bit plane (0 = first plane)\n\n");
exit(1);
}
/*
* Call-back routine for merged image output
*/
void write_it(unsigned char *data, size_t len, void *file)
{
fwrite(data, len, 1, (FILE *) file);
}
/*
* Remalloc a buffer and append a file f into its content.
* If *buflen == 0, then malloc a buffer first.
*/
void read_file(unsigned char **buf, size_t *buflen, size_t *len, FILE *f)
{
if (*buflen == 0) {
*buflen = 4000;
*len = 0;
*buf = (unsigned char *) malloc(*buflen);
if (!*buf) {
fprintf(stderr, "Sorry, not enough memory available!\n");
exit(1);
}
}
do {
*len += fread(*buf + *len, 1, *buflen - *len, f);
if (*len == *buflen) {
*buflen *= 2;
*buf = (unsigned char *) realloc(*buf, *buflen);
if (!*buf) {
fprintf(stderr, "Sorry, not enough memory available!\n");
exit(1);
}
}
if (ferror(f)) {
perror("Problem while reading input file");
exit(1);
}
} while (!feof(f));
*buflen = *len;
*buf = (unsigned char *) realloc(*buf, *buflen);
if (!*buf) {
fprintf(stderr, "Oops, realloc failed when shrinking buffer!\n");
exit(1);
}
return;
}
/* marker codes */
#define MARKER_STUFF 0x00
#define MARKER_SDNORM 0x02
#define MARKER_SDRST 0x03
#define MARKER_ABORT 0x04
#define MARKER_NEWLEN 0x05
#define MARKER_ATMOVE 0x06
#define MARKER_COMMENT 0x07
#define MARKER_ESC 0xff
/*
* Output (prefix of) a short byte sequence in hexadecimal
* for diagnostic purposes
*/
void fprint_bytes(FILE *f, unsigned char *p, size_t len, int width)
{
size_t i;
size_t max = width / 3;
if (len > max)
max -= 7;
for (i = 0; i < len && i < max; i++)
fprintf(f, "%02x ", p[i]);
if (len > i)
fprintf(f, "... %lu bytes total", (unsigned long) len);
fprintf(f, "\n");
}
/*
* Read BIE and output human readable description of content
*/
void diagnose_bie(FILE *fin)
{
unsigned char *bie, *p, *pnext;
size_t buflen = 0, len;
unsigned long xd, yd, l0;
int dl, d;
FILE *f = stdout;
extern unsigned char *jbg_next_pscdms(unsigned char *p, size_t len);
extern unsigned long jbg_stripes(unsigned long l0, unsigned long yd,
unsigned long d);
unsigned long stripes;
int layers, planes;
unsigned long sdes, sde = 0;
/* read BIH */
read_file(&bie, &buflen, &len, fin);
if (len < 20) {
fprintf(f, "Error: Input file is %lu < 20 bytes long and therefore "
"does not contain an intact BIE header!\n", (unsigned long) len);
return;
}
/* parse BIH */
fprintf(f, "BIH:\n\n DL = %d\n D = %d\n P = %d\n"
" - = %d\n XD = %lu\n YD = %lu\n L0 = %lu\n MX = %d\n"
" MY = %d\n",
dl = bie[0], d = bie[1], planes = bie[2], bie[3],
xd = ((unsigned long)bie[ 4] << 24) | ((unsigned long)bie[ 5] << 16)|
((unsigned long) bie[ 6] << 8) | ((unsigned long) bie[ 7]),
yd = ((unsigned long)bie[ 8] << 24) | ((unsigned long)bie[ 9] << 16)|
((unsigned long) bie[10] << 8) | ((unsigned long) bie[11]),
l0 = ((unsigned long)bie[12] << 24) | ((unsigned long)bie[13] << 16)|
((unsigned long) bie[14] << 8) | ((unsigned long) bie[15]),
bie[16], bie[17]);
fprintf(f, " order = %d %s%s%s%s%s\n", bie[18],
bie[18] & JBG_HITOLO ? " HITOLO" : "",
bie[18] & JBG_SEQ ? " SEQ" : "",
bie[18] & JBG_ILEAVE ? " ILEAVE" : "",
bie[18] & JBG_SMID ? " SMID" : "",
bie[18] & 0xf0 ? " other" : "");
fprintf(f, " options = %d %s%s%s%s%s%s%s%s\n", bie[19],
bie[19] & JBG_LRLTWO ? " LRLTWO" : "",
bie[19] & JBG_VLENGTH ? " VLENGTH" : "",
bie[19] & JBG_TPDON ? " TPDON" : "",
bie[19] & JBG_TPBON ? " TPBON" : "",
bie[19] & JBG_DPON ? " DPON" : "",
bie[19] & JBG_DPPRIV ? " DPPRIV" : "",
bie[19] & JBG_DPLAST ? " DPLAST" : "",
bie[19] & 0x80 ? " other" : "");
stripes = jbg_stripes(l0, yd, d);
layers = d - dl + 1;
fprintf(f, "\n %lu stripes, %d layers, %d planes => ",
stripes, layers, planes);
if ((ULONG_MAX / layers) / planes >= stripes) {
sdes = stripes * layers * planes;
fprintf(f, "%lu SDEs\n\n", sdes);
} else {
/* handle integer overflow */
fprintf(f, ">%lu SDEs!\n", ULONG_MAX);
return;
}
/* parse BID */
fprintf(f, "BID:\n\n");
p = bie + 20; /* skip BIH */
if ((bie[19] & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST))
== (JBG_DPON | JBG_DPPRIV))
p += 1728; /* skip DPTABLE */
if (p > bie + len) {
fprintf(f, "Error: Input file is %lu < 20+1728 bytes long and therefore "
"does not contain an intact BIE header with DPTABLE!\n",
(unsigned long) len);
return;
}
while (p != bie + len) {
if (p > bie + len - 2) {
fprintf(f, "%06lx: Error: single byte 0x%02x left\n",
(long) (p - bie), *p);
return;
}
pnext = jbg_next_pscdms(p, len - (p - bie));
if (p[0] != MARKER_ESC || p[1] == MARKER_STUFF) {
fprintf(f, "%06lx: PSCD: ", (long) (p - bie));
fprint_bytes(f, p, pnext ? (size_t) (pnext - p) : len - (p - bie), 60);
if (!pnext) {
fprintf(f, "Error: PSCD not terminated by SDNORM or SDRST marker\n");
return;
}
} else
switch (p[1]) {
case MARKER_SDNORM:
case MARKER_SDRST:
fprintf(f, "%06lx: ESC %s, ending SDE #%lu", (long) (p - bie),
(p[1] == MARKER_SDNORM) ? "SDNORM" : "SDRST", ++sde);
if (sde == sdes)
fprintf(f, " (final SDE)");
else if (sde == sdes + 1)
fprintf(f, " (first surplus SDE, VLENGTH = %d)",
(bie[19] & JBG_VLENGTH) > 0);
fprintf(f, "\n");
break;
case MARKER_ABORT:
fprintf(f, "%06lx: ESC ABORT\n", (long) (p - bie));
break;
case MARKER_NEWLEN:
fprintf(f, "%06lx: ESC NEWLEN ", (long) (p - bie));
if (p + 5 < bie + len) {
fprintf(f, "YD = %lu\n",
yd = (((long) p[2] << 24) | ((long) p[3] << 16) |
((long) p[4] << 8) | (long) p[5]));
stripes = jbg_stripes(l0, yd, d);
fprintf(f, " %lu stripes, %d layers, %d planes => ",
stripes, layers, planes);
if ((ULONG_MAX / layers) / planes >= stripes) {
sdes = stripes * layers * planes;
fprintf(f, "%lu SDEs\n", sdes);
} else {
/* handle integer overflow */
fprintf(f, ">%lu SDEs!\n", ULONG_MAX);
return;
}
} else
fprintf(f, "unexpected EOF\n");
break;
case MARKER_ATMOVE:
fprintf(f, "%06lx: ESC ATMOVE ", (long) (p - bie));
if (p + 7 < bie + len)
fprintf(f, "YAT = %lu, tX = %d, tY = %d\n",
(((long) p[2] << 24) | ((long) p[3] << 16) |
((long) p[4] << 8) | (long) p[5]), p[6], p[7]);
else
fprintf(f, "unexpected EOF\n");
break;
case MARKER_COMMENT:
fprintf(f, "%06lx: ESC COMMENT ", (long) (p - bie));
if (p + 5 < bie + len)
fprintf(f, "LC = %lu\n",
(((long) p[2] << 24) | ((long) p[3] << 16) |
((long) p[4] << 8) | (long) p[5]));
else
fprintf(f, "unexpected EOF\n");
break;
default:
fprintf(f, "%06lx: ESC 0x%02x\n", (long) (p - bie), p[1]);
}
if (!pnext) {
fprintf(f, "Error encountered!\n");
return;
}
p = pnext;
}
free(bie);
return;
}
int main (int argc, char **argv)
{
FILE *fin = stdin, *fout = stdout;
const char *fnin = NULL, *fnout = NULL;
int i, j, result;
int all_args = 0, files = 0;
struct jbg_dec_state s;
unsigned char *buffer, *p;
size_t buflen, len, cnt;
size_t bytes_read = 0;
unsigned long xmax = 4294967295UL, ymax = 4294967295UL, max;
int plane = -1, use_graycode = 1, diagnose = 0, multi = 0;
buflen = 8000;
buffer = (unsigned char *) malloc(buflen);
if (!buffer) {
printf("Sorry, not enough memory available!\n");
exit(1);
}
/* parse command line arguments */
progname = argv[0];
for (i = 1; i < argc; i++) {
if (!all_args && argv[i][0] == '-')
if (argv[i][1] == 0) {
if (files++) usage();
} else
for (j = 1; j > 0 && argv[i][j]; j++)
switch(argv[i][j]) {
case '-' :
all_args = 1;
break;
case 'b':
use_graycode = 0;
break;
case 'm':
multi = 1;
break;
case 'd':
diagnose = 1;
break;
case 'x':
if (++i >= argc) usage();
xmax = atol(argv[i]);
j = -1;
break;
case 'y':
if (++i >= argc) usage();
ymax = atol(argv[i]);
j = -1;
break;
case 'p':
if (++i >= argc) usage();
plane = atoi(argv[i]);
j = -1;
break;
default:
usage();
}
else
switch (files++) {
case 0: fnin = argv[i]; break;
case 1: fnout = argv[i]; break;
default:
usage();
}
}
if (fnin) {
fin = fopen(fnin, "rb");
if (!fin) {
fprintf(stderr, "Can't open input file '%s", fnin);
perror("'");
exit(1);
}
} else
fnin = "<stdin>";
if (diagnose) {
diagnose_bie(fin);
exit(0);
}
if (fnout) {
fout = fopen(fnout, "wb");
if (!fout) {
fprintf(stderr, "Can't open input file '%s", fnout);
perror("'");
exit(1);
}
} else
fnout = "<stdout>";
/* send input file to decoder */
jbg_dec_init(&s);
jbg_dec_maxsize(&s, xmax, ymax);
/* read BIH first to check VLENGTH */
len = fread(buffer, 1, 20, fin);
if (len < 20) {
fprintf(stderr, "Input file '%s' (%lu bytes) must be at least "
"20 bytes long\n", fnin, (unsigned long) len);
if (fout != stdout) {
fclose(fout);
remove(fnout);
}
exit(1);
}
if (buffer[19] & JBG_VLENGTH) {
/* VLENGTH = 1 => we might encounter a NEWLEN, therefore read entire
* input file into memory and run two passes over it */
read_file(&buffer, &buflen, &len, fin);
/* scan for NEWLEN marker segments and update BIE header accordingly */
result = jbg_newlen(buffer, len);
/* feed data to decoder */
if (result == JBG_EOK) {
p = (unsigned char *) buffer;
result = JBG_EAGAIN;
while (len > 0 &&
(result == JBG_EAGAIN || (result == JBG_EOK && multi))) {
result = jbg_dec_in(&s, p, len, &cnt);
p += cnt;
len -= cnt;
bytes_read += cnt;
}
}
} else {
/* VLENGTH = 0 => we can simply pass the input file directly to decoder */
result = JBG_EAGAIN;
do {
cnt = 0;
p = (unsigned char *) buffer;
while (len > 0 &&
(result == JBG_EAGAIN || (result == JBG_EOK && multi))) {
result = jbg_dec_in(&s, p, len, &cnt);
p += cnt;
len -= cnt;
bytes_read += cnt;
}
if (!(result == JBG_EAGAIN || (result == JBG_EOK && multi)))
break;
len = fread(buffer, 1, buflen, fin);
} while (len > 0);
if (ferror(fin)) {
fprintf(stderr, "Problem while reading input file '%s", fnin);
perror("'");
if (fout != stdout) {
fclose(fout);
remove(fnout);
}
exit(1);
}
}
if (result != JBG_EOK && result != JBG_EOK_INTR) {
fprintf(stderr, "Problem with input file '%s': %s\n"
"(error code 0x%02x, %lu = 0x%04lx BIE bytes processed)\n",
fnin, jbg_strerror(result), result,
(unsigned long) bytes_read, (unsigned long) bytes_read);
if (fout != stdout) {
fclose(fout);
remove(fnout);
}
exit(1);
}
if (plane >= 0 && jbg_dec_getplanes(&s) <= plane) {
fprintf(stderr, "Image has only %d planes!\n", jbg_dec_getplanes(&s));
if (fout != stdout) {
fclose(fout);
remove(fnout);
}
exit(1);
}
if (jbg_dec_getplanes(&s) == 1 || plane >= 0) {
/* write PBM output file */
fprintf(fout, "P4\n%10lu\n%10lu\n", jbg_dec_getwidth(&s),
jbg_dec_getheight(&s));
fwrite(jbg_dec_getimage(&s, plane < 0 ? 0 : plane), 1,
jbg_dec_getsize(&s), fout);
} else {
/* write PGM output file */
if ((size_t) jbg_dec_getplanes(&s) > sizeof(unsigned long) * 8) {
fprintf(stderr, "Image has too many planes (%d)!\n",
jbg_dec_getplanes(&s));
if (fout != stdout) {
fclose(fout);
remove(fnout);
}
exit(1);
}
max = 0;
for (i = jbg_dec_getplanes(&s); i > 0; i--)
max = (max << 1) | 1;
fprintf(fout, "P5\n%10lu\n%10lu\n%lu\n", jbg_dec_getwidth(&s),
jbg_dec_getheight(&s), max);
jbg_dec_merge_planes(&s, use_graycode, write_it, fout);
}
/* check for file errors and close fout */
if (ferror(fout) || fclose(fout)) {
fprintf(stderr, "Problem while writing output file '%s", fnout);
perror("'");
exit(1);
}
jbg_dec_free(&s);
return 0;
}

93
pbmtools/jbgtopbm.txt Normal file
View File

@ -0,0 +1,93 @@
JBGTOPBM(1) JBGTOPBM(1)
NAME
jbgtopbm - JBIG1 to portable bitmap file converter
SYNOPSIS
jbgtopbm [ options ] [ input-file | - [ output-file ]]
DESCRIPTION
Reads in a JBIG1 bi-level image entity (BIE) from a file or standard
input, decompresses it, and outputs a portable bitmap (PBM) file.
JBIG1 is a highly effective lossless compression algorithm for bi-level
images (one bit per pixel), which is particularly suitable for scanned
document pages.
A JBIG1 encoded image can be stored in several resolutions in one or
several BIEs. All resolution layers except the lowest one are stored
efficiently as differences to the next lower resolution layer. Options
-x and -y can be used to stop the decompression at a specified maximal
output image size. With option -m the input file can consist of multi-
ple concatenated BIEs which contain different increasing resolution
layers of the same image.
If more than one bit per pixel is stored in the JBIG1 file, then a PGM
file will be produced.
OPTIONS
- A single hyphen instead of an input file name will cause
jbgtopbm to read the data from standard input instead
from a file.
-x number Decode only up to the largest resolution layer which is
still not more than number pixels wide. If no such reso-
lution layer exists, then use the smallest one available.
-y number Decode only up to the largest resolution layer which is
still not more than number pixels high. If no such reso-
lution layer exists, then use the smallest one available.
Options -x and -y can also be used together in which case
the largest layer that satisfies both limits will be
selected.
-m Process multiple concatenated BIEs. If there are bytes
left after the final SDE in the first BIE, then with this
option jbgtopbm will attempt to decode these as the start
of another BIE that may contain higher resolution data.
Normally, any remaining bytes will generate a warning
message.
-b Use binary values instead of Gray code words in order to
decode pixel values from multiple bitplanes. This option
has only an effect if the input has more than one bit-
plane and a PGM output file is produced. Note that the
decoder has to be used in the same mode as the encoder
and cannot determine from the BIE, whether Gray or binary
code words were used by the encoder.
-d Diagnose a single BIE. With this option, jbgtopbm will
print a summary of the header information found in the
input file, followed by a list of all PSCD and ESC marker
sequences encountered until the end of the file is
reached.
-p number If the input contains multiple bitplanes, then extract
only the specified single plane as a PBM file. The first
plane has number 0.
BUGS
Using standard input and standard output for binary data works only on
systems where there is no difference between binary and text streams
(e.g., Unix). On other systems (e.g., MS-DOS), using standard input or
standard output may cause control characters like CR or LF to be
inserted or deleted and this will damage the binary data.
STANDARDS
This program implements the JBIG1 image coding algorithm as specified
in ISO/IEC 11544:1993 and ITU-T T.82(1993).
AUTHOR
The jbgtopbm program is part of the JBIG-KIT package, which has been
developed by Markus Kuhn. The most recent version of this portable
JBIG1 library and tools set is available from
<http://www.cl.cam.ac.uk/~mgk25/jbigkit/>.
SEE ALSO
pbm(5), pgm(5), pbmtojbg(1)
2003-06-04 JBGTOPBM(1)

205
pbmtools/jbgtopbm85.c Normal file
View File

@ -0,0 +1,205 @@
/*
* jbgtopbm85 - JBIG to Portable Bitmap converter (T.85 version)
*
* Markus Kuhn - http://www.cl.cam.ac.uk/~mgk25/jbigkit/
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include "jbig85.h"
char *progname; /* global pointer to argv[0] */
unsigned long y_0;
fpos_t ypos;
int ypos_error = 1;
unsigned long ymax = 0;
/*
* Print usage message and abort
*/
static void usage(void)
{
fprintf(stderr, "JBIGtoPBM converter " JBG85_VERSION " (T.85 version) --\n"
"reads a bi-level image entity (BIE) as input file\n\n"
"usage: %s [<input-file> | - [<output-file>]]\n\n", progname);
fprintf(stderr, "options:\n\n"
" -x number\tmaximum number of pixels per line for which memory\n"
"\t\tis allocated (default: 8192)\n"
" -y number\tinterrupt decoder after this number of lines\n"
" -B number\tinput buffer size\n\n");
exit(1);
}
/*
* Call-back routine for merged image output
*/
int line_out(const struct jbg85_dec_state *s,
unsigned char *start, size_t len, unsigned long y, void *file)
{
if (y == 0) {
/* prefix first line with PBM header */
fprintf((FILE *) file, "P4\n");
fprintf((FILE *) file, "%10lu\n", jbg85_dec_getwidth(s));
/* store file position of height, so we can update it after NEWLEN */
y_0 = jbg85_dec_getheight(s);
ypos_error = fgetpos((FILE *) file, &ypos);
fprintf((FILE *) file, "%10lu\n", y_0); /* pad number to 10 bytes */
}
fwrite(start, len, 1, (FILE *) file);
return y == ymax - 1;
}
int main (int argc, char **argv)
{
FILE *fin = stdin, *fout = stdout;
const char *fnin = NULL, *fnout = NULL;
int i, j, result;
int all_args = 0, files = 0;
struct jbg85_dec_state s;
unsigned char *inbuf, *outbuf;
size_t inbuflen = 8192, outbuflen, len, cnt, cnt2;
unsigned long xmax = 8192;
size_t bytes_read = 0;
/* parse command line arguments */
progname = argv[0];
for (i = 1; i < argc; i++) {
if (!all_args && argv[i][0] == '-')
if (argv[i][1] == 0) {
if (files++) usage();
} else
for (j = 1; j > 0 && argv[i][j]; j++)
switch(argv[i][j]) {
case '-' :
all_args = 1;
break;
case 'x':
if (++i >= argc) usage();
j = -1;
xmax = atol(argv[i]);
break;
case 'y':
if (++i >= argc) usage();
j = -1;
ymax = atol(argv[i]);
break;
case 'B':
if (++i >= argc) usage();
j = -1;
inbuflen = atol(argv[i]);
if (inbuflen < 1) usage();
break;
default:
usage();
}
else
switch (files++) {
case 0: fnin = argv[i]; break;
case 1: fnout = argv[i]; break;
default:
usage();
}
}
inbuf = (unsigned char *) malloc(inbuflen);
outbuflen = ((xmax >> 3) + !!(xmax & 7)) * 3;
outbuf = (unsigned char *) malloc(outbuflen);
if (!inbuf || !outbuf) {
printf("Sorry, not enough memory available!\n");
exit(1);
}
if (fnin) {
fin = fopen(fnin, "rb");
if (!fin) {
fprintf(stderr, "Can't open input file '%s", fnin);
perror("'");
exit(1);
}
} else
fnin = "<stdin>";
if (fnout) {
fout = fopen(fnout, "wb");
if (!fout) {
fprintf(stderr, "Can't open input file '%s", fnout);
perror("'");
exit(1);
}
} else
fnout = "<stdout>";
/* send input file to decoder */
jbg85_dec_init(&s, outbuf, outbuflen, line_out, fout);
result = JBG_EAGAIN;
while ((len = fread(inbuf, 1, inbuflen, fin))) {
result = jbg85_dec_in(&s, inbuf, len, &cnt);
bytes_read += cnt;
while (result == JBG_EOK_INTR) {
/* demonstrate decoder interrupt at given line number */
printf("Decoding interrupted after %lu lines and %lu BIE bytes "
"... continuing ...\n", s.y, (unsigned long) bytes_read);
/* and now continue decoding */
result = jbg85_dec_in(&s, inbuf + cnt, len - cnt, &cnt2);
bytes_read += cnt2;
cnt += cnt2;
}
if (result != JBG_EAGAIN)
break;
}
if (ferror(fin)) {
fprintf(stderr, "Problem while reading input file '%s", fnin);
perror("'");
if (fout != stdout) {
fclose(fout);
remove(fnout);
}
exit(1);
}
if (result == JBG_EAGAIN || result == JBG_EOK_INTR) {
/* signal end-of-BIE explicitely */
result = jbg85_dec_end(&s);
while (result == JBG_EOK_INTR) {
/* demonstrate decoder interrupt at given line number */
printf("Decoding interrupted after %lu lines and %lu BIE bytes "
"... continuing ...\n", s.y, (unsigned long) bytes_read);
result = jbg85_dec_end(&s);
}
}
if (result != JBG_EOK) {
fprintf(stderr, "Problem with input file '%s': %s\n"
"(error code 0x%02x, %lu = 0x%04lx BIE bytes "
"and %lu pixel rows processed)\n",
fnin, jbg85_strerror(result), result,
(unsigned long) bytes_read, (unsigned long) bytes_read, s.y);
if (fout != stdout) {
fclose(fout);
/*remove(fnout);*/
}
exit(1);
}
/* do we have to update the image height in the PBM header? */
if (!ypos_error && y_0 != jbg85_dec_getheight(&s)) {
if (fsetpos(fout, &ypos) == 0) {
fprintf(fout, "%10lu", jbg85_dec_getheight(&s)); /* pad to 10 bytes */
} else {
fprintf(stderr, "Problem while updating height in output file '%s",
fnout);
perror("'");
exit(1);
}
}
/* check for file errors and close fout */
if (ferror(fout) || fclose(fout)) {
fprintf(stderr, "Problem while writing output file '%s", fnout);
perror("'");
exit(1);
}
return 0;
}

91
pbmtools/pbm.5 Normal file
View File

@ -0,0 +1,91 @@
.TH pbm 5 "27 September 1991"
.SH NAME
pbm - portable bitmap file format
.SH DESCRIPTION
The portable bitmap format is a lowest common denominator monochrome
file format.
.IX "PBM file format"
It was originally designed to make it reasonable to mail bitmaps
between different types of machines using the typical stupid network
mailers we have today.
Now it serves as the common language of a large family of bitmap
conversion filters.
The definition is as follows:
.IP - 2
A "magic number" for identifying the file type.
A pbm file's magic number is the two characters "P1".
.IX "magic numbers"
.IP - 2
Whitespace (blanks, TABs, CRs, LFs).
.IP - 2
A width, formatted as ASCII characters in decimal.
.IP - 2
Whitespace.
.IP - 2
A height, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
Width * height bits, each either '1' or '0', starting at the top-left
corner of the bitmap, proceeding in normal English reading order.
.IP - 2
The character '1' means black, '0' means white.
.IP - 2
Whitespace in the bits section is ignored.
.IP - 2
Characters from a "#" to the next end-of-line are ignored (comments).
.IP - 2
No line should be longer than 70 characters.
.PP
Here is an example of a small bitmap in this format:
.nf
P1
# feep.pbm
24 7
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0
0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0
0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0
0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
.fi
.PP
Programs that read this format should be as lenient as possible,
accepting anything that looks remotely like a bitmap.
.PP
There is also a variant on the format, available
by setting the RAWBITS option at compile time. This variant is
.IX RAWBITS
different in the following ways:
.IP - 2
The "magic number" is "P4" instead of "P1".
.IP - 2
The bits are stored eight per byte, high bit first low bit last.
.IP - 2
No whitespace is allowed in the bits section, and only a single character
of whitespace (typically a newline) is allowed after the height.
.IP - 2
The files are eight times smaller and many times faster to read and write.
.SH "SEE ALSO"
atktopbm(1), brushtopbm(1), cmuwmtopbm(1), g3topbm(1),
gemtopbm(1), icontopbm(1),
macptopbm(1), mgrtopbm(1), pi3topbm(1), xbmtopbm(1),
ybmtopbm(1),
pbmto10x(1), pnmtoascii(1), pbmtoatk(1), pbmtobbnbg(1),
pbmtocmuwm(1), pbmtoepson(1),
pbmtog3(1), pbmtogem(1), pbmtogo(1), pbmtoicon(1), pbmtolj(1),
pbmtomacp(1), pbmtomgr(1), pbmtopi3(1), pbmtoplot(1), pbmtoptx(1),
pbmtox10bm(1), pbmtoxbm(1), pbmtoybm(1),
pbmtozinc(1),
pbmlife(1), pbmmake(1), pbmmask(1), pbmreduce(1),
pbmtext(1), pbmupc(1),
pnm(5), pgm(5), ppm(5)
.SH AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.

85
pbmtools/pbm.txt Normal file
View File

@ -0,0 +1,85 @@
pbm(5) pbm(5)
NAME
pbm - portable bitmap file format
DESCRIPTION
The portable bitmap format is a lowest common denominator monochrome
file format. It was originally designed to make it reasonable to mail
bitmaps between different types of machines using the typical stupid
network mailers we have today. Now it serves as the common language of
a large family of bitmap conversion filters. The definition is as fol-
lows:
- A "magic number" for identifying the file type. A pbm file's magic
number is the two characters "P1".
- Whitespace (blanks, TABs, CRs, LFs).
- A width, formatted as ASCII characters in decimal.
- Whitespace.
- A height, again in ASCII decimal.
- Whitespace.
- Width * height bits, each either '1' or '0', starting at the top-left
corner of the bitmap, proceeding in normal English reading order.
- The character '1' means black, '0' means white.
- Whitespace in the bits section is ignored.
- Characters from a "#" to the next end-of-line are ignored (comments).
- No line should be longer than 70 characters.
Here is an example of a small bitmap in this format:
P1
# feep.pbm
24 7
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0
0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0
0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0
0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Programs that read this format should be as lenient as possible,
accepting anything that looks remotely like a bitmap.
There is also a variant on the format, available by setting the RAWBITS
option at compile time. This variant is different in the following
ways:
- The "magic number" is "P4" instead of "P1".
- The bits are stored eight per byte, high bit first low bit last.
- No whitespace is allowed in the bits section, and only a single char-
acter of whitespace (typically a newline) is allowed after the
height.
- The files are eight times smaller and many times faster to read and
write.
SEE ALSO
atktopbm(1), brushtopbm(1), cmuwmtopbm(1), g3topbm(1), gemtopbm(1),
icontopbm(1), macptopbm(1), mgrtopbm(1), pi3topbm(1), xbmtopbm(1), ybm-
topbm(1), pbmto10x(1), pnmtoascii(1), pbmtoatk(1), pbmtobbnbg(1), pbm-
tocmuwm(1), pbmtoepson(1), pbmtog3(1), pbmtogem(1), pbmtogo(1), pbmto-
icon(1), pbmtolj(1), pbmtomacp(1), pbmtomgr(1), pbmtopi3(1), pbmto-
plot(1), pbmtoptx(1), pbmtox10bm(1), pbmtoxbm(1), pbmtoybm(1), pbmtoz-
inc(1), pbmlife(1), pbmmake(1), pbmmask(1), pbmreduce(1), pbmtext(1),
pbmupc(1), pnm(5), pgm(5), ppm(5)
AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
27 September 1991 pbm(5)

276
pbmtools/pbmtojbg.1 Normal file
View File

@ -0,0 +1,276 @@
.TH PBMTOJBG 1 "2003-06-04"
.SH NAME
pbmtojbg \- portable bitmap to JBIG1 file converter
.SH SYNOPSIS
.B pbmtojbg
[
.I options
]
[
.I input-file
| \- [
.I output-file
]]
.br
.SH DESCRIPTION
Reads in a portable bitmap (PBM)
from a file or standard
input, compresses it, and outputs the image as a
.I JBIG1
bi-level image entity (BIE) file.
.I JBIG1
is a highly effective lossless compression algorithm for
bi-level images (one bit per pixel), which is particularly suitable
for scanned document pages.
A
.I JBIG1
encoded image can be stored in several resolutions (progressive mode).
These resolution layers can be stored all in one single BIE or they
can be stored in several separate BIE files.
All resolution layers except the lowest one are stored merely as
differences to the next lower resolution layer, because this requires less
space than encoding the full image completely every time. Each resolution
layer has twice the number of horizontal and vertical pixels than
the next lower layer.
.I JBIG1
files can also store several bits per pixel as separate bitmap planes,
and
.I pbmtojbg
can read a PGM file and transform it into a multi-bitplane BIE.
.SH OPTIONS
.TP 14
.BI \-
A single hyphen instead of an input file name will cause
.I pbmtojbg
to read the data from standard input instead from a file.
.TP
.BI \-q
Encode the image in one single resolution layer (sequential mode). This
is usually the most efficient compression method. By default, the number
of resolution layers is chosen automatically such that the lowest layer
image is not larger than 640 \(mu 480 pixels. This is a shortcut for
.BR "-d 0" .
.TP
.BI \-x " number"
Specify the maximal horizontal size of the lowest resolution layer.
The default is 640 pixels.
.TP
.BI \-y " number"
Specify the maximal vertical size of the lowest resolution layer.
The default is 480 pixels.
.TP
.BI \-l " number"
Select the lowest resolution layer that will be written to the
BIE. It is possible to store the various resolution layers of a
.I JBIG1
image in progressive mode into different BIEs. Options
.B \-l
and
.B \-h
allow to select the resolution-layer interval that will appear
in the created BIE. The lowest resolution layer has number 0 and
this is also the default value. By default all layers will be written.
.TP
.BI \-h " number"
Select the highest resolution layer that will be written to the
BIE. By default all layers will be written. See also option
.BR \-l .
.TP
.BI \-b
Use binary values instead of Gray code words in order to encode pixel
values in multiple bitplanes. This option has only an effect if the
input is a PGM file and if more than one bitplane is produced. Note
that the decoder has to make the same selection but cannot determine
from the BIE, whether Gray or binary code words were used by the
encoder.
.TP
.BI \-d " number"
Specify the total number of differential resolution layers into which the
input image will be split in addition to the lowest layer. Each additional
layer reduces the size of layer 0 by 50 %. This option overrides options
.BI \-x
and
.BI \-y
which are usually a more comfortable way of selecting the number of
resolution layers.
.TP
.BI \-s " number"
The
.I JBIG1
algorithm splits each image into a number of horizontal stripes. This
option specifies that each stripe shall have
.I number
lines in layer 0. The default value is selected so that approximately
35 stripes will be used for the whole image.
.TP
.BI \-m " number"
Select the maximum horizontal offset of the adaptive template pixel.
The
.I JBIG1
encoder uses ten neighbour pixels to estimate the probability of the
next pixel being black or white. It can move one out of these ten
pixels. This is especially useful for dithered images, as long as the
distance of this adaptive pixel can be adjusted to the period of the
dither pattern. By default, the adaptive template pixel is allowed to
move up to 8 pixels away horizontally. This encoder supports distances
up to 127 pixels. Annex A of the standard suggests that decoders
should support at least a horizontal distance of 16 pixels, so using
values not higher than 16 for
.I number
might increase the chances of interoperability with other
.I JBIG1
implementations. On the other hand, the T.85 fax application profile
requires decoders to support horizontal offsets up to 127 pixels,
which the maximum value permitted by the standard. (The maximal
vertical offset of the adaptive template pixel is always zero for this
encoder.)
.TP
.BI \-t " number"
Encode only the specified number of most significant bit planes. This
option allows to reduce the depth of an input PGM file if not all
bits per pixel are needed in the output.
.TP
.BI \-o " number"
.I JBIG1
separates an image into several horizontal stripes, resolution layers
and planes, were each plane contains one bit per pixel. One single
stripe in one plane and layer is encoded as a data unit called stripe
data entity (SDE) inside the BIE. There are 12 different possible
orders in which the SDEs can be stored inside the BIE and
.I number
selects which one shall be used. The order of the SDEs is only relevant
for applications that want to decode a
.I JBIG1
file which has not yet completely arrived from e.g. a slow network connection.
For instance some applications prefer that the outermost of the three loops
(stripes, layers, planes) is over all layers so that all data of the lowest
resolution layer is transmitted first.
.br
The following values for
.I number
select these loop arrangements for writing the SDEs (outermost
loop first):
0 planes, layers, stripes
.br
2 layers, planes, stripes
.br
3 layers, stripes, planes
.br
4 stripes, planes, layers
.br
5 planes, stripes, layers
.br
6 stripes, layers, planes
All loops count starting with zero, however by adding 8 to the above
order code, the layer loop can be reversed so that it counts down to zero
and then higher resolution layers will be stored before lower layers.
Default order is 3 which writes at first all planes of the first
stripe and then completes layer 0 before continuing with the next
layer and so on.
.TP
.BI \-p " number"
This option allows to activate or deactivate various optional algorithms
defined in the
.I JBIG1
standard. Just add the numbers of the following options which you want to
activate in
order to get the
.I number
value:
4 deterministic prediction (DPON)
.br
8 layer 0 typical prediction (TPBON)
.br
16 diff. layer typ. pred. (TPDON)
.br
64 layer 0 two-line template (LRLTWO)
Except for special applications (like communication with
.I JBIG1
subset implementations) and for debugging purposes you will normally
not want to change anything here. The default is 28, which provides
the best compression result.
.TP
.BI \-C " string"
Add the
.I string
in a comment marker segment to the produced data stream. (There is no
support at present for adding comments that contain the zero byte.)
.TP
.BI \-c
Determine the adaptive template pixel movement as suggested in annex C
of the standard. By default the template change takes place directly
in the next line, which is most effective. However, a few conformance
test examples in the standard require the adaptive template change to
be delayed until the first line of the next stripe. This option
selects this special behavior, which is normally not required except
in order to pass some conformance tests.
.TP
.BI \-r
Use the SDRST marker instead of the normal SDNORM marker. The probably
only useful application of this option is to generate test data for
checking whether a
.I JBIG1
decoder has implemented SDRST correctly. In a normal
.I JBIG1
data stream, each stripe data entity (SDE) is terminated by an SDNORM
marker, which preserves the state of the arithmetic encoder (and more)
for the next stripe in the same layer. The alternative SDRST marker
resets this state at the end of the stripe.
.TP
.BI \-Y " number"
A long time ago, there were fax machines that couldn't even hold a
single page in memory. They had to start transmitting data before the
page was scanned in completely and the length of the image was known.
The authors of the standard added a rather ugly hack to the otherwise
beautiful JBIG1 format to support this. The NEWLEN marker segment can
override the image height stated in the BIE header anywhere later in
the data stream. Normally
.I pbmtojbg
never generates NEWLEN marker segments, as it knows the correct image
height when it outputs the header. This option is solely intended for
the purpose of generating test files with NEWLEN marker segments. It
can be used to specify a higher initial image height for use in the
BIE header, and
.I pbmtojbg
will then add a NEWLEN marker segment at the latest possible
opportunity to the data stream to signal the correct final height.
.TP
.BI \-f
This option makes the output file comply to the "facsimile application
profile" defined in ITU-T Recommendation T.85. It is a shortcut for
.BR "-q -o 0 -p 8 -s 128 -t 1 -m 127" .
.TP
.BI \-v
After the BIE has been created, a few technical details of the created
file will be listed (verbose mode).
.SH BUGS
Using standard input and standard output for binary data works only on
systems where there is no difference between binary and text streams
(e.g., Unix). On other systems (e.g., MS-DOS), using standard input or
standard output may cause control characters like CR or LF to be
inserted or deleted and this will damage the binary data.
.SH STANDARDS
This program implements the
.I JBIG1
image coding algorithm as specified in ISO/IEC 11544:1993 and
ITU-T T.82(1993).
.SH AUTHOR
The
.I pbmtojbg
program is part of the
.I JBIG-KIT
package, which has been developed by Markus Kuhn.
The most recent version of this
portable
.I JBIG1
library and tools set is available from
<http://www.cl.cam.ac.uk/~mgk25/jbigkit/>.
.SH SEE ALSO
pbm(5), pgm(5), jbgtopbm(1)

433
pbmtools/pbmtojbg.c Normal file
View File

@ -0,0 +1,433 @@
/*
* pbmtojbg - Portable Bitmap to JBIG converter
*
* Markus Kuhn - http://www.cl.cam.ac.uk/~mgk25/jbigkit/
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "jbig.h"
char *progname; /* global pointer to argv[0] */
unsigned long total_length = 0; /* used for determining output file length */
/*
* Print usage message and abort
*/
static void usage(void)
{
fprintf(stderr,
"PBMtoJBIG converter " JBG_VERSION " -- "
"creates bi-level image entity (BIE) as output file\n\n"
"usage: %s [<options>] [<input-file> | - [<output-file>]]\n\n"
"options:\n\n", progname);
fprintf(stderr,
" -q\t\tsequential coding, no differential layers (like -d 0)\n"
" -x number\tmaximum width of lowest resolution layer (default 640)\n"
" -y number\tmaximum height of lowest resolution layer (default 480)\n"
" -l number\tlowest layer written to output file (default 0)\n"
" -h number\thighest layer written to output file (default max)\n"
" -b\t\tuse binary code for multiple bitplanes (default: Gray code)\n"
" -d number\ttotal number of differential layers (overrides -x and -y)\n"
" -s number\theight of a stripe in layer 0\n");
fprintf(stderr,
" -m number\tmaximum adaptive template pixel horizontal offset (default 8)\n"
" -t number\tencode only that many most significant planes\n"
" -o number\torder byte value: add 1=SMID, 2=ILEAVE, 4=SEQ, 8=HITOLO\n"
"\t\t(default 3 = ILEAVE+SMID)\n"
" -p number\toptions byte value: add DPON=4, TPBON=8, TPDON=16, LRLTWO=64\n"
"\t\t(default 28 = DPON+TPBON+TPDON)\n");
fprintf(stderr,
" -C string\tadd the provided string as a comment marker segment\n"
" -c\t\tdelay adaptive template changes to first line of next stripe\n"
"\t\t(only provided for a conformance test)\n"
" -r\t\tterminate each stripe with SDRST marker\n"
"\t\t(only intended for decoder testing)\n" );
fprintf(stderr,
" -Y number\tannounce in header initially this larger image height\n"
"\t\t(only for generating test files with NEWLEN and VLENGTH=1)\n"
" -f\t\tchose encoding options for T.85 fax profile complianance\n"
" -v\t\tverbose output\n\n");
exit(1);
}
/*
* malloc() with exception handler
*/
void *checkedmalloc(size_t n)
{
void *p;
if ((p = malloc(n)) == NULL) {
fprintf(stderr, "Sorry, not enough memory available!\n");
exit(1);
}
return p;
}
/*
* Read an ASCII integer number from file f and skip any PBM
* comments which are encountered.
*/
static unsigned long getint(FILE *f)
{
int c;
unsigned long i;
while ((c = getc(f)) != EOF && !isdigit(c))
if (c == '#')
while ((c = getc(f)) != EOF && !(c == 13 || c == 10)) ;
if (c != EOF) {
ungetc(c, f);
fscanf(f, "%lu", &i);
}
return i;
}
/*
* Callback procedure which is used by JBIG encoder to deliver the
* encoded data. It simply sends the bytes to the output file.
*/
static void data_out(unsigned char *start, size_t len, void *file)
{
fwrite(start, len, 1, (FILE *) file);
total_length += len;
return;
}
int main (int argc, char **argv)
{
FILE *fin = stdin, *fout = stdout;
const char *fnin = NULL, *fnout = NULL;
int i, j, c;
int all_args = 0, files = 0;
unsigned long x, y;
unsigned long width, height, max, v;
unsigned long bpl;
int bpp, planes, encode_planes = -1;
size_t bitmap_size;
char type;
unsigned char **bitmap, *p, *image;
struct jbg_enc_state s;
int verbose = 0, delay_at = 0, reset = 0, use_graycode = 1;
long mwidth = 640, mheight = 480;
int dl = -1, dh = -1, d = -1, mx = -1;
unsigned long l0 = 0, y1 = 0;
char *comment = NULL;
int options = JBG_TPDON | JBG_TPBON | JBG_DPON;
int order = JBG_ILEAVE | JBG_SMID;
/* parse command line arguments */
progname = argv[0];
for (i = 1; i < argc; i++) {
if (!all_args && argv[i][0] == '-')
if (argv[i][1] == 0) {
if (files++) usage();
} else
for (j = 1; j > 0 && argv[i][j]; j++)
switch(argv[i][j]) {
case '-' :
all_args = 1;
break;
case 0 :
if (files++) usage();
break;
case 'v':
verbose = 1;
break;
case 'b':
use_graycode = 0;
break;
case 'c':
delay_at = 1;
break;
case 'r':
reset = 1;
break;
case 'f':
d = 0;
order = 0;
options = 8;
l0 = 128;
encode_planes = 1;
mx = 127;
break;
case 'x':
if (++i >= argc) usage();
j = -1;
mwidth = atol(argv[i]);
break;
case 'y':
if (++i >= argc) usage();
j = -1;
mheight = atol(argv[i]);
break;
case 'Y':
if (++i >= argc) usage();
j = -1;
y1 = atol(argv[i]);
break;
case 'o':
if (++i >= argc) usage();
j = -1;
order = atoi(argv[i]);
break;
case 'p':
if (++i >= argc) usage();
j = -1;
options = atoi(argv[i]);
break;
case 'l':
if (++i >= argc) usage();
j = -1;
dl = atoi(argv[i]);
break;
case 'h':
if (++i >= argc) usage();
j = -1;
dh = atoi(argv[i]);
break;
case 'q':
d = 0;
break;
case 'd':
if (++i >= argc) usage();
j = -1;
d = atoi(argv[i]);
break;
case 's':
if (++i >= argc) usage();
j = -1;
l0 = atol(argv[i]);
break;
case 't':
if (++i >= argc) usage();
j = -1;
encode_planes = atoi(argv[i]);
break;
case 'm':
if (++i >= argc) usage();
j = -1;
mx = atoi(argv[i]);
break;
case 'C':
if (++i >= argc) usage();
j = -1;
comment = argv[i];
break;
default:
usage();
}
else
switch (files++) {
case 0: fnin = argv[i]; break;
case 1: fnout = argv[i]; break;
default:
usage();
}
}
if (fnin) {
fin = fopen(fnin, "rb");
if (!fin) {
fprintf(stderr, "Can't open input file '%s", fnin);
perror("'");
exit(1);
}
} else
fnin = "<stdin>";
if (fnout) {
fout = fopen(fnout, "wb");
if (!fout) {
fprintf(stderr, "Can't open input file '%s", fnout);
perror("'");
exit(1);
}
} else
fnout = "<stdout>";
/* read PBM header */
while ((c = getc(fin)) != EOF && (isspace(c) || c == '#'))
if (c == '#')
while ((c = getc(fin)) != EOF && !(c == 13 || c == 10)) ;
if (c != 'P') {
fprintf(stderr, "Input file '%s' does not look like a PBM file!\n", fnin);
exit(1);
}
type = getc(fin);
width = getint(fin);
height = getint(fin);
if (type == '2' || type == '5' ||
type == '3' || type == '6')
max = getint(fin);
else
max = 1;
for (planes = 0, v = max; v; planes++, v >>= 1) ;
bpp = (planes + 7) / 8;
if (encode_planes < 0 || encode_planes > planes)
encode_planes = planes;
fgetc(fin); /* skip line feed */
/* read PBM image data */
bpl = (width + 7) / 8; /* bytes per line */
bitmap_size = bpl * (size_t) height;
bitmap = (unsigned char **) checkedmalloc(sizeof(unsigned char *) *
encode_planes);
for (i = 0; i < encode_planes; i++)
bitmap[i] = (unsigned char *) checkedmalloc(bitmap_size);
switch (type) {
case '1':
/* PBM text format */
p = bitmap[0];
for (y = 0; y < height; y++)
for (x = 0; x <= ((width-1) | 7); x++) {
*p <<= 1;
if (x < width)
*p |= getint(fin) & 1;
if ((x & 7) == 7)
++p;
}
break;
case '4':
/* PBM raw binary format */
fread(bitmap[0], bitmap_size, 1, fin);
break;
case '2':
case '5':
/* PGM */
image = (unsigned char *) checkedmalloc(width * height * bpp);
if (type == '2') {
for (x = 0; x < width * height; x++) {
v = getint(fin);
for (j = 0; j < bpp; j++)
image[x * bpp + (bpp - 1) - j] = v >> (j * 8);
}
} else
fread(image, width * height, bpp, fin);
jbg_split_planes(width, height, planes, encode_planes, image, bitmap,
use_graycode);
free(image);
break;
default:
fprintf(stderr, "Unsupported PBM type P%c!\n", type);
exit(1);
}
if (ferror(fin)) {
fprintf(stderr, "Problem while reading input file '%s", fnin);
perror("'");
exit(1);
}
if (feof(fin)) {
fprintf(stderr, "Unexpected end of input file '%s'!\n", fnin);
exit(1);
}
/* Test for valid parameters */
if (width < 1 || height < 1) {
fprintf(stderr, "Image dimensions must be positive!\n");
exit(1);
}
if (encode_planes < 1 || encode_planes > 255) {
fprintf(stderr, "Number of planes must be in range 1-255!\n");
exit(1);
}
/* Test the final byte in each image line for correct zero padding */
if ((width & 7) && type == '4') {
for (y = 0; y < height; y++)
if (bitmap[0][y * bpl + bpl - 1] & ((1 << (8 - (width & 7))) - 1)) {
fprintf(stderr, "Warning: No zero padding in last byte (0x%02x) of "
"line %lu!\n", bitmap[0][y * bpl + bpl - 1], y + 1);
break;
}
}
/* Apply JBIG algorithm and write BIE to output file */
/* initialize parameter struct for JBIG encoder*/
jbg_enc_init(&s, width, height, encode_planes, bitmap, data_out, fout);
/* Select number of resolution layers either directly or based
* on a given maximum size for the lowest resolution layer */
if (d >= 0)
jbg_enc_layers(&s, d);
else
jbg_enc_lrlmax(&s, mwidth, mheight);
/* Specify a few other options (each is ignored if negative) */
if (delay_at)
options |= JBG_DELAY_AT;
if (reset)
options |= JBG_SDRST;
if (comment) {
s.comment_len = strlen(comment);
s.comment = (unsigned char *) comment;
}
if (y1)
s.yd1 = y1;
jbg_enc_lrange(&s, dl, dh);
jbg_enc_options(&s, order, options, l0, mx, -1);
/* now encode everything and send it to data_out() */
jbg_enc_out(&s);
/* give encoder a chance to free its temporary data structures */
jbg_enc_free(&s);
/* check for file errors and close fout */
if (ferror(fout) || fclose(fout)) {
fprintf(stderr, "Problem while writing output file '%s", fnout);
perror("'");
exit(1);
}
/* In case the user wants to know all the gory details ... */
if (verbose) {
fprintf(stderr, "Information about the created JBIG bi-level image entity "
"(BIE):\n\n");
fprintf(stderr, " input image size: %lu x %lu pixel\n",
s.xd, s.yd);
fprintf(stderr, " bit planes: %d\n", s.planes);
if (s.planes > 1)
fprintf(stderr, " encoding: %s code, MSB first\n",
use_graycode ? "Gray" : "binary");
fprintf(stderr, " stripes: %lu\n", s.stripes);
fprintf(stderr, " lines per stripe in layer 0: %lu\n", s.l0);
fprintf(stderr, " total number of diff. layers: %d\n", s.d);
fprintf(stderr, " lowest layer in BIE: %d\n", s.dl);
fprintf(stderr, " highest layer in BIE: %d\n", s.dh);
fprintf(stderr, " lowest layer size: %lu x %lu pixel\n",
jbg_ceil_half(s.xd, s.d - s.dl), jbg_ceil_half(s.yd, s.d - s.dl));
fprintf(stderr, " highest layer size: %lu x %lu pixel\n",
jbg_ceil_half(s.xd, s.d - s.dh), jbg_ceil_half(s.yd, s.d - s.dh));
fprintf(stderr, " option bits:%s%s%s%s%s%s%s\n",
s.options & JBG_LRLTWO ? " LRLTWO" : "",
s.options & JBG_VLENGTH ? " VLENGTH" : "",
s.options & JBG_TPDON ? " TPDON" : "",
s.options & JBG_TPBON ? " TPBON" : "",
s.options & JBG_DPON ? " DPON" : "",
s.options & JBG_DPPRIV ? " DPPRIV" : "",
s.options & JBG_DPLAST ? " DPLAST" : "");
fprintf(stderr, " order bits:%s%s%s%s\n",
s.order & JBG_HITOLO ? " HITOLO" : "",
s.order & JBG_SEQ ? " SEQ" : "",
s.order & JBG_ILEAVE ? " ILEAVE" : "",
s.order & JBG_SMID ? " SMID" : "");
fprintf(stderr, " AT maximum x-offset: %d\n"
" AT maximum y-offset: %d\n", s.mx, s.my);
fprintf(stderr, " length of output file: %lu byte\n\n",
total_length);
}
return 0;
}

227
pbmtools/pbmtojbg.txt Normal file
View File

@ -0,0 +1,227 @@
PBMTOJBG(1) PBMTOJBG(1)
NAME
pbmtojbg - portable bitmap to JBIG1 file converter
SYNOPSIS
pbmtojbg [ options ] [ input-file | - [ output-file ]]
DESCRIPTION
Reads in a portable bitmap (PBM) from a file or standard input, com-
presses it, and outputs the image as a JBIG1 bi-level image entity
(BIE) file.
JBIG1 is a highly effective lossless compression algorithm for bi-level
images (one bit per pixel), which is particularly suitable for scanned
document pages.
A JBIG1 encoded image can be stored in several resolutions (progressive
mode). These resolution layers can be stored all in one single BIE or
they can be stored in several separate BIE files. All resolution lay-
ers except the lowest one are stored merely as differences to the next
lower resolution layer, because this requires less space than encoding
the full image completely every time. Each resolution layer has twice
the number of horizontal and vertical pixels than the next lower layer.
JBIG1 files can also store several bits per pixel as separate bitmap
planes, and pbmtojbg can read a PGM file and transform it into a multi-
bitplane BIE.
OPTIONS
- A single hyphen instead of an input file name will cause
pbmtojbg to read the data from standard input instead
from a file.
-q Encode the image in one single resolution layer (sequen-
tial mode). This is usually the most efficient compres-
sion method. By default, the number of resolution layers
is chosen automatically such that the lowest layer image
is not larger than 640 x 480 pixels. This is a shortcut
for -d 0.
-x number Specify the maximal horizontal size of the lowest resolu-
tion layer. The default is 640 pixels.
-y number Specify the maximal vertical size of the lowest resolu-
tion layer. The default is 480 pixels.
-l number Select the lowest resolution layer that will be written
to the BIE. It is possible to store the various resolu-
tion layers of a JBIG1 image in progressive mode into
different BIEs. Options -l and -h allow to select the
resolution-layer interval that will appear in the created
BIE. The lowest resolution layer has number 0 and this is
also the default value. By default all layers will be
written.
-h number Select the highest resolution layer that will be written
to the BIE. By default all layers will be written. See
also option -l.
-b Use binary values instead of Gray code words in order to
encode pixel values in multiple bitplanes. This option
has only an effect if the input is a PGM file and if more
than one bitplane is produced. Note that the decoder has
to make the same selection but cannot determine from the
BIE, whether Gray or binary code words were used by the
encoder.
-d number Specify the total number of differential resolution lay-
ers into which the input image will be split in addition
to the lowest layer. Each additional layer reduces the
size of layer 0 by 50 %. This option overrides options -x
and -y which are usually a more comfortable way of
selecting the number of resolution layers.
-s number The JBIG1 algorithm splits each image into a number of
horizontal stripes. This option specifies that each
stripe shall have number lines in layer 0. The default
value is selected so that approximately 35 stripes will
be used for the whole image.
-m number Select the maximum horizontal offset of the adaptive tem-
plate pixel. The JBIG1 encoder uses ten neighbour pixels
to estimate the probability of the next pixel being black
or white. It can move one out of these ten pixels. This
is especially useful for dithered images, as long as the
distance of this adaptive pixel can be adjusted to the
period of the dither pattern. By default, the adaptive
template pixel is allowed to move up to 8 pixels away
horizontally. This encoder supports distances up to 127
pixels. Annex A of the standard suggests that decoders
should support at least a horizontal distance of 16 pix-
els, so using values not higher than 16 for number might
increase the chances of interoperability with other JBIG1
implementations. On the other hand, the T.85 fax applica-
tion profile requires decoders to support horizontal off-
sets up to 127 pixels, which the maximum value permitted
by the standard. (The maximal vertical offset of the
adaptive template pixel is always zero for this encoder.)
-t number Encode only the specified number of most significant bit
planes. This option allows to reduce the depth of an
input PGM file if not all bits per pixel are needed in
the output.
-o number JBIG1 separates an image into several horizontal stripes,
resolution layers and planes, were each plane contains
one bit per pixel. One single stripe in one plane and
layer is encoded as a data unit called stripe data entity
(SDE) inside the BIE. There are 12 different possible
orders in which the SDEs can be stored inside the BIE and
number selects which one shall be used. The order of the
SDEs is only relevant for applications that want to
decode a JBIG1 file which has not yet completely arrived
from e.g. a slow network connection. For instance some
applications prefer that the outermost of the three loops
(stripes, layers, planes) is over all layers so that all
data of the lowest resolution layer is transmitted first.
The following values for number select these loop
arrangements for writing the SDEs (outermost loop first):
0 planes, layers, stripes
2 layers, planes, stripes
3 layers, stripes, planes
4 stripes, planes, layers
5 planes, stripes, layers
6 stripes, layers, planes
All loops count starting with zero, however by adding 8
to the above order code, the layer loop can be reversed
so that it counts down to zero and then higher resolution
layers will be stored before lower layers. Default order
is 3 which writes at first all planes of the first stripe
and then completes layer 0 before continuing with the
next layer and so on.
-p number This option allows to activate or deactivate various
optional algorithms defined in the JBIG1 standard. Just
add the numbers of the following options which you want
to activate in order to get the number value:
4 deterministic prediction (DPON)
8 layer 0 typical prediction (TPBON)
16 diff. layer typ. pred. (TPDON)
64 layer 0 two-line template (LRLTWO)
Except for special applications (like communication with
JBIG1 subset implementations) and for debugging purposes
you will normally not want to change anything here. The
default is 28, which provides the best compression
result.
-C string Add the string in a comment marker segment to the pro-
duced data stream. (There is no support at present for
adding comments that contain the zero byte.)
-c Determine the adaptive template pixel movement as sug-
gested in annex C of the standard. By default the tem-
plate change takes place directly in the next line, which
is most effective. However, a few conformance test exam-
ples in the standard require the adaptive template change
to be delayed until the first line of the next stripe.
This option selects this special behavior, which is nor-
mally not required except in order to pass some confor-
mance tests.
-r Use the SDRST marker instead of the normal SDNORM marker.
The probably only useful application of this option is to
generate test data for checking whether a JBIG1 decoder
has implemented SDRST correctly. In a normal JBIG1 data
stream, each stripe data entity (SDE) is terminated by an
SDNORM marker, which preserves the state of the arith-
metic encoder (and more) for the next stripe in the same
layer. The alternative SDRST marker resets this state at
the end of the stripe.
-Y number A long time ago, there were fax machines that couldn't
even hold a single page in memory. They had to start
transmitting data before the page was scanned in com-
pletely and the length of the image was known. The
authors of the standard added a rather ugly hack to the
otherwise beautiful JBIG1 format to support this. The
NEWLEN marker segment can override the image height
stated in the BIE header anywhere later in the data
stream. Normally pbmtojbg never generates NEWLEN marker
segments, as it knows the correct image height when it
outputs the header. This option is solely intended for
the purpose of generating test files with NEWLEN marker
segments. It can be used to specify a higher initial
image height for use in the BIE header, and pbmtojbg will
then add a NEWLEN marker segment at the latest possible
opportunity to the data stream to signal the correct
final height.
-f This option makes the output file comply to the "facsim-
ile application profile" defined in ITU-T Recommendation
T.85. It is a shortcut for -q -o 0 -p 8 -s 128 -t 1 -m
127.
-v After the BIE has been created, a few technical details
of the created file will be listed (verbose mode).
BUGS
Using standard input and standard output for binary data works only on
systems where there is no difference between binary and text streams
(e.g., Unix). On other systems (e.g., MS-DOS), using standard input or
standard output may cause control characters like CR or LF to be
inserted or deleted and this will damage the binary data.
STANDARDS
This program implements the JBIG1 image coding algorithm as specified
in ISO/IEC 11544:1993 and ITU-T T.82(1993).
AUTHOR
The pbmtojbg program is part of the JBIG-KIT package, which has been
developed by Markus Kuhn. The most recent version of this portable
JBIG1 library and tools set is available from
<http://www.cl.cam.ac.uk/~mgk25/jbigkit/>.
SEE ALSO
pbm(5), pgm(5), jbgtopbm(1)
2003-06-04 PBMTOJBG(1)

274
pbmtools/pbmtojbg85.c Normal file
View File

@ -0,0 +1,274 @@
/*
* pbmtojbg85 - Portable Bitmap to JBIG converter (T.85 version)
*
* Markus Kuhn - http://www.cl.cam.ac.uk/~mgk25/jbigkit/
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "jbig85.h"
char *progname; /* global pointer to argv[0] */
/*
* Print usage message and abort
*/
static void usage(void)
{
fprintf(stderr,
"PBMtoJBIG converter " JBG85_VERSION " (T.85 version) --\n"
"creates bi-level image entity (BIE) as output file\n\n"
"usage: %s [<options>] [<input-file> | - [<output-file>]]\n\n"
"options:\n\n", progname);
fprintf(stderr,
" -s number\theight of a stripe\n");
fprintf(stderr,
" -m number\tmaximum adaptive template pixel horizontal offset (default 8)\n"
" -p number\toptions byte value: add TPBON=8, LRLTWO=64\n"
"\t\t(default 8 = TPBON)\n");
fprintf(stderr,
" -C string\tadd the provided string as a comment marker segment\n");
fprintf(stderr,
" -Y yi yr\tannounce in header initially the larger image height yi\n"
"\t\tand then announce after line yr has been encoded the real height\n"
"\t\tusing NEWLEN marker (for testing NEWLEN and VLENGTH=1 function)\n\n");
exit(1);
}
/*
* malloc() with exception handler
*/
void *checkedmalloc(size_t n)
{
void *p;
if ((p = malloc(n)) == NULL) {
fprintf(stderr, "Sorry, not enough memory available!\n");
exit(1);
}
return p;
}
/*
* Read an ASCII integer number from file f and skip any PBM
* comments which are encountered.
*/
static unsigned long getint(FILE *f)
{
int c;
unsigned long i;
while ((c = getc(f)) != EOF && !isdigit(c))
if (c == '#')
while ((c = getc(f)) != EOF && !(c == 13 || c == 10)) ;
if (c != EOF) {
ungetc(c, f);
fscanf(f, "%lu", &i);
}
return i;
}
/*
* Callback procedure which is used by JBIG encoder to deliver the
* encoded data. It simply sends the bytes to the output file.
*/
static void data_out(unsigned char *start, size_t len, void *file)
{
fwrite(start, len, 1, (FILE *) file);
return;
}
int main (int argc, char **argv)
{
FILE *fin = stdin, *fout = stdout;
const char *fnin = NULL, *fnout = NULL;
int i, j, c;
int all_args = 0, files = 0;
unsigned long x, y;
unsigned long width, height;
size_t bpl;
char type;
unsigned char *p, *lines, *next_line;
unsigned char *prev_line = NULL, *prevprev_line = NULL;
struct jbg85_enc_state s;
int mx = -1;
unsigned long l0 = 0, yi = 0, yr = 0;
char *comment = NULL;
int options = JBG_TPBON;
/* parse command line arguments */
progname = argv[0];
for (i = 1; i < argc; i++) {
if (!all_args && argv[i][0] == '-')
if (argv[i][1] == 0) {
if (files++) usage();
} else
for (j = 1; j > 0 && argv[i][j]; j++)
switch(argv[i][j]) {
case '-' :
all_args = 1;
break;
case 0 :
if (files++) usage();
break;
case 'Y':
if (i+2 >= argc) usage();
j = -1;
yi = atol(argv[++i]);
yr = atol(argv[++i]);
break;
case 'p':
if (++i >= argc) usage();
j = -1;
options = atoi(argv[i]);
break;
case 's':
if (++i >= argc) usage();
j = -1;
l0 = atol(argv[i]);
break;
case 'm':
if (++i >= argc) usage();
j = -1;
mx = atoi(argv[i]);
break;
case 'C':
if (++i >= argc) usage();
j = -1;
comment = argv[i];
break;
default:
usage();
}
else
switch (files++) {
case 0: fnin = argv[i]; break;
case 1: fnout = argv[i]; break;
default:
usage();
}
}
/* open input file */
if (fnin) {
fin = fopen(fnin, "rb");
if (!fin) {
fprintf(stderr, "Can't open input file '%s", fnin);
perror("'");
exit(1);
}
} else
fnin = "<stdin>";
/* read PBM header */
while ((c = getc(fin)) != EOF && (isspace(c) || c == '#'))
if (c == '#')
while ((c = getc(fin)) != EOF && !(c == 13 || c == 10)) ;
type = getc(fin);
if (c != 'P' || (type != '1' && type != '4')) {
fprintf(stderr, "Input file '%s' does not look like a PBM file!\n", fnin);
exit(1);
}
width = getint(fin);
height = getint(fin);
fgetc(fin); /* skip line feed */
/* Test for valid parameters */
if (width < 1 || height < 1) {
fprintf(stderr, "Image dimensions must be positive!\n");
exit(1);
}
/* allocate buffer for a single image line */
bpl = (width >> 3) + !!(width & 7); /* bytes per line */
lines = (unsigned char *) checkedmalloc(bpl * 3);
/* open output file */
if (fnout) {
fout = fopen(fnout, "wb");
if (!fout) {
fprintf(stderr, "Can't open input file '%s", fnout);
perror("'");
exit(1);
}
} else
fnout = "<stdout>";
/* initialize parameter struct for JBIG encoder*/
jbg85_enc_init(&s, width, yi ? yi : height, data_out, fout);
/* Specify a few other options (each is ignored if negative) */
if (yi)
options |= JBG_VLENGTH;
if (comment) {
s.comment_len = strlen(comment);
s.comment = (unsigned char *) comment;
}
jbg85_enc_options(&s, options, l0, mx);
for (y = 0; y < height; y++) {
/* Use a 3-line ring buffer, because the encoder requires that the two
* previously supplied lines are still in memory when the next line is
* processed. */
next_line = lines + (y%3)*bpl;
switch (type) {
case '1':
/* PBM text format */
p = next_line;
for (x = 0; x <= ((width-1) | 7); x++) {
*p <<= 1;
if (x < width)
*p |= getint(fin) & 1;
if ((x & 7) == 7)
++p;
}
break;
case '4':
/* PBM raw binary format */
fread(next_line, bpl, 1, fin);
break;
default:
fprintf(stderr, "Unsupported PBM type P%c!\n", type);
exit(1);
}
if (ferror(fin)) {
fprintf(stderr, "Problem while reading input file '%s", fnin);
perror("'");
exit(1);
}
if (feof(fin)) {
fprintf(stderr, "Unexpected end of input file '%s'!\n", fnin);
exit(1);
}
/* JBIG compress another line and write out result via callback */
jbg85_enc_lineout(&s, next_line, prev_line, prevprev_line);
prevprev_line = prev_line;
prev_line = next_line;
/* adjust final image height via NEWLEN */
if (yi && y == yr)
jbg85_enc_newlen(&s, height);
}
/* check for file errors and close fout */
if (ferror(fout) || fclose(fout)) {
fprintf(stderr, "Problem while writing output file '%s", fnout);
perror("'");
exit(1);
}
return 0;
}

90
pbmtools/pgm.5 Normal file
View File

@ -0,0 +1,90 @@
.TH pgm 5 "12 November 1991"
.SH NAME
pgm - portable graymap file format
.SH DESCRIPTION
The portable graymap format is a lowest common denominator grayscale
file format.
.IX "PGM file format"
The definition is as follows:
.IP - 2
A "magic number" for identifying the file type.
A pgm file's magic number is the two characters "P2".
.IX "magic numbers"
.IP - 2
Whitespace (blanks, TABs, CRs, LFs).
.IP - 2
A width, formatted as ASCII characters in decimal.
.IP - 2
Whitespace.
.IP - 2
A height, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
The maximum gray value, again in ASCII decimal.
.IP - 2
Whitespace.
.IP - 2
Width * height gray values, each in ASCII decimal, between 0 and the specified
maximum value, separated by whitespace, starting at the top-left
corner of the graymap, proceeding in normal English reading order.
A value of 0 means black, and the maximum value means white.
.IP - 2
Characters from a "#" to the next end-of-line are ignored (comments).
.IP - 2
No line should be longer than 70 characters.
.PP
Here is an example of a small graymap in this format:
.nf
P2
# feep.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
.fi
.PP
Programs that read this format should be as lenient as possible,
accepting anything that looks remotely like a graymap.
.PP
There is also a variant on the format, available
by setting the RAWBITS option at compile time. This variant is
different in the following ways:
.IX RAWBITS
.IP - 2
The "magic number" is "P5" instead of "P2".
.IP - 2
The gray values are stored as plain bytes, instead of ASCII decimal.
.IP - 2
No whitespace is allowed in the grays section, and only a single character
of whitespace (typically a newline) is allowed after the maxval.
.IP - 2
The files are smaller and many times faster to read and write.
.PP
Note that this raw format can only be used for maxvals less than
or equal to 255.
If you use the
.I pgm
library and try to write a file with a larger maxval,
it will automatically fall back on the slower but more general plain
format.
.SH "SEE ALSO"
fitstopgm(1), fstopgm(1), hipstopgm(1), lispmtopgm(1), psidtopgm(1),
rawtopgm(1),
pgmbentley(1), pgmcrater(1), pgmedge(1), pgmenhance(1), pgmhist(1), pgmnorm(1),
pgmoil(1), pgmramp(1), pgmtexture(1),
pgmtofits(1), pgmtofs(1), pgmtolispm(1), pgmtopbm(1),
pnm(5), pbm(5), ppm(5)
.SH AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
.\" Permission to use, copy, modify, and distribute this software and its
.\" documentation for any purpose and without fee is hereby granted, provided
.\" that the above copyright notice appear in all copies and that both that
.\" copyright notice and this permission notice appear in supporting
.\" documentation. This software is provided "as is" without express or
.\" implied warranty.

85
pbmtools/pgm.txt Normal file
View File

@ -0,0 +1,85 @@
pgm(5) pgm(5)
NAME
pgm - portable graymap file format
DESCRIPTION
The portable graymap format is a lowest common denominator grayscale
file format. The definition is as follows:
- A "magic number" for identifying the file type. A pgm file's magic
number is the two characters "P2".
- Whitespace (blanks, TABs, CRs, LFs).
- A width, formatted as ASCII characters in decimal.
- Whitespace.
- A height, again in ASCII decimal.
- Whitespace.
- The maximum gray value, again in ASCII decimal.
- Whitespace.
- Width * height gray values, each in ASCII decimal, between 0 and the
specified maximum value, separated by whitespace, starting at the
top-left corner of the graymap, proceeding in normal English reading
order. A value of 0 means black, and the maximum value means white.
- Characters from a "#" to the next end-of-line are ignored (comments).
- No line should be longer than 70 characters.
Here is an example of a small graymap in this format:
P2
# feep.pgm
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Programs that read this format should be as lenient as possible,
accepting anything that looks remotely like a graymap.
There is also a variant on the format, available by setting the RAWBITS
option at compile time. This variant is different in the following
ways:
- The "magic number" is "P5" instead of "P2".
- The gray values are stored as plain bytes, instead of ASCII decimal.
- No whitespace is allowed in the grays section, and only a single
character of whitespace (typically a newline) is allowed after the
maxval.
- The files are smaller and many times faster to read and write.
Note that this raw format can only be used for maxvals less than or
equal to 255. If you use the pgm library and try to write a file with
a larger maxval, it will automatically fall back on the slower but more
general plain format.
SEE ALSO
fitstopgm(1), fstopgm(1), hipstopgm(1), lispmtopgm(1), psidtopgm(1),
rawtopgm(1), pgmbentley(1), pgmcrater(1), pgmedge(1), pgmenhance(1),
pgmhist(1), pgmnorm(1), pgmoil(1), pgmramp(1), pgmtexture(1),
pgmtofits(1), pgmtofs(1), pgmtolispm(1), pgmtopbm(1), pnm(5), pbm(5),
ppm(5)
AUTHOR
Copyright (C) 1989, 1991 by Jef Poskanzer.
12 November 1991 pgm(5)