Import Upstream version 2.1
This commit is contained in:
commit
5452c32bf3
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -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.
|
|
@ -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
|
|
@ -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/
|
|
@ -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
|
|
@ -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).
|
||||
|
Binary file not shown.
|
@ -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/
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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');
|
|
@ -0,0 +1,5 @@
|
|||
P5
|
||||
2
|
||||
2
|
||||
4294967295
|
||||
abcdABCD9876WXYZ
|
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
Binary file not shown.
Binary file not shown.
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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]
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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]
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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.
|
|
@ -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"
|
|
@ -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 не продолжает предыдущий"
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
|
@ -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)
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
|
@ -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)
|
Loading…
Reference in New Issue