Initial commit
This commit is contained in:
+73
@@ -0,0 +1,73 @@
|
|||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
|
project(libXISF LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||||
|
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
||||||
|
|
||||||
|
add_library(XISF SHARED
|
||||||
|
libXISF_global.h
|
||||||
|
libxisf.cpp
|
||||||
|
libxisf.h
|
||||||
|
lz4/lz4.c
|
||||||
|
lz4/lz4.h
|
||||||
|
lz4/lz4hc.c
|
||||||
|
lz4/lz4hc.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(XISF PRIVATE Qt${QT_VERSION_MAJOR}::Core)
|
||||||
|
|
||||||
|
target_compile_definitions(XISF PRIVATE LIBXISF_LIBRARY)
|
||||||
|
|
||||||
|
set_target_properties(XISF PROPERTIES PUBLIC_HEADER libxisf.h)
|
||||||
@@ -0,0 +1,674 @@
|
|||||||
|
GNU 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.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. 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
|
||||||
|
them 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 prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. 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.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey 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;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If 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 convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU 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 that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
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.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
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
|
||||||
|
state 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) {year} {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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
{project} Copyright (C) {year} {fullname}
|
||||||
|
This program 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, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU 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 Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
LibXISF
|
||||||
|
=========
|
||||||
|
|
||||||
|
LibXISF is C++ library that can read and write XISF files produced by [PixInsight](https://pixinsight.com/).
|
||||||
|
It implement [XISF 1.0 specification](https://pixinsight.com/doc/docs/XISF-1.0-spec/XISF-1.0-spec.html).
|
||||||
|
It is licensed under GPLv3. To compile you will need Qt5 Core.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef LIBXISF_GLOBAL_H
|
||||||
|
#define LIBXISF_GLOBAL_H
|
||||||
|
|
||||||
|
#include <QtCore/qglobal.h>
|
||||||
|
|
||||||
|
#if defined(LIBXISF_LIBRARY)
|
||||||
|
# define LIBXISF_EXPORT Q_DECL_EXPORT
|
||||||
|
#else
|
||||||
|
# define LIBXISF_EXPORT Q_DECL_IMPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // LIBXISF_GLOBAL_H
|
||||||
+754
@@ -0,0 +1,754 @@
|
|||||||
|
#include "libxisf.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QtEndian>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "lz4/lz4.h"
|
||||||
|
#include "lz4/lz4hc.h"
|
||||||
|
|
||||||
|
#define STRING_ENUM(e) {#e, e}
|
||||||
|
|
||||||
|
namespace LibXISF
|
||||||
|
{
|
||||||
|
|
||||||
|
static std::unordered_map<const char*, int> typeToId;
|
||||||
|
static std::unordered_map<int, const char*> idToType;
|
||||||
|
|
||||||
|
static void byteShuffle(QByteArray &data, int itemSize)
|
||||||
|
{
|
||||||
|
if(itemSize > 1)
|
||||||
|
{
|
||||||
|
QByteArray &input = data;
|
||||||
|
QByteArray output(input.size(), 0);
|
||||||
|
int num = input.size() / itemSize;
|
||||||
|
char *s = output.data();
|
||||||
|
for(int i=0; i<itemSize; i++)
|
||||||
|
{
|
||||||
|
const char *u = input.constData() + i;
|
||||||
|
for(int o=0; o<num; o++, s++, u += itemSize)
|
||||||
|
*s = *u;
|
||||||
|
}
|
||||||
|
memcpy(s, input.constData() + num * itemSize, input.size() % itemSize);
|
||||||
|
data = output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void byteUnshuffle(QByteArray &data, int itemSize)
|
||||||
|
{
|
||||||
|
if(itemSize > 1)
|
||||||
|
{
|
||||||
|
QByteArray &input = data;
|
||||||
|
QByteArray output(input.size(), 0);
|
||||||
|
int num = input.size() / itemSize;
|
||||||
|
const char *s = input.constData();
|
||||||
|
for(int i=0; i<itemSize; i++)
|
||||||
|
{
|
||||||
|
char *u = output.data() + i;
|
||||||
|
for(int o=0; o<num; o++, s++, u += itemSize)
|
||||||
|
*u = *s;
|
||||||
|
}
|
||||||
|
memcpy(output.data() + num * itemSize, s, input.size() % itemSize);
|
||||||
|
data = output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString sampleFormatToString(Image::SampleFormat format)
|
||||||
|
{
|
||||||
|
static QStringList sampleFormats = {"UInt8", "UInt16", "UInt32", "UInt64", "Float32", "Float64", "Complex32", "Complex64"};
|
||||||
|
return sampleFormats[format];
|
||||||
|
}
|
||||||
|
|
||||||
|
QString colorSpaceToString(Image::ColorSpace colorSpace)
|
||||||
|
{
|
||||||
|
static QStringList colorSpaces = {"Gray", "RGB", "CIELab"};
|
||||||
|
return colorSpaces[colorSpace];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataBlock::decompress(const QByteArray &input, const QString &encoding)
|
||||||
|
{
|
||||||
|
QByteArray tmp = input;
|
||||||
|
|
||||||
|
if(encoding == "base64")
|
||||||
|
tmp = QByteArray::fromBase64(tmp);
|
||||||
|
else if(encoding == "base16")
|
||||||
|
tmp = QByteArray::fromHex(tmp);
|
||||||
|
|
||||||
|
switch(codec)
|
||||||
|
{
|
||||||
|
case None:
|
||||||
|
data = tmp;
|
||||||
|
break;
|
||||||
|
case Zlib:
|
||||||
|
{
|
||||||
|
uint32_t size;
|
||||||
|
qToBigEndian<uint32_t>(uncompressedSize, &size);
|
||||||
|
tmp.prepend((char*)&size, sizeof(size));
|
||||||
|
data = qUncompress(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LZ4:
|
||||||
|
case LZ4HC:
|
||||||
|
data.resize(uncompressedSize);
|
||||||
|
if(LZ4_decompress_safe(tmp.constData(), data.data(), tmp.size(), data.size()) < 0)
|
||||||
|
throw std::runtime_error("LZ4 decompression failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
byteUnshuffle(data, byteShuffling);
|
||||||
|
attachmentPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataBlock::compress()
|
||||||
|
{
|
||||||
|
QByteArray tmp = data;
|
||||||
|
uncompressedSize = data.size();
|
||||||
|
|
||||||
|
byteShuffle(tmp, byteShuffling);
|
||||||
|
|
||||||
|
switch(codec)
|
||||||
|
{
|
||||||
|
case None:
|
||||||
|
data = tmp;
|
||||||
|
break;
|
||||||
|
case Zlib:
|
||||||
|
data = qCompress(tmp);
|
||||||
|
data.remove(0, sizeof(uint32_t));
|
||||||
|
break;
|
||||||
|
case LZ4:
|
||||||
|
case LZ4HC:
|
||||||
|
{
|
||||||
|
int compSize = 0;
|
||||||
|
data.resize(LZ4_compressBound(tmp.size()));
|
||||||
|
if(codec == LZ4)
|
||||||
|
compSize = LZ4_compress_default(tmp.constData(), data.data(), tmp.size(), data.size());
|
||||||
|
else
|
||||||
|
compSize = LZ4_compress_HC(tmp.constData(), data.data(), tmp.size(), data.size(), LZ4HC_CLEVEL_DEFAULT);
|
||||||
|
|
||||||
|
if(compSize <= 0)
|
||||||
|
throw std::runtime_error("LZ4 compression failed");
|
||||||
|
|
||||||
|
data.resize(compSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void planarToNormal(void *_in, void *_out, size_t channels, size_t size)
|
||||||
|
{
|
||||||
|
T *in = static_cast<T*>(_in);
|
||||||
|
T *out = static_cast<T*>(_out);
|
||||||
|
for(size_t i=0; i<size; i++)
|
||||||
|
for(size_t o=0; o<channels; o++)
|
||||||
|
out[i*channels + o] = in[o*size + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void normalToPlanar(void *_in, void *_out, size_t channels, size_t size)
|
||||||
|
{
|
||||||
|
T *in = static_cast<T*>(_in);
|
||||||
|
T *out = static_cast<T*>(_out);
|
||||||
|
for(size_t i=0; i<size; i++)
|
||||||
|
for(size_t o=0; o<channels; o++)
|
||||||
|
out[o*size + i] = in[i*channels + o];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::convertPixelStorageTo(PixelStorage storage)
|
||||||
|
{
|
||||||
|
if(pixelStorage == storage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QByteArray tmp;
|
||||||
|
tmp.resize(dataBlock.data.size());
|
||||||
|
size_t size = width*height;
|
||||||
|
|
||||||
|
switch(sampleFormat)
|
||||||
|
{
|
||||||
|
case UInt8:
|
||||||
|
if(storage == Normal)
|
||||||
|
planarToNormal<uint8_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
else
|
||||||
|
normalToPlanar<uint8_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
break;
|
||||||
|
case UInt16:
|
||||||
|
if(storage == Normal)
|
||||||
|
planarToNormal<uint16_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
else
|
||||||
|
normalToPlanar<uint16_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
break;
|
||||||
|
case UInt32:
|
||||||
|
case Float32:
|
||||||
|
if(storage == Normal)
|
||||||
|
planarToNormal<uint32_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
else
|
||||||
|
normalToPlanar<uint32_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
break;
|
||||||
|
case UInt64:
|
||||||
|
case Float64:
|
||||||
|
if(storage == Normal)
|
||||||
|
planarToNormal<uint64_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
else
|
||||||
|
normalToPlanar<uint64_t>(dataBlock.data.data(), tmp.data(), channelCount, size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dataBlock.data = tmp;
|
||||||
|
pixelStorage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::Type Image::imageTypeEnum(const QString &type)
|
||||||
|
{
|
||||||
|
static const std::unordered_map<QString, Image::Type> imageTypeMap = {STRING_ENUM(Bias),
|
||||||
|
STRING_ENUM(Dark),
|
||||||
|
STRING_ENUM(Flat),
|
||||||
|
STRING_ENUM(Light),
|
||||||
|
STRING_ENUM(MasterBias),
|
||||||
|
STRING_ENUM(MasterDark),
|
||||||
|
STRING_ENUM(MasterFlat),
|
||||||
|
STRING_ENUM(DefectMap),
|
||||||
|
STRING_ENUM(RejectionMapHigh),
|
||||||
|
STRING_ENUM(RejectionMapLow),
|
||||||
|
STRING_ENUM(BinaryRejectionMapHigh),
|
||||||
|
STRING_ENUM(BinaryRejectionMapLow),
|
||||||
|
STRING_ENUM(SlopeMap),
|
||||||
|
STRING_ENUM(WeightMap});
|
||||||
|
auto t = imageTypeMap.find(type);
|
||||||
|
return t != imageTypeMap.end() ? t->second : Image::Light;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::PixelStorage Image::pixelStorageEnum(const QString &storage)
|
||||||
|
{
|
||||||
|
if(storage == "Normal")return Image::Normal;
|
||||||
|
return Image::Planar;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::SampleFormat Image::sampleFormatEnum(const QString &format)
|
||||||
|
{
|
||||||
|
static const std::unordered_map<QString, SampleFormat> sampleFormatMap = {STRING_ENUM(UInt8),
|
||||||
|
STRING_ENUM(UInt16),
|
||||||
|
STRING_ENUM(UInt32),
|
||||||
|
STRING_ENUM(UInt64),
|
||||||
|
STRING_ENUM(Float32),
|
||||||
|
STRING_ENUM(Float64),
|
||||||
|
STRING_ENUM(Complex32),
|
||||||
|
STRING_ENUM(Complex64)};
|
||||||
|
auto t = sampleFormatMap.find(format);
|
||||||
|
return t != sampleFormatMap.end() ? t->second : Image::UInt16;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::ColorSpace Image::colorSpaceEnum(const QString &colorSpace)
|
||||||
|
{
|
||||||
|
static const std::unordered_map<QString, ColorSpace> colorSpaceMap = { STRING_ENUM(Gray), STRING_ENUM(RGB), STRING_ENUM(CIELab) };
|
||||||
|
auto t = colorSpaceMap.find(colorSpace);
|
||||||
|
return t != colorSpaceMap.end() ? t->second : Image::Gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
XISFReader::XISFReader()
|
||||||
|
{
|
||||||
|
_xml = std::make_unique<QXmlStreamReader>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::open(const QString &name)
|
||||||
|
{
|
||||||
|
QFile *fr = new QFile(name);
|
||||||
|
open(fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::open(const QByteArray &data)
|
||||||
|
{
|
||||||
|
QBuffer *buffer = new QBuffer();
|
||||||
|
buffer->setData(data);
|
||||||
|
open(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::open(QIODevice *io)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
_io.reset(io);
|
||||||
|
if(!_io->open(QIODevice::ReadOnly))
|
||||||
|
throw std::runtime_error("Failed to open file");
|
||||||
|
|
||||||
|
readSignature();
|
||||||
|
readXISFHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::close()
|
||||||
|
{
|
||||||
|
_xml->clear();
|
||||||
|
_io.reset();
|
||||||
|
_images.clear();
|
||||||
|
_properties.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int XISFReader::imagesCount() const
|
||||||
|
{
|
||||||
|
return _images.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Image& XISFReader::getImage(uint32_t n)
|
||||||
|
{
|
||||||
|
if(n >= _images.size())
|
||||||
|
throw std::runtime_error("Out of bounds");
|
||||||
|
|
||||||
|
Image &img = _images[n];
|
||||||
|
if(img.dataBlock.attachmentPos)
|
||||||
|
{
|
||||||
|
_io->seek(img.dataBlock.attachmentPos);
|
||||||
|
img.dataBlock.decompress(_io->read(img.dataBlock.attachmentSize));
|
||||||
|
}
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::readXISFHeader()
|
||||||
|
{
|
||||||
|
uint32_t headerLen[2] = {0};
|
||||||
|
_io->read((char*)&headerLen, sizeof(headerLen));
|
||||||
|
|
||||||
|
QByteArray xisfHeader = _io->read(headerLen[0]);
|
||||||
|
_xml->addData(xisfHeader);
|
||||||
|
|
||||||
|
_xml->readNextStartElement();
|
||||||
|
|
||||||
|
if(_xml->name() == "xisf" && _xml->attributes().value("version") == "1.0")
|
||||||
|
{
|
||||||
|
while(!_xml->atEnd())
|
||||||
|
{
|
||||||
|
if(!_xml->readNextStartElement())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(_xml->name() == "Image")
|
||||||
|
readImageElement();
|
||||||
|
else if(_xml->name() == "Property")
|
||||||
|
_properties.push_back(readPropertyElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else throw std::runtime_error("Unknown root XML element");
|
||||||
|
|
||||||
|
if(_xml->hasError())
|
||||||
|
throw std::runtime_error(_xml->errorString().toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::readSignature()
|
||||||
|
{
|
||||||
|
char signature[8];
|
||||||
|
if(_io->read(signature, sizeof(signature)) != sizeof(signature))
|
||||||
|
throw std::runtime_error("Failed to read from file");
|
||||||
|
|
||||||
|
if(memcmp(signature, "XISF0100", sizeof(signature)) != 0)
|
||||||
|
throw std::runtime_error("Not valid XISF 1.0 file");
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::readImageElement()
|
||||||
|
{
|
||||||
|
QXmlStreamAttributes attributes = _xml->attributes();
|
||||||
|
|
||||||
|
Image image;
|
||||||
|
|
||||||
|
QVector<QStringRef> geometry = attributes.value("geometry").split(":");
|
||||||
|
if(geometry.size() != 3)throw std::runtime_error("We support only 2D images");
|
||||||
|
image.width = geometry[0].toULongLong();
|
||||||
|
image.height = geometry[1].toULongLong();
|
||||||
|
image.channelCount = geometry[2].toULongLong();
|
||||||
|
if(!image.width || !image.height || !image.channelCount)throw std::runtime_error("Invalid image geometry");
|
||||||
|
|
||||||
|
QVector<QStringRef> bounds = attributes.value("bounds").split(":");
|
||||||
|
if(bounds.size() == 2)
|
||||||
|
{
|
||||||
|
image.bounds[0] = bounds[0].toDouble();
|
||||||
|
image.bounds[1] = bounds[1].toDouble();
|
||||||
|
}
|
||||||
|
image.imageType = Image::imageTypeEnum(attributes.value("imageType").toString());
|
||||||
|
image.pixelStorage = Image::pixelStorageEnum(attributes.value("pixelStorage").toString());
|
||||||
|
image.sampleFormat = Image::sampleFormatEnum(attributes.value("sampleFormat").toString());
|
||||||
|
image.colorSpace = Image::colorSpaceEnum(attributes.value("colorSpace").toString());
|
||||||
|
|
||||||
|
image.dataBlock = readDataBlock();
|
||||||
|
|
||||||
|
while(_xml->readNext() != QXmlStreamReader::EndElement || _xml->name() != "Image")
|
||||||
|
{
|
||||||
|
if(_xml->tokenType() == QXmlStreamReader::StartElement)
|
||||||
|
{
|
||||||
|
if(_xml->name() == "Property")
|
||||||
|
image.properties.push_back(readPropertyElement());
|
||||||
|
else if(image.dataBlock.embedded && _xml->name() == "Data")
|
||||||
|
readDataElement(image.dataBlock);
|
||||||
|
else if(_xml->name() == "ICCProfile")
|
||||||
|
{
|
||||||
|
DataBlock icc = readDataBlock();
|
||||||
|
image.iccProfile = icc.data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_xml->skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_images.push_back(std::move(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
Property XISFReader::readPropertyElement()
|
||||||
|
{
|
||||||
|
QXmlStreamAttributes attributes = _xml->attributes();
|
||||||
|
Property property;
|
||||||
|
property.id = attributes.value("id").toString();
|
||||||
|
property.format = attributes.value("format").toString();
|
||||||
|
property.comment = attributes.value("comment").toString();
|
||||||
|
|
||||||
|
QStringRef type = attributes.value("type");
|
||||||
|
QStringRef value = attributes.value("value");
|
||||||
|
if(type == "Int8")
|
||||||
|
property.value.setValue((Int8)value.toInt());
|
||||||
|
else if(type == "Int16")
|
||||||
|
property.value.setValue((Int16)value.toInt());
|
||||||
|
else if(type == "Int32")
|
||||||
|
property.value.setValue((Int32)value.toInt());
|
||||||
|
else if(type == "Int64")
|
||||||
|
property.value.setValue((Int64)value.toLongLong());
|
||||||
|
else if(type == "UInt8")
|
||||||
|
property.value.setValue((Int8)value.toInt());
|
||||||
|
else if(type == "UInt16")
|
||||||
|
property.value.setValue((Int16)value.toInt());
|
||||||
|
else if(type == "UInt32")
|
||||||
|
property.value.setValue<UInt32>(value.toUInt());
|
||||||
|
else if(type == "UInt64")
|
||||||
|
property.value.setValue<UInt64>(value.toULongLong());
|
||||||
|
else if(type == "Float32")
|
||||||
|
property.value = value.toFloat();
|
||||||
|
else if(type == "Float64")
|
||||||
|
property.value = value.toDouble();
|
||||||
|
else if(type == "TimePoint")
|
||||||
|
property.value = QDateTime::fromString(value.toString(), Qt::ISODate);
|
||||||
|
else if(type == "String")
|
||||||
|
{
|
||||||
|
if(attributes.hasAttribute("location"))
|
||||||
|
{
|
||||||
|
DataBlock dataBlock = readDataBlock();
|
||||||
|
if(dataBlock.embedded)
|
||||||
|
readDataElement(dataBlock);
|
||||||
|
property.value = QString::fromUtf8(dataBlock.data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
property.value = _xml->readElementText();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
property.value = value.toString();
|
||||||
|
|
||||||
|
qDebug() << property.id << type << property.value.typeName() << property.value;
|
||||||
|
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::readDataElement(DataBlock &dataBlock)
|
||||||
|
{
|
||||||
|
readCompression(dataBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBlock XISFReader::readDataBlock()
|
||||||
|
{
|
||||||
|
DataBlock dataBlock;
|
||||||
|
QXmlStreamAttributes attributes = _xml->attributes();
|
||||||
|
QVector<QStringRef> location = attributes.value("location").split(":");
|
||||||
|
|
||||||
|
readCompression(dataBlock);
|
||||||
|
|
||||||
|
if(location.size() && location[0] == "embedded")
|
||||||
|
{
|
||||||
|
dataBlock.embedded = true;
|
||||||
|
}
|
||||||
|
else if(location.size() >= 2 && location[0] == "inline")
|
||||||
|
{
|
||||||
|
QByteArray text = _xml->readElementText().toUtf8();
|
||||||
|
dataBlock.decompress(text, location[1].toString());
|
||||||
|
}
|
||||||
|
else if(location.size() >= 3 && location[0] == "attachment")
|
||||||
|
{
|
||||||
|
bool ok1, ok2;
|
||||||
|
dataBlock.attachmentPos = location[1].toULongLong(&ok1);
|
||||||
|
dataBlock.attachmentSize = location[2].toULongLong(&ok2);
|
||||||
|
if(!ok1 || !ok2)throw std::runtime_error("Invalid attachment");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid data block");
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFReader::readCompression(DataBlock &dataBlock)
|
||||||
|
{
|
||||||
|
QVector<QStringRef> compression = _xml->attributes().value("compression").split(":");
|
||||||
|
if(compression.size() >= 2)
|
||||||
|
{
|
||||||
|
if(compression[0].startsWith("zlib"))
|
||||||
|
dataBlock.codec = DataBlock::Zlib;
|
||||||
|
else if(compression[0].startsWith("lz4hc"))
|
||||||
|
dataBlock.codec = DataBlock::LZ4HC;
|
||||||
|
else if(compression[0].startsWith("lz4"))
|
||||||
|
dataBlock.codec = DataBlock::LZ4;
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Unknown compression codec");
|
||||||
|
|
||||||
|
dataBlock.uncompressedSize = compression[1].toULongLong();
|
||||||
|
|
||||||
|
if(compression[0].endsWith("+sh"))
|
||||||
|
{
|
||||||
|
if(compression.size() == 3)
|
||||||
|
dataBlock.byteShuffling = compression[2].toInt();
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Missing byte shuffling size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XISFWriter::XISFWriter()
|
||||||
|
{
|
||||||
|
_xml = std::make_unique<QXmlStreamWriter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::save(const QString &name)
|
||||||
|
{
|
||||||
|
QFile fw(name);
|
||||||
|
|
||||||
|
if(!fw.open(QIODevice::WriteOnly))
|
||||||
|
throw std::runtime_error("Failed to open file");
|
||||||
|
|
||||||
|
save(fw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::save(QByteArray &data)
|
||||||
|
{
|
||||||
|
QBuffer buffer(&data);
|
||||||
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
save(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::save(QIODevice &io)
|
||||||
|
{
|
||||||
|
writeHeader();
|
||||||
|
|
||||||
|
io.write(_xisfHeader);
|
||||||
|
|
||||||
|
for(auto &image : _images)
|
||||||
|
{
|
||||||
|
io.write(image.dataBlock.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::writeImage(const Image &image)
|
||||||
|
{
|
||||||
|
_images.push_back(image);
|
||||||
|
_images.back().dataBlock.attachmentPos = 1;
|
||||||
|
_images.back().dataBlock.compress();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::writeHeader()
|
||||||
|
{
|
||||||
|
const char signature[16] = {'X', 'I', 'S', 'F', '0', '1', '0', '0', 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
QBuffer buffer(&_xisfHeader);
|
||||||
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
buffer.write(signature, sizeof(signature));
|
||||||
|
|
||||||
|
_xml->setDevice(&buffer);
|
||||||
|
|
||||||
|
_xml->writeStartDocument();
|
||||||
|
_xml->writeComment("\nExtensible Image Serialization Format - XISF version 1.0\nCreated with libXISF - https://nouspiro.space\n");
|
||||||
|
_xml->writeStartElement("xisf");
|
||||||
|
_xml->writeAttribute("version", "1.0");
|
||||||
|
_xml->writeDefaultNamespace("http://www.pixinsight.com/xisf");
|
||||||
|
_xml->writeNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi");
|
||||||
|
_xml->writeAttribute("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "http://www.pixinsight.com/xisf http://pixinsight.com/xisf/xisf-1.0.xsd");
|
||||||
|
|
||||||
|
for(Image &image : _images)
|
||||||
|
{
|
||||||
|
writeImageElement(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeMetadata();
|
||||||
|
|
||||||
|
_xml->writeEndElement();
|
||||||
|
|
||||||
|
uint32_t size = _xisfHeader.size();
|
||||||
|
QByteArray blockPos = QByteArray::number(size);
|
||||||
|
_xisfHeader.replace("#########", blockPos);
|
||||||
|
uint32_t headerSize = _xisfHeader.size() - sizeof(signature);
|
||||||
|
_xisfHeader.append(size - _xisfHeader.size(), '\0');
|
||||||
|
|
||||||
|
|
||||||
|
buffer.seek(8);
|
||||||
|
buffer.write((char*)&headerSize, sizeof(size));
|
||||||
|
|
||||||
|
_xml->writeEndDocument();
|
||||||
|
|
||||||
|
if(_xml->hasError())
|
||||||
|
throw std::runtime_error("Failed to write XML header");
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::writeImageElement(const Image &image)
|
||||||
|
{
|
||||||
|
_xml->writeStartElement("Image");
|
||||||
|
_xml->writeAttribute("geometry", QString("%1:%2:%3").arg(image.width).arg(image.height).arg(image.channelCount));
|
||||||
|
_xml->writeAttribute("sampleFormat", sampleFormatToString(image.sampleFormat));
|
||||||
|
_xml->writeAttribute("colorSpace", colorSpaceToString(image.colorSpace));
|
||||||
|
writeDataBlockAttributes(image.dataBlock);
|
||||||
|
for(auto &property : image.properties)
|
||||||
|
writePropertyElement(property);
|
||||||
|
|
||||||
|
_xml->writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::writeDataBlockAttributes(const DataBlock &dataBlock)
|
||||||
|
{
|
||||||
|
writeCompressionAttributes(dataBlock);
|
||||||
|
|
||||||
|
if(dataBlock.embedded)
|
||||||
|
{
|
||||||
|
_xml->writeAttribute("location", "embedded");
|
||||||
|
}
|
||||||
|
else if(dataBlock.attachmentPos == 0)
|
||||||
|
{
|
||||||
|
_xml->writeAttribute("location", QString("inline:base64"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_xml->writeAttribute("location", QString("attachment:#########:%1").arg(dataBlock.data.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::writeCompressionAttributes(const DataBlock &dataBlock)
|
||||||
|
{
|
||||||
|
QString codec;
|
||||||
|
|
||||||
|
if(dataBlock.codec == DataBlock::Zlib)
|
||||||
|
codec = "zlib";
|
||||||
|
else if(dataBlock.codec == DataBlock::LZ4)
|
||||||
|
codec = "lz4";
|
||||||
|
else if(dataBlock.codec == DataBlock::LZ4HC)
|
||||||
|
codec = "lz4hc";
|
||||||
|
|
||||||
|
if(dataBlock.byteShuffling > 1)
|
||||||
|
codec += "+sh";
|
||||||
|
|
||||||
|
if(!codec.isEmpty())
|
||||||
|
{
|
||||||
|
codec += QString(":%1").arg(dataBlock.uncompressedSize);
|
||||||
|
if(dataBlock.byteShuffling > 1)
|
||||||
|
codec += QString(":%1").arg(dataBlock.byteShuffling);
|
||||||
|
|
||||||
|
_xml->writeAttribute("compression", codec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::writePropertyElement(const Property &property)
|
||||||
|
{
|
||||||
|
_xml->writeStartElement("Property");
|
||||||
|
_xml->writeAttribute("id", property.id);
|
||||||
|
_xml->writeAttribute("type", idToType[property.value.type()]);
|
||||||
|
|
||||||
|
if(!property.format.isEmpty())
|
||||||
|
_xml->writeAttribute("format", property.format);
|
||||||
|
|
||||||
|
if(!property.comment.isEmpty())
|
||||||
|
_xml->writeAttribute("comment", property.comment);
|
||||||
|
|
||||||
|
if((QMetaType::Type)property.value.type() == QMetaType::QString)
|
||||||
|
_xml->writeCharacters(property.value.toString());
|
||||||
|
else
|
||||||
|
_xml->writeAttribute("value", property.value.toString());
|
||||||
|
_xml->writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XISFWriter::writeMetadata()
|
||||||
|
{
|
||||||
|
_xml->writeStartElement("Metadata");
|
||||||
|
|
||||||
|
writePropertyElement({"XISF:CreationTime", QDateTime::currentDateTimeUtc().toString(Qt::ISODate), QString(), QString()});
|
||||||
|
|
||||||
|
_xml->writeStartElement("Property");
|
||||||
|
_xml->writeAttribute("id", "XISF:CreatorApplication");
|
||||||
|
_xml->writeAttribute("type", "String");
|
||||||
|
_xml->writeCharacters("LibXISF");
|
||||||
|
_xml->writeEndElement();
|
||||||
|
|
||||||
|
_xml->writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define REGISTER_METATYPE(type) qRegisterMetaType<type>("LibXISF::"#type); \
|
||||||
|
typeToId.insert({#type, QMetaType::fromType<type>().id()}); \
|
||||||
|
idToType.insert({QMetaType::fromType<type>().id(), #type})
|
||||||
|
|
||||||
|
struct TypesInit
|
||||||
|
{
|
||||||
|
TypesInit()
|
||||||
|
{
|
||||||
|
REGISTER_METATYPE(Boolean);
|
||||||
|
REGISTER_METATYPE(Int8);
|
||||||
|
REGISTER_METATYPE(UInt8);
|
||||||
|
REGISTER_METATYPE(Int16);
|
||||||
|
REGISTER_METATYPE(UInt16);
|
||||||
|
REGISTER_METATYPE(Int32);
|
||||||
|
REGISTER_METATYPE(UInt32);
|
||||||
|
REGISTER_METATYPE(Int64);
|
||||||
|
REGISTER_METATYPE(UInt64);
|
||||||
|
REGISTER_METATYPE(Float32);
|
||||||
|
REGISTER_METATYPE(Float64);
|
||||||
|
REGISTER_METATYPE(Complex32);
|
||||||
|
REGISTER_METATYPE(Complex64);
|
||||||
|
REGISTER_METATYPE(I8Vector);
|
||||||
|
REGISTER_METATYPE(UI8Vector);
|
||||||
|
REGISTER_METATYPE(I16Vector);
|
||||||
|
REGISTER_METATYPE(UI16Vector);
|
||||||
|
REGISTER_METATYPE(I32Vector);
|
||||||
|
REGISTER_METATYPE(UI32Vector);
|
||||||
|
REGISTER_METATYPE(I64Vector);
|
||||||
|
REGISTER_METATYPE(UI64Vector);
|
||||||
|
REGISTER_METATYPE(F32Vector);
|
||||||
|
REGISTER_METATYPE(F64Vector);
|
||||||
|
REGISTER_METATYPE(C32Vector);
|
||||||
|
REGISTER_METATYPE(C64Vector);
|
||||||
|
REGISTER_METATYPE(I8Matrix);
|
||||||
|
REGISTER_METATYPE(UI8Matrix);
|
||||||
|
REGISTER_METATYPE(I16Matrix);
|
||||||
|
REGISTER_METATYPE(UI16Matrix);
|
||||||
|
REGISTER_METATYPE(I32Matrix);
|
||||||
|
REGISTER_METATYPE(UI32Matrix);
|
||||||
|
REGISTER_METATYPE(I64Matrix);
|
||||||
|
REGISTER_METATYPE(UI64Matrix);
|
||||||
|
REGISTER_METATYPE(F32Matrix);
|
||||||
|
REGISTER_METATYPE(F64Matrix);
|
||||||
|
REGISTER_METATYPE(C32Matrix);
|
||||||
|
REGISTER_METATYPE(C64Matrix);
|
||||||
|
REGISTER_METATYPE(String);
|
||||||
|
|
||||||
|
QMetaType::registerConverter<Complex32, QString>([](const Complex32 &c){ return QString("(%1,%2)").arg(c.real).arg(c.imag); });
|
||||||
|
QMetaType::registerConverter<Complex64, QString>([](const Complex64 &c){ return QString("(%1,%2)").arg(c.real).arg(c.imag); });
|
||||||
|
QMetaType::registerConverter<QString, Complex32>([](QString s)
|
||||||
|
{
|
||||||
|
Complex32 c;
|
||||||
|
s.remove('(');
|
||||||
|
s.remove(')');
|
||||||
|
int comma = s.indexOf(',');
|
||||||
|
c.real = s.leftRef(comma).toFloat();
|
||||||
|
c.imag = s.rightRef(comma+1).toFloat();
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
QMetaType::registerConverter<QString, Complex64>([](QString s)
|
||||||
|
{
|
||||||
|
Complex64 c;
|
||||||
|
s.remove('(');
|
||||||
|
s.remove(')');
|
||||||
|
int comma = s.indexOf(',');
|
||||||
|
c.real = s.leftRef(comma).toDouble();
|
||||||
|
c.imag = s.rightRef(comma+1).toDouble();
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static TypesInit typesInit;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
#ifndef LIBXISF_H
|
||||||
|
#define LIBXISF_H
|
||||||
|
|
||||||
|
#include "libXISF_global.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
|
class QXmlStreamReader;
|
||||||
|
|
||||||
|
namespace LibXISF
|
||||||
|
{
|
||||||
|
|
||||||
|
struct DataBlock
|
||||||
|
{
|
||||||
|
enum CompressionCodec
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Zlib,
|
||||||
|
LZ4,
|
||||||
|
LZ4HC
|
||||||
|
};
|
||||||
|
bool embedded = false;
|
||||||
|
uint32_t byteShuffling = 0;
|
||||||
|
uint64_t attachmentPos = 0;
|
||||||
|
uint64_t attachmentSize = 0;
|
||||||
|
uint64_t uncompressedSize = 0;
|
||||||
|
CompressionCodec codec = None;
|
||||||
|
QByteArray data;
|
||||||
|
void decompress(const QByteArray &input, const QString &encoding = "");
|
||||||
|
void compress();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Property
|
||||||
|
{
|
||||||
|
QString id;
|
||||||
|
QVariant value;
|
||||||
|
QString comment;
|
||||||
|
QString format;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Image
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Bias,
|
||||||
|
Dark,
|
||||||
|
Flat,
|
||||||
|
Light,
|
||||||
|
MasterBias,
|
||||||
|
MasterDark,
|
||||||
|
MasterFlat,
|
||||||
|
DefectMap,
|
||||||
|
RejectionMapHigh,
|
||||||
|
RejectionMapLow,
|
||||||
|
BinaryRejectionMapHigh,
|
||||||
|
BinaryRejectionMapLow,
|
||||||
|
SlopeMap,
|
||||||
|
WeightMap
|
||||||
|
};
|
||||||
|
enum PixelStorage
|
||||||
|
{
|
||||||
|
Planar,
|
||||||
|
Normal
|
||||||
|
};
|
||||||
|
enum SampleFormat
|
||||||
|
{
|
||||||
|
UInt8,
|
||||||
|
UInt16,
|
||||||
|
UInt32,
|
||||||
|
UInt64,
|
||||||
|
Float32,
|
||||||
|
Float64,
|
||||||
|
Complex32,
|
||||||
|
Complex64
|
||||||
|
};
|
||||||
|
enum ColorSpace
|
||||||
|
{
|
||||||
|
Gray,
|
||||||
|
RGB,
|
||||||
|
CIELab
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t width = 0;
|
||||||
|
uint64_t height = 0;
|
||||||
|
uint64_t channelCount = 0;
|
||||||
|
double bounds[2] = {0.0, 1.0};
|
||||||
|
Type imageType = Light;
|
||||||
|
PixelStorage pixelStorage = Planar;
|
||||||
|
SampleFormat sampleFormat = UInt16;
|
||||||
|
ColorSpace colorSpace = Gray;
|
||||||
|
DataBlock dataBlock;
|
||||||
|
QByteArray iccProfile;
|
||||||
|
std::vector<Property> properties;
|
||||||
|
|
||||||
|
void convertPixelStorageTo(PixelStorage storage);
|
||||||
|
|
||||||
|
static Type imageTypeEnum(const QString &type);
|
||||||
|
static PixelStorage pixelStorageEnum(const QString &storage);
|
||||||
|
static SampleFormat sampleFormatEnum(const QString &format);
|
||||||
|
static ColorSpace colorSpaceEnum(const QString &colorSpace);
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBXISF_EXPORT XISFReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XISFReader();
|
||||||
|
void open(const QString &name);
|
||||||
|
void open(const QByteArray &data);
|
||||||
|
void open(QIODevice *io);
|
||||||
|
void close();
|
||||||
|
int imagesCount() const;
|
||||||
|
const Image& getImage(uint32_t n);
|
||||||
|
private:
|
||||||
|
void readXISFHeader();
|
||||||
|
void readSignature();
|
||||||
|
void readImageElement();
|
||||||
|
Property readPropertyElement();
|
||||||
|
void readDataElement(DataBlock &dataBlock);
|
||||||
|
DataBlock readDataBlock();
|
||||||
|
void readCompression(DataBlock &dataBlock);
|
||||||
|
|
||||||
|
std::unique_ptr<QIODevice> _io;
|
||||||
|
std::unique_ptr<QXmlStreamReader> _xml;
|
||||||
|
std::vector<Image> _images;
|
||||||
|
std::vector<Property> _properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBXISF_EXPORT XISFWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XISFWriter();
|
||||||
|
void save(const QString &name);
|
||||||
|
void save(QByteArray &data);
|
||||||
|
void save(QIODevice &io);
|
||||||
|
void writeImage(const Image &image);
|
||||||
|
private:
|
||||||
|
void writeHeader();
|
||||||
|
void writeImageElement(const Image &image);
|
||||||
|
void writeDataBlockAttributes(const DataBlock &dataBlock);
|
||||||
|
void writeCompressionAttributes(const DataBlock &dataBlock);
|
||||||
|
void writePropertyElement(const Property &property);
|
||||||
|
void writeMetadata();
|
||||||
|
std::unique_ptr<QXmlStreamWriter> _xml;
|
||||||
|
QByteArray _xisfHeader;
|
||||||
|
QByteArray _attachmentsData;
|
||||||
|
std::vector<Image> _images;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Complex32
|
||||||
|
{
|
||||||
|
float real;
|
||||||
|
float imag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Complex64
|
||||||
|
{
|
||||||
|
double real;
|
||||||
|
double imag;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Matrix
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
std::vector<T> elem;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef bool Boolean;
|
||||||
|
typedef int8_t Int8;
|
||||||
|
typedef uint8_t UInt8;
|
||||||
|
typedef int16_t Int16;
|
||||||
|
typedef uint16_t UInt16;
|
||||||
|
typedef int32_t Int32;
|
||||||
|
typedef uint32_t UInt32;
|
||||||
|
typedef int64_t Int64;
|
||||||
|
typedef uint64_t UInt64;
|
||||||
|
typedef float Float32;
|
||||||
|
typedef double Float64;
|
||||||
|
typedef QDateTime TimePoint;
|
||||||
|
typedef std::vector<int8_t> I8Vector;
|
||||||
|
typedef std::vector<uint8_t> UI8Vector;
|
||||||
|
typedef std::vector<int16_t> I16Vector;
|
||||||
|
typedef std::vector<uint16_t> UI16Vector;
|
||||||
|
typedef std::vector<int32_t> I32Vector;
|
||||||
|
typedef std::vector<uint32_t> UI32Vector;
|
||||||
|
typedef std::vector<int64_t> I64Vector;
|
||||||
|
typedef std::vector<uint64_t> UI64Vector;
|
||||||
|
typedef std::vector<float> F32Vector;
|
||||||
|
typedef std::vector<double> F64Vector;
|
||||||
|
typedef std::vector<Complex32> C32Vector;
|
||||||
|
typedef std::vector<Complex64> C64Vector;
|
||||||
|
typedef Matrix<Int8> I8Matrix;
|
||||||
|
typedef Matrix<UInt8> UI8Matrix;
|
||||||
|
typedef Matrix<Int16> I16Matrix;
|
||||||
|
typedef Matrix<UInt16> UI16Matrix;
|
||||||
|
typedef Matrix<Int32> I32Matrix;
|
||||||
|
typedef Matrix<UInt32> UI32Matrix;
|
||||||
|
typedef Matrix<Int64> I64Matrix;
|
||||||
|
typedef Matrix<UInt64> UI64Matrix;
|
||||||
|
typedef Matrix<float> F32Matrix;
|
||||||
|
typedef Matrix<double> F64Matrix;
|
||||||
|
typedef Matrix<Complex32> C32Matrix;
|
||||||
|
typedef Matrix<Complex64> C64Matrix;
|
||||||
|
typedef QString String;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug dbg, const LibXISF::Complex32 &c);
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Boolean);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Int8);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UInt8);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Int16);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UInt16);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Int32);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UInt32);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Int64);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UInt64);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Float32);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Float64);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Complex32);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::Complex64);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I8Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI8Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I16Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI16Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I32Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI32Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I64Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI64Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::F32Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::F64Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::C32Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::C64Vector);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I8Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI8Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I16Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI16Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I32Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI32Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::I64Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::UI64Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::F32Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::F64Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::C32Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::C64Matrix);
|
||||||
|
Q_DECLARE_METATYPE(LibXISF::String);
|
||||||
|
|
||||||
|
#endif // LIBXISF_H
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
LZ4 Library
|
||||||
|
Copyright (c) 2011-2020, Yann Collet
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
+187
@@ -0,0 +1,187 @@
|
|||||||
|
LZ4 - Library Files
|
||||||
|
================================
|
||||||
|
|
||||||
|
The `/lib` directory contains many files, but depending on project's objectives,
|
||||||
|
not all of them are required.
|
||||||
|
Limited systems may want to reduce the nb of source files to include
|
||||||
|
as a way to reduce binary size and dependencies.
|
||||||
|
|
||||||
|
Capabilities are added at the "level" granularity, detailed below.
|
||||||
|
|
||||||
|
#### Level 1 : Minimal LZ4 build
|
||||||
|
|
||||||
|
The minimum required is **`lz4.c`** and **`lz4.h`**,
|
||||||
|
which provides the fast compression and decompression algorithms.
|
||||||
|
They generate and decode data using the [LZ4 block format].
|
||||||
|
|
||||||
|
|
||||||
|
#### Level 2 : High Compression variant
|
||||||
|
|
||||||
|
For more compression ratio at the cost of compression speed,
|
||||||
|
the High Compression variant called **lz4hc** is available.
|
||||||
|
Add files **`lz4hc.c`** and **`lz4hc.h`**.
|
||||||
|
This variant also compresses data using the [LZ4 block format],
|
||||||
|
and depends on regular `lib/lz4.*` source files.
|
||||||
|
|
||||||
|
|
||||||
|
#### Level 3 : Frame support, for interoperability
|
||||||
|
|
||||||
|
In order to produce compressed data compatible with `lz4` command line utility,
|
||||||
|
it's necessary to use the [official interoperable frame format].
|
||||||
|
This format is generated and decoded automatically by the **lz4frame** library.
|
||||||
|
Its public API is described in `lib/lz4frame.h`.
|
||||||
|
In order to work properly, lz4frame needs all other modules present in `/lib`,
|
||||||
|
including, lz4 and lz4hc, and also **xxhash**.
|
||||||
|
So it's necessary to also include `xxhash.c` and `xxhash.h`.
|
||||||
|
|
||||||
|
|
||||||
|
#### Level 4 : File compression operations
|
||||||
|
|
||||||
|
As a helper around file operations,
|
||||||
|
the library has been recently extended with `lz4file.c` and `lz4file.h`
|
||||||
|
(still considered experimental at the time of this writing).
|
||||||
|
These helpers allow opening, reading, writing, and closing files
|
||||||
|
using transparent LZ4 compression / decompression.
|
||||||
|
As a consequence, using `lz4file` adds a dependency on `<stdio.h>`.
|
||||||
|
|
||||||
|
`lz4file` relies on `lz4frame` in order to produce compressed data
|
||||||
|
conformant to the [LZ4 Frame format] specification.
|
||||||
|
Consequently, to enable this capability,
|
||||||
|
it's necessary to include all `*.c` and `*.h` files from `lib/` directory.
|
||||||
|
|
||||||
|
|
||||||
|
#### Advanced / Experimental API
|
||||||
|
|
||||||
|
Definitions which are not guaranteed to remain stable in future versions,
|
||||||
|
are protected behind macros, such as `LZ4_STATIC_LINKING_ONLY`.
|
||||||
|
As the name suggests, these definitions should only be invoked
|
||||||
|
in the context of static linking ***only***.
|
||||||
|
Otherwise, dependent application may fail on API or ABI break in the future.
|
||||||
|
The associated symbols are also not exposed by the dynamic library by default.
|
||||||
|
Should they be nonetheless needed, it's possible to force their publication
|
||||||
|
by using build macros `LZ4_PUBLISH_STATIC_FUNCTIONS`
|
||||||
|
and `LZ4F_PUBLISH_STATIC_FUNCTIONS`.
|
||||||
|
|
||||||
|
|
||||||
|
#### Build macros
|
||||||
|
|
||||||
|
The following build macro can be selected to adjust source code behavior at compilation time :
|
||||||
|
|
||||||
|
- `LZ4_FAST_DEC_LOOP` : this triggers a speed optimized decompression loop, more powerful on modern cpus.
|
||||||
|
This loop works great on `x86`, `x64` and `aarch64` cpus, and is automatically enabled for them.
|
||||||
|
It's also possible to enable or disable it manually, by passing `LZ4_FAST_DEC_LOOP=1` or `0` to the preprocessor.
|
||||||
|
For example, with `gcc` : `-DLZ4_FAST_DEC_LOOP=1`,
|
||||||
|
and with `make` : `CPPFLAGS+=-DLZ4_FAST_DEC_LOOP=1 make lz4`.
|
||||||
|
|
||||||
|
- `LZ4_DISTANCE_MAX` : control the maximum offset that the compressor will allow.
|
||||||
|
Set to 65535 by default, which is the maximum value supported by lz4 format.
|
||||||
|
Reducing maximum distance will reduce opportunities for LZ4 to find matches,
|
||||||
|
hence will produce a worse compression ratio.
|
||||||
|
Setting a smaller max distance could allow compatibility with specific decoders with limited memory budget.
|
||||||
|
This build macro only influences the compressed output of the compressor.
|
||||||
|
|
||||||
|
- `LZ4_DISABLE_DEPRECATE_WARNINGS` : invoking a deprecated function will make the compiler generate a warning.
|
||||||
|
This is meant to invite users to update their source code.
|
||||||
|
Should this be a problem, it's generally possible to make the compiler ignore these warnings,
|
||||||
|
for example with `-Wno-deprecated-declarations` on `gcc`,
|
||||||
|
or `_CRT_SECURE_NO_WARNINGS` for Visual Studio.
|
||||||
|
This build macro offers another project-specific method
|
||||||
|
by defining `LZ4_DISABLE_DEPRECATE_WARNINGS` before including the LZ4 header files.
|
||||||
|
|
||||||
|
- `LZ4_FORCE_SW_BITCOUNT` : by default, the compression algorithm tries to determine lengths
|
||||||
|
by using bitcount instructions, generally implemented as fast single instructions in many cpus.
|
||||||
|
In case the target cpus doesn't support it, or compiler intrinsic doesn't work, or feature bad performance,
|
||||||
|
it's possible to use an optimized software path instead.
|
||||||
|
This is achieved by setting this build macros.
|
||||||
|
In most cases, it's not expected to be necessary,
|
||||||
|
but it can be legitimately considered for less common platforms.
|
||||||
|
|
||||||
|
- `LZ4_ALIGN_TEST` : alignment test ensures that the memory area
|
||||||
|
passed as argument to become a compression state is suitably aligned.
|
||||||
|
This test can be disabled if it proves flaky, by setting this value to 0.
|
||||||
|
|
||||||
|
- `LZ4_USER_MEMORY_FUNCTIONS` : replace calls to `<stdlib.h>`'s `malloc()`, `calloc()` and `free()`
|
||||||
|
by user-defined functions, which must be named `LZ4_malloc()`, `LZ4_calloc()` and `LZ4_free()`.
|
||||||
|
User functions must be available at link time.
|
||||||
|
|
||||||
|
- `LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION` :
|
||||||
|
Remove support of dynamic memory allocation.
|
||||||
|
For more details, see description of this macro in `lib/lz4.c`.
|
||||||
|
|
||||||
|
- `LZ4_FREESTANDING` : by setting this build macro to 1,
|
||||||
|
LZ4/HC removes dependencies on the C standard library,
|
||||||
|
including allocation functions and `memmove()`, `memcpy()`, and `memset()`.
|
||||||
|
This build macro is designed to help use LZ4/HC in restricted environments
|
||||||
|
(embedded, bootloader, etc).
|
||||||
|
For more details, see description of this macro in `lib/lz4.h`.
|
||||||
|
|
||||||
|
- `LZ4_HEAPMODE` : Select how stateless compression functions like `LZ4_compress_default()`
|
||||||
|
allocate memory for their hash table,
|
||||||
|
in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
|
||||||
|
|
||||||
|
- `LZ4HC_HEAPMODE` : Select how stateless HC compression functions like `LZ4_compress_HC()`
|
||||||
|
allocate memory for their workspace:
|
||||||
|
in stack (0), or in heap (1:default).
|
||||||
|
Since workspace is rather large, stack can be inconvenient, hence heap mode is recommended.
|
||||||
|
|
||||||
|
- `LZ4F_HEAPMODE` : selects how `LZ4F_compressFrame()` allocates the compression state,
|
||||||
|
either on stack (default, value 0) or using heap memory (value 1).
|
||||||
|
|
||||||
|
|
||||||
|
#### Makefile variables
|
||||||
|
|
||||||
|
The following `Makefile` variables can be selected to alter the profile of produced binaries :
|
||||||
|
- `BUILD_SHARED` : generate `libzstd` dynamic library (enabled by default)
|
||||||
|
- `BUILD_STATIC` : generate `libzstd` static library (enabled by default)
|
||||||
|
|
||||||
|
|
||||||
|
#### Amalgamation
|
||||||
|
|
||||||
|
lz4 source code can be amalgamated into a single file.
|
||||||
|
One can combine all source code into `lz4_all.c` by using following command:
|
||||||
|
```
|
||||||
|
cat lz4.c lz4hc.c lz4frame.c > lz4_all.c
|
||||||
|
```
|
||||||
|
(`cat` file order is important) then compile `lz4_all.c`.
|
||||||
|
All `*.h` files present in `/lib` remain necessary to compile `lz4_all.c`.
|
||||||
|
|
||||||
|
|
||||||
|
#### Windows : using MinGW+MSYS to create DLL
|
||||||
|
|
||||||
|
DLL can be created using MinGW+MSYS with the `make liblz4` command.
|
||||||
|
This command creates `dll\liblz4.dll` and the import library `dll\liblz4.lib`.
|
||||||
|
To override the `dlltool` command when cross-compiling on Linux, just set the `DLLTOOL` variable. Example of cross compilation on Linux with mingw-w64 64 bits:
|
||||||
|
```
|
||||||
|
make BUILD_STATIC=no CC=x86_64-w64-mingw32-gcc DLLTOOL=x86_64-w64-mingw32-dlltool OS=Windows_NT
|
||||||
|
```
|
||||||
|
The import library is only required with Visual C++.
|
||||||
|
The header files `lz4.h`, `lz4hc.h`, `lz4frame.h` and the dynamic library
|
||||||
|
`dll\liblz4.dll` are required to compile a project using gcc/MinGW.
|
||||||
|
The dynamic library has to be added to linking options.
|
||||||
|
It means that if a project that uses LZ4 consists of a single `test-dll.c`
|
||||||
|
file it should be linked with `dll\liblz4.dll`. For example:
|
||||||
|
```
|
||||||
|
$(CC) $(CFLAGS) -Iinclude/ test-dll.c -o test-dll dll\liblz4.dll
|
||||||
|
```
|
||||||
|
The compiled executable will require LZ4 DLL which is available at `dll\liblz4.dll`.
|
||||||
|
|
||||||
|
|
||||||
|
#### Miscellaneous
|
||||||
|
|
||||||
|
Other files present in the directory are not source code. They are :
|
||||||
|
|
||||||
|
- `LICENSE` : contains the BSD license text
|
||||||
|
- `Makefile` : `make` script to compile and install lz4 library (static and dynamic)
|
||||||
|
- `liblz4.pc.in` : for `pkg-config` (used in `make install`)
|
||||||
|
- `README.md` : this file
|
||||||
|
|
||||||
|
[official interoperable frame format]: ../doc/lz4_Frame_format.md
|
||||||
|
[LZ4 Frame format]: ../doc/lz4_Frame_format.md
|
||||||
|
[LZ4 block format]: ../doc/lz4_Block_format.md
|
||||||
|
|
||||||
|
|
||||||
|
#### License
|
||||||
|
|
||||||
|
All source material within __lib__ directory are BSD 2-Clause licensed.
|
||||||
|
See [LICENSE](LICENSE) for details.
|
||||||
|
The license is also reminded at the top of each source file.
|
||||||
@@ -0,0 +1,862 @@
|
|||||||
|
/*
|
||||||
|
* LZ4 - Fast LZ compression algorithm
|
||||||
|
* Header File
|
||||||
|
* Copyright (C) 2011-2020, Yann Collet.
|
||||||
|
|
||||||
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
You can contact the author at :
|
||||||
|
- LZ4 homepage : http://www.lz4.org
|
||||||
|
- LZ4 source repository : https://github.com/lz4/lz4
|
||||||
|
*/
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LZ4_H_2983827168210
|
||||||
|
#define LZ4_H_2983827168210
|
||||||
|
|
||||||
|
/* --- Dependency --- */
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
|
||||||
|
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
|
||||||
|
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
|
||||||
|
|
||||||
|
The LZ4 compression library provides in-memory compression and decompression functions.
|
||||||
|
It gives full buffer control to user.
|
||||||
|
Compression can be done in:
|
||||||
|
- a single step (described as Simple Functions)
|
||||||
|
- a single step, reusing a context (described in Advanced Functions)
|
||||||
|
- unbounded multiple steps (described as Streaming compression)
|
||||||
|
|
||||||
|
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
|
||||||
|
Decompressing such a compressed block requires additional metadata.
|
||||||
|
Exact metadata depends on exact decompression function.
|
||||||
|
For the typical case of LZ4_decompress_safe(),
|
||||||
|
metadata includes block's compressed size, and maximum bound of decompressed size.
|
||||||
|
Each application is free to encode and pass such metadata in whichever way it wants.
|
||||||
|
|
||||||
|
lz4.h only handle blocks, it can not generate Frames.
|
||||||
|
|
||||||
|
Blocks are different from Frames (doc/lz4_Frame_format.md).
|
||||||
|
Frames bundle both blocks and metadata in a specified manner.
|
||||||
|
Embedding metadata is required for compressed data to be self-contained and portable.
|
||||||
|
Frame format is delivered through a companion API, declared in lz4frame.h.
|
||||||
|
The `lz4` CLI can only manage frames.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*^***************************************************************
|
||||||
|
* Export parameters
|
||||||
|
*****************************************************************/
|
||||||
|
/*
|
||||||
|
* LZ4_DLL_EXPORT :
|
||||||
|
* Enable exporting of functions when building a Windows DLL
|
||||||
|
* LZ4LIB_VISIBILITY :
|
||||||
|
* Control library symbols visibility.
|
||||||
|
*/
|
||||||
|
#ifndef LZ4LIB_VISIBILITY
|
||||||
|
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||||
|
# else
|
||||||
|
# define LZ4LIB_VISIBILITY
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
|
||||||
|
# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
|
||||||
|
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
|
||||||
|
# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||||
|
#else
|
||||||
|
# define LZ4LIB_API LZ4LIB_VISIBILITY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_FREESTANDING :
|
||||||
|
* When this macro is set to 1, it enables "freestanding mode" that is
|
||||||
|
* suitable for typical freestanding environment which doesn't support
|
||||||
|
* standard C library.
|
||||||
|
*
|
||||||
|
* - LZ4_FREESTANDING is a compile-time switch.
|
||||||
|
* - It requires the following macros to be defined:
|
||||||
|
* LZ4_memcpy, LZ4_memmove, LZ4_memset.
|
||||||
|
* - It only enables LZ4/HC functions which don't use heap.
|
||||||
|
* All LZ4F_* functions are not supported.
|
||||||
|
* - See tests/freestanding.c to check its basic setup.
|
||||||
|
*/
|
||||||
|
#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)
|
||||||
|
# define LZ4_HEAPMODE 0
|
||||||
|
# define LZ4HC_HEAPMODE 0
|
||||||
|
# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1
|
||||||
|
# if !defined(LZ4_memcpy)
|
||||||
|
# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'."
|
||||||
|
# endif
|
||||||
|
# if !defined(LZ4_memset)
|
||||||
|
# error "LZ4_FREESTANDING requires macro 'LZ4_memset'."
|
||||||
|
# endif
|
||||||
|
# if !defined(LZ4_memmove)
|
||||||
|
# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'."
|
||||||
|
# endif
|
||||||
|
#elif ! defined(LZ4_FREESTANDING)
|
||||||
|
# define LZ4_FREESTANDING 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*------ Version ------*/
|
||||||
|
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||||
|
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
|
||||||
|
#define LZ4_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */
|
||||||
|
|
||||||
|
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||||
|
|
||||||
|
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
||||||
|
#define LZ4_QUOTE(str) #str
|
||||||
|
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
||||||
|
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */
|
||||||
|
|
||||||
|
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */
|
||||||
|
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Tuning parameter
|
||||||
|
**************************************/
|
||||||
|
#define LZ4_MEMORY_USAGE_MIN 10
|
||||||
|
#define LZ4_MEMORY_USAGE_DEFAULT 14
|
||||||
|
#define LZ4_MEMORY_USAGE_MAX 20
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* LZ4_MEMORY_USAGE :
|
||||||
|
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; )
|
||||||
|
* Increasing memory usage improves compression ratio, at the cost of speed.
|
||||||
|
* Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.
|
||||||
|
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||||||
|
*/
|
||||||
|
#ifndef LZ4_MEMORY_USAGE
|
||||||
|
# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)
|
||||||
|
# error "LZ4_MEMORY_USAGE is too small !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)
|
||||||
|
# error "LZ4_MEMORY_USAGE is too large !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Simple Functions
|
||||||
|
**************************************/
|
||||||
|
/*! LZ4_compress_default() :
|
||||||
|
* Compresses 'srcSize' bytes from buffer 'src'
|
||||||
|
* into already allocated 'dst' buffer of size 'dstCapacity'.
|
||||||
|
* Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
|
||||||
|
* It also runs faster, so it's a recommended setting.
|
||||||
|
* If the function cannot compress 'src' into a more limited 'dst' budget,
|
||||||
|
* compression stops *immediately*, and the function result is zero.
|
||||||
|
* In which case, 'dst' content is undefined (invalid).
|
||||||
|
* srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
|
||||||
|
* dstCapacity : size of buffer 'dst' (which must be already allocated)
|
||||||
|
* @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
|
||||||
|
* or 0 if compression fails
|
||||||
|
* Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
|
||||||
|
|
||||||
|
/*! LZ4_decompress_safe() :
|
||||||
|
* @compressedSize : is the exact complete size of the compressed block.
|
||||||
|
* @dstCapacity : is the size of destination buffer (which must be already allocated),
|
||||||
|
* is an upper bound of decompressed size.
|
||||||
|
* @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
||||||
|
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
||||||
|
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||||
|
* Note 1 : This function is protected against malicious data packets :
|
||||||
|
* it will never writes outside 'dst' buffer, nor read outside 'source' buffer,
|
||||||
|
* even if the compressed block is maliciously modified to order the decoder to do these actions.
|
||||||
|
* In such case, the decoder stops immediately, and considers the compressed block malformed.
|
||||||
|
* Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.
|
||||||
|
* The implementation is free to send / store / derive this information in whichever way is most beneficial.
|
||||||
|
* If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Advanced Functions
|
||||||
|
**************************************/
|
||||||
|
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||||
|
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||||
|
|
||||||
|
/*! LZ4_compressBound() :
|
||||||
|
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
|
||||||
|
This function is primarily useful for memory allocation purposes (destination buffer size).
|
||||||
|
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||||
|
Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
|
||||||
|
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
|
||||||
|
return : maximum output size in a "worst case" scenario
|
||||||
|
or 0, if input size is incorrect (too large or negative)
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compressBound(int inputSize);
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast() :
|
||||||
|
Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
|
||||||
|
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||||
|
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||||
|
An acceleration value of "1" is the same as regular LZ4_compress_default()
|
||||||
|
Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).
|
||||||
|
Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast_extState() :
|
||||||
|
* Same as LZ4_compress_fast(), using an externally allocated memory space for its state.
|
||||||
|
* Use LZ4_sizeofState() to know how much memory must be allocated,
|
||||||
|
* and allocate it on 8-bytes boundaries (using `malloc()` typically).
|
||||||
|
* Then, provide this buffer as `void* state` to compression function.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_sizeofState(void);
|
||||||
|
LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_destSize() :
|
||||||
|
* Reverse the logic : compresses as much data as possible from 'src' buffer
|
||||||
|
* into already allocated buffer 'dst', of size >= 'targetDestSize'.
|
||||||
|
* This function either compresses the entire 'src' content into 'dst' if it's large enough,
|
||||||
|
* or fill 'dst' buffer completely with as much data as possible from 'src'.
|
||||||
|
* note: acceleration parameter is fixed to "default".
|
||||||
|
*
|
||||||
|
* *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
|
||||||
|
* New value is necessarily <= input value.
|
||||||
|
* @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
|
||||||
|
* or 0 if compression fails.
|
||||||
|
*
|
||||||
|
* Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):
|
||||||
|
* the produced compressed content could, in specific circumstances,
|
||||||
|
* require to be decompressed into a destination buffer larger
|
||||||
|
* by at least 1 byte than the content to decompress.
|
||||||
|
* If an application uses `LZ4_compress_destSize()`,
|
||||||
|
* it's highly recommended to update liblz4 to v1.9.2 or better.
|
||||||
|
* If this can't be done or ensured,
|
||||||
|
* the receiving decompression function should provide
|
||||||
|
* a dstCapacity which is > decompressedSize, by at least 1 byte.
|
||||||
|
* See https://github.com/lz4/lz4/issues/859 for details
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_decompress_safe_partial() :
|
||||||
|
* Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
|
||||||
|
* into destination buffer 'dst' of size 'dstCapacity'.
|
||||||
|
* Up to 'targetOutputSize' bytes will be decoded.
|
||||||
|
* The function stops decoding on reaching this objective.
|
||||||
|
* This can be useful to boost performance
|
||||||
|
* whenever only the beginning of a block is required.
|
||||||
|
*
|
||||||
|
* @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)
|
||||||
|
* If source stream is detected malformed, function returns a negative result.
|
||||||
|
*
|
||||||
|
* Note 1 : @return can be < targetOutputSize, if compressed block contains less data.
|
||||||
|
*
|
||||||
|
* Note 2 : targetOutputSize must be <= dstCapacity
|
||||||
|
*
|
||||||
|
* Note 3 : this function effectively stops decoding on reaching targetOutputSize,
|
||||||
|
* so dstCapacity is kind of redundant.
|
||||||
|
* This is because in older versions of this function,
|
||||||
|
* decoding operation would still write complete sequences.
|
||||||
|
* Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,
|
||||||
|
* it could write more bytes, though only up to dstCapacity.
|
||||||
|
* Some "margin" used to be required for this operation to work properly.
|
||||||
|
* Thankfully, this is no longer necessary.
|
||||||
|
* The function nonetheless keeps the same signature, in an effort to preserve API compatibility.
|
||||||
|
*
|
||||||
|
* Note 4 : If srcSize is the exact size of the block,
|
||||||
|
* then targetOutputSize can be any value,
|
||||||
|
* including larger than the block's decompressed size.
|
||||||
|
* The function will, at most, generate block's decompressed size.
|
||||||
|
*
|
||||||
|
* Note 5 : If srcSize is _larger_ than block's compressed size,
|
||||||
|
* then targetOutputSize **MUST** be <= block's decompressed size.
|
||||||
|
* Otherwise, *silent corruption will occur*.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
|
/*-*********************************************
|
||||||
|
* Streaming Compression Functions
|
||||||
|
***********************************************/
|
||||||
|
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
Note about RC_INVOKED
|
||||||
|
|
||||||
|
- RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros
|
||||||
|
|
||||||
|
- Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)
|
||||||
|
and reports warning "RC4011: identifier truncated".
|
||||||
|
|
||||||
|
- To eliminate the warning, we surround long preprocessor symbol with
|
||||||
|
"#if !defined(RC_INVOKED) ... #endif" block that means
|
||||||
|
"skip this block when rc.exe is trying to read it".
|
||||||
|
*/
|
||||||
|
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
|
||||||
|
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
||||||
|
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
||||||
|
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
||||||
|
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_resetStream_fast() : v1.9.0+
|
||||||
|
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
|
||||||
|
* (e.g., LZ4_compress_fast_continue()).
|
||||||
|
*
|
||||||
|
* An LZ4_stream_t must be initialized once before usage.
|
||||||
|
* This is automatically done when created by LZ4_createStream().
|
||||||
|
* However, should the LZ4_stream_t be simply declared on stack (for example),
|
||||||
|
* it's necessary to initialize it first, using LZ4_initStream().
|
||||||
|
*
|
||||||
|
* After init, start any new stream with LZ4_resetStream_fast().
|
||||||
|
* A same LZ4_stream_t can be re-used multiple times consecutively
|
||||||
|
* and compress multiple streams,
|
||||||
|
* provided that it starts each new stream with LZ4_resetStream_fast().
|
||||||
|
*
|
||||||
|
* LZ4_resetStream_fast() is much faster than LZ4_initStream(),
|
||||||
|
* but is not compatible with memory regions containing garbage data.
|
||||||
|
*
|
||||||
|
* Note: it's only useful to call LZ4_resetStream_fast()
|
||||||
|
* in the context of streaming compression.
|
||||||
|
* The *extState* functions perform their own resets.
|
||||||
|
* Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
|
||||||
|
|
||||||
|
/*! LZ4_loadDict() :
|
||||||
|
* Use this function to reference a static dictionary into LZ4_stream_t.
|
||||||
|
* The dictionary must remain available during compression.
|
||||||
|
* LZ4_loadDict() triggers a reset, so any previous data will be forgotten.
|
||||||
|
* The same dictionary will have to be loaded on decompression side for successful decoding.
|
||||||
|
* Dictionary are useful for better compression of small data (KB range).
|
||||||
|
* While LZ4 accept any input as dictionary,
|
||||||
|
* results are generally better when using Zstandard's Dictionary Builder.
|
||||||
|
* Loading a size of 0 is allowed, and is the same as reset.
|
||||||
|
* @return : loaded dictionary size, in bytes (necessarily <= 64 KB)
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast_continue() :
|
||||||
|
* Compress 'src' content using data from previously compressed blocks, for better compression ratio.
|
||||||
|
* 'dst' buffer must be already allocated.
|
||||||
|
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
|
||||||
|
*
|
||||||
|
* @return : size of compressed block
|
||||||
|
* or 0 if there is an error (typically, cannot fit into 'dst').
|
||||||
|
*
|
||||||
|
* Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.
|
||||||
|
* Each block has precise boundaries.
|
||||||
|
* Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata.
|
||||||
|
* It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.
|
||||||
|
*
|
||||||
|
* Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory !
|
||||||
|
*
|
||||||
|
* Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.
|
||||||
|
* Make sure that buffers are separated, by at least one byte.
|
||||||
|
* This construction ensures that each block only depends on previous block.
|
||||||
|
*
|
||||||
|
* Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
|
||||||
|
*
|
||||||
|
* Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
/*! LZ4_saveDict() :
|
||||||
|
* If last 64KB data cannot be guaranteed to remain available at its current memory location,
|
||||||
|
* save it into a safer place (char* safeBuffer).
|
||||||
|
* This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
|
||||||
|
* but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
|
||||||
|
* @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
|
||||||
|
|
||||||
|
|
||||||
|
/*-**********************************************
|
||||||
|
* Streaming Decompression Functions
|
||||||
|
* Bufferless synchronous API
|
||||||
|
************************************************/
|
||||||
|
typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
|
||||||
|
|
||||||
|
/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
|
||||||
|
* creation / destruction of streaming decompression tracking context.
|
||||||
|
* A tracking context can be re-used multiple times.
|
||||||
|
*/
|
||||||
|
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
|
||||||
|
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
||||||
|
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
||||||
|
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
||||||
|
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_setStreamDecode() :
|
||||||
|
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
|
||||||
|
* Use this function to start decompression of a new stream of blocks.
|
||||||
|
* A dictionary can optionally be set. Use NULL or size 0 for a reset order.
|
||||||
|
* Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
|
||||||
|
* @return : 1 if OK, 0 if error
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
|
||||||
|
|
||||||
|
/*! LZ4_decoderRingBufferSize() : v1.8.2+
|
||||||
|
* Note : in a ring buffer scenario (optional),
|
||||||
|
* blocks are presumed decompressed next to each other
|
||||||
|
* up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),
|
||||||
|
* at which stage it resumes from beginning of ring buffer.
|
||||||
|
* When setting such a ring buffer for streaming decompression,
|
||||||
|
* provides the minimum size of this ring buffer
|
||||||
|
* to be compatible with any source respecting maxBlockSize condition.
|
||||||
|
* @return : minimum ring buffer size,
|
||||||
|
* or 0 if there is an error (invalid maxBlockSize).
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
|
||||||
|
#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */
|
||||||
|
|
||||||
|
/*! LZ4_decompress_safe_continue() :
|
||||||
|
* This decoding function allows decompression of consecutive blocks in "streaming" mode.
|
||||||
|
* The difference with the usual independent blocks is that
|
||||||
|
* new blocks are allowed to find references into former blocks.
|
||||||
|
* A block is an unsplittable entity, and must be presented entirely to the decompression function.
|
||||||
|
* LZ4_decompress_safe_continue() only accepts one block at a time.
|
||||||
|
* It's modeled after `LZ4_decompress_safe()` and behaves similarly.
|
||||||
|
*
|
||||||
|
* @LZ4_streamDecode : decompression state, tracking the position in memory of past data
|
||||||
|
* @compressedSize : exact complete size of one compressed block.
|
||||||
|
* @dstCapacity : size of destination buffer (which must be already allocated),
|
||||||
|
* must be an upper bound of decompressed size.
|
||||||
|
* @return : number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
||||||
|
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
||||||
|
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||||
|
*
|
||||||
|
* The last 64KB of previously decoded data *must* remain available and unmodified
|
||||||
|
* at the memory position where they were previously decoded.
|
||||||
|
* If less than 64KB of data has been decoded, all the data must be present.
|
||||||
|
*
|
||||||
|
* Special : if decompression side sets a ring buffer, it must respect one of the following conditions :
|
||||||
|
* - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).
|
||||||
|
* maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.
|
||||||
|
* In which case, encoding and decoding buffers do not need to be synchronized.
|
||||||
|
* Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.
|
||||||
|
* - Synchronized mode :
|
||||||
|
* Decompression buffer size is _exactly_ the same as compression buffer size,
|
||||||
|
* and follows exactly same update rule (block boundaries at same positions),
|
||||||
|
* and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),
|
||||||
|
* _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||||
|
* - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.
|
||||||
|
* In which case, encoding and decoding buffers do not need to be synchronized,
|
||||||
|
* and encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||||
|
*
|
||||||
|
* Whenever these conditions are not possible,
|
||||||
|
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
|
||||||
|
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int
|
||||||
|
LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,
|
||||||
|
const char* src, char* dst,
|
||||||
|
int srcSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_decompress_safe_usingDict() :
|
||||||
|
* Works the same as
|
||||||
|
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_safe_continue()
|
||||||
|
* However, it's stateless: it doesn't need any LZ4_streamDecode_t state.
|
||||||
|
* Dictionary is presumed stable : it must remain accessible and unmodified during decompression.
|
||||||
|
* Performance tip : Decompression speed can be substantially increased
|
||||||
|
* when dst == dictStart + dictSize.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int
|
||||||
|
LZ4_decompress_safe_usingDict(const char* src, char* dst,
|
||||||
|
int srcSize, int dstCapacity,
|
||||||
|
const char* dictStart, int dictSize);
|
||||||
|
|
||||||
|
/*! LZ4_decompress_safe_partial_usingDict() :
|
||||||
|
* Behaves the same as LZ4_decompress_safe_partial()
|
||||||
|
* with the added ability to specify a memory segment for past data.
|
||||||
|
* Performance tip : Decompression speed can be substantially increased
|
||||||
|
* when dst == dictStart + dictSize.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int
|
||||||
|
LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,
|
||||||
|
int compressedSize,
|
||||||
|
int targetOutputSize, int maxOutputSize,
|
||||||
|
const char* dictStart, int dictSize);
|
||||||
|
|
||||||
|
#endif /* LZ4_H_2983827168210 */
|
||||||
|
|
||||||
|
|
||||||
|
/*^*************************************
|
||||||
|
* !!!!!! STATIC LINKING ONLY !!!!!!
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
/*-****************************************************************************
|
||||||
|
* Experimental section
|
||||||
|
*
|
||||||
|
* Symbols declared in this section must be considered unstable. Their
|
||||||
|
* signatures or semantics may change, or they may be removed altogether in the
|
||||||
|
* future. They are therefore only safe to depend on when the caller is
|
||||||
|
* statically linked against the library.
|
||||||
|
*
|
||||||
|
* To protect against unsafe usage, not only are the declarations guarded,
|
||||||
|
* the definitions are hidden by default
|
||||||
|
* when building LZ4 as a shared/dynamic library.
|
||||||
|
*
|
||||||
|
* In order to access these declarations,
|
||||||
|
* define LZ4_STATIC_LINKING_ONLY in your application
|
||||||
|
* before including LZ4's headers.
|
||||||
|
*
|
||||||
|
* In order to make their implementations accessible dynamically, you must
|
||||||
|
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef LZ4_STATIC_LINKING_ONLY
|
||||||
|
|
||||||
|
#ifndef LZ4_STATIC_3504398509
|
||||||
|
#define LZ4_STATIC_3504398509
|
||||||
|
|
||||||
|
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
|
||||||
|
#define LZ4LIB_STATIC_API LZ4LIB_API
|
||||||
|
#else
|
||||||
|
#define LZ4LIB_STATIC_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast_extState_fastReset() :
|
||||||
|
* A variant of LZ4_compress_fast_extState().
|
||||||
|
*
|
||||||
|
* Using this variant avoids an expensive initialization step.
|
||||||
|
* It is only safe to call if the state buffer is known to be correctly initialized already
|
||||||
|
* (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized").
|
||||||
|
* From a high level, the difference is that
|
||||||
|
* this function initializes the provided state with a call to something like LZ4_resetStream_fast()
|
||||||
|
* while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
/*! LZ4_attach_dictionary() :
|
||||||
|
* This is an experimental API that allows
|
||||||
|
* efficient use of a static dictionary many times.
|
||||||
|
*
|
||||||
|
* Rather than re-loading the dictionary buffer into a working context before
|
||||||
|
* each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
|
||||||
|
* working LZ4_stream_t, this function introduces a no-copy setup mechanism,
|
||||||
|
* in which the working stream references the dictionary stream in-place.
|
||||||
|
*
|
||||||
|
* Several assumptions are made about the state of the dictionary stream.
|
||||||
|
* Currently, only streams which have been prepared by LZ4_loadDict() should
|
||||||
|
* be expected to work.
|
||||||
|
*
|
||||||
|
* Alternatively, the provided dictionaryStream may be NULL,
|
||||||
|
* in which case any existing dictionary stream is unset.
|
||||||
|
*
|
||||||
|
* If a dictionary is provided, it replaces any pre-existing stream history.
|
||||||
|
* The dictionary contents are the only history that can be referenced and
|
||||||
|
* logically immediately precede the data compressed in the first subsequent
|
||||||
|
* compression call.
|
||||||
|
*
|
||||||
|
* The dictionary will only remain attached to the working stream through the
|
||||||
|
* first compression call, at the end of which it is cleared. The dictionary
|
||||||
|
* stream (and source buffer) must remain in-place / accessible / unchanged
|
||||||
|
* through the completion of the first compression call on the stream.
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API void
|
||||||
|
LZ4_attach_dictionary(LZ4_stream_t* workingStream,
|
||||||
|
const LZ4_stream_t* dictionaryStream);
|
||||||
|
|
||||||
|
|
||||||
|
/*! In-place compression and decompression
|
||||||
|
*
|
||||||
|
* It's possible to have input and output sharing the same buffer,
|
||||||
|
* for highly constrained memory environments.
|
||||||
|
* In both cases, it requires input to lay at the end of the buffer,
|
||||||
|
* and decompression to start at beginning of the buffer.
|
||||||
|
* Buffer size must feature some margin, hence be larger than final size.
|
||||||
|
*
|
||||||
|
* |<------------------------buffer--------------------------------->|
|
||||||
|
* |<-----------compressed data--------->|
|
||||||
|
* |<-----------decompressed size------------------>|
|
||||||
|
* |<----margin---->|
|
||||||
|
*
|
||||||
|
* This technique is more useful for decompression,
|
||||||
|
* since decompressed size is typically larger,
|
||||||
|
* and margin is short.
|
||||||
|
*
|
||||||
|
* In-place decompression will work inside any buffer
|
||||||
|
* which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).
|
||||||
|
* This presumes that decompressedSize > compressedSize.
|
||||||
|
* Otherwise, it means compression actually expanded data,
|
||||||
|
* and it would be more efficient to store such data with a flag indicating it's not compressed.
|
||||||
|
* This can happen when data is not compressible (already compressed, or encrypted).
|
||||||
|
*
|
||||||
|
* For in-place compression, margin is larger, as it must be able to cope with both
|
||||||
|
* history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,
|
||||||
|
* and data expansion, which can happen when input is not compressible.
|
||||||
|
* As a consequence, buffer size requirements are much higher,
|
||||||
|
* and memory savings offered by in-place compression are more limited.
|
||||||
|
*
|
||||||
|
* There are ways to limit this cost for compression :
|
||||||
|
* - Reduce history size, by modifying LZ4_DISTANCE_MAX.
|
||||||
|
* Note that it is a compile-time constant, so all compressions will apply this limit.
|
||||||
|
* Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,
|
||||||
|
* so it's a reasonable trick when inputs are known to be small.
|
||||||
|
* - Require the compressor to deliver a "maximum compressed size".
|
||||||
|
* This is the `dstCapacity` parameter in `LZ4_compress*()`.
|
||||||
|
* When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,
|
||||||
|
* in which case, the return code will be 0 (zero).
|
||||||
|
* The caller must be ready for these cases to happen,
|
||||||
|
* and typically design a backup scheme to send data uncompressed.
|
||||||
|
* The combination of both techniques can significantly reduce
|
||||||
|
* the amount of margin required for in-place compression.
|
||||||
|
*
|
||||||
|
* In-place compression can work in any buffer
|
||||||
|
* which size is >= (maxCompressedSize)
|
||||||
|
* with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.
|
||||||
|
* LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,
|
||||||
|
* so it's possible to reduce memory requirements by playing with them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)
|
||||||
|
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
|
||||||
|
|
||||||
|
#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */
|
||||||
|
# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */
|
||||||
|
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
|
||||||
|
|
||||||
|
#endif /* LZ4_STATIC_3504398509 */
|
||||||
|
#endif /* LZ4_STATIC_LINKING_ONLY */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LZ4_H_98237428734687
|
||||||
|
#define LZ4_H_98237428734687
|
||||||
|
|
||||||
|
/*-************************************************************
|
||||||
|
* Private Definitions
|
||||||
|
**************************************************************
|
||||||
|
* Do not use these definitions directly.
|
||||||
|
* They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
|
||||||
|
* Accessing members will expose user code to API and/or ABI break in future versions of the library.
|
||||||
|
**************************************************************/
|
||||||
|
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
|
||||||
|
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
|
||||||
|
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
|
||||||
|
|
||||||
|
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||||
|
# include <stdint.h>
|
||||||
|
typedef int8_t LZ4_i8;
|
||||||
|
typedef uint8_t LZ4_byte;
|
||||||
|
typedef uint16_t LZ4_u16;
|
||||||
|
typedef uint32_t LZ4_u32;
|
||||||
|
#else
|
||||||
|
typedef signed char LZ4_i8;
|
||||||
|
typedef unsigned char LZ4_byte;
|
||||||
|
typedef unsigned short LZ4_u16;
|
||||||
|
typedef unsigned int LZ4_u32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_stream_t :
|
||||||
|
* Never ever use below internal definitions directly !
|
||||||
|
* These definitions are not API/ABI safe, and may change in future versions.
|
||||||
|
* If you need static allocation, declare or allocate an LZ4_stream_t object.
|
||||||
|
**/
|
||||||
|
|
||||||
|
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
||||||
|
struct LZ4_stream_t_internal {
|
||||||
|
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
|
||||||
|
const LZ4_byte* dictionary;
|
||||||
|
const LZ4_stream_t_internal* dictCtx;
|
||||||
|
LZ4_u32 currentOffset;
|
||||||
|
LZ4_u32 tableType;
|
||||||
|
LZ4_u32 dictSize;
|
||||||
|
/* Implicit padding to ensure structure is aligned */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */
|
||||||
|
union LZ4_stream_u {
|
||||||
|
char minStateSize[LZ4_STREAM_MINSIZE];
|
||||||
|
LZ4_stream_t_internal internal_donotuse;
|
||||||
|
}; /* previously typedef'd to LZ4_stream_t */
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_initStream() : v1.9.0+
|
||||||
|
* An LZ4_stream_t structure must be initialized at least once.
|
||||||
|
* This is automatically done when invoking LZ4_createStream(),
|
||||||
|
* but it's not when the structure is simply declared on stack (for example).
|
||||||
|
*
|
||||||
|
* Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t.
|
||||||
|
* It can also initialize any arbitrary buffer of sufficient size,
|
||||||
|
* and will @return a pointer of proper type upon initialization.
|
||||||
|
*
|
||||||
|
* Note : initialization fails if size and alignment conditions are not respected.
|
||||||
|
* In which case, the function will @return NULL.
|
||||||
|
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
|
||||||
|
* Note3: Before v1.9.0, use LZ4_resetStream() instead
|
||||||
|
**/
|
||||||
|
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_streamDecode_t :
|
||||||
|
* Never ever use below internal definitions directly !
|
||||||
|
* These definitions are not API/ABI safe, and may change in future versions.
|
||||||
|
* If you need static allocation, declare or allocate an LZ4_streamDecode_t object.
|
||||||
|
**/
|
||||||
|
typedef struct {
|
||||||
|
const LZ4_byte* externalDict;
|
||||||
|
const LZ4_byte* prefixEnd;
|
||||||
|
size_t extDictSize;
|
||||||
|
size_t prefixSize;
|
||||||
|
} LZ4_streamDecode_t_internal;
|
||||||
|
|
||||||
|
#define LZ4_STREAMDECODE_MINSIZE 32
|
||||||
|
union LZ4_streamDecode_u {
|
||||||
|
char minStateSize[LZ4_STREAMDECODE_MINSIZE];
|
||||||
|
LZ4_streamDecode_t_internal internal_donotuse;
|
||||||
|
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Obsolete Functions
|
||||||
|
**************************************/
|
||||||
|
|
||||||
|
/*! Deprecation warnings
|
||||||
|
*
|
||||||
|
* Deprecated functions make the compiler generate a warning when invoked.
|
||||||
|
* This is meant to invite users to update their source code.
|
||||||
|
* Should deprecation warnings be a problem, it is generally possible to disable them,
|
||||||
|
* typically with -Wno-deprecated-declarations for gcc
|
||||||
|
* or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||||
|
*
|
||||||
|
* Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
* before including the header file.
|
||||||
|
*/
|
||||||
|
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
|
||||||
|
#else
|
||||||
|
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||||
|
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
|
# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
|
||||||
|
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
|
# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
|
||||||
|
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
|
||||||
|
# else
|
||||||
|
# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
|
||||||
|
# define LZ4_DEPRECATED(message) /* disabled */
|
||||||
|
# endif
|
||||||
|
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||||
|
|
||||||
|
/*! Obsolete compression functions (since v1.7.3) */
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
|
||||||
|
/*! Obsolete decompression functions (since v1.8.0) */
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
|
||||||
|
|
||||||
|
/* Obsolete streaming functions (since v1.7.0)
|
||||||
|
* degraded functionality; do not use!
|
||||||
|
*
|
||||||
|
* In order to perform streaming compression, these functions depended on data
|
||||||
|
* that is no longer tracked in the state. They have been preserved as well as
|
||||||
|
* possible: using them will still produce a correct output. However, they don't
|
||||||
|
* actually retain any history between compression calls. The compression ratio
|
||||||
|
* achieved will therefore be no better than compressing each chunk
|
||||||
|
* independently.
|
||||||
|
*/
|
||||||
|
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
|
||||||
|
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
|
||||||
|
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
|
||||||
|
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
|
||||||
|
|
||||||
|
/*! Obsolete streaming decoding functions (since v1.7.0) */
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||||
|
|
||||||
|
/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :
|
||||||
|
* These functions used to be faster than LZ4_decompress_safe(),
|
||||||
|
* but this is no longer the case. They are now slower.
|
||||||
|
* This is because LZ4_decompress_fast() doesn't know the input size,
|
||||||
|
* and therefore must progress more cautiously into the input buffer to not read beyond the end of block.
|
||||||
|
* On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
|
||||||
|
* As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
|
||||||
|
*
|
||||||
|
* The last remaining LZ4_decompress_fast() specificity is that
|
||||||
|
* it can decompress a block without knowing its compressed size.
|
||||||
|
* Such functionality can be achieved in a more secure manner
|
||||||
|
* by employing LZ4_decompress_safe_partial().
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* originalSize : is the uncompressed size to regenerate.
|
||||||
|
* `dst` must be already allocated, its size must be >= 'originalSize' bytes.
|
||||||
|
* @return : number of bytes read from source buffer (== compressed size).
|
||||||
|
* The function expects to finish at block's end exactly.
|
||||||
|
* If the source stream is detected malformed, the function stops decoding and returns a negative result.
|
||||||
|
* note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer.
|
||||||
|
* However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds.
|
||||||
|
* Also, since match offsets are not validated, match reads from 'src' may underflow too.
|
||||||
|
* These issues never happen if input (compressed) data is correct.
|
||||||
|
* But they may happen if input data is invalid (error or intentional tampering).
|
||||||
|
* As a consequence, use these functions in trusted environments with trusted data **only**.
|
||||||
|
*/
|
||||||
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
|
||||||
|
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
|
||||||
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
|
||||||
|
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
|
||||||
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead")
|
||||||
|
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
|
||||||
|
|
||||||
|
/*! LZ4_resetStream() :
|
||||||
|
* An LZ4_stream_t structure must be initialized at least once.
|
||||||
|
* This is done with LZ4_initStream(), or LZ4_resetStream().
|
||||||
|
* Consider switching to LZ4_initStream(),
|
||||||
|
* invoking LZ4_resetStream() will trigger deprecation warnings in the future.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* LZ4_H_98237428734687 */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+1637
File diff suppressed because it is too large
Load Diff
+413
@@ -0,0 +1,413 @@
|
|||||||
|
/*
|
||||||
|
LZ4 HC - High Compression Mode of LZ4
|
||||||
|
Header File
|
||||||
|
Copyright (C) 2011-2020, Yann Collet.
|
||||||
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
You can contact the author at :
|
||||||
|
- LZ4 source repository : https://github.com/lz4/lz4
|
||||||
|
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||||
|
*/
|
||||||
|
#ifndef LZ4_HC_H_19834876238432
|
||||||
|
#define LZ4_HC_H_19834876238432
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* --- Dependency --- */
|
||||||
|
/* note : lz4hc requires lz4.h/lz4.c for compilation */
|
||||||
|
#include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
|
||||||
|
|
||||||
|
|
||||||
|
/* --- Useful constants --- */
|
||||||
|
#define LZ4HC_CLEVEL_MIN 3
|
||||||
|
#define LZ4HC_CLEVEL_DEFAULT 9
|
||||||
|
#define LZ4HC_CLEVEL_OPT_MIN 10
|
||||||
|
#define LZ4HC_CLEVEL_MAX 12
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Block Compression
|
||||||
|
**************************************/
|
||||||
|
/*! LZ4_compress_HC() :
|
||||||
|
* Compress data from `src` into `dst`, using the powerful but slower "HC" algorithm.
|
||||||
|
* `dst` must be already allocated.
|
||||||
|
* Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h")
|
||||||
|
* Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h")
|
||||||
|
* `compressionLevel` : any value between 1 and LZ4HC_CLEVEL_MAX will work.
|
||||||
|
* Values > LZ4HC_CLEVEL_MAX behave the same as LZ4HC_CLEVEL_MAX.
|
||||||
|
* @return : the number of bytes written into 'dst'
|
||||||
|
* or 0 if compression fails.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel);
|
||||||
|
|
||||||
|
|
||||||
|
/* Note :
|
||||||
|
* Decompression functions are provided within "lz4.h" (BSD license)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_HC_extStateHC() :
|
||||||
|
* Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`.
|
||||||
|
* `state` size is provided by LZ4_sizeofStateHC().
|
||||||
|
* Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() should do properly).
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_sizeofStateHC(void);
|
||||||
|
LZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_HC_destSize() : v1.9.0+
|
||||||
|
* Will compress as much data as possible from `src`
|
||||||
|
* to fit into `targetDstSize` budget.
|
||||||
|
* Result is provided in 2 parts :
|
||||||
|
* @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)
|
||||||
|
* or 0 if compression fails.
|
||||||
|
* `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src`
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC,
|
||||||
|
const char* src, char* dst,
|
||||||
|
int* srcSizePtr, int targetDstSize,
|
||||||
|
int compressionLevel);
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Streaming Compression
|
||||||
|
* Bufferless synchronous API
|
||||||
|
**************************************/
|
||||||
|
typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */
|
||||||
|
|
||||||
|
/*! LZ4_createStreamHC() and LZ4_freeStreamHC() :
|
||||||
|
* These functions create and release memory for LZ4 HC streaming state.
|
||||||
|
* Newly created states are automatically initialized.
|
||||||
|
* A same state can be used multiple times consecutively,
|
||||||
|
* starting with LZ4_resetStreamHC_fast() to start a new stream of blocks.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void);
|
||||||
|
LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
These functions compress data in successive blocks of any size,
|
||||||
|
using previous blocks as dictionary, to improve compression ratio.
|
||||||
|
One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
|
||||||
|
There is an exception for ring buffers, which can be smaller than 64 KB.
|
||||||
|
Ring-buffer scenario is automatically detected and handled within LZ4_compress_HC_continue().
|
||||||
|
|
||||||
|
Before starting compression, state must be allocated and properly initialized.
|
||||||
|
LZ4_createStreamHC() does both, though compression level is set to LZ4HC_CLEVEL_DEFAULT.
|
||||||
|
|
||||||
|
Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream)
|
||||||
|
or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental).
|
||||||
|
LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once,
|
||||||
|
which is automatically the case when state is created using LZ4_createStreamHC().
|
||||||
|
|
||||||
|
After reset, a first "fictional block" can be designated as initial dictionary,
|
||||||
|
using LZ4_loadDictHC() (Optional).
|
||||||
|
|
||||||
|
Invoke LZ4_compress_HC_continue() to compress each successive block.
|
||||||
|
The number of blocks is unlimited.
|
||||||
|
Previous input blocks, including initial dictionary when present,
|
||||||
|
must remain accessible and unmodified during compression.
|
||||||
|
|
||||||
|
It's allowed to update compression level anytime between blocks,
|
||||||
|
using LZ4_setCompressionLevel() (experimental).
|
||||||
|
|
||||||
|
'dst' buffer should be sized to handle worst case scenarios
|
||||||
|
(see LZ4_compressBound(), it ensures compression success).
|
||||||
|
In case of failure, the API does not guarantee recovery,
|
||||||
|
so the state _must_ be reset.
|
||||||
|
To ensure compression success
|
||||||
|
whenever `dst` buffer size cannot be made >= LZ4_compressBound(),
|
||||||
|
consider using LZ4_compress_HC_continue_destSize().
|
||||||
|
|
||||||
|
Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks,
|
||||||
|
it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC().
|
||||||
|
Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB)
|
||||||
|
|
||||||
|
After completing a streaming compression,
|
||||||
|
it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state,
|
||||||
|
just by resetting it, using LZ4_resetStreamHC_fast().
|
||||||
|
*/
|
||||||
|
|
||||||
|
LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); /* v1.9.0+ */
|
||||||
|
LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
|
||||||
|
|
||||||
|
LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr,
|
||||||
|
const char* src, char* dst,
|
||||||
|
int srcSize, int maxDstSize);
|
||||||
|
|
||||||
|
/*! LZ4_compress_HC_continue_destSize() : v1.9.0+
|
||||||
|
* Similar to LZ4_compress_HC_continue(),
|
||||||
|
* but will read as much data as possible from `src`
|
||||||
|
* to fit into `targetDstSize` budget.
|
||||||
|
* Result is provided into 2 parts :
|
||||||
|
* @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)
|
||||||
|
* or 0 if compression fails.
|
||||||
|
* `srcSizePtr` : on success, *srcSizePtr will be updated to indicate how much bytes were read from `src`.
|
||||||
|
* Note that this function may not consume the entire input.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr,
|
||||||
|
const char* src, char* dst,
|
||||||
|
int* srcSizePtr, int targetDstSize);
|
||||||
|
|
||||||
|
LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*^**********************************************
|
||||||
|
* !!!!!! STATIC LINKING ONLY !!!!!!
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
|
/*-******************************************************************
|
||||||
|
* PRIVATE DEFINITIONS :
|
||||||
|
* Do not use these definitions directly.
|
||||||
|
* They are merely exposed to allow static allocation of `LZ4_streamHC_t`.
|
||||||
|
* Declare an `LZ4_streamHC_t` directly, rather than any type below.
|
||||||
|
* Even then, only do so in the context of static linking, as definitions may change between versions.
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
#define LZ4HC_DICTIONARY_LOGSIZE 16
|
||||||
|
#define LZ4HC_MAXD (1<<LZ4HC_DICTIONARY_LOGSIZE)
|
||||||
|
#define LZ4HC_MAXD_MASK (LZ4HC_MAXD - 1)
|
||||||
|
|
||||||
|
#define LZ4HC_HASH_LOG 15
|
||||||
|
#define LZ4HC_HASHTABLESIZE (1 << LZ4HC_HASH_LOG)
|
||||||
|
#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)
|
||||||
|
|
||||||
|
|
||||||
|
/* Never ever use these definitions directly !
|
||||||
|
* Declare or allocate an LZ4_streamHC_t instead.
|
||||||
|
**/
|
||||||
|
typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;
|
||||||
|
struct LZ4HC_CCtx_internal
|
||||||
|
{
|
||||||
|
LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];
|
||||||
|
LZ4_u16 chainTable[LZ4HC_MAXD];
|
||||||
|
const LZ4_byte* end; /* next block here to continue on current prefix */
|
||||||
|
const LZ4_byte* prefixStart; /* Indexes relative to this position */
|
||||||
|
const LZ4_byte* dictStart; /* alternate reference for extDict */
|
||||||
|
LZ4_u32 dictLimit; /* below that point, need extDict */
|
||||||
|
LZ4_u32 lowLimit; /* below that point, no more dict */
|
||||||
|
LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */
|
||||||
|
short compressionLevel;
|
||||||
|
LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set,
|
||||||
|
otherwise, favor compression ratio */
|
||||||
|
LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */
|
||||||
|
const LZ4HC_CCtx_internal* dictCtx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LZ4_STREAMHC_MINSIZE 262200 /* static size, for inter-version compatibility */
|
||||||
|
union LZ4_streamHC_u {
|
||||||
|
char minStateSize[LZ4_STREAMHC_MINSIZE];
|
||||||
|
LZ4HC_CCtx_internal internal_donotuse;
|
||||||
|
}; /* previously typedef'd to LZ4_streamHC_t */
|
||||||
|
|
||||||
|
/* LZ4_streamHC_t :
|
||||||
|
* This structure allows static allocation of LZ4 HC streaming state.
|
||||||
|
* This can be used to allocate statically on stack, or as part of a larger structure.
|
||||||
|
*
|
||||||
|
* Such state **must** be initialized using LZ4_initStreamHC() before first use.
|
||||||
|
*
|
||||||
|
* Note that invoking LZ4_initStreamHC() is not required when
|
||||||
|
* the state was created using LZ4_createStreamHC() (which is recommended).
|
||||||
|
* Using the normal builder, a newly created state is automatically initialized.
|
||||||
|
*
|
||||||
|
* Static allocation shall only be used in combination with static linking.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* LZ4_initStreamHC() : v1.9.0+
|
||||||
|
* Required before first use of a statically allocated LZ4_streamHC_t.
|
||||||
|
* Before v1.9.0 : use LZ4_resetStreamHC() instead
|
||||||
|
*/
|
||||||
|
LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC(void* buffer, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Deprecated Functions
|
||||||
|
**************************************/
|
||||||
|
/* see lz4.h LZ4_DISABLE_DEPRECATE_WARNINGS to turn off deprecation warnings */
|
||||||
|
|
||||||
|
/* deprecated compression functions */
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC (const char* source, char* dest, int inputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
|
||||||
|
/* Obsolete streaming functions; degraded functionality; do not use!
|
||||||
|
*
|
||||||
|
* In order to perform streaming compression, these functions depended on data
|
||||||
|
* that is no longer tracked in the state. They have been preserved as well as
|
||||||
|
* possible: using them will still produce a correct output. However, use of
|
||||||
|
* LZ4_slideInputBufferHC() will truncate the history of the stream, rather
|
||||||
|
* than preserve a window-sized chunk of history.
|
||||||
|
*/
|
||||||
|
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
||||||
|
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);
|
||||||
|
LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data);
|
||||||
|
#endif
|
||||||
|
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||||
|
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void);
|
||||||
|
LZ4_DEPRECATED("use LZ4_initStreamHC() instead") LZ4LIB_API int LZ4_resetStreamStateHC(void* state, char* inputBuffer);
|
||||||
|
|
||||||
|
|
||||||
|
/* LZ4_resetStreamHC() is now replaced by LZ4_initStreamHC().
|
||||||
|
* The intention is to emphasize the difference with LZ4_resetStreamHC_fast(),
|
||||||
|
* which is now the recommended function to start a new stream of blocks,
|
||||||
|
* but cannot be used to initialize a memory segment containing arbitrary garbage data.
|
||||||
|
*
|
||||||
|
* It is recommended to switch to LZ4_initStreamHC().
|
||||||
|
* LZ4_resetStreamHC() will generate deprecation warnings in a future version.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LZ4_HC_H_19834876238432 */
|
||||||
|
|
||||||
|
|
||||||
|
/*-**************************************************
|
||||||
|
* !!!!! STATIC LINKING ONLY !!!!!
|
||||||
|
* Following definitions are considered experimental.
|
||||||
|
* They should not be linked from DLL,
|
||||||
|
* as there is no guarantee of API stability yet.
|
||||||
|
* Prototypes will be promoted to "stable" status
|
||||||
|
* after successful usage in real-life scenarios.
|
||||||
|
***************************************************/
|
||||||
|
#ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */
|
||||||
|
#ifndef LZ4_HC_SLO_098092834
|
||||||
|
#define LZ4_HC_SLO_098092834
|
||||||
|
|
||||||
|
#define LZ4_STATIC_LINKING_ONLY /* LZ4LIB_STATIC_API */
|
||||||
|
#include "lz4.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_setCompressionLevel() : v1.8.0+ (experimental)
|
||||||
|
* It's possible to change compression level
|
||||||
|
* between successive invocations of LZ4_compress_HC_continue*()
|
||||||
|
* for dynamic adaptation.
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API void LZ4_setCompressionLevel(
|
||||||
|
LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);
|
||||||
|
|
||||||
|
/*! LZ4_favorDecompressionSpeed() : v1.8.2+ (experimental)
|
||||||
|
* Opt. Parser will favor decompression speed over compression ratio.
|
||||||
|
* Only applicable to levels >= LZ4HC_CLEVEL_OPT_MIN.
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API void LZ4_favorDecompressionSpeed(
|
||||||
|
LZ4_streamHC_t* LZ4_streamHCPtr, int favor);
|
||||||
|
|
||||||
|
/*! LZ4_resetStreamHC_fast() : v1.9.0+
|
||||||
|
* When an LZ4_streamHC_t is known to be in a internally coherent state,
|
||||||
|
* it can often be prepared for a new compression with almost no work, only
|
||||||
|
* sometimes falling back to the full, expensive reset that is always required
|
||||||
|
* when the stream is in an indeterminate state (i.e., the reset performed by
|
||||||
|
* LZ4_resetStreamHC()).
|
||||||
|
*
|
||||||
|
* LZ4_streamHCs are guaranteed to be in a valid state when:
|
||||||
|
* - returned from LZ4_createStreamHC()
|
||||||
|
* - reset by LZ4_resetStreamHC()
|
||||||
|
* - memset(stream, 0, sizeof(LZ4_streamHC_t))
|
||||||
|
* - the stream was in a valid state and was reset by LZ4_resetStreamHC_fast()
|
||||||
|
* - the stream was in a valid state and was then used in any compression call
|
||||||
|
* that returned success
|
||||||
|
* - the stream was in an indeterminate state and was used in a compression
|
||||||
|
* call that fully reset the state (LZ4_compress_HC_extStateHC()) and that
|
||||||
|
* returned success
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* A stream that was last used in a compression call that returned an error
|
||||||
|
* may be passed to this function. However, it will be fully reset, which will
|
||||||
|
* clear any existing history and settings from the context.
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API void LZ4_resetStreamHC_fast(
|
||||||
|
LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);
|
||||||
|
|
||||||
|
/*! LZ4_compress_HC_extStateHC_fastReset() :
|
||||||
|
* A variant of LZ4_compress_HC_extStateHC().
|
||||||
|
*
|
||||||
|
* Using this variant avoids an expensive initialization step. It is only safe
|
||||||
|
* to call if the state buffer is known to be correctly initialized already
|
||||||
|
* (see above comment on LZ4_resetStreamHC_fast() for a definition of
|
||||||
|
* "correctly initialized"). From a high level, the difference is that this
|
||||||
|
* function initializes the provided state with a call to
|
||||||
|
* LZ4_resetStreamHC_fast() while LZ4_compress_HC_extStateHC() starts with a
|
||||||
|
* call to LZ4_resetStreamHC().
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API int LZ4_compress_HC_extStateHC_fastReset (
|
||||||
|
void* state,
|
||||||
|
const char* src, char* dst,
|
||||||
|
int srcSize, int dstCapacity,
|
||||||
|
int compressionLevel);
|
||||||
|
|
||||||
|
/*! LZ4_attach_HC_dictionary() :
|
||||||
|
* This is an experimental API that allows for the efficient use of a
|
||||||
|
* static dictionary many times.
|
||||||
|
*
|
||||||
|
* Rather than re-loading the dictionary buffer into a working context before
|
||||||
|
* each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a
|
||||||
|
* working LZ4_streamHC_t, this function introduces a no-copy setup mechanism,
|
||||||
|
* in which the working stream references the dictionary stream in-place.
|
||||||
|
*
|
||||||
|
* Several assumptions are made about the state of the dictionary stream.
|
||||||
|
* Currently, only streams which have been prepared by LZ4_loadDictHC() should
|
||||||
|
* be expected to work.
|
||||||
|
*
|
||||||
|
* Alternatively, the provided dictionary stream pointer may be NULL, in which
|
||||||
|
* case any existing dictionary stream is unset.
|
||||||
|
*
|
||||||
|
* A dictionary should only be attached to a stream without any history (i.e.,
|
||||||
|
* a stream that has just been reset).
|
||||||
|
*
|
||||||
|
* The dictionary will remain attached to the working stream only for the
|
||||||
|
* current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the
|
||||||
|
* dictionary context association from the working stream. The dictionary
|
||||||
|
* stream (and source buffer) must remain in-place / accessible / unchanged
|
||||||
|
* through the lifetime of the stream session.
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API void LZ4_attach_HC_dictionary(
|
||||||
|
LZ4_streamHC_t *working_stream,
|
||||||
|
const LZ4_streamHC_t *dictionary_stream);
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LZ4_HC_SLO_098092834 */
|
||||||
|
#endif /* LZ4_HC_STATIC_LINKING_ONLY */
|
||||||
Reference in New Issue
Block a user