Project

General

Profile

« Previous | Next » 

Revision 8756569f

Added by david.sorber 8 months ago

  • ID 8756569f98ae990f7ead6bb53870aa72f3ce9a43

Moving libpackjpg to its own repo. Last commit was main #3599f0a5.

View differences:

LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser 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
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
Readme.txt
packJPG v2.5k (01/22/2016)
~~~~~~~~~~~~~~~~~~~~~~~~~~
packJPG is a compression program specially designed for further
compression of JPEG images without causing any further loss. Typically
it reduces the file size of a JPEG file by 20%.
LGPL v3 license and special permissions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All programs in this package are free software; you can redistribute
them and/or modify them under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.
The package 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 Lesser
General Public License for more details at
http://www.gnu.org/copyleft/lgpl.html.
If the LGPL v3 license is not compatible with your software project you
might contact us and ask for a special permission to use the packJPG
library under different conditions. In any case, usage of the packJPG
algorithm under the LGPL v3 or above is highly advised and special
permissions will only be given where necessary on a case by case basis.
This offer is aimed mainly at closed source freeware developers seeking
to add PJG support to their software projects.
Copyright 2006...2014 by HTW Aalen University and Matthias Stirner.
Usage of packJPG
~~~~~~~~~~~~~~~~
JPEG files are compressed and PJG files are decompressed using this
command:
"packJPG [file(s)]"
packJPG recognizes file types on its own and decides whether to compress
(JPG) or decompress (PJG). For unrecognized file types no action is
taken. Files are recognized by content, not by extension.
packJPG supports wildcards like "*.*" and drag and drop of multiple
files. Filenames for output files are created automatically. In default
mode, files are never overwritten. If a filename is already in use,
packJPG creates a new filename by adding underscores.
If "-" is used as a filename input from stdin is assumed and output is
written to stdout. This can be useful for example if jpegtran is to be
used as a preprocessor.
Usage examples:
"packJPG *.pjg"
"packJPG lena.jpg"
"packJPG kodim??.jpg"
"packJPG - < sail.pjg > sail.jpg"
Command line switches
~~~~~~~~~~~~~~~~~~~~~
-ver verify files after processing
-v? level of verbosity; 0,1 or 2 is allowed (default 0)
-np no pause after processing files
-o overwrite existing files
-p proceed on warnings
-d discard meta-info
By default, compression is cancelled on warnings. If warnings are
skipped by using "-p", most files with warnings can also be compressed,
but JPEG files reconstructed from PJG files might not be bitwise
identical with the original JPEG files. There won't be any loss to
image data or quality however.
Unnecessary meta information can be discarded using "-d". This reduces
compressed files' sizes. Be warned though, reconstructed files won't be
bitwise identical with the original files and meta information will be
lost forever. As with "-p" there won't be any loss to image data or
quality.
There is no known case in which a file compressed by packJPG (without
the "-p" option, see above) couldn't be reconstructed to exactly the
state it was before. If you want an additional layer of safety you can
also use the verify option "-ver". In this mode, files are compressed,
then decompressed and the decompressed file compared to the original
file. If this test doesn't pass there will be an error message and the
compressed file won't be written to the drive.
Please note that the "-ver" option should never be used in conjunction
with the "-d" and/or "-p" options. As stated above, the "-p" and "-d"
options will most likely lead to reconstructed JPG files not being
bitwise identical to the original JPG files. In turn, the verification
process may fail on various files although nothing actually went wrong.
Usage examples:
"packJPG -v1 -o baboon.pjg"
"packJPG -ver lena.jpg"
"packJPG -d tiffany.jpg"
"packJPG -p *.jpg"
Known Limitations
~~~~~~~~~~~~~~~~~
packJPG is a compression program specially for JPEG files, so it doesn't
compress other file types.
packJPG has low error tolerance. JPEG files might not work with packJPG
even if they work perfectly with other image processing software. The
command line switch "-p" can be used to increase error tolerance and
compatibility.
If you try to drag and drop to many files at once, there might be a
windowed error message about missing privileges. In that case you can
try it again with less files or consider using the command prompt.
packJPG has been tested to work perfectly with thousands of files from
the command line. This issue also happens with drag and drop in other
applications, so it might not be a limitation of packJPG but a
limitation of Windows.
Compressed PJG files are not compatible between different packJPG
versions. You will get an error message if you try to decompress PJG
files with a different version than the one used for compression. You
may download older versions of packJPG from:
http://www.elektronik.htw-aalen.de/packJPG/binaries/old/
Open source release / developer info
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The packJPG source codes is found inside the "source" subdirectory.
Additional documents aimed to developers, containing detailed
instructions on compiling the source code and using special
functionality, are included in the "packJPG" subdirectory.
History
~~~~~~~
v1.9a (04/20/2007) (non public)
- first released version
- only for testing purposes
v2.0 (05/28/2007) (public)
- first public version of packJPG
- minor improvements to overall compression
- minor bugfixes
v2.2 (08/05/2007) (public)
- around 40% faster compression & decompression
- major improvements to overall compression (around 2% on average)
- reading from stdin, writing to stdout
- smaller executable
- minor bugfixes
- various minor improvements
v2.3 (09/18/2007) (public)
- compatibility with JPEG progressive mode
- compatibility with JPEG extended sequential mode
- compatibility with the CMYK color space
- compatibility with older CPUs
- around 15% faster compression & decompression
- new switch: [-d] (discard meta-info)
- various bugfixes
v2.3a (11/21/2007) (public)
- crash issue with certain images fixed
- compatibility with packJPG v2.3 maintained
v2.3b (12/20/2007) (public)
- some minor errors in the packJPG library fixed
- compatibility with packJPG v2.3 maintained
v2.4 (03/24/2010) (public)
- major improvements (1%...2%) to overall compression
- around 10% faster compression & decompression
- major improvements to JPG compatibility
- size of executable reduced to ~33%
- new switch: [-ver] (verify file after processing)
- new switch: [-np] (no pause after processing)
- new progress bar output mode
- arithmetic coding routines rewritten from scratch
- various smaller improvements to numerous to list here
- new SFX (self extracting) archive format
v2.5 (11/11/2011) (public)
- improvements (~0.5%) to overall compression
- several minor bugfixes
- major code cleanup
- removed packJPX from the package
- added packARC to the package
- packJPG is now open source!
v2.5a (11/21/11) (public)
- source code compatibility improvements (Gerhard Seelmann)
- avoid some compiler warnings (Gerhard Seelmann)
- source code clean up (Gerhard Seelmann)
v2.5b (01/27/12) (public)
- further removal of redundant code
- some fixes for the packJPG static library
- compiler fix for Mac OS (thanks to Sergio Lopez)
- improved compression ratio calculation
- eliminated the need for temp files
v2.5c (04/13/12) (public)
- various source code optimizations
v2.5d (07/03/12) (public)
- fixed a rare bug with progressive JPEG
v2.5e (07/03/12) (public)
- some minor source code optimizations
- changed packJPG licensing to LGPL
- moved packARC to a separate package
v2.5f (02/24/13) (public)
- fixed a minor bug in the JPG parser (thanks to Stephan Busch)
v2.5g (09/14/13) (public)
- fixed a rare crash bug with manipulated JPEG files
v2.5h (12/07/13) (public)
- added a warning for inefficient huffman coding (thanks to Moinak Ghosh)
v2.5i (12/26/13) (public)
- fixed possible crash with malformed JPEG (thanks to Moinak Ghosh)
v2.5j (01/15/14) (public)
- various source code optimizations (using cppcheck)
v2.5k (01/22/16) (public)
- Updated contact info
- fixed a minor bug
Acknowledgements
~~~~~~~~~~~~~~~~
packJPG is the result of countless hours of research and development. It
is part of my final year project for Hochschule Aalen.
Prof. Dr. Gerhard Seelmann from Hochschule Aalen supported my
development of packJPG with his extensive knowledge in the field of data
compression. Without his advice, packJPG would not be possible.
The official developer blog for packJPG is hosted by encode.ru.
packJPG logo and icon are designed by Michael Kaufmann.
Contact
~~~~~~~
The official developer blog for packJPG:
http://packjpg.encode.ru/
For questions and bug reports:
packjpg (at) matthiasstirner.com
____________________________________
packJPG by Matthias Stirner, 01/2016
docs/contents.txt
packJPG package - table of contents
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Source files
~~~~~~~~~~~~
All files needed to compile packJPG as an executable or as a library are
included in the 'source' subdirectory':
- 'Makefile' (universal makefile)
- 'aricoder.cpp' (arithmetic coder source file)
- 'aricoder.h' (arithmetic coder header file)
- 'bitops.cpp' (bitwise file I/O routines source file)
- 'bitops.h' (bitwise file I/O routines header file)
- 'dct8x8.h' (discrete cosine transform header file)
- 'packjpg.cpp' (packJPG main source file)
- 'packjpglib.h' (packJPG static library header file)
- 'pjpgtbl.h' (helper tables header file)
These files are included as well, but are not necessarily needed for
compiling packJPG:
- 'packjpg.spec' (RPM spec file, provided by Bryan Stillwell)
- 'Makefile_osx' (special OS X Makefile, provided by Ryan Flynn)
- 'packjpgdll.h' (packJPG DLL header file)
- 'file_icon.ico' (suggested .pjg icon in .ico format)
- 'app_icon.ico' (application icon in .ico format)
- 'icon.res' (application icon in Windows .res format)
Documentation
~~~~~~~~~~~~~
The packJPG source code is well commented. Additionally, these files are
included in the 'doc' subdirectory.
- 'developer.txt' (information about developer functions)
- 'sample_images.zip' (sample images, referenced in 'developer.txt')
- 'AalenUniv.jpg' (sample image, showing Aalen University)
- 'dsci0692.jpg' (sample image, showing a flower)
- 'usage.txt' (generic usage information)
- 'howtocompile.txt' (compile instructions)
- 'versionnumbering.txt' (version numbering guideline)
- 'contents.txt' (the file you are currently reading)
*NOT* included
~~~~~~~~~~~~~~
There's no further documentation on the packJPG algorithms - all
documentation is included within the source code.
____________________________________
packJPG by Matthias Stirner, 10/2012
docs/developer.txt
-Developer functions detailed descriptions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-packJPG contains functionality especially designed for developers. This
-document details how to use the developer functions.
-
-
-Developer switches
-~~~~~~~~~~~~~~~~~~
-
- -dev needed to enable any of the switches bewlow
-
- -test test algorithms, alert if error
- -split split jpeg (to header & image data)
- -coll? write coefficients (0=std,1=dhf,2=squ,3=unc)
- -fcol? write filtered coefficients (see above)
- -zdst write zero distribution lists to files
- -info write debug info to .nfo file
- -dist write distribution data to file
- -pgm convert and write to pgm files
-
- -s? set global number of segments (1<=s<=49)
- -t? set global noise threshold (0<=t<=10)
- -s?,? set number of segments for component
- -t?,? set noise threshold for component
-
-
-Developer switches usage
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-The developer switch "-ver" is needed the enable any developer function.
-Other developer functions won't work without it.
-
-"-test" is a special case of the "-ver" option. Files are also verified,
-but if any error happens, all the output will be kept for the developer
-to have a look at it.
-
-"-split" splits a JPEG file to huffman coded image data and header data.
-This mode is useful if a closer look at the header of a given file is
-needed.
-
-"-coll?" and "-fcol?" write decompressed DCT coefficients to separate
-files (one for each color component). DCT coefficients are stored in two
-byte signed short integers. In the "-fcol?" option, DC coefficents are
-replaced by the corresponding DC prediction errors, while using the
-"-coll?" option will dump DC coeffcients without any prediction applied.
-The "?" has to be replaced by a number 0, 1, 2 or 3, which will
-determine the order the coefficients will be stored inside the files.
-Have a look at the included sample images or the source code to get an
-idea on which each number stands for.
-
-"-zdst" writes zero distribution lists to files (one for each color
-component). For each 8x8 image data block in a given color component, a
-zero distribution list contains the number of coefficients unequal zero.
-These numbers are stored as unsigned one byte chars. In packJPG, zero
-distribution lists are used as a replacement for JPEGs EOB symbol and
-for segmentation of data.
-
-"-info" dumps a ".nfo" text file with data about the JPEG file.
-Structure of header, type of coding and quantization tables for each
-component are included in this file.
-
-"-dump" dumps distribution for a given file to ".dist" files (again, one
-file per color component). For each band seperately this files contain
-the number of coefficients = 0; 1; 2; 3; 4; .... (absolute values). Have
-a look at the source code to get an idea about the structure of these
-files.
-
-"-pgm" mainly serves as a test function for the integrated DCT routines.
-Each color component is transformed back to it's image representation
-using the IDCT and dumped seperately as a ".PGM" (Portable GrayMap)
-file.
-
-"-t?" and "-s?" control specific compression settings. By manipulating
-these parameters, you might achieve higher compression. By default,
-these values are set automatically. The default for segmentation ("-s?")
-is 10. The default for the noise threshold ("-t?") is dependant on the
-size of the input file. Higher sizes mean higher t - theres more data
-for the statistical model to learn in bigger files, so less has to be
-considered noise.
-
-
-____________________________________
-packJPG by Matthias Stirner, 11/2011
docs/howtocompile.txt
How to compile packJPG (01/30/2012)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This document gives detailed instructions on compiling packJPG either as
an executable or a static/shared libary.
Compiling packJPG as an executable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Makefiles or provided for Microsoft Windows NT ('Makefile') and Unix
('Makefile.unix'). Both have been tested and verified to work in GCC
v3.4.5, but they should work with other compilers and newer/older
versions of the GCC as well. If you want to compile packJPG in Microsoft
Visual Studio for Microsoft Windows, just create a new project and add
all source files to it.
Compiling packJPG as a static or shared library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to compile packJPG as a static or shared library, add all
the source files to a new static/shared library project. 'BUILD_LIB'
(without the ') has to be defined either at the beginning of
'packJPG.cpp' or from the compilers options. 'BUILD_DLL' has to be
defined in addition only if a shared library is to be compiled (don't
define this for a static library!).
The source file 'packJPGdll.h' contains all public function declarations
of the library and can be included in external projects which use the
packJPG shared library.
Compiling developer functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to include developer functions in the packJPG executable,
'DEV_BUILD' has to be defined. Developer functions are not available in
the packJPG library. They are not needed in any way for basic packJPG
functionality (i.e. compression and decompression) and can be left out
to compile a smaller executable. Read 'developer.txt' for more
information.
Defines overview / summary
~~~~~~~~~~~~~~~~~~~~~~~~~~
This paragraph gives a short overview over preprocessor defines
mentioned in the above paragraphs.
BUILD_LIB
Has to be defined when compiling a static or shared library.
BUILD_DLL
Has to defined when compiling a shared library only.
BUILD_DEV
If this is defined, developer functions are included in the executable.
In library builds developer functions are not available.
____________________________________
packJPG by Matthias Stirner, 01/2012
docs/lgpl-3.0.txt
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser 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
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
docs/versionnumbering.txt
Version numbering guideline
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The packJPG version consists of two parts the main version number and
the sub version string. An example: 'packJPG v2.4a', an older version of
packJPG, has the main version number '2.4' and the sub version string
'a'.
Compressed .pjg files are required to be compatible between subversions:
packJPG v2.4a compressed .pjg files can be extracted by packJPG v2.4,
packJPG v2.4b, packJPG v2.4c, ... and vice versa. Only if there is a
change in the main version number, encoded files can be incompatible
between each other: packJPG v2.4 won't extract packJPG v2.3 compressed
.pjg files and vice versa.
The subversion string is used to indicate smaller changes that won't
break compatibility, like, f.e., bug fixes or speed improvements. It can
also be empty (for the first new main version in a series) and should be
enumerated as 'a', 'b', 'c', ... , 'z', 'aa', 'ab', 'ac', ..., 'zz'. For
any highly specific improvements it might also be used differently, to
indicate these changes, f.e. 'packJPG v2.5fast'.
The main version number is changed directly in the source code via the
'pjgversion' (main version number) and the 'subversion' (subversion
string) constant variables.
lib_src/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
PROJECT("packJPG")
################################################################################
# Check GCC version
################################################################################
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# Require at least gcc 10.3 for C++20 support
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.3)
MESSAGE(FATAL_ERROR "GCC version must be at least 10.3!")
ENDIF()
ENDIF()
# This is a neat trick to prevent in source builds
IF (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
MESSAGE(FATAL_ERROR "Prevented in-tree build. This is bad practice; you "
"should be running cmake from inside a build directory.")
ENDIF()
################################################################################
# Build configuration options
################################################################################
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ReleaseWithDebug CACHE STRING
"Choose the type of build, options are: None Debug ReceiverRelease ReleaseWithDebug."
FORCE )
ENDIF()
MESSAGE(STATUS "Build Type: " ${CMAKE_BUILD_TYPE})
ADD_CUSTOM_TARGET(Debug
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
COMMENT "Switch CMAKE_BUILD_TYPE to Debug"
)
ADD_CUSTOM_TARGET(ReceiverRelease
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=LibRelease ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
COMMENT "Switch CMAKE_BUILD_TYPE to ReceiverRelease"
)
ADD_CUSTOM_TARGET(ReleaseWithDebug
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=ReleaseWithDebug ${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
COMMENT "Switch CMAKE_BUILD_TYPE to ReleaseWithDebug"
)
# Use /etc/os-release to determine Linux flavor and version
EXECUTE_PROCESS(COMMAND bash -c "grep \"^NAME=\" /etc/os-release | cut -c7- | rev | cut -c2- | rev"
OUTPUT_VARIABLE DISTRIB_ID
OUTPUT_STRIP_TRAILING_WHITESPACE
)
EXECUTE_PROCESS(COMMAND bash -c "grep \"^VERSION_ID=\" /etc/os-release | cut -c13- | rev | cut -c2- | rev"
OUTPUT_VARIABLE DISTRIB_RELEASE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Output the parsed ID and release version
MESSAGE(STATUS "DISTRIB_ID: " ${DISTRIB_ID})
MESSAGE(STATUS "DISTRIB_RELEASE: " ${DISTRIB_RELEASE})
# Do not let CMake add the build directory path to RPATH. This means that CL/SL
# cannot be run from the build directory and must be properly installed.
SET(CMAKE_SKIP_BUILD_RPATH TRUE)
# Uncomment this line to enable AddressSanitizer
# SET(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
# Detect presence of mold linker and use it if found
IF (EXISTS "/usr/bin/mold")
MESSAGE(STATUS "Using mold linker!")
# Note this only works on gcc >= 12.1
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=mold")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=mold")
ELSE()
MESSAGE(WARNING "Mold linker not detected. Consider installing mold (add BL APT repo: "
"https://athena.blacklynx.tech/apt/): sudo apt install mold")
ENDIF()
#
# Set the compile flags
#
SET(CMAKE_CXX_STANDARD 20)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
# SET(CMAKE_CXX_VISIBILITY_PRESET hidden)
# This length is used along with the __FILE__ macro for logging
STRING(LENGTH ${CMAKE_CURRENT_SOURCE_DIR} BPLEN)
ADD_DEFINITIONS("-DBUILD_PATH_LEN=${BPLEN}")
# Ensure symbols from statically linked libraries are hidden
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--exclude-libs=ALL")
# Enable warnings
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter")
IF (CMAKE_BUILD_TYPE STREQUAL "LibRelease")
# Tune for Haswell minimum
SET(COMPILE_FLAGS "-O3 -flto=auto -ffast-math -ffp-contract=fast -fno-verbose-asm -march=skylake -mfma -mavx2")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILE_FLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")
ELSEIF (CMAKE_BUILD_TYPE STREQUAL "ReleaseWithDebug")
# Tune for Haswell minimum
# SET(COMPILE_FLAGS "-g -O3 -flto=auto -march=haswell -mtune=generic -mavx2")
SET(COMPILE_FLAGS "-g -O3 -flto=auto -ffast-math -ffp-contract=fast -fno-verbose-asm -march=skylake -mfma -mavx2")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILE_FLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")
ELSEIF (CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(COMPILE_FLAGS "-g -O0 -march=skylake -mtune=generic")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILE_FLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")
ENDIF()
# Set the library install path depending on the Linux flavor
SET(LIBRARY_INSTALL_PATH "")
IF ((DISTRIB_ID STREQUAL "Ubuntu") OR (DISTRIB_ID STREQUAL "Linux Mint"))
SET(LIBRARY_INSTALL_PATH "usr/lib/x86_64-linux-gnu/")
ELSE()
# CentOS/RedHat/Scientific
SET(LIBRARY_INSTALL_PATH "usr/lib64/")
ENDIF()
IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "/" CACHE PATH "..." FORCE)
ENDIF()
################################################################################
# Library Dependencies
################################################################################
SET(EXTERNAL_LIBS)
################################################################################
# Source
################################################################################
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/external)
SET(packjpg_sources
${CMAKE_CURRENT_SOURCE_DIR}/src/aricoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/bitops.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/packjpg.cpp
)
################################################################################
# Target: shared library
################################################################################
ADD_LIBRARY(packjpg SHARED ${packjpg_sources} "${CMAKE_CURRENT_SOURCE_DIR}/src/packjpg.h")
SET_TARGET_PROPERTIES(packjpg PROPERTIES
CXX_STANDARD 17
PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/packjpg.h")
INSTALL(TARGETS packjpg
LIBRARY DESTINATION ${LIBRARY_INSTALL_PATH})
INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/packjpg.h" DESTINATION "usr/include")
################################################################################
# Target: static library
################################################################################
ADD_LIBRARY(packjpg_static STATIC ${packjpg_sources} "${CMAKE_CURRENT_SOURCE_DIR}/src/packjpg.h")
SET_TARGET_PROPERTIES(packjpg_static PROPERTIES OUTPUT_NAME "packjpg")
SET_TARGET_PROPERTIES(packjpg_static PROPERTIES
CXX_STANDARD 17
PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/packjpg.h")
INSTALL(TARGETS packjpg_static
ARCHIVE DESTINATION "${LIBRARY_INSTALL_PATH}"
PUBLIC_HEADER DESTINATION "usr/include")
################################################################################
# Target: simple utility
################################################################################
ADD_EXECUTABLE(packjpg_simple
${CMAKE_CURRENT_SOURCE_DIR}/src/bin/packjpg_simple.cc)
TARGET_LINK_LIBRARIES(packjpg_simple packjpg )
lib_src/src/aricoder.cpp
#include "aricoder.h"
#include "bitops.h"
#include <algorithm>
#include <cstdlib>
#include <functional>
#include <limits>
template <std::uint8_t bit>
void ArithmeticBitWriter::write_bit()
{
// add bit at last position
curr_byte_ = (curr_byte_ << 1) | bit;
// increment bit position
curr_bit_++;
// write bit if done
if (curr_bit_ == 8)
{
data_.emplace_back(curr_byte_);
curr_bit_ = 0;
}
}
void ArithmeticBitWriter::write_n_zero_bits(std::size_t n)
{
if (n + curr_bit_ >= 8)
{
auto remainingBits = 8 - curr_bit_;
n -= remainingBits;
curr_byte_ <<= remainingBits;
data_.emplace_back(curr_byte_);
curr_bit_ = 0;
}
while (n >= 8)
{
data_.emplace_back(0);
n -= 8;
}
curr_byte_ <<= n;
curr_bit_ += n;
}
void ArithmeticBitWriter::write_n_one_bits(std::size_t n)
{
constexpr std::uint8_t all_ones = std::numeric_limits<std::uint8_t>::max();
if (n + curr_bit_ >= 8)
{
auto remainingBits = 8 - curr_bit_;
n -= remainingBits;
curr_byte_ <<= remainingBits;
curr_byte_ |= all_ones >> (8 - remainingBits);
data_.emplace_back(curr_byte_);
curr_bit_ = 0;
}
while (n >= 8)
{
data_.emplace_back(all_ones);
n -= 8;
}
curr_byte_ = (curr_byte_ << n) | (all_ones >> (8 - n));
curr_bit_ += n;
}
void ArithmeticBitWriter::pad()
{
while (curr_bit_ > 0)
{
write_bit<0>();
}
}
std::vector<std::uint8_t> ArithmeticBitWriter::get_data() const
{
return data_;
}
ArithmeticDecoder::ArithmeticDecoder(Reader& reader) : reader_(reader)
{
// code buffer has to be filled before starting decoding
for (std::uint32_t i = 0; i < CODER_USE_BITS; i++)
{
ccode = (ccode << 1) | read_bit();
}
}
ArithmeticEncoder::ArithmeticEncoder(Writer& writer) : writer_(writer) {}
ArithmeticEncoder::~ArithmeticEncoder()
{
if (!finalized)
{
this->finalize();
}
}
void ArithmeticEncoder::finalize()
{
if (finalized)
{
return;
}
// due to clow < CODER_LIMIT050, and chigh >= CODER_LIMIT050
// there are only two possible cases
if (clow < CODER_LIMIT025)
{
bitwriter_->write_bit<0>();
bitwriter_->write_bit<1>();
bitwriter_->write_n_one_bits(nrbits);
nrbits = 0;
}
else
{
// case b.), clow >= CODER_LIMIT025
bitwriter_->write_bit<1>();
}
// done, zeroes are auto-read by the decoder
bitwriter_->pad(); // Pad code with zeroes.
writer_.write(bitwriter_->get_data());
finalized = true;
}
/* -----------------------------------------------
arithmetic encoder function
----------------------------------------------- */
void ArithmeticEncoder::encode(symbol* s)
{
// Make local copies of clow_ and chigh_ for cache performance:
uint32_t clow_local = clow;
uint32_t chigh_local = chigh;
// update steps, low count, high count
cstep = (chigh_local - clow_local + 1) / s->scale;
chigh_local = clow_local + (cstep * s->high_count) - 1;
clow_local = clow_local + (cstep * s->low_count);
// e3 scaling is performed for speed and to avoid underflows
// if both, low and high are either in the lower half or in the higher half
// one bit can be safely shifted out
while (clow_local >= CODER_LIMIT050 || chigh_local < CODER_LIMIT050)
{
if (chigh_local < CODER_LIMIT050) // this means both, high and low are below, and 0 can be safely shifted out
{
// write 0 bit
bitwriter_->write_bit<0>();
// shift out remaing e3 bits
bitwriter_->write_n_one_bits(nrbits);
nrbits = 0;
}
else // if the first wasn't the case, it's clow >= CODER_LIMIT050
{
// write 1 bit
bitwriter_->write_bit<1>();
clow_local &= CODER_LIMIT050 - 1;
chigh_local &= CODER_LIMIT050 - 1;
// shift out remaing e3 bits
bitwriter_->write_n_zero_bits(nrbits);
nrbits = 0;
}
clow_local <<= 1;
chigh_local <<= 1;
chigh_local++;
}
// e3 scaling, to make sure that theres enough space between low and high
while ((clow_local >= CODER_LIMIT025) && (chigh_local < CODER_LIMIT075))
{
nrbits++;
clow_local &= CODER_LIMIT025 - 1;
chigh_local ^= CODER_LIMIT025 + CODER_LIMIT050;
// clow -= CODER_LIMIT025;
// chigh -= CODER_LIMIT025;
clow_local <<= 1;
chigh_local <<= 1;
chigh_local++;
}
clow = clow_local;
chigh = chigh_local;
}
/* -----------------------------------------------
arithmetic decoder get count function
----------------------------------------------- */
unsigned int ArithmeticDecoder::decode_count(symbol* s)
{
// update cstep, which is needed to remove the symbol from the stream later
cstep = ((chigh - clow) + 1) / s->scale;
// return counts, needed to decode the symbol from the statistical model
return (ccode - clow) / cstep;
}
/* -----------------------------------------------
arithmetic decoder function
----------------------------------------------- */
void ArithmeticDecoder::decode(symbol* s)
{
// no actual decoding takes place, as this has to happen in the statistical model
// the symbol has to be removed from the stream, though
// alread have steps updated from decoder_count
// update low count and high count
uint32_t ccode_local = ccode;
uint32_t clow_local = clow;
uint32_t chigh_local = clow_local + (cstep * s->high_count) - 1;
clow_local = clow_local + (cstep * s->low_count);
// e3 scaling is performed for speed and to avoid underflows
// if both, low and high are either in the lower half or in the higher half
// one bit can be safely shifted out
while ((clow_local >= CODER_LIMIT050) || (chigh_local < CODER_LIMIT050))
{
if (clow_local >= CODER_LIMIT050)
{
clow_local &= CODER_LIMIT050 - 1;
chigh_local &= CODER_LIMIT050 - 1;
ccode_local &= CODER_LIMIT050 - 1;
} // if the first wasn't the case, it's chigh < CODER_LIMIT050
clow_local <<= 1;
chigh_local <<= 1;
chigh_local++;
ccode_local <<= 1;
ccode_local |= read_bit();
}
// e3 scaling, to make sure that theres enough space between low and high
while ((clow_local >= CODER_LIMIT025) && (chigh_local < CODER_LIMIT075))
{
clow_local &= CODER_LIMIT025 - 1;
chigh_local ^= CODER_LIMIT025 + CODER_LIMIT050;
// clow -= CODER_LIMIT025;
// chigh -= CODER_LIMIT025;
ccode_local -= CODER_LIMIT025;
clow_local <<= 1;
chigh_local <<= 1;
chigh_local++;
ccode_local <<= 1;
ccode_local |= read_bit();
}
chigh = chigh_local;
clow = clow_local;
ccode = ccode_local;
}
/* -----------------------------------------------
bit reader function
----------------------------------------------- */
unsigned char ArithmeticDecoder::read_bit()
{
// read in new byte if needed
if (cbit == 0)
{
if (!reader_.read_byte(&bbyte)) // read next byte if available
{
bbyte = 0; // if no more data is left in the stream
}
cbit = 8;
}
// decrement current bit position
cbit--;
// return bit at cbit position
return BITN(bbyte, cbit);
}
/* -----------------------------------------------
universal statistical model for arithmetic coding
boundaries of this model:
max_s (maximum symbol) -> 1 <= max_s <= 1024 (???)
max_c (maximum context) -> 1 <= max_c <= 1024 (???)
max_o (maximum order) -> -1 <= max_o <= 4
c_lim (maximum count) -> 2 <= c_lim <= 4096 (???)
WARNING: this can be memory intensive, so don't overdo it
max_s == 256; max_c == 256; max_o == 4 would be way too much
----------------------------------------------- */
model_s::model_s(int max_s, int max_c, int max_o, int c_lim) :
// Copy settings into the model:
max_symbol(max_s),
max_context(max_c),
max_order(max_o + 1),
max_count(c_lim),
current_order(max_o + 1),
sb0_count(max_s),
totals(max_s + 2),
scoreboard(new bool[max_s]),
contexts(max_o + 3)
{
std::fill(scoreboard, scoreboard + max_symbol, false);
// set up null table
table_s* null_table = new table_s;
null_table->counts = std::vector<uint16_t>(max_symbol, uint16_t(1)); // Set all probabilities to 1.
// set up internal counts
null_table->max_count = 1;
null_table->max_symbol = max_symbol;
// set up start table
table_s* start_table = new table_s;
start_table->links = std::vector<table_s*>(max_context);
// integrate tables into contexts
contexts[ 0 ] = null_table;
contexts[ 1 ] = start_table;
// build initial 'normal' tables
for (int i = 2; i <= max_order; i++)
{
// set up current order table
contexts[i] = new table_s;
// build forward links
if (i < max_order)
{
contexts[i]->links = std::vector<table_s*>(max_context);
}
contexts[ i - 1 ]->links[ 0 ] = contexts[ i ];
}
}
/* -----------------------------------------------
model class destructor - recursive cleanup of memory is done here
----------------------------------------------- */
model_s::~model_s()
{
// clean up each 'normal' table
delete contexts[1];
// clean up null table
delete contexts[0];
// free everything else
delete[] scoreboard;
}
/* -----------------------------------------------
Updates statistics for a specific symbol / resets to highest order.
Use -1 if you just want to reset without updating statistics.
----------------------------------------------- */
void model_s::update_model(int symbol)
{
// only contexts, that were actually used to encode
// the symbol get its count updated
if (symbol >= 0)
{
for (int local_order = (current_order < 1) ? 1 : current_order;
local_order <= max_order; local_order++)
{
table_s* context = contexts[ local_order ];
auto& count = context->counts[symbol];
// update count for specific symbol & scale
count++;
// store side information for totalize_table
context->max_count = std::max(count, context->max_count);
context->max_symbol = std::max(uint16_t(symbol + 1), context->max_symbol);
// if count for that symbol have gone above the maximum count
// the table has to be resized (scale factor 2)
if (count == max_count)
{
context->rescale_table();
}
}
}
// reset scoreboard and current order
current_order = max_order;
std::fill(scoreboard, scoreboard + max_symbol, false);
sb0_count = max_symbol;
}
/* -----------------------------------------------
shift in one context (max no of contexts is max_c)
----------------------------------------------- */
void model_s::shift_context(int c)
{
// shifting is not possible if max_order is below 1
// or context index is negative
if ((max_order < 2) || (c < 0))
{
return;
}
// shift each orders' context
for (int i = max_order; i > 1; i--)
{
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff