├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── FLIF-CLA-template.txt
├── LICENSE
├── LICENSE_Apache2
├── LICENSE_GPL
├── LICENSE_LGPL
├── Makefile
├── README.md
├── build
└── MSVC
│ ├── .gitignore
│ ├── Makefile
│ ├── dl_make_vs.bat
│ ├── dl_make_vs_x64.bat
│ ├── getopt
│ ├── getopt.c
│ └── getopt.h
│ └── make_vs.bat
├── configure.py
├── doc
├── flif.1
├── flif.bash-completion
├── flif.magic
├── flif.pdf
├── metadata
└── produce_documentation
├── extern
├── lodepng.cpp
├── lodepng.h
├── stb_image.h
└── stb_image_write.h
├── raw-tools
├── raw2flif
├── raw2rggb
├── raw2rggb.bat
└── sony_arw
│ ├── README
│ ├── arw_compress.sh
│ ├── arw_decompress.sh
│ ├── arw_encode.c
│ └── dcraw.c
├── src
├── CMakeLists.txt
├── Makefile
├── common.cpp
├── common.hpp
├── compiler-specific.hpp
├── config.h
├── fileio.hpp
├── flif-dec.cpp
├── flif-dec.hpp
├── flif-enc.cpp
├── flif-enc.hpp
├── flif-mime.xml
├── flif-pixbuf-loader.c
├── flif.cpp
├── flif_config.h
├── image
│ ├── color_range.cpp
│ ├── color_range.hpp
│ ├── crc32k.cpp
│ ├── crc32k.hpp
│ ├── image-metadata.cpp
│ ├── image-metadata.hpp
│ ├── image-pam.cpp
│ ├── image-pam.hpp
│ ├── image-png-metadata.hpp
│ ├── image-png.cpp
│ ├── image-png.hpp
│ ├── image-pnm.cpp
│ ├── image-pnm.hpp
│ ├── image-rggb.cpp
│ ├── image-rggb.hpp
│ ├── image.cpp
│ └── image.hpp
├── io.cpp
├── io.hpp
├── library
│ ├── flif-interface-private.hpp
│ ├── flif-interface-private_common.hpp
│ ├── flif-interface-private_dec.hpp
│ ├── flif-interface-private_enc.hpp
│ ├── flif-interface.cpp
│ ├── flif-interface_common.cpp
│ ├── flif-interface_dec.cpp
│ ├── flif-interface_enc.cpp
│ ├── flif.h
│ ├── flif_common.h
│ ├── flif_dec.h
│ └── flif_enc.h
├── maniac
│ ├── bit.cpp
│ ├── bit.hpp
│ ├── chance.cpp
│ ├── chance.hpp
│ ├── compound.hpp
│ ├── compound_enc.hpp
│ ├── rac.hpp
│ ├── rac_enc.hpp
│ ├── symbol.cpp
│ ├── symbol.hpp
│ ├── symbol_enc.hpp
│ └── util.hpp
├── transform
│ ├── bounds.hpp
│ ├── colorbuckets.hpp
│ ├── factory.cpp
│ ├── factory.hpp
│ ├── framecombine.hpp
│ ├── framedup.hpp
│ ├── frameshape.hpp
│ ├── palette.hpp
│ ├── palette_A.hpp
│ ├── palette_C.hpp
│ ├── permute.hpp
│ ├── transform.hpp
│ ├── yc1c2.hpp
│ └── ycocg.hpp
└── viewflif.c
├── testFiles
└── sig05-014.png
└── tools
├── 2_webp_ll.png
├── apng2flif
├── bouncing_ball_frames
├── bouncing-ball-frame01.png
├── bouncing-ball-frame02.png
├── bouncing-ball-frame03.png
├── bouncing-ball-frame04.png
├── bouncing-ball-frame05.png
├── bouncing-ball-frame06.png
├── bouncing-ball-frame07.png
├── bouncing-ball-frame08.png
├── bouncing-ball-frame09.png
├── bouncing-ball-frame10.png
├── bouncing-ball-frame11.png
├── bouncing-ball-frame12.png
├── bouncing-ball-frame13.png
├── bouncing-ball-frame14.png
├── bouncing-ball-frame15.png
├── bouncing-ball-frame16.png
├── bouncing-ball-frame17.png
├── bouncing-ball-frame18.png
├── bouncing-ball-frame19.png
└── bouncing-ball-frame20.png
├── build-libpng.sh
├── endless_war.gif
├── gif2flif
├── kodim01.png
├── sizes.sh
├── test-lossy.sh
├── test-metadata.sh
├── test-roundtrip.sh
├── test-roundtrip_anim.sh
├── test-roundtrip_anim_framedir.sh
└── test.c
/.gitignore:
--------------------------------------------------------------------------------
1 | # build system
2 | obj/
3 | *.pyc
4 | *.pyo
5 | *.o
6 | *.cpp.d
7 | *.c.d
8 | *.h.d
9 | *.gch.d
10 | *.gch
11 | .ninja*
12 | build.ninja
13 |
14 | tags
15 |
16 | # binarys
17 | src/flif
18 | src/flif.asan
19 | src/flif.dbg
20 | src/flif.prof
21 | src/flif.stats
22 | src/libflif.dbg.so
23 | src/libflif.so
24 | src/libflif.dylib
25 | src/libflif.0.dylib
26 |
27 | src/test-interface
28 | src/viewflif
29 | src/dflif
30 |
31 | /*.png
32 | *.xcworkspace/*
33 | *.xcworkspace
34 | *.xcodeproj
35 |
36 | *.so.0
37 | *.so
38 | */*dSYM/*
39 |
40 | flif.osx
41 |
42 | *.swp
43 |
44 | #MSVC
45 | *.exe
46 | *.obj
47 | *.pdb
48 | *.ilk
49 | build/tmp-test/
50 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 |
3 | compiler:
4 | - gcc
5 | - clang
6 |
7 | sudo: true
8 | dist: trusty
9 |
10 | env:
11 | - BUILDTYPE=GNUMAKE
12 |
13 | addons:
14 | apt:
15 | packages:
16 | - libsdl2-dev
17 |
18 | before_install:
19 | - sudo apt-get install build-essential imagemagick libimage-exiftool-perl
20 | # workaround clang not system wide, fail on sudo make install for adms
21 | - export CC=`which $CC`
22 |
23 | install: sudo ./tools/build-libpng.sh
24 |
25 | script:
26 | - if [[ "$BUILDTYPE" == "GNUMAKE" ]]; then cd src && make && make test ; fi
27 | - if [[ "$BUILDTYPE" == "ASAN" ]]; then mkdir build_cmake && cd build_cmake && cmake ../src -DMAKE_BUILD_TYPE=Release -DUSE_ASAN=ON && make && make test ; fi
28 | - if [[ "$BUILDTYPE" == "CMAKE" ]]; then mkdir build_cmake && cd build_cmake && cmake ../src -DMAKE_BUILD_TYPE=Release && make && make test ; fi
29 |
30 | notifications:
31 | webhooks:
32 | urls:
33 | - https://webhooks.gitter.im/e/d7137bab0c1e0a1d1089
34 | on_success: change # options: [always|never|change] default: always
35 | on_failure: always # options: [always|never|change] default: always
36 | on_start: never # options: [always|never|change] default: always
37 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
2 | Thanks for you interest in contributing to FLIF!
3 |
4 | Do you want to contribute, but you do not know where to start?
5 | Take a look here:
6 | - The open issues in the main FLIF repository: https://github.com/FLIF-hub/FLIF/issues (mostly C++ / C)
7 | - poly-flif is a browser poly-fill for FLIF: https://github.com/UprootLabs/poly-flif (JS / emscripten)
8 | - UGUI: FLIF is a graphical user interface wrapper for the command-line utility: https://github.com/FLIF-hub/UGUI_FLIF (HTML / CSS / JS)
9 | - http://flif.info is the official FLIF website. It is hosted on github, and you're invited to contribute to it! https://github.com/FLIF-hub/FLIF-hub.github.io (Jekyll / HTML / CSS)
10 | - Benchmarks are useful not just to compare FLIF to other formats, but also to evaluate modifications in FLIF itself. Test images and benchmark scripts are collected here: https://github.com/FLIF-hub/benchmarks (Shell scripts / Gnuplot)
11 | - Documentation related to FLIF (including, eventually, the detailed format specification) is here: https://github.com/FLIF-hub/FLIF-doc (LaTeX)
12 |
13 | FLIF is currently licensed under the GNU LGPL v3+. The decoder library `libflif_dec` is licensed under the Apache 2.0 license.
14 | When the project is more mature, we (Jon Sneyers and Pieter Wuille, the primary/initial authors of FLIF)
15 | may want to release it under an even more permissive or a different Free Software license should that become desirable.
16 |
17 | For this reason, we ask contributors (i.e. authors of a pull request) to agree to the Contributor License Agreement (CLA) you can
18 | find in the file FLIF-CLA-template.txt in this repository. That allows us to relicense FLIF, including your contributions, if needed.
19 |
20 | More precisely, the set of _potential_ outbound licenses that can be considered,
21 | are the GPL-Compatible Free Software Licenses as listed on this page:
22 | https://gnu.org/licenses/license-list.html#GPLCompatibleLicenses
23 |
24 | Please add your signed CLA to http://github.com/jonsneyers/FLIF-CLAs/
25 | (you can find a template in FLIF-CLA-template.txt)
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | This is the reference implementation of FLIF, copyright (C) 2016 Jon Sneyers and Pieter Wuille.
3 |
4 | It is released under the terms of the GNU Lesser General Public License version 3 or later (LGPLv3+).
5 | The license terms can be found in the files LICENSE_GPL and LICENSE_LGPL.
6 |
7 | The code of the FLIF decoder (not the encoder!) is released under the terms of the Apache 2.0 license.
8 | The library libflif_dec is available under these terms.
9 | A copy of the Apache 2.0 license is available in the file LICENSE_Apache2.
--------------------------------------------------------------------------------
/LICENSE_LGPL:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | cd src && $(MAKE)
3 |
4 | flif:
5 | cd src && $(MAKE) flif
6 |
7 | install:
8 | cd src && $(MAKE) install
9 |
10 | install-dev:
11 | cd src && $(MAKE) install-dev
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ---
3 | **FLIF development has stopped since FLIF is superseded by FUIF and then again by [JPEG XL](https://jpeg.org/jpegxl/), which is based on a combination of [Pik](https://github.com/google/pik) and [FUIF](https://github.com/cloudinary/fuif).
4 | A royalty-free and open source reference implementation of JPEG XL is available on [GitHub](https://github.com/libjxl/libjxl). For more information, see [JPEG XL community page](https://jpegxl.info) or visit the [JPEG XL Discord server](https://discord.gg/DqkQgDRTFu).**
5 |
6 | ---
7 |
8 | # FLIF: Free Lossless Image Format
9 |
10 | [](https://travis-ci.org/FLIF-hub/FLIF)
11 | [](https://gitter.im/jonsneyers/FLIF?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
12 | [](https://snapcraft.io/flif)
13 |
14 | FLIF is a lossless image format based on MANIAC compression. MANIAC (Meta-Adaptive Near-zero Integer Arithmetic Coding)
15 | is a variant of CABAC (context-adaptive binary arithmetic coding), where the contexts are nodes of decision trees
16 | which are dynamically learned at encode time.
17 |
18 | FLIF outperforms PNG, FFV1, lossless WebP, lossless BPG and lossless JPEG2000 in terms of compression ratio.
19 |
20 | Moreover, FLIF supports a form of progressive interlacing (essentially a generalization/improvement of PNG's Adam7)
21 | which means that any prefix (e.g. partial download) of a compressed file can be used as a reasonable lossy encoding of the entire image.
22 |
23 | For more information on FLIF, visit https://flif.info
24 |
25 | * * *
26 |
27 | ## License
28 |
29 | FLIF is copylefted free/libre software: you can redistribute it and/or modify it, provided that you share back.
30 |
31 | The reference implementation of FLIF is released under the terms of the GNU Lesser General Public License version 3 or later (LGPLv3+).
32 |
33 | The decoder library `libflif_dec` is released under a weaker, non-copyleft free software license: the Apache 2.0 license.
34 |
35 | The example application `viewflif` illustrates how to use the decode library.
36 | The example code in `viewflif.c` is in the public domain (Creative Commons CC0 1.0 Universal).
37 |
38 | * * *
39 |
40 | ## Build Instructions
41 |
42 | ### GNU/Linux
43 |
44 | #### Install the dependencies
45 |
46 | On Debian:
47 |
48 | * for the encoder/decoder: `sudo apt-get install libpng-dev`
49 | * for the viewer: `sudo apt-get install libsdl2-dev`
50 |
51 | On Fedora:
52 |
53 | * for the encoder/decoder: `sudo dnf install libpng-devel`
54 | * for the viewer: `sudo dnf install SDL-devel`
55 |
56 | On Ubuntu:
57 |
58 | * for the encoder/decoder: `sudo apt-get install libpng-dev make pkg-config`
59 | * for the viewer: `sudo apt-get install libsdl2-dev`
60 |
61 | #### Compile
62 |
63 | * Navigate to the FLIF/src directory and run `make` to compile everything, or
64 | * `make flif` to build just the `flif` command line tool
65 | * `make libflif.so` to build the LGPL'ed shared library
66 | * `make libflif_dec.so` to build the Apache licensed decode-only shared library
67 | * `make viewflif` to build the example viewer (it depends on the decode library)
68 |
69 | #### Install
70 |
71 | * `sudo make install` if you want to install it globally
72 |
73 | ### Windows
74 |
75 | * Install Visual Studio
76 | ([VS Community 2015](https://www.visualstudio.com/en-us/products/free-developer-offers-vs.aspx)
77 | is free for open source projects)
78 | * Open the `build\MSVC` folder and double-click the `dl_make_vs.bat` file.
79 | This will download required libraries and run `nmake` to build `flif.exe`.
80 | Then, run in the command line:
81 | * `nmake libflif.dll` to build the shared library
82 | * `nmake viewflif.exe` to build the example viewer
83 |
84 | ### OS X
85 |
86 | * Install [homebrew](http://brew.sh)
87 | * Install the dependencies: `brew install pkg-config libpng sdl2`
88 | * Run `make` in the FLIF/src directory
89 |
90 |
91 | * * *
92 |
93 | ## Pre-Built Binaries
94 |
95 | These will be available on the Release page
96 |
97 | * https://github.com/FLIF-hub/FLIF/releases
98 |
99 | Or, you can get the Snap package:
100 |
101 | [](https://snapcraft.io/flif)
102 |
103 | * * *
104 |
105 | ## Related Projects
106 |
107 | * **[Poly FLIF](https://github.com/UprootLabs/poly-flif)** - A javascript polyfill that allows you to use FLIF files in the browser. ([Demo](https://uprootlabs.github.io/poly-flif))
108 | * **[UGUI: FLIF](http://flif.info/UGUI_FLIF)** - A GUI that allows you to convert and view FLIF files.
109 | * **[Ivy, the Taggable Image Viewer](https://github.com/lehitoskin/ivy)** – An image viewer that supports FLIF via [riff](https://github.com/lehitoskin/riff)
110 | * **[flifcrush](https://github.com/FLIF-hub/flifcrush)** - A brute-force FLIF optimizer.
111 | * **[libflif.js](https://github.com/saschanaz/libflif.js/)** – A javascript FLIF encoder and decoder. ([Demo](https://saschanaz.github.io/libflif.js/))
112 | * **[flif.rs](https://github.com/dgriffen/flif.rs)** – A work-in-progress implementation of FLIF in Rust.
113 | * **[FLIF Windows Codec](https://github.com/peirick/FlifWICCodec)** – A plugin that allows you to decode and encode FLIF files in Windows aplications using the Windows Imaging Component (WIC) API. That allows e.g., to see the files in Windows PhotoViewer and Windows Explorer.
114 | * **[FLIF Windows Plugin](https://github.com/fherzog2/flif_windows_plugin)** – This plugin enables decoding of FLIF images in applications which use the Windows Imaging Component API. In this way, FLIF images can be viewed in Windows Explorer like other common image formats.
115 | * **[qt-flif-plugin](https://github.com/spillerrec/qt-flif-plugin)** – Enables Qt4 and Qt5 applications to load images in the FLIF image format.
116 | * **[go-flif](https://github.com/chrisfelesoid/go-flif)** – Go FLIF Library Bindings.
117 | * **[Phew](https://sveinbjorn.org/phew)** - Image viewer for macOS with QuickLook plugin
118 | * **[SDWebImageFLIFCoder](https://github.com/SDWebImage/SDWebImage)** - A popular image loading framework [SDWebImage](https://github.com/SDWebImage/SDWebImage)'s coder plugin, supports iOS/macOS/tvOS/watchOS all Apple platforms.
119 | * **[libflif-Xcode](https://github.com/SDWebImage/libflif-Xcode)** - Xcode project to build libflif on iOS/macOS/tvOS/watchOS all Apple platforms.
120 | * **[flif-wasm](https://github.com/saschanaz/flif-wasm)** - Node.js-ported FLIF command-line tool.
121 | * **[node-flif](https://github.com/FLIF-hub/node-flif)** - A Node.JS wrapper that allows you to use JavaScript to interact with the CLI.
122 | * **[SimplEx FLIF](https://github.com/Atrus09/SimplEx-FLIF)** - A simple and extensive GUI intermediary for the native executables.
123 | * **[WinFLIF](https://github.com/Zaczero/WinFLIF)** - Small Windows desktop app for converting to/from FLIF/PNG stills.
124 | * **[imageio-FLIF](https://codeberg.org/monilophyta/imageio-flif)** - An [Imageio](https://imageio.github.io) (Python) plugin for reading and writing FLIF images and animations
125 |
--------------------------------------------------------------------------------
/build/MSVC/.gitignore:
--------------------------------------------------------------------------------
1 | */
2 |
3 | *.zip
4 | *.dll
5 | *.flif
6 | *.png
7 |
8 | !getopt/
9 |
10 | !include/
11 | include/*
12 |
13 |
--------------------------------------------------------------------------------
/build/MSVC/Makefile:
--------------------------------------------------------------------------------
1 | lpngdir = libpng-libpng-1.6.20-master-signed
2 | zlibdir = zlib-1.2.8
3 | sdl2dir = SDL2-2.0.3
4 |
5 | Incdir = include
6 |
7 | !ifndef PLATFORM
8 | PLATFORM=x86
9 | !endif
10 |
11 | Rt = MD
12 | LibDir = $(PLATFORM)_$(Rt)
13 | SrcDir = ..\..\src
14 | ExtDir = ..\..\extern
15 |
16 | !if "$(Rt)" == "MT" || "$(Rt)" == "MD"
17 | CFLAGS = /nologo /WX /EHsc /GL /Ox /Oy /Gy /DNDEBUG /$(Rt)
18 | LDFLAGS= /nologo /LTCG
19 | !elseif "$(Rt)" == "MTd" || "$(Rt)" == "MDd"
20 | CFLAGS = /nologo /WX /EHsc /Zi /DDEBUG /$(Rt)
21 | LDFLAGS= /nologo /DEBUG
22 | !else
23 | !ERROR Rt=[MT|MD|MTd|MDd]
24 | !endif
25 |
26 | OBJDIR = $(LibDir)\Obj
27 | O = $(OBJDIR)\\
28 |
29 | OBJ1 = $Oflif-dec.obj $Oflif-enc.obj $Oio.obj $Ocommon.obj $Ocolor_range.obj $Ocrc32k.obj $Obit.obj $Ochance.obj $Ofactory.obj $Oimage-metadata.obj $Olodepng.obj
30 | OBJ2 = $Oimage.obj $Oimage-pam.obj $Oimage-png.obj $Oimage-pnm.obj $Oimage-rggb.obj
31 | LIBOBJS = $(OBJ1)
32 | FLIFOBJS = $(OBJ1) $(OBJ2)
33 |
34 | all: flif.exe libflif_dec.dll viewflif.exe test-interface.exe
35 |
36 | flif.exe: $(OBJDIR) $(LibDir)\zlib.lib $(LibDir)\libpng.lib $(FLIFOBJS)
37 | cl $(CFLAGS) /I$(Incdir) /Igetopt $(SrcDir)\flif.cpp getopt\getopt.c /DSTATIC_GETOPT /Fd$O /Fo$O -c
38 | link /out:$(LibDir)\$@ $Oflif.obj $Ogetopt.obj $(FLIFOBJS) $(LibDir)\zlib.lib $(LibDir)\libpng.lib $(LDFLAGS)
39 | copy "$(LibDir)\$@" $@
40 |
41 | libflif.dll: $(OBJDIR) $(LIBOBJS)
42 | cl $(CFLAGS) $(SrcDir)\library\flif-interface.cpp /DFLIF_BUILD_DLL /Fd$O /Fo$O -c
43 | link /dll /out:"$(LibDir)\$@" $Oflif-interface.obj $(LIBOBJS) $(LDFLAGS)
44 | copy "$(LibDir)\$@" $@
45 |
46 | libflif_dec.dll: $(OBJDIR) $(LIBOBJS)
47 | cl $(CFLAGS) $(SrcDir)\library\flif-interface_dec.cpp /DFLIF_BUILD_DLL /Fd$O /Fo$O -c
48 | link /dll /out:"$(LibDir)\$@" $Oflif-interface_dec.obj $(LIBOBJS) $(LDFLAGS)
49 | copy "$(LibDir)\$@" $@
50 |
51 | viewflif.exe: libflif_dec.dll
52 | cl $(CFLAGS) /I$(SrcDir)\ /I$(SrcDir)\library\ /I$(sdl2dir)\include /Tp $(SrcDir)\viewflif.c /DFLIF_USE_DLL /Fd$O /Fo$O -c
53 | link /out:$(LibDir)\$@ $Oviewflif.obj libflif_dec.lib SDL2.lib SDL2main.lib $(LDFLAGS) /SUBSYSTEM:CONSOLE /LIBPATH:$(LibDir) /LIBPATH:$(sdl2dir)\lib\$(PLATFORM)\
54 | copy "$(LibDir)\$@" $@
55 | copy $(sdl2dir)\lib\$(PLATFORM)\SDL2.dll SDL2.dll
56 |
57 | test: flif.exe test-interface.exe
58 | if exist output.flif del output.flif
59 | @echo ./flif.exe ../../tools/kodim01.png output.flif
60 | @powershell "Measure-Command{ ./flif.exe ../../tools/kodim01.png output.flif}"
61 | if exist output.png del output.png
62 | flif output.flif output.png
63 | @if exist "viewflif.exe" viewflif.exe output.flif
64 | @if not exist "..\tmp-test\" mkdir ..\tmp-test
65 | if exist "test-interface.exe" test-interface.exe ..\tmp-test\dummy.flif
66 | start output.png
67 |
68 | test-interface.exe: libflif.dll
69 | cl $(CFLAGS) /I$(Incdir) /I$(SrcDir)\ /I$(SrcDir)\library\ ..\..\tools\test.c /DFLIF_USE_DLL /Fd$O /Fo$O -c
70 | link /out:$(LibDir)\$@ $Otest.obj libflif.lib $(LDFLAGS) /LIBPATH:$(LibDir)
71 | copy "$(LibDir)\$@" $@
72 |
73 | $(OBJDIR):
74 | @if not exist "$(@)/" mkdir "$(@)"
75 |
76 | $(LibDir)\zlib.lib: $(OBJDIR)
77 | @if not exist include mkdir include
78 | cd $(zlibdir)
79 | @nmake -f win32\Makefile.msc clean
80 | nmake -f win32\Makefile.msc zlib.lib CFLAGS="$(CFLAGS) /TC /Fdzlib" ARFLAGS="$(LDFLAGS)"
81 | copy zlib.lib ..\$(LibDir)\\
82 | copy zlib.h ..\$(Incdir)\\
83 | copy zconf.h ..\$(Incdir)\\
84 | cd ..
85 |
86 | $(LibDir)\libpng.lib: $(LibDir)\zlib.lib
87 | @if not exist include mkdir include
88 | cd $(lpngdir)
89 | @nmake -f scripts\Makefile.vcwin32 clean
90 | nmake -f scripts\Makefile.vcwin32 libpng.lib CPPFLAGS="/I..\$(Incdir) " CFLAGS="$(CFLAGS) /TC /D_CRT_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS" ARFLAGS="$(LDFLAGS)"
91 | copy libpng.lib ..\$(LibDir)\\
92 | copy png.h ..\$(Incdir)\\
93 | copy pngconf.h ..\$(Incdir)\\
94 | copy pnglibconf.h ..\$(Incdir)\\
95 | cd ..
96 |
97 | {$(SrcDir)\}.cpp{$(O)}.obj:
98 | cl $(CFLAGS) /Fd$O /Fo$O -c $<
99 | {getopt\}.c{$(O)}.obj:
100 | cl $(CFLAGS) /DSTATIC_GETOPT /Fd$O /Fo$O -c $<
101 | {$(SrcDir)\image\}.cpp{$(O)}.obj:
102 | cl $(CFLAGS) /I$(Incdir) /Fd$O /Fo$O -c $<
103 | {$(SrcDir)\maniac\}.cpp{$(O)}.obj:
104 | cl $(CFLAGS) /Fd$O /Fo$O -c $<
105 | {$(SrcDir)\transform\}.cpp{$(O)}.obj:
106 | cl $(CFLAGS) /Fd$O /Fo$O -c $<
107 | {$(ExtDir)\}.cpp{$(O)}.obj:
108 | cl $(CFLAGS) /Fd$O /Fo$O -c $<
109 |
110 | clean:
111 | -del flif.exe
112 | -del test-interface.exe
113 | -del viewflif.exe
114 | -del SDL2.dll
115 | -del libflif.dll
116 | -del libflif_dec.dll
117 | -del output.png
118 | -del output.flif
119 | -rd /s /q ..\tmp-test
120 | -rd /s /q $(LibDir)
121 |
--------------------------------------------------------------------------------
/build/MSVC/dl_make_vs.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set lpngurl=https://github.com/glennrp/libpng/archive/libpng-1.6.20-master-signed.zip
4 | set lpngzip=libpng-1.6.20-master-signed.zip
5 | set lpngdir=libpng-libpng-1.6.20-master-signed
6 |
7 | set zliburl=https://sourceforge.net/projects/libpng/files/zlib/1.2.8/zlib128.zip/download
8 | set zlibzip=zlib128.zip
9 | set zlibdir=zlib-1.2.8
10 |
11 | set sdl2url=https://www.libsdl.org/release/SDL2-devel-2.0.3-VC.zip
12 | set sdl2zip=SDL2-devel-2.0.3-VC.zip
13 | set sdl2dir=SDL2-2.0.3
14 |
15 | set vswhereurl=https://github.com/Microsoft/vswhere/releases/download/2.4.1/vswhere.exe
16 | set vswherefile=vswhere.exe
17 |
18 |
19 | cd /d %~dp0
20 |
21 | if not exist "%vswherefile%" (
22 | echo download %vswherefile%
23 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%vswhereurl%', '%vswherefile%')"
24 | )
25 |
26 | if not defined VISUALSTUDIOVERSION (
27 | for /f "usebackq tokens=1* delims=: " %%i in (`%vswherefile% -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop`) do (
28 | if /i "%%i"=="installationPath" (
29 | CALL "%%j\VC\Auxiliary\Build\vcvarsall.bat" x86 %1
30 | )
31 | )
32 | )
33 | if not defined VISUALSTUDIOVERSION (
34 | CALL "%VSAPPIDDIR%..\..\VC\Auxiliary\Build\vcvarsall.bat" x86 %1
35 | )
36 | if not defined VISUALSTUDIOVERSION (
37 | CALL "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %1
38 | )
39 | if not defined VISUALSTUDIOVERSION (
40 | echo visual studio not detected
41 | goto end
42 | )
43 | if not defined PLATFORM set PLATFORM=x86
44 |
45 | cd /d %~dp0
46 |
47 | if not exist "%lpngzip%" (
48 | echo download %lpngzip%
49 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%lpngurl%', '%lpngzip%')"
50 | )
51 | if not exist "%lpngdir%\\" (
52 | echo unzip %lpngzip%
53 | PowerShell "(New-Object -ComObject shell.application).NameSpace('%CD%').CopyHere((New-Object -ComObject shell.application).NameSpace('%CD%\%lpngzip%').Items())"
54 | )
55 |
56 | if not exist "%zlibzip%" (
57 | echo download %zlibzip%
58 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%zliburl%', '%zlibzip%')"
59 | )
60 | if not exist "%zlibdir%\\" (
61 | echo unzip %zlibzip%
62 | PowerShell "$s=New-Object -Com shell.application;$s.NameSpace('%CD%').CopyHere($s.NameSpace('%CD%\%zlibzip%').Items())"
63 | )
64 |
65 | if not exist "%sdl2zip%" (
66 | echo download %sdl2zip%
67 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%sdl2url%', '%sdl2zip%')"
68 | )
69 | if not exist "%sdl2dir%\\" (
70 | echo unzip %sdl2zip%
71 | PowerShell "$s=New-Object -Com shell.application;$s.NameSpace('%CD%').CopyHere($s.NameSpace('%CD%\%sdl2zip%').Items())"
72 | )
73 |
74 | nmake Rt=MD
75 | nmake Rt=MD test
76 | rem nmake Rt=MT flif.exe
77 | rem debug MTd|MDd
78 | rem nmake Rt=MDd all
79 |
80 | :end
81 | cmd
82 |
--------------------------------------------------------------------------------
/build/MSVC/dl_make_vs_x64.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set lpngurl=https://github.com/glennrp/libpng/archive/libpng-1.6.20-master-signed.zip
4 | set lpngzip=libpng-1.6.20-master-signed.zip
5 | set lpngdir=libpng-libpng-1.6.20-master-signed
6 |
7 | set zliburl=https://sourceforge.net/projects/libpng/files/zlib/1.2.8/zlib128.zip/download
8 | set zlibzip=zlib128.zip
9 | set zlibdir=zlib-1.2.8
10 |
11 | set sdl2url=https://www.libsdl.org/release/SDL2-devel-2.0.3-VC.zip
12 | set sdl2zip=SDL2-devel-2.0.3-VC.zip
13 | set sdl2dir=SDL2-2.0.3
14 |
15 | set vswhereurl=https://github.com/Microsoft/vswhere/releases/download/2.4.1/vswhere.exe
16 | set vswherefile=vswhere.exe
17 |
18 |
19 | cd /d %~dp0
20 |
21 | if not exist "%vswherefile%" (
22 | echo download %vswherefile%
23 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%vswhereurl%', '%vswherefile%')"
24 | )
25 |
26 | if not defined VISUALSTUDIOVERSION (
27 | for /f "usebackq tokens=1* delims=: " %%i in (`%vswherefile% -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop`) do (
28 | if /i "%%i"=="installationPath" (
29 | CALL "%%j\VC\Auxiliary\Build\vcvarsall.bat" amd64 %1
30 | )
31 | )
32 | )
33 | if not defined VISUALSTUDIOVERSION (
34 | CALL "%VSAPPIDDIR%..\..\VC\Auxiliary\Build\vcvarsall.bat" amd64 %1
35 | )
36 | if not defined VISUALSTUDIOVERSION (
37 | CALL "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %1
38 | )
39 | if not defined VISUALSTUDIOVERSION (
40 | echo visual studio not detected
41 | goto end
42 | )
43 | if not defined PLATFORM set PLATFORM=x86
44 |
45 | cd /d %~dp0
46 |
47 | if not exist "%lpngzip%" (
48 | echo download %lpngzip%
49 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%lpngurl%', '%lpngzip%')"
50 | )
51 | if not exist "%lpngdir%\\" (
52 | echo unzip %lpngzip%
53 | PowerShell "(New-Object -ComObject shell.application).NameSpace('%CD%').CopyHere((New-Object -ComObject shell.application).NameSpace('%CD%\%lpngzip%').Items())"
54 | )
55 |
56 | if not exist "%zlibzip%" (
57 | echo download %zlibzip%
58 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%zliburl%', '%zlibzip%')"
59 | )
60 | if not exist "%zlibdir%\\" (
61 | echo unzip %zlibzip%
62 | PowerShell "$s=New-Object -Com shell.application;$s.NameSpace('%CD%').CopyHere($s.NameSpace('%CD%\%zlibzip%').Items())"
63 | )
64 |
65 | if not exist "%sdl2zip%" (
66 | echo download %sdl2zip%
67 | PowerShell "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('%sdl2url%', '%sdl2zip%')"
68 | )
69 | if not exist "%sdl2dir%\\" (
70 | echo unzip %sdl2zip%
71 | PowerShell "$s=New-Object -Com shell.application;$s.NameSpace('%CD%').CopyHere($s.NameSpace('%CD%\%sdl2zip%').Items())"
72 | )
73 |
74 | nmake Rt=MD
75 | nmake Rt=MD test
76 | rem nmake Rt=MT flif.exe
77 | rem debug MTd|MDd
78 | rem nmake Rt=MDd all
79 |
80 | :end
81 | cmd
82 |
--------------------------------------------------------------------------------
/build/MSVC/getopt/getopt.h:
--------------------------------------------------------------------------------
1 | /* Getopt for Microsoft C
2 | This code is a modification of the Free Software Foundation, Inc.
3 | Getopt library for parsing command line argument the purpose was
4 | to provide a Microsoft Visual C friendly derivative. This code
5 | provides functionality for both Unicode and Multibyte builds.
6 |
7 | Date: 02/03/2011 - Ludvik Jerabek - Initial Release
8 | Version: 1.0
9 | Comment: Supports getopt, getopt_long, and getopt_long_only
10 | and POSIXLY_CORRECT environment flag
11 | License: LGPL
12 |
13 | Revisions:
14 |
15 | 02/03/2011 - Ludvik Jerabek - Initial Release
16 | 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
17 | 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
18 | 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
19 | 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
20 | 02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
21 | 08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
22 | 10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
23 | 06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable
24 |
25 | **DISCLAIMER**
26 | THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
27 | EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
28 | IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
29 | PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
30 | EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
31 | APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
32 | DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
33 | USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
34 | PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
35 | YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
36 | EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37 | */
38 | #ifndef __GETOPT_H_
39 | #define __GETOPT_H_
40 |
41 | #ifdef _GETOPT_API
42 | #undef _GETOPT_API
43 | #endif
44 |
45 | #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT)
46 | #error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually"
47 | #elif defined(STATIC_GETOPT)
48 | #pragma message("Warning static builds of getopt violate the Lesser GNU Public License")
49 | #define _GETOPT_API
50 | #elif defined(EXPORTS_GETOPT)
51 | #pragma message("Exporting getopt library")
52 | #define _GETOPT_API __declspec(dllexport)
53 | #else
54 | #pragma message("Importing getopt library")
55 | #define _GETOPT_API __declspec(dllimport)
56 | #endif
57 |
58 | // Change behavior for C\C++
59 | #ifdef __cplusplus
60 | #define _BEGIN_EXTERN_C extern "C" {
61 | #define _END_EXTERN_C }
62 | #define _GETOPT_THROW throw()
63 | #else
64 | #define _BEGIN_EXTERN_C
65 | #define _END_EXTERN_C
66 | #define _GETOPT_THROW
67 | #endif
68 |
69 | // Standard GNU options
70 | #define null_argument 0 /*Argument Null*/
71 | #define no_argument 0 /*Argument Switch Only*/
72 | #define required_argument 1 /*Argument Required*/
73 | #define optional_argument 2 /*Argument Optional*/
74 |
75 | // Shorter Options
76 | #define ARG_NULL 0 /*Argument Null*/
77 | #define ARG_NONE 0 /*Argument Switch Only*/
78 | #define ARG_REQ 1 /*Argument Required*/
79 | #define ARG_OPT 2 /*Argument Optional*/
80 |
81 | #include
82 | #include
83 |
84 | _BEGIN_EXTERN_C
85 |
86 | extern _GETOPT_API int optind;
87 | extern _GETOPT_API int opterr;
88 | extern _GETOPT_API int optopt;
89 |
90 | // Ansi
91 | struct option_a
92 | {
93 | const char* name;
94 | int has_arg;
95 | int *flag;
96 | int val;
97 | };
98 | extern _GETOPT_API char *optarg_a;
99 | extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char *optstring) _GETOPT_THROW;
100 | extern _GETOPT_API int getopt_long_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW;
101 | extern _GETOPT_API int getopt_long_only_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW;
102 |
103 | // Unicode
104 | struct option_w
105 | {
106 | const wchar_t* name;
107 | int has_arg;
108 | int *flag;
109 | int val;
110 | };
111 | extern _GETOPT_API wchar_t *optarg_w;
112 | extern _GETOPT_API int getopt_w(int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW;
113 | extern _GETOPT_API int getopt_long_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW;
114 | extern _GETOPT_API int getopt_long_only_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW;
115 |
116 | _END_EXTERN_C
117 |
118 | #undef _BEGIN_EXTERN_C
119 | #undef _END_EXTERN_C
120 | #undef _GETOPT_THROW
121 | #undef _GETOPT_API
122 |
123 | #ifdef _UNICODE
124 | #define getopt getopt_w
125 | #define getopt_long getopt_long_w
126 | #define getopt_long_only getopt_long_only_w
127 | #define option option_w
128 | #define optarg optarg_w
129 | #else
130 | #define getopt getopt_a
131 | #define getopt_long getopt_long_a
132 | #define getopt_long_only getopt_long_only_a
133 | #define option option_a
134 | #define optarg optarg_a
135 | #endif
136 | #endif // __GETOPT_H_
137 |
--------------------------------------------------------------------------------
/build/MSVC/make_vs.bat:
--------------------------------------------------------------------------------
1 | echo release
2 | cl /nologo /DFLIF_USE_STB_IMAGE /Feflif.exe -I getopt\ /DSTATIC_GETOPT ..\..\src\flif.cpp ..\..\src\flif-dec.cpp ..\..\src\flif-enc.cpp ..\..\src\common.cpp ..\..\src\io.cpp ..\..\src\maniac\*.c* ..\..\src\transform\*.cpp ..\..\src\image\*.c* getopt/getopt.c ..\..\extern\lodepng.cpp /WX /EHsc /Ox /Oy /MT /DNDEBUG
3 |
4 | echo debug
5 | cl /nologo /DFLIF_USE_STB_IMAGE /Feflif-d.exe -I getopt\ /DSTATIC_GETOPT ..\..\src\flif.cpp ..\..\src\flif-dec.cpp ..\..\src\flif-enc.cpp ..\..\src\common.cpp ..\..\src\io.cpp ..\..\src\maniac\*.c* ..\..\src\transform\*.cpp ..\..\src\image\*.c* getopt/getopt.c ..\..\extern\lodepng.cpp /WX /EHsc /Zi /Oy- /MDd /DDEBUG
6 |
7 | del *.obj
8 |
9 | echo test
10 | if exist output.flif del output.flif
11 | flif ..\..\tools/kodim01.png output.flif
12 | if exist output.png del output.png
13 | flif output.flif output.png
14 | start output.png
--------------------------------------------------------------------------------
/configure.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | import os
3 | import sys
4 | import fnmatch
5 |
6 |
7 | __doc__ = """Build configurator for FLIF.
8 |
9 | Usage:
10 | configure.py [options] [-D var]...
11 |
12 | Options:
13 | --native Enable native optimizations.
14 | -d, --debug Compile with debug.
15 | -D var Define variable. Also -D EXAMPLE=1.
16 | -o file Output ninja file [default: build.ninja].
17 | -h, --help Show this screen.
18 | """
19 |
20 | def find_objects(n, dirpaths):
21 | objects = []
22 | for dirpath in dirpaths:
23 | for root, dirnames, filenames in os.walk(dirpath):
24 | for filename in fnmatch.filter(filenames, "*.cpp"):
25 | if "flif-interface" in filename:
26 | continue
27 | src = os.path.join(root, filename)
28 | obj = os.path.join("obj", os.path.splitext(src)[0] + ".o")
29 | n.build(obj, "cxx", src)
30 | objects.append(obj)
31 | return objects
32 |
33 | def write_ninja(n, args):
34 | ########################
35 | # Generic build rules. #
36 | ########################
37 | exe_ext = ".exe" if os.name == "nt" else ""
38 | n.variable("cxx", "g++")
39 |
40 | if args["--debug"]:
41 | n.variable("dbgflags", "-ggdb")
42 | debug_flag = ""
43 | else:
44 | n.variable("dbgflags", "")
45 | debug_flag = " -DNDEBUG"
46 |
47 | native_flag = " -march=native" if args["--native"] else ""
48 | n.variable("optflags", "-O2 -ftree-vectorize" + native_flag + debug_flag)
49 |
50 | defines = [" -D" + d for d in args["-D"]]
51 | cxxflags = "-std=c++11 -Wall -pedantic `pkg-config --cflags zlib libpng`"
52 | n.variable("cxxflags", cxxflags + "".join(defines))
53 | n.variable("cxxlinkflags", "`pkg-config --libs libpng`")
54 |
55 | n.rule("cxx",
56 | "$cxx $xtype -MMD -MF $out.d $optflags $dbgflags $cxxflags -c $in -o $out",
57 | depfile="$out.d")
58 |
59 | n.rule("cxxlink", "$cxx $optflags $dbgflags $in $cxxlinkflags -o $out")
60 |
61 | ###################
62 | # Build commands. #
63 | ###################
64 | objects = find_objects(n, ["extern", "src"])
65 | n.build("src/flif" + exe_ext, "cxxlink", objects)
66 | n.default("src/flif" + exe_ext)
67 |
68 |
69 | try:
70 | from docopt import docopt
71 | import ninja_syntax
72 | except ImportError:
73 | msg = """You are missing one or more dependencies, install using:
74 |
75 | {} -m pip install --user docopt ninja-syntax
76 |
77 | If you are using an old version of Python, and don't have pip,
78 | download https://bootstrap.pypa.io/get-pip.py and run it."""
79 |
80 | print(msg.format(os.path.basename(sys.executable)))
81 | sys.exit(1)
82 |
83 |
84 | args = docopt(__doc__)
85 |
86 | # Check if we're likely running for the first time.
87 | first_time = not os.path.isfile(args["-o"])
88 |
89 | # Write ninja build file.
90 | with open(args["-o"], "w") as ninja_file:
91 | n = ninja_syntax.Writer(ninja_file)
92 | write_ninja(n, args)
93 |
94 | # Check if we have ninja in path.
95 | path = os.environ.get("PATH", os.defpath).split(os.pathsep)
96 | if sys.platform == "win32":
97 | path.insert(0, os.curdir)
98 | pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
99 | files = ["ninja" + ext for ext in pathext]
100 | else:
101 | files = ["ninja"]
102 |
103 | is_exe = lambda p: os.path.exists(p) and os.access(p, os.F_OK | os.X_OK) and not os.path.isdir(p)
104 | has_ninja = any(is_exe(os.path.join(d, f)) for d in path for f in files)
105 |
106 | if first_time:
107 | if not has_ninja:
108 | msg = """It appears you're running configure.py for the first time, but do not have
109 | ninja in your path. On Windows we recommend simply downloading the binary:
110 |
111 | https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip
112 |
113 | Extract anywhere in your path, or even inside this directory.
114 |
115 | On linux it's easiest to compile from source:
116 |
117 | wget https://github.com/ninja-build/ninja/archive/v1.6.0.tar.gz
118 | tar xf v1.6.0.tar.gz && rm v1.6.0.tar.gz && cd ninja-1.6.0
119 | {} configure.py --bootstrap
120 | sudo cp ninja /usr/local/bin
121 |
122 | This should only take half a minute or so."""
123 | print(msg.format(os.path.basename(sys.executable)))
124 | else:
125 | print("Type 'ninja' to build FLIF.")
126 |
--------------------------------------------------------------------------------
/doc/flif.bash-completion:
--------------------------------------------------------------------------------
1 | # flif(1) completion -*- shell-script -*-
2 |
3 | _flif()
4 | {
5 | local cur prev words cword split
6 | _init_completion -s || return
7 |
8 | action=unknown
9 | next_arg_needed=unknown
10 | base_name=output
11 |
12 | # scan the previous arguments to guess what we are doing: encoding or decoding?
13 | for pw in "${words[@]:1:$((cword - 1))}"; do
14 | case $pw in
15 | -d|--decode)
16 | action=decode
17 | next_arg_needed=flif
18 | ;;
19 | -i|--identify)
20 | action=identify
21 | next_arg_needed=flif
22 | ;;
23 | -t|--transcode)
24 | action=transcode
25 | next_arg_needed=flif
26 | ;;
27 | -e|--encode)
28 | action=encode
29 | next_arg_needed=nonflif
30 | ;;
31 | -*)
32 | ;;
33 | *.flif|*.flf)
34 | case $action in
35 | unknown|decode)
36 | action=decode
37 | base_name=$pw
38 | base_name=$(basename "$base_name" .flif)
39 | base_name=$(basename "$base_name" .flf)
40 | case $next_arg_needed in
41 | flif|unknown)
42 | next_arg_needed=nonflif
43 | ;;
44 | nonflif)
45 | action=transcode
46 | next_arg_needed=none
47 | ;;
48 | esac
49 | ;;
50 | transcode)
51 | case $next_arg_needed in
52 | flif)
53 | next_arg_needed=flif2
54 | base_name=$pw
55 | base_name=$(basename "$base_name" .flif)
56 | base_name=$(basename "$base_name" .flf)
57 | base_name="$base_name-transcoded"
58 | ;;
59 | flif2)
60 | next_arg_needed=none
61 | ;;
62 | esac
63 | ;;
64 | encode)
65 | next_arg_needed=none
66 | ;;
67 | esac
68 | ;;
69 | *)
70 | case $action in
71 | unknown|encode)
72 | action=encode
73 | next_arg_needed=flif
74 | base_name=$pw
75 | base_name=$(basename "$base_name" .png)
76 | base_name=$(basename "$base_name" .pnm)
77 | base_name=$(basename "$base_name" .pam)
78 | base_name=$(basename "$base_name" .ppm)
79 | base_name=$(basename "$base_name" .pgm)
80 | base_name=$(basename "$base_name" .pbm)
81 | base_name=$(basename "$base_name" .rggb)
82 | ;;
83 | decode)
84 | next_arg_needed=none
85 | ;;
86 | esac
87 | ;;
88 | esac
89 | done
90 | if [[ $cur != "" ]]; then
91 | base_name=$cur
92 | fi
93 |
94 |
95 | case $action-$next_arg_needed in
96 | # input file names
97 | decode-flif|identify-flif|transcode-flif)
98 | _filedir '@(flif|flf)'
99 | return
100 | ;;
101 | encode-nonflif)
102 | _filedir '@(png|pnm|pam|ppm|pgm|pbm|rggb)'
103 | return
104 | ;;
105 |
106 | # suggest sensible name for output file
107 | encode-flif)
108 | if [[ $cur == -* ]]; then
109 | COMPREPLY=( $( compgen -W '$( _parse_help "$1" -vvveh )' -- "$cur" ) )
110 | [[ $COMPREPLY == *= ]] && compopt -o nospace
111 | return
112 | fi
113 | COMPREPLY=$base_name.flif
114 | return
115 | ;;
116 | transcode-flif2)
117 | if [[ $cur == -* ]]; then
118 | COMPREPLY=( $( compgen -W '$( _parse_help "$1" -vvvh )' -- "$cur" ) )
119 | [[ $COMPREPLY == *= ]] && compopt -o nospace
120 | return
121 | fi
122 | COMPREPLY=$base_name.flif
123 | return
124 | ;;
125 | decode-nonflif)
126 | if [[ $cur == -* ]]; then
127 | COMPREPLY=( $( compgen -W '$( _parse_help "$1" -vvvdh )' -- "$cur" ) )
128 | [[ $COMPREPLY == *= ]] && compopt -o nospace
129 | return
130 | fi
131 | COMPREPLY=$base_name.png
132 | return
133 | ;;
134 |
135 | # no more arguments needed, suggest options
136 | decode-none)
137 | # only show decode options
138 | COMPREPLY=( $( compgen -W '$( _parse_help "$1" -vvvdh)' -- "$cur") )
139 | [[ $COMPREPLY == *= ]] && compopt -o nospace
140 | return
141 | ;;
142 | encode-none)
143 | # only show encode options
144 | COMPREPLY=( $( compgen -W '$( _parse_help "$1" -vvveh)' -- "$cur" ) )
145 | [[ $COMPREPLY == *= ]] && compopt -o nospace
146 | return
147 | ;;
148 | *-none)
149 | # show all options
150 | COMPREPLY=( $( compgen -W '$( _parse_help "$1" -vvvh)' -- "$cur" ) )
151 | [[ $COMPREPLY == *= ]] && compopt -o nospace
152 | return
153 | ;;
154 | esac
155 |
156 | $split && return 0
157 |
158 | if [[ $cur == -* ]]; then
159 | COMPREPLY=( $( compgen -W '$( _parse_help "$1" -vvvh )' -- "$cur" ) )
160 | [[ $COMPREPLY == *= ]] && compopt -o nospace
161 | return
162 | fi
163 |
164 | # suggest filenames
165 | _filedir '@(flif|flf|png|pnm|pam|ppm|pgm|pbm|rggb)'
166 | } &&
167 | complete -F _flif flif
168 |
--------------------------------------------------------------------------------
/doc/flif.magic:
--------------------------------------------------------------------------------
1 | # Magic data for file(1) command. (append to /etc/magic)
2 |
3 | # FLIF (Free Lossless Image Format)
4 | 0 string FLIF FLIF
5 | >4 string 5 string 1 8-bit/color
7 | >5 string 2 16-bit/color
8 | >4 string 1 grayscale, non-interlaced
9 | >4 string 3 RGB, non-interlaced
10 | >4 string 4 RGBA, non-interlaced
11 | >4 string A grayscale
12 | >4 string C RGB, interlaced
13 | >4 string D RGBA, interlaced
14 | >4 string >H animation data,
15 | >4 string Q grayscale, non-interlaced
16 | >4 string S RGB, non-interlaced
17 | >4 string T RGBA, non-interlaced
18 | >4 string a grayscale
19 | >4 string c RGB, interlaced
20 | >4 string d RGBA, interlaced
21 |
22 | #TODO: parse width/height/nb_frames (can this be done?)
--------------------------------------------------------------------------------
/doc/flif.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/doc/flif.pdf
--------------------------------------------------------------------------------
/doc/metadata:
--------------------------------------------------------------------------------
1 |
2 |
3 | Chunks are defined similar to PNG chunks, except the chunk size is encoded with a variable number of bytes, and there is no chunk CRC.
4 | Also, the first chunk (which is always "FLIF") has no explicit chunk size.
5 |
6 | Chunk names are either 4 letters (4 bytes), or 1 byte with a value below 32.
7 |
8 | The convention of using upper and lower case letters is kept, but the meaning of the bits is slightly different.
9 | - First letter: uppercase=critical, lowercase=non-critical --> non-critical chunks can be stripped while keeping a valid file (it might be rendered differently though)
10 | - Second letter: uppercase=public, lowercase=private
11 | - Third letter: uppercase=needed to correctly display the image (e.g. a color profile), lowercase=can be stripped safely without changing anything visually
12 | - Fourth letter: uppercase=safe to copy blindly (when editing the actual image data), lowercase=may depend on image data (e.g. contain a thumbnail)
13 |
14 | Variable-size integer encoding:
15 | An unsigned integer (Big-Endian, MSB first) stored on a variable number of bytes.
16 | All the bytes except the last one have a '1' as their first bit.
17 | The unsigned integer is represented as the concatenation of the remaining 7 bit codewords.
18 |
19 | All non-obligatory chunks have a contents that is compressed with DEFLATE.
20 |
21 | The simplest FLIF file is simply a FLIF chunk followed by a \0 chunk with the actual image data.
22 |
23 |
24 | Chunk name: FLIF
25 | Obligatory: yes
26 | Description: header chunk
27 | Chunk size: not encoded
28 | Contents:
29 | First byte (byte 5 in the file) : encodes number of channels, animation or not ("1"=Grayscale non-interlaced, "3"=RGB, "4"=RGBA, +0x10 for interlaced, +0x20 for animation)
30 | Second byte (byte 6) : encodes color depth ("1" = 8-bit, "2" = 16-bit, "0" = custom)
31 | Next the image width - 1, encoded in a variable number of bytes
32 | Next the image height - 1, encoded in a variable number of bytes
33 | If it's an animation, then the number of frames - 2, encoded in a variable number of bytes
34 |
35 |
36 | Chunk name: tRko
37 | Obligatory: no
38 | Description: list of truncation offsets
39 | Contents:
40 | To be defined.
41 | Will contain a list of offsets which correspond to good truncation points,
42 | e.g. for use on a web server that uses Client Hints to send truncated FLIF files. Offsets should be relative to the start of the image data (\0 chunk
43 | for a FLIF16 image).
44 |
45 |
46 | Chunk name: iCCP
47 | Obligatory: no
48 | Description: ICC color profile. If this chunk is not present, the color profile is implicitly sRGB.
49 | Contents:
50 | the raw ICC color profile data
51 |
52 | Chunk name: eXif
53 | Obligatory: no
54 | Description: Exif metadata
55 | Contents: "Exif\0\0" header followed immediately by a TIFF header and the EXIF data.
56 |
57 | Chunk name: eXmp
58 | Obligatory: no
59 | Description: XMP metadata
60 | Contents: XMP contained within a read-only xpacket with no padding.
61 |
62 | Chunk name: \0
63 | Obligatory: yes
64 | Description: image data encoded in the FLIF16 format (future revisions of the format will use a different name, we have room for 30 revisions)
65 | Chunk size: not encoded
66 | Has to be the last chunk in the stream
67 | Contains actual image data
68 |
--------------------------------------------------------------------------------
/doc/produce_documentation:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | for manual in flif
4 | do
5 | man -l -t ./$manual.1 | ps2pdf - $manual.pdf
6 | done
7 |
--------------------------------------------------------------------------------
/raw-tools/raw2flif:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | FLIF="../src/flif -vvv"
4 | TMPDIR="tmp_raw2flif"
5 |
6 | if ! $FLIF -h >/dev/null
7 | then
8 | echo FLIF not found, please compile FLIF first!
9 | exit 1
10 | fi
11 |
12 | if [ $# -lt 2 ]
13 | then
14 | echo "Usage: $0 input_raw_file output.flif"
15 | else
16 | mkdir -p $TMPDIR
17 | rm -f $TMPDIR/*
18 | if dcraw -i "$1" > $TMPDIR/__dcraw_id
19 | then
20 | # extract metadata
21 | exiv2 ex -l $TMPDIR "$1"
22 | # extract raw data by using raw2rggb
23 | ./raw2rggb "$1" $TMPDIR/_image_tmp.rggb
24 | # flif it
25 | $FLIF $TMPDIR/_image_tmp.rggb $TMPDIR/__image.flif
26 | # remove the uncompressed data
27 | rm $TMPDIR/_image_tmp.rggb
28 | # put it all (id, metadata, compressed raw data) in an archive
29 | ar r "$2" $TMPDIR/*
30 | else
31 | echo "Not a camera raw file: $1"
32 | fi
33 | rm -f $TMPDIR/*
34 | rmdir $TMPDIR
35 | fi
36 |
--------------------------------------------------------------------------------
/raw-tools/raw2rggb:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | FLIF="./flif -vvv"
4 |
5 | if [ $# -lt 2 ]
6 | then
7 | echo "Usage: $0 input_raw_file output.rggb"
8 | else
9 | if dcraw -i "$1" > /dev/null
10 | then
11 | # get Filter pattern //Fuji_xf1: BGGRBGGRBGGRBGGR, Pana_gh3: GBRGGBRGGBRGGBRG, leica_m82: RGGBRGGBRGGBRGGB
12 | CFAPattern=`dcraw -i -v "$1" | grep "Filter pattern: " | sed "s/Filter pattern: //g"`
13 | if [ -z "$CFAPattern" ]
14 | then
15 | Raw_color=`dcraw -i -v "$1" | grep "Raw colors: " | sed "s/Raw colors: //g"`
16 | if [ "$Raw_color" == "3" ]
17 | then
18 | PNMType="P6"
19 | else
20 | echo "This raw color is unknown: $Raw_color"
21 | exit 1
22 | fi
23 | else
24 | PNMType="P5"
25 | fi
26 | Rotate=""
27 | if [ "$PNMType" == "P5" ]
28 | then
29 | # get Orientation: "Horizontal (normal)", "Rotate 90 CW", "Rotate 180 CW", "Rotate 270 CW"
30 | Orientation=`exiftool -Orientation "$1" | sed "s/Orientation : //g"`
31 | # TODO: Remove this case part when FLIF can handle the "CFAPattern" comment
32 | # case "$CFAPattern" in
33 | # RGGBRGGBRGGBRGGB)
34 | # Rotate="-t 0";;
35 | # GRBGGRBGGRBGGRBG)
36 | # Rotate="-t 270";;
37 | # BGGRBGGRBGGRBGGR)
38 | # Rotate="-t 180";;
39 | # GBRGGBRGGBRGGBRG)
40 | # Rotate="-t 90";;
41 | # *)
42 | # echo "This pattern is unknown: $CFAPattern"
43 | # exit 1
44 | # esac
45 | # Determine the CFA pattern of output image (without the -t parameter)
46 | case "$CFAPattern" in
47 | RGGBRGGBRGGBRGGB)
48 | case "$Orientation" in
49 | "Horizontal (normal)")
50 | CFAPattern="RGGB";;
51 | "Rotate 90 CW")
52 | CFAPattern="GRBG";;
53 | "Rotate 180 CW")
54 | CFAPattern="BGGR";;
55 | "Rotate 270 CW")
56 | CFAPattern="GBRG";;
57 | *)
58 | echo "This orientation is unknown: $Orientation"". Assuming Horizontal."
59 | CFAPattern="RGGB";;
60 | esac;;
61 | GRBGGRBGGRBGGRBG)
62 | case "$Orientation" in
63 | "Horizontal (normal)")
64 | CFAPattern="GRBG";;
65 | "Rotate 90 CW")
66 | CFAPattern="BGGR";;
67 | "Rotate 180 CW")
68 | CFAPattern="GBRG";;
69 | "Rotate 270 CW")
70 | CFAPattern="RGGB";;
71 | *)
72 | echo "This orientation is unknown: $Orientation"". Assuming Horizontal."
73 | CFAPattern="GRBG";;
74 | esac;;
75 | BGGRBGGRBGGRBGGR)
76 | case "$Orientation" in
77 | "Horizontal (normal)")
78 | CFAPattern="BGGR";;
79 | "Rotate 90 CW")
80 | CFAPattern="GBRG";;
81 | "Rotate 180 CW")
82 | CFAPattern="RGGB";;
83 | "Rotate 270 CW")
84 | CFAPattern="GRBG";;
85 | *)
86 | echo "This orientation is unknown: $Orientation"". Assuming Horizontal."
87 | CFAPattern="BGGR";;
88 | esac;;
89 | GBRGGBRGGBRGGBRG)
90 | case "$Orientation" in
91 | "Horizontal (normal)")
92 | CFAPattern="GBRG";;
93 | "Rotate 90 CW")
94 | CFAPattern="RGGB";;
95 | "Rotate 180 CW")
96 | CFAPattern="GRBG";;
97 | "Rotate 270 CW")
98 | CFAPattern="BGGR";;
99 | *)
100 | echo "This orientation is unknown: $Orientation"". Assuming Horizontal."
101 | CFAPattern="GBRG";;
102 | esac;;
103 | *)
104 | echo "This pattern is unknown: $CFAPattern"
105 | exit 1
106 | esac
107 | fi
108 | # Add CFAPattern comment
109 | echo "$PNMType" > "$2"
110 | if [ "$PNMType" == "P5" ]
111 | then
112 | echo "# CFAPattern: $CFAPattern" >> "$2"
113 | fi
114 | # extract raw data, presumably in some kind of RGGB format
115 | dcraw -E -4 -c "$1" | sed -b -e "1d" >> "$2"
116 | else
117 | echo "Not a camera raw file: $1"
118 | fi
119 | fi
120 |
--------------------------------------------------------------------------------
/raw-tools/raw2rggb.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | SET EXIFTOOL=exiftool.exe
3 | SET DCRAW=dcraw.exe
4 | SET SED=sed.exe
5 |
6 | SET CMDFI=%0
7 | SET INFI=%1
8 | SET OUTFI=%2
9 | SET NOTFI=%3
10 |
11 | IF NOT "%NOTFI%"=="" IF "%OUFI%"=="" (
12 | ECHO Usage: raw2rggb.bat input_raw_file output.rggb
13 | EXIT /B 1
14 | )
15 |
16 |
17 | IF "%DCRAW% -i %INFI%"=="" (
18 | ECHO Not a camera raw file: %INFI%
19 | EXIT /B 1
20 | )
21 |
22 |
23 | REM get Filter pattern //Fuji_xf1: BGGRBGGRBGGRBGGR, Pana_gh3: GBRGGBRGGBRGGBRG, leica_m82: RGGBRGGBRGGBRGGB
24 | SET RCOLOR=
25 | SET PNMTYPE=P5
26 | SET Rotate=
27 | SET CFAP=
28 | for /f "delims=" %%a in ('%DCRAW% -i -v %INFI% ^| findstr "Filter pattern: " ^| %SED% "s/Filter pattern: //g" ^| %SED% "s/\///g"') do @set CFAP=%%a
29 | for /f "delims=" %%a in ('%DCRAW% -i -v %INFI% ^| findstr "Raw colors: " ^| %SED% "s/Raw colors: //g"') do @set RCOLOR=%%a
30 | IF "%CFAP%"=="" (
31 | IF "%RCOLOR%"=="3" (
32 | SET PNMTYPE=P6
33 | GOTO GT_DECOMP
34 | ) ELSE (
35 | ECHO This raw color is unknown: %RCOLOR%
36 | EXIT /B 1
37 | )
38 | )
39 |
40 | REM get Orientation: "Horizontal (normal)", "Rotate 90 CW", "Rotate 180 CW", "Rotate 270 CW"
41 | SET Orientation=
42 | for /f "delims=" %%a in ('%EXIFTOOL% -Orientation %1 ^| %SED% "s/Orientation : //g" ^| %SED% "s/ (normal)//g"') do @set Orientation=%%a
43 | IF !Orientation!=="Horizontal" SET Orientation=Horizontal
44 | IF !Orientation!=="Rotate 90 CW" SET Orientation=90CW
45 | IF !Orientation!=="Rotate 180 CW" SET Orientation=180CW
46 | IF !Orientation!=="Rotate 270 CW" SET Orientation=270CW
47 |
48 | REM SET Rotate=-t 0
49 | REM TODO: Remove this case part when FLIF can handle the "CFAP" comment
50 | REM IF "%CFAP%"=="RGGB" (
51 | REM SET Rotate=-t 0
52 | REM) ELSE IF "%CFAP%"=="GRBG" (
53 | REM SET Rotate=-t 270
54 | REM ) ELSE IF "%CFAP%"=="BGGR" (
55 | REM SET Rotate=-t 180
56 | REM) ELSE IF "%CFAP%"=="GBRG" (
57 | REM SET Rotate=-t 90
58 | REM) ELSE (
59 | REM ECHO This pattern is unknown: %CFAP%
60 | REM EXIT /B 1
61 | REM)
62 |
63 | REM Determine the CFA pattern of output image (without the -t parameter)
64 | IF "%CFAP%"=="RGGB" (
65 | IF "%Orientation%"=="90CW" (
66 | SET CFAP=GRBG
67 | ) ELSE IF "%Orientation%"=="180CW" (
68 | SET CFAP=BGGR
69 | ) ELSE IF "%Orientation%"=="270CW" (
70 | SET CFAP=GBRG
71 | ) ELSE IF NOT "%Orientation%"=="Horizontal" (
72 | ECHO This orientation is unknown: %Orientation%. Assuming Horizontal.
73 | )
74 | ) ELSE IF "%CFAP%"=="GRBG" (
75 | IF "%Orientation%"=="90CW" (
76 | SET CFAP=BGGR
77 | ) ELSE IF "%Orientation%"=="180CW" (
78 | SET CFAP=GBRG
79 | ) ELSE IF "%Orientation%"=="270CW" (
80 | SET CFAP=RGGB
81 | ) ELSE IF NOT "%Orientation%"=="Horizontal" (
82 | ECHO This orientation is unknown: %Orientation%. Assuming Horizontal.
83 | )
84 | ) ELSE IF "%CFAP%"=="BGGR" (
85 | IF "%Orientation%"=="90CW" (
86 | SET CFAP=GBRG
87 | ) ELSE IF "%Orientation%"=="180CW" (
88 | SET CFAP=RGGB
89 | ) ELSE IF "%Orientation%"=="270CW" (
90 | SET CFAP=GRBG
91 | ) ELSE IF NOT "%Orientation%"=="Horizontal" (
92 | ECHO This orientation is unknown: %Orientation%. Assuming Horizontal.
93 | )
94 | ) ELSE IF "%CFAP%"=="GBRG" (
95 | IF "%Orientation%"=="90CW" (
96 | SET CFAP=RGGB
97 | ) ELSE IF "%Orientation%"=="180CW" (
98 | SET CFAP=GRBG
99 | ) ELSE IF "%Orientation%"=="270CW" (
100 | SET CFAP=BGGR
101 | ) ELSE IF NOT "%Orientation%"=="Horizontal" (
102 | ECHO This orientation is unknown: %Orientation%. Assuming Horizontal.
103 | )
104 | ) ELSE (
105 | ECHO This pattern is unknown: %CFAP%
106 | EXIT /B 1
107 | )
108 |
109 | :GT_DECOMP
110 | REM Add CFAP comment
111 | REM ECHO %PNMTYPE%>%OUTFI%
112 | IF "%PNMTYPE%"=="P5" ECHO # CFAPattern: %CFAP%>%OUTFI%
113 | REM extract raw data, presumably in some kind of RGGB format
114 | %DCRAW% -E -4 -c %INFI%>>%OUTFI%
115 |
--------------------------------------------------------------------------------
/raw-tools/sony_arw/README:
--------------------------------------------------------------------------------
1 | These tools can losslessly compress and decompress a Sony ARW (RAW) image file.
2 |
3 | INSTALLATION
4 |
5 | First, compile the C stuff:
6 | $ gcc -o arw_encode arw_encode.c
7 | $ gcc -o dcraw_hack -lm dcraw.c
8 |
9 | Then, ensure that you have flif (http://flif.info/) and the binaries above
10 | in your $PATH. You'll also need ImageMagick's convert, as well as some
11 | standard tools like sha256sum and tar (see *.sh for details).
12 |
13 | USAGE
14 |
15 | To compress, use
16 | $ arw_compress.sh filename.ARW
17 |
18 | This should create a filename.ARW.flifraw that's generally 50-75% the size
19 | of the .ARW file.
20 |
21 | To recover your original .ARW file:
22 | $ arw_decompress.sh filename.ARW.flifraw
23 |
24 | LICENSE
25 |
26 | GPLv3 or later. Includes modified code of dcraw (see header of dcraw.c
27 | for details).
28 |
29 | TECHNICAL INFO
30 |
31 | These tools create a .tar.xz file which contains the ARW header (which
32 | usually includes a lossy JPG preview - this is untouched), a flif-compressed
33 | image of the raw sensor data (in 16 bits per channel), and a list of "alarms",
34 | ie. some sony-specific fixup data that allows us to recreate the original ARW
35 | perfectly.
36 |
37 | arw_encode then reads this list of "alarms" and recreates the ARW file.
38 |
39 | The need for those "alarms" arises from a funny encoding that Sony uses
40 | in their RAW files. The original sensor data is about 11-bits per pixel,
41 | but it is compressed into 8 bits, sometimes losing some detail. The
42 | compression is pretty simple: it takes 16 pixel values, encodes the
43 | minimum and the maximum value of those 16, and then encodes the remaining 14
44 | values as 8-bit differences from the minimum. There's also a "shift" amount
45 | applied in case the range of those 16 pixels is larger than 255 (that's when
46 | data loss happens). Because sometimes there's more than one "minimum" or
47 | "maximum" value pixel, there can be multiple ways that Sony can encode these.
48 | I couldn't find a consistent way in which this is encoded, so if the ARW
49 | differs from the simple heuristic I used, an "alarm" is raised and stored in
50 | an exceptions file.
51 |
52 | This exceptions file could probably be ignored and the resulting ARW file
53 | would be pixel-for-pixel identical with the original, but I wanted to make
54 | sure the compression scheme is truly lossless and preserves the file
55 | perfectly.
56 |
--------------------------------------------------------------------------------
/raw-tools/sony_arw/arw_compress.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | set -e
4 |
5 | SRC="$1"
6 | DST="$2"
7 |
8 | if [ "x$SRC" == "x" ]
9 | then
10 | echo "Need a source file!"
11 | exit 1
12 | fi
13 |
14 | if [ "x$DST" == "x" ]
15 | then
16 | DST="$SRC.flifraw"
17 | fi
18 |
19 | if [ -e "$DST" ]
20 | then
21 | echo "Destination $DST already exists, refusing to overwrite"
22 | exit 1
23 | fi
24 |
25 | DIR=$(mktemp -d "$DST.XXXXXX")
26 |
27 | cat < "$DIR"/file.list
28 | $DIR/alarms.bin
29 | $DIR/begin
30 | $DIR/orig.sha256
31 | EOL
32 |
33 | sha256sum - < "$SRC" > "$DIR"/orig.sha256
34 | dcraw_hack "$SRC" > "$DIR"/temp.rgba 2> "$DIR"/err
35 | HALF_SIZE=$(head -n1 "$DIR"/err | sed -e 's/^.*, half=\([0-9]*x[0-9]*\)$/\1/')
36 | convert -depth 16 -size $HALF_SIZE rgba:"$DIR"/temp.rgba png:"$DIR"/temp.png
37 | grep ALARM "$DIR"/err | cut -c 8- | xxd -r -ps > "$DIR"/alarms.bin
38 | LAST_LINE=$(tail -n1 "$DIR"/err)
39 | PADDING_BYTE=00
40 | if (echo "$LAST_LINE" | grep -q PADDING "$DIR"/err)
41 | then
42 | PADDING_BYTE=$(echo "$LAST_LINE" | cut -c 10-)
43 | echo $PADDING_BYTE | xxd -r -ps > "$DIR"/padding
44 | echo "$DIR"/padding >> "$DIR"/file.list
45 | fi
46 |
47 | START=$(head -n1 "$DIR"/err | sed -e 's/^.*data_at=//' -e 's/, .*$//')
48 | HALF_WIDTH=$(echo $HALF_SIZE | sed -e 's/x.*$//')
49 |
50 | flif -e --keep-invisible-rgb "$DIR"/temp.png "$DIR"/result.flif
51 |
52 | flif -d "$DIR"/result.flif "$DIR"/result.flif.png
53 | head -c $START "$SRC" > "$DIR"/begin
54 |
55 | if (cat "$DIR"/begin; convert "$DIR"/result.flif.png -depth 16 rgba:- | arw_encode $HALF_WIDTH $START "$DIR"/alarms.bin $PADDING_BYTE) | cmp - "$SRC"
56 | then
57 | cat "$DIR"/file.list | xargs tar --transform 's=^.*/==' -Jcf "$DIR"/extra.tar.xz
58 | tar --transform 's=^.*/==' -cf "$DST" "$DIR"/extra.tar.xz "$DIR"/result.flif
59 | cat "$DIR"/file.list | xargs rm "$DIR"/{extra.tar.xz,result.flif,err,result.flif.png,temp.png,temp.rgba,file.list}
60 | rmdir "$DIR"
61 | else
62 | echo data mismatch, temp stuff left in $DIR
63 | exit 1
64 | fi
65 |
--------------------------------------------------------------------------------
/raw-tools/sony_arw/arw_decompress.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | set -e
4 |
5 | SRC="$1"
6 | DST="$2"
7 |
8 | if [ "x$SRC" == "x" ]
9 | then
10 | echo "Need a source file!"
11 | exit 1
12 | fi
13 |
14 | if [ "x$DST" == "x" ]
15 | then
16 | DST=$(echo "$SRC" | sed -e 's/\.flifraw$//')
17 | fi
18 |
19 | if [ -e "$DST" ]
20 | then
21 | echo "Destination $DST already exists, refusing to overwrite"
22 | exit 1
23 | fi
24 |
25 | DIR=$(mktemp -d "$DST.XXXXXX")
26 |
27 | tar -C "$DIR" -xf "$SRC"
28 | tar -C "$DIR" -Jxf "$DIR"/extra.tar.xz
29 | START=$(stat -c '%s' "$DIR"/begin)
30 | HALF_WIDTH=$(flif -i "$DIR"/result.flif | sed -e 's/^.*FLIF image, \([0-9]*\)x.*$/\1/')
31 | PADDING=00
32 | if [ -e "$DIR"/padding ]
33 | then
34 | PADDING=$(head -c1 "$DIR/padding" | xxd -ps)
35 | rm "$DIR"/padding
36 | fi
37 |
38 | flif -d "$DIR"/result.flif "$DIR"/result.flif.png
39 | (cat "$DIR"/begin; convert "$DIR"/result.flif.png -depth 16 rgba:- | arw_encode $HALF_WIDTH $START "$DIR"/alarms.bin $PADDING) > "$DST"
40 | if ! sha256sum --quiet -c "$DIR"/orig.sha256 < "$DST"
41 | then
42 | echo "SHA mismatch, $DST broken, stuff left in $DIR :-("
43 | exit 1
44 | fi
45 | rm "$DIR"/{extra.tar.xz,result.flif,result.flif.png,begin,orig.sha256,alarms.bin}
46 | rmdir "$DIR"
47 |
--------------------------------------------------------------------------------
/raw-tools/sony_arw/arw_encode.c:
--------------------------------------------------------------------------------
1 | #define _GNU_SOURCE
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | void writebits(uint8_t *dst, int from, int len, uint16_t data)
8 | {
9 | int bit;
10 |
11 | for(bit = 0; bit < len; bit++) {
12 | int val = (data & (1 << bit));
13 | int obyte = (from + bit) >> 3;
14 | int bitpos = (from+bit) & 0x07;
15 |
16 | if(val)
17 | dst[obyte] = dst[obyte] | (1 << bitpos);
18 | else
19 | dst[obyte] = dst[obyte] & ~(1 << bitpos);
20 | }
21 | }
22 |
23 | struct exception {
24 | uint32_t chunk;
25 | uint8_t minmax;
26 | };
27 |
28 | struct exception load_exception(FILE *f)
29 | {
30 | struct exception rv;
31 | unsigned char buf[5];
32 | rv.chunk=0xffffffff;
33 |
34 | if(!f)
35 | return rv;
36 |
37 | if(fread(buf, 1, 5, f) != 5)
38 | return rv;
39 |
40 | rv.chunk = 0;
41 | rv.chunk |= buf[3];
42 | rv.chunk |= buf[2] << 8;
43 | rv.chunk |= buf[1] << 16;
44 | rv.chunk |= buf[0] << 24;
45 | rv.minmax = buf[4];
46 |
47 | return rv;
48 | }
49 |
50 | static inline int exception_valid(struct exception *e)
51 | {
52 | return e->chunk != 0xffffffff;
53 | }
54 |
55 | uint32_t chunk_cnt=0;
56 | struct exception exception;
57 | FILE *excf=NULL;
58 |
59 | void arw_encode(uint16_t *buf)
60 | {
61 | uint8_t outbuf[16];
62 | uint16_t max=0, min=0xffff, imax, imin, sh;
63 | int i, pos;
64 |
65 | // find min/max
66 | if(exception_valid(&exception) && exception.chunk == chunk_cnt) {
67 | imin = exception.minmax >> 4;
68 | imax = exception.minmax & 0x0f;
69 | min = buf[imin];
70 | max = buf[imax];
71 | exception = load_exception(excf);
72 | } else {
73 | for(i = 0; i < 16; i++) {
74 | if(buf[i] >= max) {
75 | max = buf[i];
76 | imax = i;
77 | }
78 | if(buf[i] < min) {
79 | min = buf[i];
80 | imin = i;
81 | }
82 | }
83 | }
84 |
85 | // find shift
86 | for(sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
87 |
88 | writebits(outbuf, 0, 11, max);
89 | writebits(outbuf, 11, 11, min);
90 | writebits(outbuf, 22, 4, imax);
91 | writebits(outbuf, 26, 4, imin);
92 |
93 | pos = 30;
94 | for(i = 0; i < 16; i++) {
95 | if(i != imin && i != imax) {
96 | writebits(outbuf, pos, 7, (buf[i]-min) >> sh);
97 | pos += 7;
98 | }
99 | }
100 |
101 | fwrite(outbuf, 1, 16, stdout);
102 | chunk_cnt++;
103 | }
104 |
105 | void flush_arw(uint16_t *outbuf, int *outcnt)
106 | {
107 | if(*outcnt >= 32) {
108 | uint16_t arwbuf[32];
109 | int arwbuf_cnt = 0;
110 |
111 | int j;
112 | for(j = 0; j < 32; j+=2) {
113 | arwbuf[arwbuf_cnt++] = outbuf[j];
114 | }
115 | for(j = 1; j < 32; j+=2) {
116 | arwbuf[arwbuf_cnt++] = outbuf[j];
117 | }
118 |
119 | arw_encode(arwbuf);
120 | arw_encode(arwbuf+16);
121 |
122 | *outcnt = 0;
123 | }
124 | }
125 |
126 | void write_padding(long headerlen, int val)
127 | {
128 | long our_len = headerlen + chunk_cnt * 16;
129 | long shouldbe = (our_len / 0x8000) * 0x8000 + 0x8000;
130 | long missing = shouldbe - our_len;
131 |
132 | char *buf;
133 | buf = malloc(missing);
134 | if(!buf) {
135 | fprintf(stderr, "woops, can't alloc padding\n");
136 | } else {
137 | memset(buf, val, missing);
138 | fwrite(buf, 1, missing, stdout);
139 | free(buf);
140 | }
141 | }
142 |
143 | int main(int argc, char **argv)
144 | {
145 | long width, headerlen;
146 | uint16_t *buf;
147 | uint16_t arw_buf[32];
148 | int arw_buf_cnt = 0;
149 | int padding = 0;
150 |
151 | if(argc < 3) {
152 | fprintf(stderr, "need at least a width, a headerlen, and possibly an exceptions file\n");
153 | return 1;
154 | }
155 |
156 | width = atol(argv[1]);
157 | headerlen = atol(argv[2]);
158 |
159 | buf = malloc(sizeof(uint16_t) * width * 4);
160 | if(!buf) {
161 | fprintf(stderr, "alloc error\n");
162 | return 1;
163 | }
164 |
165 | if(argc > 3)
166 | excf = fopen(argv[3], "r");
167 |
168 | if(argc > 4)
169 | padding = strtol(argv[4], NULL, 16);
170 |
171 | exception = load_exception(excf);
172 |
173 | while(!feof(stdin)) {
174 | size_t rv;
175 | int i;
176 | if((rv=fread(buf, sizeof(uint16_t), width*4, stdin)) != width*4) {
177 | if(rv != 0)
178 | fprintf(stderr, "read only %lu\n", (unsigned long) rv);
179 | continue;
180 | }
181 |
182 | for(i = 0; i < width * 4; i += 4) {
183 | arw_buf[arw_buf_cnt++] = buf[i] >> 5;
184 | arw_buf[arw_buf_cnt++] = buf[i+1] >> 5;
185 | flush_arw(arw_buf, &arw_buf_cnt);
186 | }
187 | for(i = 0; i < width * 4; i += 4) {
188 | arw_buf[arw_buf_cnt++] = buf[i+3] >> 5;
189 | arw_buf[arw_buf_cnt++] = buf[i+2] >> 5;
190 | flush_arw(arw_buf, &arw_buf_cnt);
191 | }
192 | }
193 |
194 | free(buf);
195 |
196 | write_padding(headerlen, padding);
197 |
198 | return 0;
199 | }
200 |
--------------------------------------------------------------------------------
/src/compiler-specific.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifdef _MSC_VER
4 | #define ATTRIBUTE_HOT
5 | #else
6 | #define ATTRIBUTE_HOT __attribute__ ((hot))
7 | #endif
--------------------------------------------------------------------------------
/src/config.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*****************************************/
4 | /* OPTIONS TO DISABLE SOME FUNCTIONALITY */
5 | /*****************************************/
6 |
7 | // define this flag if you want support for > 8 bit per channel
8 | #ifndef ONLY_8BIT
9 | #define SUPPORT_HDR 1
10 | #endif
11 |
12 | // include encoder related functionality in build. Disable when only interested in decoder
13 | #ifndef DECODER_ONLY
14 | #define HAS_ENCODER 1
15 | #endif
16 |
17 | // support animations
18 | #ifndef STILL_ONLY
19 | #define SUPPORT_ANIMATION 1
20 | #endif
21 |
22 |
23 | // during decode, check for unexpected file end and interpolate from there
24 | #define CHECK_FOR_BROKENFILES 1
25 |
26 | // maximum image buffer size to attempt to decode
27 | // (the format supports larger images/animations, but this threshold helps to avoid malicious input to grab too much memory)
28 | // this is one frame of 1000 megapixels 8-bit RGB (it's 5 bytes per pixel because YCoCg uses 2 bytes each for Co/Cg)
29 | // (or 1000 frames of 1 megapixel)
30 | #define MAX_IMAGE_BUFFER_SIZE 1000ULL*1000000ULL*5ULL
31 |
32 | // refuse to decode something which claims to have more frames than this
33 | #define MAX_FRAMES 50000
34 |
35 | /************************/
36 | /* COMPILATION OPTIONS */
37 | /************************/
38 |
39 | // speed / binary size trade-off: 0, 1, 2 (higher number -> bigger and faster binary)
40 | #define LARGE_BINARY 1
41 |
42 | #ifndef __clang__
43 | #define USE_SIMD 1
44 | #endif
45 |
46 | /**************************/
47 | /* FIX COMPILER WARNINGS */
48 | /**************************/
49 |
50 | #ifdef FLIF_UNUSED
51 | #elif defined(__GNUC__) || defined(__clang__)
52 | # define FLIF_UNUSED(x) x __attribute__((unused))
53 | #elif defined(__LCLINT__)
54 | # define FLIF_UNUSED(x) /*@unused@*/ x
55 | #else
56 | # define FLIF_UNUSED(x) x
57 | #endif
58 |
59 | /*************************************************/
60 | /* OPTIONS TO CHANGE DEFAULT ENCODING PARAMETERS */
61 | /*************************************************/
62 |
63 | // more repeats makes encoding more expensive, but results in better trees (smaller files)
64 | #define TREE_LEARN_REPEATS 2
65 |
66 | #define DEFAULT_MAX_PALETTE_SIZE 512
67 |
68 | // 8 byte improvement needed before splitting a MANIAC leaf node
69 | #define CONTEXT_TREE_SPLIT_THRESHOLD 5461*8*8
70 |
71 | #define CONTEXT_TREE_COUNT_DIV 30
72 | #define CONTEXT_TREE_MIN_SUBTREE_SIZE 50
73 |
74 |
75 |
76 | /**************************************************/
77 | /* DANGER ZONE: OPTIONS THAT CHANGE THE BITSTREAM */
78 | /* If you modify these, the bitstream format */
79 | /* changes, so it is no longer compatible! */
80 | /**************************************************/
81 |
82 | // output the first K zoomlevels without building trees (too little data anyway to learn much from it)
83 | #define NB_NOLEARN_ZOOMS 12
84 | // this is enough to get a reasonable thumbnail/icon before the tree gets built/transmitted (at most 64x64 pixels)
85 |
86 | // faster decoding, less compression (disable multi-scale bitchances, use 24-bit rac)
87 | #define FAST_BUT_WORSE_COMPRESSION 1
88 |
89 | // bounds for node counters
90 | #define CONTEXT_TREE_MIN_COUNT 1
91 | #define CONTEXT_TREE_MAX_COUNT 512
92 |
93 |
94 |
95 | // DEFAULT ENCODE/DECODE OPTIONS ARE DEFINED BELOW
96 |
97 |
98 | #include
99 | #include
100 |
101 | enum class Optional : uint8_t {
102 | undefined = 0
103 | };
104 |
105 | enum class flifEncoding : uint8_t {
106 | nonInterlaced = 1,
107 | interlaced = 2
108 | };
109 |
110 | union flifEncodingOptional {
111 | flifEncoding encoding;
112 | Optional o;
113 | flifEncodingOptional() : o(Optional::undefined) {}
114 | };
115 |
116 | struct flif_options {
117 | #ifdef HAS_ENCODER
118 | int learn_repeats;
119 | int acb;
120 | std::vector frame_delay;
121 | int palette_size;
122 | int lookback;
123 | int divisor;
124 | int min_size;
125 | int split_threshold;
126 | int ycocg;
127 | int subtract_green;
128 | int plc;
129 | int frs;
130 | int alpha_zero_special;
131 | int loss;
132 | int adaptive;
133 | int predictor[5];
134 | int chroma_subsampling;
135 | #endif
136 | flifEncodingOptional method;
137 | int invisible_predictor;
138 | int alpha;
139 | int cutoff;
140 | int crc_check;
141 | int metadata;
142 | int color_profile;
143 | int quality;
144 | int scale;
145 | int resize_width;
146 | int resize_height;
147 | int fit;
148 | int overwrite;
149 | int just_add_loss;
150 | int show_breakpoints;
151 | int no_full_decode;
152 | int keep_palette;
153 | };
154 |
155 | const struct flif_options FLIF_DEFAULT_OPTIONS = {
156 | #ifdef HAS_ENCODER
157 | -1, // learn_repeats
158 | -1, // acb, try auto color buckets
159 | {100}, // frame_delay
160 | -1, // palette_size
161 | 1, // lookback
162 | CONTEXT_TREE_COUNT_DIV, // divisor
163 | CONTEXT_TREE_MIN_SUBTREE_SIZE, // min_size
164 | CONTEXT_TREE_SPLIT_THRESHOLD, // split_threshold
165 | 1, // ycocg
166 | 1, // subtract_green
167 | 1, // plc
168 | 1, // frs
169 | 1, // alpha_zero_special
170 | 0, // loss
171 | 0, // adaptive
172 | {-2,-2,-2,-2,-2}, // predictor, heuristically pick a fixed predictor on all planes
173 | 0, // chroma_subsampling
174 | #endif
175 | flifEncodingOptional(), // method
176 | 2, // invisible_predictor
177 | 19, // alpha
178 | 2, // cutoff
179 | -1, // crc_check
180 | 1, // metadata
181 | 1, // color_profile
182 | 100, // quality, 100 = everything, positive value: partial decode, negative value: only rough data
183 | 1, // scale
184 | 0, // resize_width
185 | 0, // resize_height
186 | 0, // fit
187 | 0, // overwrite
188 | 0, // just_add_loss
189 | 0, // show_breakpoints
190 | 0, // no_full_decode
191 | 0, // keep_palette
192 | };
193 |
--------------------------------------------------------------------------------
/src/fileio.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | class FileIO
25 | {
26 | private:
27 | FILE *file;
28 | const char *name;
29 | public:
30 | // prevent copy
31 | FileIO(const FileIO&) = delete;
32 | void operator=(const FileIO&) = delete;
33 | // prevent move, for now
34 | FileIO(FileIO&&) = delete;
35 | void operator=(FileIO&&) = delete;
36 |
37 | const int EOS = EOF;
38 |
39 | FileIO(FILE* fil, const char *aname) : file(fil), name(aname) { }
40 | ~FileIO() {
41 | if (file) fclose(file);
42 | }
43 | void flush() {
44 | fflush(file);
45 | }
46 | bool isEOF() {
47 | return feof(file);
48 | }
49 | long ftell() {
50 | return ::ftell(file);
51 | }
52 | int get_c() {
53 | return fgetc(file);
54 | }
55 | char * gets(char *buf, int n) {
56 | return fgets(buf, n, file);
57 | }
58 | int fputs(const char *s) {
59 | return ::fputs(s, file);
60 | }
61 | int fputc(int c) {
62 | return ::fputc(c, file);
63 | }
64 | void fseek(long offset, int where) {
65 | ::fseek(file, offset,where);
66 | }
67 | const char* getName() const {
68 | return name;
69 | }
70 | };
71 |
72 | /*!
73 | * Read-only IO interface for a constant memory block
74 | */
75 | class BlobReader
76 | {
77 | private:
78 | const uint8_t* data;
79 | size_t data_array_size;
80 | size_t seek_pos;
81 | bool readEOS;
82 | public:
83 | const int EOS = -1;
84 |
85 | BlobReader(const uint8_t* _data, size_t _data_array_size)
86 | : data(_data)
87 | , data_array_size(_data_array_size)
88 | , seek_pos(0)
89 | , readEOS(false)
90 | {
91 | }
92 |
93 | bool isEOF() const {
94 | if(readEOS) {
95 | return true;
96 | } else {
97 | return false;
98 | }
99 | }
100 | long ftell() const {
101 | return seek_pos;
102 | }
103 | int get_c() {
104 | if(seek_pos >= data_array_size) {
105 | readEOS = true;
106 | return EOS;
107 | }
108 | return data[seek_pos++];
109 | }
110 | char * gets(char *buf, int n) {
111 | int i = 0;
112 | const int max_write = n-1;
113 | while(seek_pos < data_array_size && i < max_write)
114 | buf[i++] = data[seek_pos++];
115 | buf[n-1] = '\0';
116 |
117 | if(i < max_write) {
118 | readEOS = true;
119 | return 0;
120 | } else {
121 | return buf;
122 | }
123 | }
124 | int fputc(int FLIF_UNUSED(c)) {
125 | // cannot write on const memory
126 | return EOS;
127 | }
128 | void fseek(long offset, int where) {
129 | readEOS = false;
130 | switch(where) {
131 | case SEEK_SET:
132 | seek_pos = offset;
133 | break;
134 | case SEEK_CUR:
135 | seek_pos += offset;
136 | break;
137 | case SEEK_END:
138 | seek_pos = long(data_array_size) + offset;
139 | break;
140 | }
141 | }
142 | static const char* getName() {
143 | return "BlobReader";
144 | }
145 | };
146 |
147 | /*!
148 | * IO interface for a growable memory block
149 | */
150 | class BlobIO
151 | {
152 | private:
153 | uint8_t* data;
154 | // keeps track how large the array really is
155 | // HINT: should only be used in the grow() function
156 | size_t data_array_size;
157 | // keeps track how many bytes were written
158 | size_t bytes_used;
159 | size_t seek_pos;
160 | bool readEOS;
161 |
162 | void grow(size_t necessary_size) {
163 | readEOS = false;
164 | if(necessary_size < data_array_size)
165 | return;
166 |
167 | size_t new_size = necessary_size;
168 | // start with reasonably large array
169 | if(new_size < 4096)
170 | new_size = 4096;
171 |
172 | if(new_size < data_array_size * 3 / 2)
173 | new_size = data_array_size * 3 / 2;
174 | uint8_t* new_data = new uint8_t[new_size];
175 |
176 | memcpy(new_data, data, bytes_used);
177 | // if seek_pos has been moved beyond the written bytes,
178 | // fill the empty space with zeroes
179 | for(size_t i = bytes_used; i < seek_pos; ++i)
180 | new_data[i] = 0;
181 | delete [] data;
182 | data = new_data;
183 | std::swap(data_array_size, new_size);
184 | }
185 | public:
186 | const int EOS = -1;
187 |
188 | BlobIO()
189 | : data(0)
190 | , data_array_size(0)
191 | , bytes_used(0)
192 | , seek_pos(0)
193 | , readEOS(false)
194 | {
195 | }
196 |
197 | ~BlobIO() {
198 | delete [] data;
199 | }
200 |
201 | uint8_t* release(size_t* array_size)
202 | {
203 | uint8_t* ptr = data;
204 | *array_size = bytes_used;
205 |
206 | data = 0;
207 | data_array_size = 0;
208 | bytes_used = 0;
209 | seek_pos = 0;
210 | return ptr;
211 | }
212 |
213 | static void flush() {
214 | // nothing to do
215 | }
216 | bool isEOF() const {
217 | if(readEOS) {
218 | return true;
219 | } else {
220 | return false;
221 | }
222 | }
223 | long ftell() const {
224 | return seek_pos;
225 | }
226 | int get_c() {
227 | if(seek_pos >= bytes_used) {
228 | readEOS = true;
229 | return EOS;
230 | }
231 | return data[seek_pos++];
232 | }
233 | char * gets(char *buf, int n) {
234 | int i = 0;
235 | const int max_write = n-1;
236 | while(seek_pos < bytes_used && i < max_write)
237 | buf[i++] = data[seek_pos++];
238 | buf[n-1] = '\0';
239 |
240 | if(i < max_write) {
241 | readEOS = true;
242 | return 0;
243 | } else {
244 | return buf;
245 | }
246 | }
247 | int fputs(const char *s) {
248 | size_t i = 0;
249 | // null-terminated string
250 | while(s[i])
251 | {
252 | grow(seek_pos + 1);
253 | data[seek_pos++] = s[i++];
254 | if(bytes_used < seek_pos)
255 | bytes_used = seek_pos+1;
256 | }
257 | return 0;
258 | }
259 | int fputc(int c) {
260 | grow(seek_pos + 1);
261 |
262 | data[seek_pos++] = static_cast(c);
263 | if(bytes_used < seek_pos)
264 | bytes_used = seek_pos+1;
265 | return c;
266 | }
267 | void fseek(long offset, int where) {
268 | readEOS = false;
269 | switch(where) {
270 | case SEEK_SET:
271 | seek_pos = offset;
272 | break;
273 | case SEEK_CUR:
274 | seek_pos += offset;
275 | break;
276 | case SEEK_END:
277 | seek_pos = long(bytes_used) + offset;
278 | break;
279 | }
280 | }
281 | static const char* getName() {
282 | return "BlobIO";
283 | }
284 | };
285 |
286 |
--------------------------------------------------------------------------------
/src/flif-dec.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct FLIF_INFO
4 | {
5 | FLIF_INFO();
6 |
7 | uint32_t width;
8 | uint32_t height;
9 | uint8_t channels;
10 | uint8_t bit_depth;
11 | size_t num_images;
12 | };
13 |
14 | typedef uint32_t (*callback_t)(uint32_t quality, int64_t bytes_read, uint8_t decode_over, void *user_data, void *context);
15 |
16 | /*!
17 | * @param[out] info An info struct to fill. If this is not a null pointer, the decoding will exit after reading the file header.
18 | */
19 |
20 | template
21 | bool flif_decode(IO& io, Images &images, callback_t callback, void *user_data, int, Images &partial_images, flif_options &options, metadata_options &md, FLIF_INFO* info);
22 |
23 | template
24 | bool flif_decode(IO& io, Images &images, flif_options &options, metadata_options &md) {
25 | return flif_decode(io, images, NULL, NULL, 0, images, options, md, 0);
26 | }
27 |
--------------------------------------------------------------------------------
/src/flif-enc.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "image/color_range.hpp"
4 | #include "transform/factory.hpp"
5 | #include "common.hpp"
6 |
7 | template
8 | bool flif_encode(IO& io, Images &images, const std::vector &transDesc, flif_options &options);
9 |
10 | template
11 | bool flif_encode(IO& io, Images &images, const std::vector &transDesc =
12 | {"YCoCg","Bounds","Palette_Alpha","Palette","Color_Buckets","Duplicate_Frame","Frame_Shape","Frame_Lookback"}) {
13 | flif_options options = FLIF_DEFAULT_OPTIONS;
14 | return flif_encode(io, images, transDesc, options);
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/flif-mime.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FLIF image
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/flif_config.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "config.h"
3 | #include "maniac/rac.hpp"
4 |
5 | #include "fileio.hpp"
6 |
7 | template using RacIn = RacInput24;
8 |
9 | #ifdef HAS_ENCODER
10 | template using RacOut = RacOutput24;
11 | #endif
12 |
13 | #include "maniac/compound.hpp"
14 | #ifdef FAST_BUT_WORSE_COMPRESSION
15 | typedef SimpleBitChance FLIFBitChanceMeta;
16 | #else
17 | typedef MultiscaleBitChance<6,SimpleBitChance> FLIFBitChanceMeta;
18 | #endif
19 |
--------------------------------------------------------------------------------
/src/image/color_range.cpp:
--------------------------------------------------------------------------------
1 | #include "color_range.hpp"
2 |
3 | const ColorRanges *getRanges(const Image &image) {
4 | StaticColorRangeList ranges;
5 | for (int p = 0; p < image.numPlanes(); p++) {
6 | ranges.push_back(std::make_pair(image.min(p), image.max(p)));
7 | }
8 | return new StaticColorRanges(ranges);
9 | }
10 |
11 | const ColorRanges *getRanges(const ColorRanges *ranges) {
12 | return new DupColorRanges(ranges);
13 | }
14 |
--------------------------------------------------------------------------------
/src/image/color_range.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "image.hpp"
6 |
7 | typedef std::vector prevPlanes;
8 |
9 |
10 | class ColorRanges
11 | {
12 | public:
13 | virtual ~ColorRanges() {};
14 | virtual int numPlanes() const =0;
15 | virtual ColorVal min(int p) const =0;
16 | virtual ColorVal max(int p) const =0;
17 | virtual void minmax(const int p, const prevPlanes &, ColorVal &minv, ColorVal &maxv) const { minv=min(p); maxv=max(p); }
18 | virtual void snap(const int p, const prevPlanes &pp, ColorVal &minv, ColorVal &maxv, ColorVal &v) const {
19 | minmax(p,pp,minv,maxv);
20 | if (minv > maxv) { //e_printf("Corruption detected!\n");
21 | // this should only happen on malicious/corrupt input files, or while adding loss
22 | maxv=minv;
23 | }
24 | assert(minv <= maxv);
25 | if(v>maxv) v=maxv;
26 | if(v= minv);
29 | }
30 | virtual bool isStatic() const { return true; }
31 | virtual const ColorRanges* previous() const { return NULL; }
32 | };
33 |
34 | typedef std::vector > StaticColorRangeList;
35 |
36 | class StaticColorRanges : public ColorRanges
37 | {
38 | protected:
39 | const StaticColorRangeList ranges;
40 |
41 | public:
42 | explicit StaticColorRanges(StaticColorRangeList &r) : ranges(r) {}
43 | int numPlanes() const override { return ranges.size(); }
44 | ColorVal min(int p) const override { if (p >= numPlanes()) return 0; assert(p= numPlanes()) return 0; assert(pnumPlanes(); }
57 | ColorVal min(int p) const override { return ranges->min(p); }
58 | ColorVal max(int p) const override { return ranges->max(p); }
59 | void minmax(const int p, const prevPlanes &pp, ColorVal &minv, ColorVal &maxv) const override { ranges->minmax(p,pp,minv,maxv); }
60 | void snap(const int p, const prevPlanes &pp, ColorVal &minv, ColorVal &maxv, ColorVal &v) const override { ranges->snap(p,pp,minv,maxv,v); }
61 | bool isStatic() const override { return ranges->isStatic(); }
62 | const ColorRanges* previous() const override { return ranges; }
63 | };
64 |
65 | const ColorRanges *dupRanges(const ColorRanges *ranges);
66 |
--------------------------------------------------------------------------------
/src/image/crc32k.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | // define endianess and some integer data types
6 | #if defined(_MSC_VER) || defined(__MINGW32__)
7 | typedef unsigned __int8 uint8_t;
8 | typedef unsigned __int16 uint16_t;
9 | typedef unsigned __int32 uint32_t;
10 | typedef signed __int32 int32_t;
11 |
12 | #define __ORDER_BIG_ENDIAN__ 4321
13 | #define __ORDER_LITTLE_ENDIAN__ 1234
14 | #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
15 |
16 | #include
17 | #ifdef __MINGW32__
18 | #define PREFETCH(location) __builtin_prefetch(location)
19 | #else
20 | #define PREFETCH(location) _mm_prefetch(location, _MM_HINT_T0)
21 | #endif
22 | #else
23 | // uint8_t, uint32_t, in32_t
24 | #include
25 | // defines __BYTE_ORDER as __LITTLE_ENDIAN or __BIG_ENDIAN
26 | #include
27 |
28 | #ifdef __GNUC__
29 | #define PREFETCH(location) __builtin_prefetch(location)
30 | #else
31 | #define PREFETCH(location) ;
32 | #endif
33 | #endif
34 |
35 |
36 | /// zlib's CRC32 polynomial
37 | const uint32_t Polynomial = 0xEDB88320;
38 |
39 | /// swap endianess
40 | static inline uint32_t swap(uint32_t x)
41 | {
42 | #if defined(__GNUC__) || defined(__clang__)
43 | return __builtin_bswap32(x);
44 | #else
45 | return (x >> 24) |
46 | ((x >> 8) & 0x0000FF00) |
47 | ((x << 8) & 0x00FF0000) |
48 | (x << 24);
49 | #endif
50 | }
51 |
52 | /// swap endianess
53 | inline uint16_t swap16(uint16_t x)
54 | {
55 | #if defined(__GNUC__) || defined(__clang__)
56 | return __builtin_bswap16(x);
57 | #else
58 | return (x >> 8) |
59 | (x << 8);
60 | #endif
61 | }
62 |
63 | uint32_t crc32_fast(const void* data, size_t length, uint32_t previousCrc32 = 0);
64 |
--------------------------------------------------------------------------------
/src/image/image-metadata.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "image.hpp"
8 |
9 | #ifdef HAS_ENCODER
10 |
11 |
12 | bool image_load_metadata(const char *filename, Image& image, const char *chunkname) {
13 | FILE *fp = fopen(filename,"rb");
14 | if (!fp) {
15 | e_printf("Could not open file: %s\n", filename);
16 | return false;
17 | }
18 | image.init(0, 0, 0, 0, 0);
19 |
20 | fseek(fp, 0, SEEK_END);
21 | long fsize = ftell(fp);
22 | fseek(fp, 0, SEEK_SET);
23 |
24 | std::vector contents(fsize + 1);
25 | if (!fread(contents.data(), fsize, 1, fp)) {
26 | e_printf("Could not read file: %s\n", filename);
27 | fclose(fp);
28 | return false;
29 | }
30 | fclose(fp);
31 | image.set_metadata(chunkname, contents.data(), fsize);
32 | return true;
33 | }
34 | #endif
35 |
36 | bool image_save_metadata(const char *filename, const Image& image, const char *chunkname) {
37 | unsigned char * contents;
38 | size_t length;
39 | if (image.get_metadata(chunkname, &contents, &length)) {
40 | FILE *fp = fopen(filename,"wb");
41 | if (!fp) {
42 | return false;
43 | }
44 | fwrite((void *) contents, length, 1, fp);
45 | fclose(fp);
46 | free(contents);
47 | return true;
48 | } else {
49 | e_printf("Asking to write metadata of type %s to file %s, however no such metadata is present in the input file.\n", chunkname, filename);
50 | return false;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/image/image-metadata.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "image.hpp"
4 |
5 | #ifdef HAS_ENCODER
6 | bool image_load_metadata(const char *filename, Image& image, const char *chunkname);
7 | #endif
8 | bool image_save_metadata(const char *filename, const Image& image, const char *chunkname);
9 |
10 |
--------------------------------------------------------------------------------
/src/image/image-pam.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "image.hpp"
7 | #include "image-pam.hpp"
8 | #include "image-pnm.hpp"
9 |
10 | #define PPMREADBUFLEN 256
11 |
12 | #ifdef HAS_ENCODER
13 | bool image_load_pam(const char *filename, Image& image) {
14 | FILE *fp = fopen(filename,"rb");
15 | char buf[PPMREADBUFLEN];
16 |
17 | if (!fp) {
18 | return false;
19 | }
20 | if (!fgets(buf, PPMREADBUFLEN, fp)) { fclose(fp); return false; }
21 | int type=0;
22 | if ( (!strncmp(buf, "P7\n", 3)) ) type=7;
23 | if (type==0) {
24 | fclose(fp);
25 | if ( (!strncmp(buf, "P4", 2))
26 | || (!strncmp(buf, "P5", 2))
27 | || (!strncmp(buf, "P6", 2))) {
28 | return image_load_pnm(filename, image);
29 | }
30 | e_printf("PAM file is not of type P7, cannot read other types.\n");
31 | return false;
32 | }
33 | return image_load_pam_fp(fp, image);
34 | }
35 | bool image_load_pam_fp(FILE *fp, Image& image) {
36 | char buf[PPMREADBUFLEN], *t;
37 | int maxlines=100;
38 | unsigned int width=0,height=0;
39 | unsigned int maxval=0;
40 | unsigned int depth = 0;
41 | do {
42 | t = fgets(buf, PPMREADBUFLEN, fp);
43 | if ( t == NULL ) {
44 | fclose(fp);
45 | return true;
46 | }
47 | /* Px formats can have # comments after first line */
48 | if (strncmp(buf, "#", 1) == 0 || strncmp(buf, "\n", 1) == 0)
49 | continue;
50 |
51 | sscanf(buf, "WIDTH %u\n", &width);
52 | sscanf(buf, "HEIGHT %u\n", &height);
53 | sscanf(buf, "DEPTH %u\n", &depth);
54 | sscanf(buf, "MAXVAL %u\n", &maxval);
55 |
56 | if (maxlines-- < 1) {
57 | e_printf("Problem while parsing PAM header.\n");
58 | fclose(fp);
59 | return false;
60 | }
61 | } while ( strncmp(buf, "ENDHDR", 6) != 0 );
62 | if (depth>4 || depth <1 || width <1 || height < 1 || maxval<1 || maxval > 0xffff) {
63 | e_printf("Couldn't parse PAM header, or unsupported kind of PAM file.\n");
64 | fclose(fp);
65 | return false;
66 | }
67 |
68 | #ifndef SUPPORT_HDR
69 | if (maxval > 0xff) {
70 | e_printf("PAM file has more than 8 bit per channel, this FLIF cannot handle that.\n");
71 | fclose(fp);
72 | return false;
73 | }
74 | #endif
75 |
76 | unsigned int nbplanes=depth;
77 | image.init(width, height, 0, maxval, nbplanes);
78 | if (maxval > 0xff) {
79 | for (unsigned int y=0; y maxval)
91 | pixel = maxval;
92 | image.set(c,y,x, pixel);
93 | }
94 | }
95 | }
96 | } else {
97 | for (unsigned int y=0; y maxval)
107 | pixel = maxval;
108 | image.set(c,y,x, pixel);
109 | }
110 | }
111 | }
112 | }
113 |
114 | if (fp!=stdin) fclose(fp);
115 | return true;
116 | }
117 | #endif
118 |
119 | bool image_save_pam(const char *filename, const Image& image)
120 | {
121 | if (image.numPlanes() < 4) return image_save_pnm(filename, image);
122 | FILE *fp = NULL;
123 | if (!strcmp(filename,"-")) fp = stdout;
124 | else fp = fopen(filename,"wb");
125 | if (!fp) {
126 | return false;
127 | }
128 |
129 | ColorVal max = image.max(0);
130 |
131 | if (max > 0xffff) {
132 | e_printf("Cannot store as PAM. Find out why.\n");
133 | fclose(fp);
134 | return false;
135 | }
136 | unsigned int height = image.rows(), width = image.cols();
137 | fprintf(fp,"P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL %i\nTUPLTYPE RGB_ALPHA\nENDHDR\n", width, height, max);
138 |
139 |
140 | // experiment: output RGBA pixels in FLIF's Adam-infinity interlaced order
141 | /*
142 | fputc(image(0,0,0) & 0xFF,fp);
143 | fputc(image(1,0,0) & 0xFF,fp);
144 | fputc(image(2,0,0) & 0xFF,fp);
145 | fputc(image(3,0,0) & 0xFF,fp);
146 |
147 | for (int z = image.zooms(); z >= 0; z--) {
148 | if (z % 2 == 0) {
149 | for (uint32_t y = 1; y < image.rows(z); y += 2) {
150 | for (uint32_t x = 0; x < image.cols(z); x++) {
151 | if (max > 0xff) fputc(image(0,z,y,x) >> 8,fp);
152 | fputc(image(0,z,y,x) & 0xFF,fp);
153 | if (max > 0xff) fputc(image(1,z,y,x) >> 8,fp);
154 | fputc(image(1,z,y,x) & 0xFF,fp);
155 | if (max > 0xff) fputc(image(2,z,y,x) >> 8,fp);
156 | fputc(image(2,z,y,x) & 0xFF,fp);
157 | if (max > 0xff) fputc(image(3,z,y,x) >> 8,fp);
158 | fputc(image(3,z,y,x) & 0xFF,fp);
159 | }
160 | }
161 | } else {
162 | for (uint32_t y = 0; y < image.rows(z); y++) {
163 | for (uint32_t x = 1; x < image.cols(z); x += 2) {
164 | if (max > 0xff) fputc(image(0,z,y,x) >> 8,fp);
165 | fputc(image(0,z,y,x) & 0xFF,fp);
166 | if (max > 0xff) fputc(image(1,z,y,x) >> 8,fp);
167 | fputc(image(1,z,y,x) & 0xFF,fp);
168 | if (max > 0xff) fputc(image(2,z,y,x) >> 8,fp);
169 | fputc(image(2,z,y,x) & 0xFF,fp);
170 | if (max > 0xff) fputc(image(3,z,y,x) >> 8,fp);
171 | fputc(image(3,z,y,x) & 0xFF,fp);
172 | }
173 | }
174 | }
175 | }
176 | */
177 |
178 |
179 | for (unsigned int y = 0; y < height; y++) {
180 | for (unsigned int x = 0; x < width; x++) {
181 | if (max > 0xff) fputc(image(0,y,x) >> 8,fp);
182 | fputc(image(0,y,x) & 0xFF,fp);
183 | if (max > 0xff) fputc(image(1,y,x) >> 8,fp);
184 | fputc(image(1,y,x) & 0xFF,fp);
185 | if (max > 0xff) fputc(image(2,y,x) >> 8,fp);
186 | fputc(image(2,y,x) & 0xFF,fp);
187 | if (max > 0xff) fputc(image(3,y,x) >> 8,fp);
188 | fputc(image(3,y,x) & 0xFF,fp);
189 | }
190 | }
191 |
192 | // if (fp != stdout) fclose(fp);
193 | if (image.get_metadata("iCCP")) {
194 | v_printf(1,"Warning: input image has color profile, which cannot be stored in output image format.\n");
195 | }
196 | fclose(fp);
197 | return true;
198 |
199 | }
200 |
--------------------------------------------------------------------------------
/src/image/image-pam.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "image.hpp"
4 |
5 | #ifdef HAS_ENCODER
6 | bool image_load_pam(const char *filename, Image& image);
7 | bool image_load_pam_fp(FILE *fp, Image& image);
8 | #endif
9 | bool image_save_pam(const char *filename, const Image& image);
10 |
--------------------------------------------------------------------------------
/src/image/image-png-metadata.hpp:
--------------------------------------------------------------------------------
1 | // This bit of code is based from some code from libwebp 0.5.0 (specifically from examples/pngdec.c)
2 | // It is BSD-licensed
3 |
4 |
5 | // Converts the NULL terminated 'hexstring' which contains 2-byte character
6 | // representations of hex values to raw data.
7 | // 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs,
8 | // e.g., 7af2..., separated by any number of newlines.
9 | // 'expected_length' is the anticipated processed size.
10 | // On success the raw buffer is returned with its length equivalent to
11 | // 'expected_length'. NULL is returned if the processed length is less than
12 | // 'expected_length' or any character aside from those above is encountered.
13 | // The returned buffer must be freed by the caller.
14 | static unsigned char* HexStringToBytes(const char* hexstring,
15 | size_t expected_length) {
16 | const char* src = hexstring;
17 | size_t actual_length = 0;
18 | unsigned char* const raw_data = (unsigned char*)malloc(expected_length);
19 | unsigned char* dst;
20 |
21 | if (raw_data == NULL) return NULL;
22 |
23 | for (dst = raw_data; actual_length < expected_length && *src != '\0'; ++src) {
24 | char* end;
25 | char val[3];
26 | if (*src == '\n') continue;
27 | val[0] = *src++;
28 | val[1] = *src;
29 | val[2] = '\0';
30 | *dst++ = (uint8_t)strtol(val, &end, 16);
31 | if (end != val + 2) break;
32 | ++actual_length;
33 | }
34 |
35 | if (actual_length != expected_length) {
36 | free(raw_data);
37 | return NULL;
38 | }
39 | return raw_data;
40 | }
41 |
42 | static int ProcessRawProfile(const char* profile, size_t profile_len,
43 | unsigned char ** payload, size_t* payload_len) {
44 | const char* src = profile;
45 | char* end;
46 | int expected_length;
47 |
48 | if (profile == NULL || profile_len == 0) return 0;
49 |
50 | // ImageMagick formats 'raw profiles' as
51 | // '\n\n(%8lu)\n\n'.
52 | if (*src != '\n') {
53 | fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
54 | *src);
55 | return 0;
56 | }
57 | ++src;
58 | // skip the profile name and extract the length.
59 | while (*src != '\0' && *src++ != '\n') {}
60 | expected_length = (int)strtol(src, &end, 10);
61 | if (*end != '\n') {
62 | fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
63 | *end);
64 | return 0;
65 | }
66 | ++end;
67 |
68 | // 'end' now points to the profile payload.
69 | *payload = HexStringToBytes(end, expected_length);
70 | *payload_len = expected_length;
71 | if (*payload == NULL) return 0;
72 | return 1;
73 | }
--------------------------------------------------------------------------------
/src/image/image-png.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "image.hpp"
4 |
5 | #ifdef HAS_ENCODER
6 | int image_load_png(const char *filename, Image &image, metadata_options &md);
7 | #endif
8 | int image_save_png(const char *filename, const Image &image);
9 |
--------------------------------------------------------------------------------
/src/image/image-pnm.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "image.hpp"
7 | #include "image-pnm.hpp"
8 | #include "image-pam.hpp"
9 |
10 | #define PPMREADBUFLEN 256
11 |
12 | #ifdef HAS_ENCODER
13 |
14 | // auxiliary function to read a non-zero number from a PNM header, ignoring whitespace and comments
15 | unsigned int read_pnm_int(FILE *fp, char* buf, char** t) {
16 | long result = strtol(*t,t,10);
17 | if (result == 0) {
18 | // no valid int found here, try next line
19 | do {
20 | *t = fgets(buf, PPMREADBUFLEN, fp);
21 | if ( *t == NULL ) {return false;}
22 | } while ( strncmp(buf, "#", 1) == 0 || strncmp(buf, "\n", 1) == 0);
23 | result = strtol(*t,t,10);
24 | if (result == 0) { e_printf("Invalid PNM file.\n"); fclose(fp); }
25 | }
26 | return result;
27 | }
28 |
29 | bool image_load_pnm(const char *filename, Image& image) {
30 | FILE *fp = NULL;
31 | if (!strcmp(filename,"-")) fp = stdin;
32 | else fp = fopen(filename,"rb");
33 |
34 | char buf[PPMREADBUFLEN], *t;
35 | if (!fp) {
36 | e_printf("Could not open file: %s\n", filename);
37 | return false;
38 | }
39 | unsigned int width=0,height=0;
40 | unsigned int maxval=0;
41 | do {
42 | /* # comments before the first line */
43 | t = fgets(buf, PPMREADBUFLEN, fp);
44 | if ( t == NULL ) return false;
45 | } while ( strncmp(buf, "#", 1) == 0 || strncmp(buf, "\n", 1) == 0);
46 | int type=0;
47 | if ( (!strncmp(buf, "P4", 2)) ) type=4;
48 | if ( (!strncmp(buf, "P5", 2)) ) type=5;
49 | if ( (!strncmp(buf, "P6", 2)) ) type=6;
50 | if ( (!strncmp(buf, "P7", 2)) ) {return image_load_pam_fp(fp, image);}
51 | if (type==0) {
52 | if (buf[0] == 'P') e_printf("PNM file is not of type P4, P5, P6 or P7, cannot read other types.\n");
53 | else e_printf("This does not look like a PNM file.\n");
54 | fclose(fp);
55 | return false;
56 | }
57 | t += 2;
58 | if (!(width = read_pnm_int(fp,buf,&t))) return false;
59 | if (!(height = read_pnm_int(fp,buf,&t))) return false;
60 | if (type>4) {
61 | if (!(maxval = read_pnm_int(fp,buf,&t))) return false;
62 | if ( maxval > 0xffff ) {
63 | e_printf("Invalid PNM file (more than 16-bit?)\n");
64 | fclose(fp);
65 | return false;
66 | }
67 | } else maxval=1;
68 | #ifndef SUPPORT_HDR
69 | if (maxval > 0xff) {
70 | e_printf("PNM file has more than 8 bit per channel, this FLIF cannot handle that.\n");
71 | return false;
72 | }
73 | #endif
74 | unsigned int nbplanes=(type==6?3:1);
75 | image.init(width, height, 0, maxval, nbplanes);
76 | if (type==4) {
77 | char byte=0;
78 | for (unsigned int y=0; y>(x%8)) ? 0 : 1));
82 | }
83 | }
84 | } else {
85 | if (maxval > 0xff) {
86 | for (unsigned int y=0; y (int)maxval) {
92 | fclose(fp);
93 | e_printf("Invalid PNM file: value %i is larger than declared maxval %u\n", pixel, maxval);
94 | return false;
95 | }
96 | image.set(c,y,x, pixel);
97 | }
98 | }
99 | }
100 | } else {
101 | for (unsigned int y=0; y= 3) {
125 | if (image.numPlanes() == 4 && image.uses_alpha())
126 | v_printf(1,"WARNING: image has alpha channel, saving to flat PPM! Use .png or .pam if you want to keep the alpha channel!\n");
127 | ColorVal max = image.max(0);
128 |
129 | if (max > 0xffff) {
130 | e_printf("Cannot store as PNM. Find out why.\n");
131 | fclose(fp);
132 | return false;
133 | }
134 |
135 | unsigned int height = image.rows(), width = image.cols();
136 | fprintf(fp,"P6\n%u %u\n%i\n", width, height, max);
137 | for (unsigned int y = 0; y < height; y++) {
138 | for (unsigned int x = 0; x < width; x++) {
139 | if (max > 0xff) fputc(image(0,y,x) >> 8,fp);
140 | fputc(image(0,y,x) & 0xFF,fp);
141 | if (max > 0xff) fputc(image(1,y,x) >> 8,fp);
142 | fputc(image(1,y,x) & 0xFF,fp);
143 | if (max > 0xff) fputc(image(2,y,x) >> 8,fp);
144 | fputc(image(2,y,x) & 0xFF,fp);
145 | }
146 | }
147 | } else if (image.numPlanes() == 1) {
148 | ColorVal max = image.max(0);
149 |
150 | if (max > 0xffff) {
151 | e_printf("Cannot store as PNM. Find out why.\n");
152 | fclose(fp);
153 | return false;
154 | }
155 |
156 | unsigned int height = image.rows(), width = image.cols();
157 | fprintf(fp,"P5\n%u %u\n%i\n", width, height, max);
158 | for (unsigned int y = 0; y < height; y++) {
159 | for (unsigned int x = 0; x < width; x++) {
160 | if (max > 0xff) fputc(image(0,y,x) >> 8,fp);
161 | fputc(image(0,y,x) & 0xFF,fp);
162 | }
163 | }
164 | } else {
165 | e_printf("Cannot store as PNM. Find out why.\n");
166 | fclose(fp);
167 | return false;
168 | }
169 | // if (fp != stdout) fclose(fp);
170 | if (image.get_metadata("iCCP")) {
171 | v_printf(1,"Warning: input image has color profile, which cannot be stored in output image format.\n");
172 | }
173 | fclose(fp);
174 | return true;
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/src/image/image-pnm.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "image.hpp"
4 |
5 | #ifdef HAS_ENCODER
6 | bool image_load_pnm(const char *filename, Image& image);
7 | #endif
8 | bool image_save_pnm(const char *filename, const Image& image);
9 |
--------------------------------------------------------------------------------
/src/image/image-rggb.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "image.hpp"
4 |
5 | #ifdef HAS_ENCODER
6 | bool image_load_rggb(const char *filename, Image& image, metadata_options &md);
7 | #endif
8 | bool image_save_rggb(const char *filename, const Image& image);
9 |
--------------------------------------------------------------------------------
/src/image/image.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "image.hpp"
4 | #include "image-png.hpp"
5 | #include "image-pnm.hpp"
6 | #include "image-pam.hpp"
7 | #include "image-rggb.hpp"
8 | #include "image-metadata.hpp"
9 |
10 | #ifdef _MSC_VER
11 | #define strcasecmp _stricmp
12 | #endif
13 |
14 | #ifdef HAS_ENCODER
15 | bool Image::load(const char *filename, metadata_options &options)
16 | {
17 | if (!strcmp(filename,"-")) {
18 | v_printf(2,"Reading input as PAM/PPM from standard input. ");
19 | return image_load_pnm(filename,*this);
20 | }
21 | const char *f = strrchr(filename,'/');
22 | const char *ext = f ? strrchr(f,'.') : strrchr(filename,'.');
23 | v_printf(2,"Loading input file: %s ",filename);
24 | if (ext && !strcasecmp(ext,".png")) {
25 | return !image_load_png(filename,*this,options);
26 | }
27 | if (ext && !strcasecmp(ext,".pnm")) {
28 | return image_load_pnm(filename,*this);
29 | }
30 | if (ext && !strcasecmp(ext,".pbm")) {
31 | return image_load_pnm(filename,*this);
32 | }
33 | if (ext && !strcasecmp(ext,".pgm")) {
34 | return image_load_pnm(filename,*this);
35 | }
36 | if (ext && !strcasecmp(ext,".ppm")) {
37 | return image_load_pnm(filename,*this);
38 | }
39 | if (ext && !strcasecmp(ext,".pam")) {
40 | return image_load_pam(filename,*this);
41 | }
42 | if (ext && !strcasecmp(ext,".rggb")) {
43 | return image_load_rggb(filename,*this, options);
44 | }
45 | if (ext && !strcasecmp(ext,".icc")) {
46 | return image_load_metadata(filename,*this,"iCCP");
47 | }
48 | if (ext && !strcasecmp(ext,".xmp")) {
49 | return image_load_metadata(filename,*this,"eXmp");
50 | }
51 | if (ext && !strcasecmp(ext,".exif")) {
52 | return image_load_metadata(filename,*this,"eXif");
53 | }
54 | if (image_load_pnm(filename,*this) || !image_load_png(filename,*this,options)) return true;
55 | e_printf("ERROR: Unknown input file type to read from: %s\n",ext ? ext : "(none)");
56 | return false;
57 | }
58 | #endif
59 |
60 | bool Image::save(const char *filename) const
61 | {
62 | if (!strcmp(filename,"-")) {
63 | v_printf(2,"Writing output as PAM to standard output. ");
64 | return image_save_pam(filename,*this);
65 | }
66 | const char *f = strrchr(filename,'/');
67 | const char *ext = f ? strrchr(f,'.') : strrchr(filename,'.');
68 | v_printf(2,"Saving output file: %s ",filename);
69 | if (ext && !strcasecmp(ext,".png")) {
70 | return !image_save_png(filename,*this);
71 | }
72 | if (ext && !strcasecmp(ext,".pnm")) {
73 | return image_save_pnm(filename,*this);
74 | }
75 | if (ext && !strcasecmp(ext,".pgm")) {
76 | return image_save_pnm(filename,*this);
77 | }
78 | if (ext && !strcasecmp(ext,".ppm")) {
79 | return image_save_pnm(filename,*this);
80 | }
81 | if (ext && !strcasecmp(ext,".pam")) {
82 | return image_save_pam(filename,*this);
83 | }
84 | if (ext && !strcasecmp(ext,".rggb")) {
85 | return image_save_rggb(filename,*this);
86 | }
87 | if (ext && !strcasecmp(ext,".icc")) {
88 | return image_save_metadata(filename,*this,"iCCP");
89 | }
90 | if (ext && !strcasecmp(ext,".xmp")) {
91 | return image_save_metadata(filename,*this,"eXmp");
92 | }
93 | if (ext && !strcasecmp(ext,".exif")) {
94 | return image_save_metadata(filename,*this,"eXif");
95 | }
96 | e_printf("ERROR: Unknown extension to write to: %s\n",ext ? ext : "(none)");
97 | return false;
98 | }
99 |
--------------------------------------------------------------------------------
/src/io.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #include
20 | #include
21 | #ifdef _WIN32
22 | #include
23 | #else
24 | #include
25 | #endif
26 |
27 | #include "io.hpp"
28 |
29 | void e_printf(const char *format, ...) {
30 | va_list args;
31 | va_start(args, format);
32 | vfprintf(stderr, format, args);
33 | fflush(stderr);
34 | va_end(args);
35 | }
36 |
37 | #ifdef DEBUG
38 | static int verbosity = 10;
39 | #else
40 | static int verbosity = 1;
41 | #endif
42 | static FILE * my_stdout = stdout;
43 | void increase_verbosity(int how_much) {
44 | verbosity += how_much;
45 | }
46 |
47 | int get_verbosity() {
48 | return verbosity;
49 | }
50 |
51 | void v_printf(const int v, const char *format, ...) {
52 | if (verbosity < v) return;
53 | va_list args;
54 | va_start(args, format);
55 | vfprintf(my_stdout, format, args);
56 | fflush(my_stdout);
57 | va_end(args);
58 | }
59 |
60 | void v_printf_tty(const int v, const char *format, ...) {
61 | if (verbosity < v) return;
62 | #ifdef _WIN32
63 | if(!_isatty(_fileno(my_stdout))) return;
64 | #else
65 | if(!isatty(fileno(my_stdout))) return;
66 | #endif
67 | va_list args;
68 | va_start(args, format);
69 | vfprintf(my_stdout, format, args);
70 | fflush(my_stdout);
71 | va_end(args);
72 | }
73 |
74 | void redirect_stdout_to_stderr() {
75 | my_stdout = stderr;
76 | }
77 |
--------------------------------------------------------------------------------
/src/io.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | void e_printf(const char *format, ...);
22 | void v_printf(const int v, const char *format, ...);
23 | void v_printf_tty(const int v, const char *format, ...);
24 | void redirect_stdout_to_stderr();
25 |
26 | void increase_verbosity(int how_much=1);
27 | int get_verbosity();
28 |
29 | template
30 | bool ioget_int_8bit (IO& io, int* result)
31 | {
32 | int c = io.get_c();
33 | if (c == io.EOS) {
34 | e_printf ("Unexpected EOS");
35 | return false;
36 | }
37 |
38 | *result = c;
39 | return true;
40 | }
41 |
42 | template
43 | bool ioget_int_16bit_bigendian (IO& io, int* result)
44 | {
45 | int c1;
46 | int c2;
47 | if (!(ioget_int_8bit (io, &c1) &&
48 | ioget_int_8bit (io, &c2)))
49 | return false;
50 |
51 | *result = (c1 << 8) + c2;
52 | return true;
53 | }
54 |
--------------------------------------------------------------------------------
/src/library/flif-interface-private.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "flif-interface-private_enc.hpp"
4 | #include "flif-interface-private_dec.hpp"
5 |
--------------------------------------------------------------------------------
/src/library/flif-interface-private_common.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | #include "flif_common.h"
22 |
23 | #include "../image/image.hpp"
24 | #include "../fileio.hpp"
25 |
26 | #ifdef _WIN32
27 | #ifdef FLIF_BUILD_DLL
28 | #define FLIF_DLLEXPORT __declspec(dllexport)
29 | #else
30 | #define FLIF_DLLEXPORT
31 | #endif
32 | #else
33 | #define FLIF_DLLEXPORT __attribute__ ((visibility ("default")))
34 | #endif
35 |
36 | struct FLIF_IMAGE
37 | {
38 | FLIF_IMAGE();
39 |
40 | void write_row_RGBA8(uint32_t row, const void* buffer, size_t buffer_size_bytes);
41 | void read_row_RGBA8(uint32_t row, void* buffer, size_t buffer_size_bytes);
42 |
43 | void write_row_RGBA16(uint32_t row, const void* buffer, size_t buffer_size_bytes);
44 | void read_row_RGBA16(uint32_t row, void* buffer, size_t buffer_size_bytes);
45 |
46 | void write_row_RGB8(uint32_t row, const void* buffer, size_t buffer_size_bytes);
47 | void write_row_GRAY8(uint32_t row, const void* buffer, size_t buffer_size_bytes);
48 | void read_row_GRAY8(uint32_t row, void* buffer, size_t buffer_size_bytes);
49 | void write_row_GRAY16(uint32_t row, const void* buffer, size_t buffer_size_bytes);
50 | void read_row_GRAY16(uint32_t row, void* buffer, size_t buffer_size_bytes);
51 | void write_row_PALETTE8(uint32_t row, const void* buffer, size_t buffer_size_bytes);
52 | void read_row_PALETTE8(uint32_t row, void* buffer, size_t buffer_size_bytes);
53 |
54 | Image image;
55 | };
56 |
--------------------------------------------------------------------------------
/src/library/flif-interface-private_dec.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 |
23 | #include "flif-interface-private_common.hpp"
24 | #include "../flif-dec.hpp"
25 |
26 | struct FLIF_DECODER
27 | {
28 | FLIF_DECODER();
29 |
30 | int32_t decode_file(const char* filename);
31 | int32_t decode_filepointer(FILE *file, const char* filename);
32 | int32_t decode_memory(const void* buffer, size_t buffer_size_bytes);
33 | int32_t abort();
34 | size_t num_images();
35 | int32_t num_loops();
36 | FLIF_IMAGE* get_image(size_t index);
37 |
38 | flif_options options;
39 | void* callback;
40 | void* user_data;
41 | int32_t first_quality;
42 | ~FLIF_DECODER() {
43 | // get rid of palettes
44 | if (internal_images.size()) internal_images[0].clear();
45 | if (images.size()) images[0].clear();
46 | }
47 |
48 | private:
49 | Images internal_images;
50 | Images images;
51 | std::vector> requested_images;
52 | bool working;
53 | };
54 |
--------------------------------------------------------------------------------
/src/library/flif-interface-private_enc.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF encoder - Free Lossless Image Format
3 | Copyright (C) 2010-2015 Jon Sneyers & Pieter Wuille, LGPL v3+
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Lesser General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include "flif-interface-private_common.hpp"
22 | #include "../flif-enc.hpp"
23 |
24 | struct FLIF_ENCODER
25 | {
26 | FLIF_ENCODER();
27 |
28 | void add_image(FLIF_IMAGE* image);
29 | void add_image_move(FLIF_IMAGE* image);
30 | void set_alpha_zero_flags();
31 | int32_t encode_file(const char* filename);
32 | int32_t encode_memory(void** buffer, size_t* buffer_size_bytes);
33 |
34 | flif_options options;
35 |
36 | ~FLIF_ENCODER() {
37 | // get rid of palette
38 | if (images.size()) images[0].clear();
39 | }
40 |
41 |
42 | private:
43 | void transformations(std::vector &desc);
44 | void set_options(flif_options &options);
45 | std::vector images;
46 | };
47 |
--------------------------------------------------------------------------------
/src/library/flif-interface.cpp:
--------------------------------------------------------------------------------
1 | #include "flif-interface_dec.cpp"
2 | #ifdef HAS_ENCODER
3 | #include "flif-interface_enc.cpp"
4 | #endif
5 |
--------------------------------------------------------------------------------
/src/library/flif.h:
--------------------------------------------------------------------------------
1 | #ifndef FLIF_INTERFACE_H
2 | #define FLIF_INTERFACE_H
3 |
4 | /*
5 | FLIF - Free Lossless Image Format
6 | Copyright (C) 2010-2015 Jon Sneyers & Pieter Wuille, LGPL v3+
7 |
8 | This program is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | #include "flif_dec.h"
23 | #include "flif_enc.h"
24 |
25 | // libflif version 0.2.0
26 | #define FLIF_VERSION ((0 << 16) | (0 << 8) | 2)
27 | #define FLIF_ABI_VERSION 0
28 |
29 | #endif // FLIF_INTERFACE_H
30 |
--------------------------------------------------------------------------------
/src/library/flif_common.h:
--------------------------------------------------------------------------------
1 | #ifndef FLIF_INTERFACE_COMMON_H
2 | #define FLIF_INTERFACE_COMMON_H
3 |
4 | /*
5 | FLIF - Free Lossless Image Format
6 |
7 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
8 |
9 | Licensed under the Apache License, Version 2.0 (the "License");
10 | you may not use this file except in compliance with the License.
11 | You may obtain a copy of the License at
12 |
13 | http://www.apache.org/licenses/LICENSE-2.0
14 |
15 | Unless required by applicable law or agreed to in writing, software
16 | distributed under the License is distributed on an "AS IS" BASIS,
17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | See the License for the specific language governing permissions and
19 | limitations under the License.
20 | */
21 |
22 | #include
23 | #include
24 |
25 | #ifdef _WIN32
26 | #define FLIF_API __cdecl
27 | #ifdef FLIF_BUILD_DLL
28 | #define FLIF_DLLIMPORT __declspec(dllexport)
29 | #elif FLIF_USE_DLL
30 | #define FLIF_DLLIMPORT __declspec(dllimport)
31 | #endif
32 | #else
33 | #define FLIF_API
34 | #endif
35 |
36 | #ifndef FLIF_DLLIMPORT
37 | #define FLIF_DLLIMPORT
38 | #endif
39 |
40 | #ifdef __cplusplus
41 | extern "C" {
42 | #endif // __cplusplus
43 |
44 | typedef struct FLIF_IMAGE FLIF_IMAGE;
45 |
46 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_create_image(uint32_t width, uint32_t height); // RGBA
47 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_create_image_RGB(uint32_t width, uint32_t height);
48 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_create_image_GRAY(uint32_t width, uint32_t height);
49 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_create_image_GRAY16(uint32_t width, uint32_t height);
50 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_create_image_PALETTE(uint32_t width, uint32_t height);
51 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_create_image_HDR(uint32_t width, uint32_t height);
52 |
53 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_RGBA(uint32_t width, uint32_t height, const void* rgba, uint32_t rgba_stride);
54 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_RGB(uint32_t width, uint32_t height, const void* rgb, uint32_t rgb_stride);
55 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_GRAY(uint32_t width, uint32_t height, const void* gray, uint32_t gray_stride);
56 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_GRAY16(uint32_t width, uint32_t height, const void* gray, uint32_t gray_stride);
57 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_PALETTE(uint32_t width, uint32_t height, const void* gray, uint32_t gray_stride);
58 | FLIF_DLLIMPORT void FLIF_API flif_destroy_image(FLIF_IMAGE* image);
59 |
60 | FLIF_DLLIMPORT uint32_t FLIF_API flif_image_get_width(FLIF_IMAGE* image);
61 | FLIF_DLLIMPORT uint32_t FLIF_API flif_image_get_height(FLIF_IMAGE* image);
62 | FLIF_DLLIMPORT uint8_t FLIF_API flif_image_get_nb_channels(FLIF_IMAGE* image);
63 | FLIF_DLLIMPORT uint8_t FLIF_API flif_image_get_depth(FLIF_IMAGE* image);
64 | FLIF_DLLIMPORT uint32_t FLIF_API flif_image_get_palette_size(FLIF_IMAGE* image); // 0 = no palette, 1-256 = nb of colors in palette
65 | FLIF_DLLIMPORT void FLIF_API flif_image_get_palette(FLIF_IMAGE* image, void* buffer); // puts RGBA colors in buffer (4*palette_size bytes)
66 | FLIF_DLLIMPORT void FLIF_API flif_image_set_palette(FLIF_IMAGE* image, const void* buffer, uint32_t palette_size); // puts RGBA colors in buffer (4*palette_size bytes)
67 | FLIF_DLLIMPORT uint32_t FLIF_API flif_image_get_frame_delay(FLIF_IMAGE* image);
68 | FLIF_DLLIMPORT void FLIF_API flif_image_set_frame_delay(FLIF_IMAGE* image, uint32_t delay);
69 |
70 | FLIF_DLLIMPORT void FLIF_API flif_image_set_metadata(FLIF_IMAGE* image, const char* chunkname, const unsigned char* data, size_t length);
71 | FLIF_DLLIMPORT uint8_t FLIF_API flif_image_get_metadata(FLIF_IMAGE* image, const char* chunkname, unsigned char** data, size_t* length);
72 | FLIF_DLLIMPORT void FLIF_API flif_image_free_metadata(FLIF_IMAGE* image, unsigned char* data);
73 |
74 | FLIF_DLLIMPORT void FLIF_API flif_image_write_row_PALETTE8(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes);
75 | FLIF_DLLIMPORT void FLIF_API flif_image_read_row_PALETTE8(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes);
76 |
77 | FLIF_DLLIMPORT void FLIF_API flif_image_write_row_GRAY8(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes);
78 | FLIF_DLLIMPORT void FLIF_API flif_image_read_row_GRAY8(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes);
79 |
80 | FLIF_DLLIMPORT void FLIF_API flif_image_write_row_GRAY16(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes);
81 | FLIF_DLLIMPORT void FLIF_API flif_image_read_row_GRAY16(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes);
82 |
83 | FLIF_DLLIMPORT void FLIF_API flif_image_write_row_RGBA8(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes);
84 | FLIF_DLLIMPORT void FLIF_API flif_image_read_row_RGBA8(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes);
85 |
86 | FLIF_DLLIMPORT void FLIF_API flif_image_write_row_RGBA16(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes);
87 | FLIF_DLLIMPORT void FLIF_API flif_image_read_row_RGBA16(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes);
88 |
89 | FLIF_DLLIMPORT void FLIF_API flif_free_memory(void* buffer);
90 |
91 | #ifdef __cplusplus
92 | }
93 | #endif // __cplusplus
94 |
95 | #endif // FLIF_INTERFACE_COMMON_H
96 |
--------------------------------------------------------------------------------
/src/library/flif_dec.h:
--------------------------------------------------------------------------------
1 | #ifndef FLIF_INTERFACE_DEC_H
2 | #define FLIF_INTERFACE_DEC_H
3 |
4 | /*
5 | FLIF - Free Lossless Image Format
6 |
7 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
8 |
9 | Licensed under the Apache License, Version 2.0 (the "License");
10 | you may not use this file except in compliance with the License.
11 | You may obtain a copy of the License at
12 |
13 | http://www.apache.org/licenses/LICENSE-2.0
14 |
15 | Unless required by applicable law or agreed to in writing, software
16 | distributed under the License is distributed on an "AS IS" BASIS,
17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | See the License for the specific language governing permissions and
19 | limitations under the License.
20 | */
21 |
22 | #include
23 |
24 | #include "flif_common.h"
25 |
26 | #ifdef __cplusplus
27 | extern "C" {
28 | #endif // __cplusplus
29 |
30 | typedef uint32_t (*callback_t)(uint32_t quality, int64_t bytes_read, uint8_t decode_over, void *user_data, void *context);
31 |
32 | typedef struct FLIF_DECODER FLIF_DECODER;
33 | typedef struct FLIF_INFO FLIF_INFO;
34 |
35 | // initialize a FLIF decoder
36 | FLIF_DLLIMPORT FLIF_DECODER* FLIF_API flif_create_decoder();
37 |
38 | // decode a given FLIF file
39 | FLIF_DLLIMPORT int32_t FLIF_API flif_decoder_decode_file(FLIF_DECODER* decoder, const char* filename);
40 | // decode a FLIF blob in memory: buffer should point to the blob and buffer_size_bytes should be its size
41 | FLIF_DLLIMPORT int32_t FLIF_API flif_decoder_decode_memory(FLIF_DECODER* decoder, const void* buffer, size_t buffer_size_bytes);
42 |
43 | /*
44 | * Decode a given FLIF from a file pointer
45 | * The filename here is used for error messages.
46 | * It would be helpful to pass an actual filename here, but a non-NULL dummy one can be used instead.
47 | */
48 | FLIF_DLLIMPORT int32_t FLIF_API flif_decoder_decode_filepointer(FLIF_DECODER* decoder, FILE *filepointer, const char *filename);
49 |
50 | // returns the number of frames (1 if it is not an animation)
51 | FLIF_DLLIMPORT size_t FLIF_API flif_decoder_num_images(FLIF_DECODER* decoder);
52 | // only relevant for animations: returns the loop count (0 = loop forever)
53 | FLIF_DLLIMPORT int32_t FLIF_API flif_decoder_num_loops(FLIF_DECODER* decoder);
54 | // returns a pointer to a given frame, counting from 0 (use index=0 for still images)
55 | FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_decoder_get_image(FLIF_DECODER* decoder, size_t index);
56 |
57 | FLIF_DLLIMPORT void FLIF_API flif_decoder_generate_preview(void *context);
58 |
59 | // release an decoder (has to be called after decoding is done, to avoid memory leaks)
60 | FLIF_DLLIMPORT void FLIF_API flif_destroy_decoder(FLIF_DECODER* decoder);
61 | // abort a decoder (can be used before decoding is completed)
62 | FLIF_DLLIMPORT int32_t FLIF_API flif_abort_decoder(FLIF_DECODER* decoder);
63 |
64 | // decode options, all optional, can be set after decoder initialization and before actual decoding
65 | FLIF_DLLIMPORT void FLIF_API flif_decoder_set_crc_check(FLIF_DECODER* decoder, int32_t crc_check); // default: no (0)
66 | FLIF_DLLIMPORT void FLIF_API flif_decoder_set_quality(FLIF_DECODER* decoder, int32_t quality); // valid quality: 0-100
67 | FLIF_DLLIMPORT void FLIF_API flif_decoder_set_scale(FLIF_DECODER* decoder, uint32_t scale); // valid scales: 1,2,4,8,16,...
68 | FLIF_DLLIMPORT void FLIF_API flif_decoder_set_resize(FLIF_DECODER* decoder, uint32_t width, uint32_t height);
69 | FLIF_DLLIMPORT void FLIF_API flif_decoder_set_fit(FLIF_DECODER* decoder, uint32_t width, uint32_t height);
70 |
71 | // Progressive decoding: set a callback function. The callback will be called after a certain quality is reached,
72 | // and it should return the desired next quality that should be reached before it will be called again.
73 | // The qualities are expressed on a scale from 0 to 10000 (not 0 to 100!) for fine-grained control.
74 | // `user_data` can be NULL or a pointer to any user-defined context. The decoder doesn't care about its contents;
75 | // it just passes the pointer value back to the callback.
76 | FLIF_DLLIMPORT void FLIF_API flif_decoder_set_callback(FLIF_DECODER* decoder, callback_t callback, void *user_data);
77 | FLIF_DLLIMPORT void FLIF_API flif_decoder_set_first_callback_quality(FLIF_DECODER* decoder, int32_t quality); // valid quality: 0-10000
78 |
79 | // Reads the header of a FLIF file and packages it as a FLIF_INFO struct.
80 | // May return a null pointer if the file is not in the right format.
81 | // The caller takes ownership of the return value and must call flif_destroy_info().
82 | FLIF_DLLIMPORT FLIF_INFO* FLIF_API flif_read_info_from_memory(const void* buffer, size_t buffer_size_bytes);
83 | // deallocator function for FLIF_INFO
84 | FLIF_DLLIMPORT void FLIF_API flif_destroy_info(FLIF_INFO* info);
85 |
86 | // get the image width
87 | FLIF_DLLIMPORT uint32_t FLIF_API flif_info_get_width(FLIF_INFO* info);
88 | // get the image height
89 | FLIF_DLLIMPORT uint32_t FLIF_API flif_info_get_height(FLIF_INFO* info);
90 | // get the number of color channels
91 | FLIF_DLLIMPORT uint8_t FLIF_API flif_info_get_nb_channels(FLIF_INFO* info);
92 | // get the number of bits per channel
93 | FLIF_DLLIMPORT uint8_t FLIF_API flif_info_get_depth(FLIF_INFO* info);
94 | // get the number of animation frames
95 | FLIF_DLLIMPORT size_t FLIF_API flif_info_num_images(FLIF_INFO* info);
96 |
97 |
98 | #ifdef __cplusplus
99 | }
100 | #endif // __cplusplus
101 |
102 | #endif // FLIF_INTERFACE_DEC_H
103 |
--------------------------------------------------------------------------------
/src/library/flif_enc.h:
--------------------------------------------------------------------------------
1 | #ifndef FLIF_INTERFACE_ENC_H
2 | #define FLIF_INTERFACE_ENC_H
3 |
4 | /*
5 | FLIF encoder - Free Lossless Image Format
6 | Copyright (C) 2010-2015 Jon Sneyers & Pieter Wuille, LGPL v3+
7 |
8 | This program is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU Lesser General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU Lesser General Public License
19 | along with this program. If not, see .
20 | */
21 |
22 | #include "flif_common.h"
23 |
24 | #ifdef __cplusplus
25 | extern "C" {
26 | #endif // __cplusplus
27 |
28 | typedef struct FLIF_ENCODER FLIF_ENCODER;
29 |
30 | // initialize a FLIF encoder
31 | FLIF_DLLIMPORT FLIF_ENCODER* FLIF_API flif_create_encoder();
32 |
33 | // give it an image to encode; add more than one image to encode an animation; it will CLONE the image
34 | // (so the input image is not touched and you have to call flif_destroy_image on it yourself to free that memory)
35 | FLIF_DLLIMPORT void FLIF_API flif_encoder_add_image(FLIF_ENCODER* encoder, FLIF_IMAGE* image);
36 |
37 | // give it an image to encode; add more than one image to encode an animation; it will MOVE the input image
38 | // (input image becomes invalid during encode and flif_destroy_encoder will free it)
39 | FLIF_DLLIMPORT void FLIF_API flif_encoder_add_image_move(FLIF_ENCODER* encoder, FLIF_IMAGE* image);
40 |
41 | // encode to a file
42 | FLIF_DLLIMPORT int32_t FLIF_API flif_encoder_encode_file(FLIF_ENCODER* encoder, const char* filename);
43 |
44 | // encode to memory (afterwards, buffer will point to the blob and buffer_size_bytes contains its size)
45 | FLIF_DLLIMPORT int32_t FLIF_API flif_encoder_encode_memory(FLIF_ENCODER* encoder, void** buffer, size_t* buffer_size_bytes);
46 |
47 | // release an encoder (has to be called to avoid memory leaks)
48 | FLIF_DLLIMPORT void FLIF_API flif_destroy_encoder(FLIF_ENCODER* encoder);
49 |
50 | // encoder options (these are all optional, the defaults should be fine)
51 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_interlaced(FLIF_ENCODER* encoder, uint32_t interlaced); // 0 = -N, 1 = -I (default: -I)
52 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_learn_repeat(FLIF_ENCODER* encoder, uint32_t learn_repeats); // default: 2 (-R)
53 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_auto_color_buckets(FLIF_ENCODER* encoder, uint32_t acb); // 0 = -B, 1 = default
54 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_palette_size(FLIF_ENCODER* encoder, int32_t palette_size); // default: 512 (max palette size)
55 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_lookback(FLIF_ENCODER* encoder, int32_t lookback); // default: 1 (-L)
56 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_divisor(FLIF_ENCODER* encoder, int32_t divisor); // default: 30 (-D)
57 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_min_size(FLIF_ENCODER* encoder, int32_t min_size); // default: 50 (-M)
58 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_split_threshold(FLIF_ENCODER* encoder, int32_t threshold); // default: 64 (-T)
59 | // The default is to not store RGB values of fully transparent pixels. If you want to avoid that, you have to change it with this function!
60 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_alpha_zero(FLIF_ENCODER* encoder, int32_t lossless); // 0 = default (RGB undefined when A=0), 1 = keep RGB at A=0 (-K)
61 | //error: dllimport cannot be applied to non-inline function definition
62 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_alpha_zero_lossless(FLIF_ENCODER* encoder);
63 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_chance_cutoff(FLIF_ENCODER* encoder, int32_t cutoff); // default: 2 (-X)
64 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_chance_alpha(FLIF_ENCODER* encoder, int32_t alpha); // default: 19 (-Z)
65 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_crc_check(FLIF_ENCODER* encoder, uint32_t crc_check); // 0 = no CRC, 1 = add CRC
66 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_channel_compact(FLIF_ENCODER* encoder, uint32_t plc); // 0 = -C, 1 = default
67 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_ycocg(FLIF_ENCODER* encoder, uint32_t ycocg); // 0 = -Y, 1 = default
68 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_frame_shape(FLIF_ENCODER* encoder, uint32_t frs); // 0 = -S, 1 = default
69 |
70 | //set amount of quality loss, 0 for no loss, 100 for maximum loss, negative values indicate adaptive lossy (second image should be the saliency map)
71 | FLIF_DLLIMPORT void FLIF_API flif_encoder_set_lossy(FLIF_ENCODER* encoder, int32_t loss); // default: 0 (lossless)
72 |
73 |
74 |
75 | #ifdef __cplusplus
76 | }
77 | #endif // __cplusplus
78 |
79 | #endif // FLIF_INTERFACE_ENC_H
80 |
--------------------------------------------------------------------------------
/src/maniac/bit.cpp:
--------------------------------------------------------------------------------
1 | #ifdef _MSC_VER
2 |
3 | #include
4 | int __builtin_clz(unsigned int value)
5 | {
6 | unsigned long r;
7 | _BitScanReverse(&r, value);
8 | return (31 - r);
9 | }
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/src/maniac/bit.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifdef _MSC_VER
3 |
4 | int __builtin_clz(unsigned int value);
5 |
6 | #endif
--------------------------------------------------------------------------------
/src/maniac/chance.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #include "chance.hpp"
20 | #include "bit.hpp"
21 | #include
22 |
23 | void build_table(uint16_t *zero_state, uint16_t *one_state, size_t size, uint32_t factor, unsigned int max_p)
24 | {
25 | const int64_t one = 1LL << 32;
26 | int64_t p;
27 | unsigned int last_p8, p8;
28 | unsigned int i;
29 |
30 | memset(zero_state,0,sizeof(uint16_t) * size);
31 | memset(one_state,0,sizeof(uint16_t) * size);
32 |
33 | last_p8 = 0;
34 | p = one / 2;
35 | for (i = 0; i < size / 2; i++) {
36 | p8 = (size * p + one / 2) >> 32; //FIXME try without the one
37 | if (p8 <= last_p8) p8 = last_p8 + 1;
38 | if (last_p8 && last_p8 < size && p8 <= max_p) one_state[last_p8] = p8;
39 |
40 | p += ((one - p) * factor + one / 2) >> 32;
41 | last_p8 = p8;
42 | }
43 |
44 | for (i = size - max_p; i <= max_p; i++) {
45 | if (one_state[i]) continue;
46 |
47 | p = (i * one + size / 2) / size;
48 | p += ((one - p) * factor + one / 2) >> 32;
49 | p8 = (size * p + one / 2) >> 32; //FIXME try without the one
50 | if (p8 <= i) p8 = i + 1;
51 | if (p8 > max_p) p8 = max_p;
52 | one_state[i] = p8;
53 | }
54 |
55 | for (i = 1; i < size; i++)
56 | zero_state[i] = size - one_state[size - i];
57 | }
58 |
59 | /** Computes an approximation of log(4096 / x) / log(2) * base */
60 | static uint32_t log4kf(int x, uint32_t base) {
61 | int bits = 8 * sizeof(int) - __builtin_clz(x);
62 | uint64_t y = ((uint64_t)x) << (32 - bits);
63 | uint32_t res = base * (13 - bits);
64 | uint32_t add = base;
65 | while ((add > 1) && ((y & 0x7FFFFFFF) != 0)) {
66 | y = (((uint64_t)y) * y + 0x40000000) >> 31;
67 | add >>= 1;
68 | if ((y >> 32) != 0) {
69 | res -= add;
70 | y >>= 1;
71 | }
72 | }
73 | return res;
74 | }
75 |
76 | Log4kTable::Log4kTable() {
77 | data[0] = 0;
78 | for (int i = 1; i <= 4096; i++) {
79 | data[i] = (log4kf(i, (65535UL << 16) / 12) + (1 << 15)) >> 16;
80 | }
81 | scale = 65535 / 12;
82 | }
83 |
84 | const Log4kTable log4k;
85 |
--------------------------------------------------------------------------------
/src/maniac/chance.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | struct Log4kTable {
28 | uint16_t data[4097];
29 | int scale;
30 |
31 | Log4kTable();
32 | };
33 |
34 | extern const Log4kTable log4k;
35 |
36 | void extern build_table(uint16_t *zero_state, uint16_t *one_state, size_t size, uint32_t factor, unsigned int max_p);
37 |
38 | class SimpleBitChanceTable
39 | {
40 | public:
41 | uint16_t next[2][4096]; // stored as 12-bit numbers
42 | uint32_t alpha;
43 |
44 | void init(int cut, int alpha_) {
45 | alpha = alpha_;
46 | build_table(next[0], next[1], 4096, alpha_, 4096-cut);
47 | }
48 |
49 | SimpleBitChanceTable(int cut = 2, int alpha = 0xFFFFFFFF / 19) {
50 | init(cut, alpha);
51 | }
52 | };
53 |
54 | #ifdef STATS
55 | struct BitChanceStats
56 | {
57 | double weight;
58 | double sum;
59 | double factor;
60 |
61 | BitChanceStats() : weight(0), sum(0), factor(1.0) {}
62 |
63 | void add(bool bit, unsigned int alpha) {
64 | weight += factor;
65 | if (bit) {
66 | sum += factor;
67 | }
68 | factor *= (1.0 - alpha / 4294967296.0);
69 | }
70 |
71 | BitChanceStats& operator+=(const BitChanceStats& stats) {
72 | weight += stats.weight;
73 | sum += stats.sum;
74 | return *this;
75 | }
76 |
77 | std::string format() const {
78 | std::stringstream ss;
79 | ss << sum << ',' << weight;
80 | return ss.str();
81 | }
82 | };
83 | #endif
84 |
85 | class SimpleBitChance
86 | {
87 | protected:
88 | uint16_t chance; // stored as a 12-bit number
89 | #ifdef STATS
90 | BitChanceStats stats_;
91 | #endif
92 |
93 | public:
94 | typedef SimpleBitChanceTable Table;
95 |
96 | SimpleBitChance() {
97 | chance = 0x800;
98 | }
99 |
100 | uint16_t inline get_12bit() const {
101 | return chance;
102 | }
103 | void set_12bit(uint16_t chance) {
104 | this->chance = chance;
105 | }
106 | void inline put(bool bit, const Table &table) {
107 | #ifdef STATS
108 | stats_.add(bit, table.alpha);
109 | #endif
110 | chance = table.next[bit][chance];
111 | }
112 |
113 | void estim(bool bit, uint64_t &total) const {
114 | total += log4k.data[bit ? chance : 4096-chance];
115 | }
116 |
117 | static int scale() {
118 | return log4k.scale;
119 | }
120 |
121 | #ifdef STATS
122 | const BitChanceStats& stats() const {
123 | return stats_;
124 | }
125 | #endif
126 | };
127 |
128 |
129 | #ifndef FAST_BUT_WORSE_COMPRESSION
130 |
131 | static const uint32_t MULTISCALE_ALPHAS[] = {
132 | 21590903, 66728412, 214748365, 7413105, 106514140, 10478104,
133 | //41729744, 5081644, 154536134, 53610361, 14808157, 83024800,
134 | //31468986, 3483142, 8675949, 6333940,128332124,12654046,75606698,47300557,203951463,58885392,35675766,94047111,3071053,4623799,17881424,26067561,9534590,5584795,8146883,6960985,11514860,116922432,71030141,50357314,180327910,62685268,88366071,3950501,245135590,33506680,140836325,4924204,15769017,23724167,37984644,5244115,5947593,44428377,19649020,100089021,9239337,29554783,80475310,8407260,57072137,13475351,7183492,3169265,2794299,164387337,7650051,4341711,109877739,48805148,285518438,22990693,120609957,223623543,3709472,136540575,64675496,4771639,16792101,26898887,25261851,10153668,34574286,40442237,6536419,91162830,20923221,6137730,78003381,55314351,191784837,68845961,73283013,32471914,103252233,60755844,149830100,45842100,51958541,85654236,36812186,43058031,19041256,2623791,332276342,97021591,113346113,10812893,30496923,5411776,174853162,260577854,14349874,132373756,2975884,4480536,124412038,28641651,3594527,11882728,3375207,185970177,216869333,6745365,4207184,39194272,7894563,230582101,145264850,5763342,22279836,2707704,3828091,159387120,410190395,9839267,197776890,8953217,2883663,13905751,11158365,3270616,169541181,12262333,303407934,276959225,210313815,24480974,4076824,27756639,585189062,13058253,363764189,15281050,2542478,18452249,237750805,20276138,16272536,294332358,252742534,2130583863,462185550,268647915,17328222,386315419,352964365,312752266,2313344,874357947,505177649,342471031,435457062,374878495,322372603,2463684,1348207122,696492758,535880669,2172176,398083245,476120461,1061088123,638637072,1903342123,759025196,2039621,422645434,2241650,551873246,2387331,448634113,977298116,490448053,1690401179,1181956121,2038126651,716804021,620344619,803443341,520318678,676701158,568306117,924600596,1493527858,1816328538,1120194691,1004588004,2104856,850135566,1279659514,1947720708,602531930,657419257,737644875,1976407,899176673,1649701506,1090312381,1383509600,780954783,826500455,950638308,1032515596,1992655788,1246411823,1570275450,1419498079,2084110791,1150740857,1859538985,1213845117,1915153,1773726365,1456171521,1313590710,1609656898,1531563934,1731746439
135 | };
136 |
137 |
138 | template class MultiscaleBitChanceTable {
139 | public:
140 | typedef typename BitChance::Table SubTable;
141 | SubTable subTable[N];
142 |
143 | explicit MultiscaleBitChanceTable(int cut = 8) {
144 | for (int i= 0; i class MultiscaleBitChance
151 | {
152 | protected:
153 | BitChance chances[N];
154 | uint32_t quality[N];
155 | uint8_t best;
156 | #ifdef STATS
157 | BitChanceStats stats_;
158 | #endif
159 |
160 | public:
161 | typedef MultiscaleBitChanceTable Table;
162 |
163 | MultiscaleBitChance() {
164 | set_12bit(0x800);
165 | }
166 |
167 | void set_12bit(uint16_t chanceIn) {
168 | for (int i = 0; i>9;
191 | quality[i] = (oqual*255 + sbits*4097 + 128)>>8;
192 | // quality[i] = (oqual*127 + sbits*2049 + 64)>>7;
193 | // if (quality[i] < quality[best]) best=i;
194 | chances[i].put(bit, table.subTable[i]);
195 | }
196 |
197 | for (int i=0; i
23 | #endif
24 |
25 | #include
26 | #include
27 | #include "../config.h"
28 | #include "../compiler-specific.hpp"
29 |
30 | /* RAC configuration for 24-bit RAC */
31 | class RacConfig24 {
32 | public:
33 | typedef uint_fast32_t data_t;
34 | static const data_t MAX_RANGE_BITS = 24;
35 | static const data_t MIN_RANGE_BITS = 16;
36 | static const data_t MIN_RANGE = (1UL << MIN_RANGE_BITS);
37 | static const data_t BASE_RANGE = (1UL << MAX_RANGE_BITS);
38 |
39 | static inline data_t chance_12bit_chance(int b12, data_t range) {
40 | assert(b12 > 0);
41 | assert((b12 >> 12) == 0);
42 | // We want to compute (range * b12 + 0x800) >> 12. On 64-bit architectures this is no problem
43 | if (sizeof(data_t) > 4) return (range * b12 + 0x800) >> 12;
44 | // Unfortunately, this can overflow the 32-bit data type on 32-bit architectures, so split range
45 | // in its lower and upper 12 bits, and compute separately.
46 | else return ((((range & 0xFFF) * b12 + 0x800) >> 12) + ((range >> 12) * b12));
47 | // (no worries, the compiler eliminates this branching)
48 | }
49 | };
50 |
51 | template class RacInput {
52 | public:
53 | typedef typename Config::data_t rac_t;
54 | protected:
55 | IO& io;
56 | private:
57 | #ifdef STATS
58 | uint64_t samples;
59 | #endif
60 | rac_t range;
61 | rac_t low;
62 | private:
63 | rac_t read_catch_eof() {
64 | rac_t c = io.get_c();
65 | // no reason to branch here to catch end-of-stream, just return garbage (0xFF I guess) if a premature EOS happens
66 | //if(c == io.EOS) return 0;
67 | return c;
68 | }
69 | void inline input() {
70 | if (range <= Config::MIN_RANGE) {
71 | low <<= 8;
72 | range <<= 8;
73 | low |= read_catch_eof();
74 | }
75 | if (range <= Config::MIN_RANGE) {
76 | low <<= 8;
77 | range <<= 8;
78 | low |= read_catch_eof();
79 | }
80 | }
81 | bool inline get(rac_t chance) {
82 | #ifdef STATS
83 | samples++;
84 | #endif
85 | assert(chance > 0);
86 | assert(chance < range);
87 | if (low >= range-chance) {
88 | low -= range-chance;
89 | range = chance;
90 | input();
91 | return true;
92 | } else {
93 | range -= chance;
94 | input();
95 | return false;
96 | }
97 | }
98 | public:
99 | explicit RacInput(IO& ioin) : io(ioin), range(Config::BASE_RANGE), low(0) {
100 | #ifdef STATS
101 | samples = 0;
102 | #endif
103 | rac_t r = Config::BASE_RANGE;
104 | while (r > 1) {
105 | low <<= 8;
106 | low |= read_catch_eof();
107 | r >>= 8;
108 | }
109 | }
110 |
111 | #ifdef STATS
112 | ~RacInput() {
113 | fprintf(stdout, "Total samples read from range coder: %llu\n", (unsigned long long)samples);
114 | }
115 | #endif
116 |
117 | bool inline read_12bit_chance(uint16_t b12) ATTRIBUTE_HOT {
118 | return get(Config::chance_12bit_chance(b12, range));
119 | }
120 |
121 | bool inline read_bit() {
122 | return get(range >> 1);
123 | }
124 | };
125 |
126 |
127 | template class RacInput24 : public RacInput {
128 | public:
129 | explicit RacInput24(IO& io) : RacInput(io) { }
130 | };
131 |
132 | #ifdef HAS_ENCODER
133 | #include "rac_enc.hpp"
134 | #endif
135 |
--------------------------------------------------------------------------------
/src/maniac/rac_enc.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF encoder - Free Lossless Image Format
3 | Copyright (C) 2010-2015 Jon Sneyers & Pieter Wuille, LGPL v3+
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Lesser General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | template class RacOutput {
22 | public:
23 | typedef typename Config::data_t rac_t;
24 | protected:
25 | IO& io;
26 | private:
27 | rac_t range;
28 | rac_t low;
29 | int delayed_byte;
30 | int delayed_count;
31 |
32 | void inline output() {
33 | while (range <= Config::MIN_RANGE) {
34 | int byte = low >> Config::MIN_RANGE_BITS;
35 | if (delayed_byte < 0) { // first generated byte
36 | delayed_byte = byte;
37 | } else if (((low + range) >> 8) < Config::MIN_RANGE) { // definitely no overflow
38 | io.fputc(delayed_byte);
39 | while (delayed_count) {
40 | io.fputc(0xFF);
41 | delayed_count--;
42 | }
43 | delayed_byte = byte;
44 | } else if ((low >> 8) >= Config::MIN_RANGE) { // definitely overflow
45 | io.fputc(delayed_byte + 1);
46 | while (delayed_count) {
47 | io.fputc(0);
48 | delayed_count--;
49 | }
50 | delayed_byte = byte & 0xFF;
51 | } else {
52 | delayed_count++;
53 | }
54 | low = (low & (Config::MIN_RANGE - 1)) << 8;
55 | range <<= 8;
56 | }
57 | }
58 | void inline put(rac_t chance, bool bit) {
59 | assert(chance > 0);
60 | assert(chance < range);
61 | if (bit) {
62 | low += range - chance;
63 | range = chance;
64 | } else {
65 | range -= chance;
66 | }
67 | output();
68 | }
69 | public:
70 | RacOutput(IO& ioin) : io(ioin), range(Config::BASE_RANGE), low(0), delayed_byte(-1), delayed_count(0) { }
71 |
72 | void inline write_12bit_chance(uint16_t b12, bool bit) {
73 | put(Config::chance_12bit_chance(b12, range), bit);
74 | }
75 |
76 | void inline write_bit(bool bit) {
77 | put(range >> 1, bit);
78 | }
79 |
80 | void inline flush() {
81 | low += (Config::MIN_RANGE - 1);
82 | // is this the correct way to reliably flush?
83 | range = Config::MIN_RANGE - 1;
84 | output();
85 | range = Config::MIN_RANGE - 1;
86 | output();
87 | range = Config::MIN_RANGE - 1;
88 | output();
89 | range = Config::MIN_RANGE - 1;
90 | output();
91 | io.flush();
92 | }
93 | };
94 |
95 |
96 | class RacDummy {
97 | public:
98 | static void inline write_12bit_chance(FLIF_UNUSED(uint16_t b12), bool) { }
99 | static void inline write_bit(bool) { }
100 | static void inline flush() { }
101 | };
102 |
103 |
104 | template class RacOutput24 : public RacOutput {
105 | public:
106 | RacOutput24(IO& io) : RacOutput(io) { }
107 | };
108 |
--------------------------------------------------------------------------------
/src/maniac/symbol.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "symbol.hpp"
4 |
5 | #ifdef STATS
6 | std::string SymbolChanceStats::format() const {
7 | std::stringstream ss;
8 | ss << "zero," << stats_zero.format() << ", ";
9 | ss << "sign," << stats_sign.format() << ", ";
10 | for (int i = 0; i < 17; i++) {
11 | ss << "e" << i << "," << stats_exp[i].format() << ", ";
12 | }
13 | for (int i = 0; i < 18; i++) {
14 | ss << "m" << i << "," << stats_mant[i].format() << ", ";
15 | }
16 | return ss.str();
17 | }
18 |
19 | SymbolChanceStats::~SymbolChanceStats() {
20 | fprintf(stderr, "STATS: %s\n", format().c_str());
21 | }
22 |
23 | SymbolChanceStats global_symbol_stats;
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/maniac/symbol_enc.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF encoder - Free Lossless Image Format
3 | Copyright (C) 2010-2015 Jon Sneyers & Pieter Wuille, LGPL v3+
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Lesser General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | template
22 | void UniformSymbolCoder::write_int(int min, int max, int val) {
23 | assert(max >= min);
24 | if (min != 0) {
25 | max -= min;
26 | val -= min;
27 | }
28 | if (max == 0) return;
29 |
30 | // split in [0..med] [med+1..max]
31 | int med = max/2;
32 | if (val > med) {
33 | rac.write_bit(true);
34 | write_int(med+1, max, val);
35 | } else {
36 | rac.write_bit(false);
37 | write_int(0, med, val);
38 | }
39 | return;
40 | }
41 |
42 |
43 | template void writer(SymbolCoder& coder, int bits, int value) {
44 | int pos=0;
45 | while (pos++ < bits) {
46 | coder.write(value&1, BIT_MANT, pos);
47 | value >>= 1;
48 | }
49 | }
50 |
51 | template void writer(SymbolCoder& coder, int min, int max, int value) {
52 | assert(min<=max);
53 | assert(value>=min);
54 | assert(value<=max);
55 |
56 | // avoid doing anything if the value is already known
57 | if (min == max) return;
58 |
59 | if (value == 0) { // value is zero
60 | coder.write(true, BIT_ZERO);
61 | return;
62 | }
63 |
64 | assert(min <= 0 && max >= 0); // should always be the case, because guess should always be in valid range
65 |
66 | // only output zero bit if value could also have been zero
67 | //if (max >= 0 && min <= 0)
68 | coder.write(false,BIT_ZERO);
69 | int sign = (value > 0 ? 1 : 0);
70 | if (max > 0 && min < 0) {
71 | // only output sign bit if value can be both pos and neg
72 | coder.write(sign,BIT_SIGN);
73 | }
74 | if (sign) min = 1;
75 | if (!sign) max = -1;
76 | const int a = abs(value);
77 | const int e = maniac::util::ilog2(a);
78 | int amin = sign ? abs(min) : abs(max);
79 | int amax = sign ? abs(max) : abs(min);
80 |
81 | int emax = maniac::util::ilog2(amax);
82 | int i = maniac::util::ilog2(amin);
83 |
84 | while (i < emax) {
85 | // if exponent >i is impossible, we are done
86 | if ((1 << (i+1)) > amax) break;
87 | // if exponent i is possible, output the exponent bit
88 | coder.write(i==e, BIT_EXP, (i<<1) + sign);
89 | if (i==e) break;
90 | i++;
91 | }
92 | // e_printf("exp=%i\n",e);
93 | int have = (1 << e);
94 | int left = have-1;
95 | for (int pos = e; pos>0;) {
96 | int bit = 1;
97 | left ^= (1 << (--pos));
98 | int minabs1 = have | (1< amax) { // 1-bit is impossible
103 | bit = 0;
104 | } else if (maxabs0 >= amin) { // 0-bit and 1-bit are both possible
105 | bit = (a >> pos) & 1;
106 | coder.write(bit, BIT_MANT, pos);
107 | }
108 | have |= (bit << pos);
109 | }
110 | }
111 |
112 |
113 | template
114 | void SimpleSymbolBitCoder::write(bool bit, SymbolChanceBitType typ, int i) {
115 | BitChance& bch = ctx.bit(typ, i);
116 | rac.write_12bit_chance(bch.get_12bit(), bit);
117 | bch.put(bit, table);
118 | }
119 |
120 |
121 | template
122 | void SimpleSymbolCoder::write_int(int min, int max, int value) {
123 | SimpleSymbolBitCoder bitCoder(table, ctx, rac);
124 | writer >(bitCoder, min, max, value);
125 | }
126 | template
127 | void SimpleSymbolCoder::write_int(int nbits, int value) {
128 | assert (nbits <= bits);
129 | SimpleSymbolBitCoder bitCoder(table, ctx, rac);
130 | writer(bitCoder, nbits, value);
131 | }
132 |
--------------------------------------------------------------------------------
/src/maniac/util.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include "bit.hpp"
23 |
24 | namespace maniac {
25 | namespace util {
26 |
27 | static inline int ilog2(uint32_t l) {
28 | if (l == 0) { return 0; }
29 | // return sizeof(unsigned int) * 8 - __builtin_clz(l) - 1;
30 | return sizeof(unsigned int) * 8 - 1 - __builtin_clz(l);
31 | }
32 |
33 | void indent(int n);
34 |
35 |
36 | } // namespace util
37 | } // namespace maniac
38 |
--------------------------------------------------------------------------------
/src/transform/bounds.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include "transform.hpp"
25 | #include "../maniac/symbol.hpp"
26 |
27 | class ColorRangesBounds final : public ColorRanges {
28 | protected:
29 | const std::vector > bounds;
30 | const ColorRanges *ranges;
31 | public:
32 | ColorRangesBounds(const std::vector > &boundsIn, const ColorRanges *rangesIn) : bounds(boundsIn), ranges(rangesIn) {}
33 | bool isStatic() const override { return false; }
34 | int numPlanes() const override { return bounds.size(); }
35 | ColorVal min(int p) const override { assert(pmin(p), bounds[p].first); }
36 | ColorVal max(int p) const override { assert(pmax(p), bounds[p].second); }
37 | void snap(const int p, const prevPlanes &pp, ColorVal &min, ColorVal &max, ColorVal &v) const override {
38 | if (p==0 || p==3) { min=bounds[p].first; max=bounds[p].second; } // optimization for special case
39 | else {
40 | ranges->snap(p,pp,min,max,v);
41 | if (min < bounds[p].first) min=bounds[p].first;
42 | if (max > bounds[p].second) max=bounds[p].second;
43 | if (min>max) {
44 | // should happen only if alpha=0 interpolation produces YI combination for which Q range from ColorRangesYIQ is outside bounds
45 | min=bounds[p].first;
46 | max=bounds[p].second;
47 | }
48 | }
49 | if(v>max) v=max;
50 | if(vminmax(p, pp, min, max);
56 | if (min < bounds[p].first) min=bounds[p].first;
57 | if (max > bounds[p].second) max=bounds[p].second;
58 | if (min>max) {
59 | // should happen only if alpha=0 interpolation produces YI combination for which Q range from ColorRangesYIQ is outside bounds
60 | min=bounds[p].first;
61 | max=bounds[p].second;
62 | }
63 | assert(min <= max);
64 | }
65 | };
66 |
67 |
68 | template
69 | class TransformBounds : public Transform {
70 | protected:
71 | std::vector > bounds;
72 |
73 | bool undo_redo_during_decode() override { return false; }
74 |
75 | const ColorRanges *meta(Images&, const ColorRanges *srcRanges) override {
76 | if (srcRanges->isStatic()) {
77 | return new StaticColorRanges(bounds);
78 | } else {
79 | return new ColorRangesBounds(bounds, srcRanges);
80 | }
81 | }
82 |
83 | bool load(const ColorRanges *srcRanges, RacIn &rac) override {
84 | if (srcRanges->numPlanes() > 4) return false; // something wrong if Bounds is done on FRA
85 | SimpleSymbolCoder, 18> coder(rac);
86 | bounds.clear();
87 | for (int p=0; pnumPlanes(); p++) {
88 | // ColorVal min = coder.read_int(0, srcRanges->max(p) - srcRanges->min(p)) + srcRanges->min(p);
89 | // ColorVal max = coder.read_int(0, srcRanges->max(p) - min) + min;
90 | ColorVal min = coder.read_int2(srcRanges->min(p), srcRanges->max(p));
91 | ColorVal max = coder.read_int2(min, srcRanges->max(p));
92 | if (min > max) return false;
93 | if (min < srcRanges->min(p)) return false;
94 | if (max > srcRanges->max(p)) return false;
95 | bounds.push_back(std::make_pair(min,max));
96 | v_printf(5,"[%i:%i..%i]",p,min,max);
97 | }
98 | return true;
99 | }
100 |
101 | #ifdef HAS_ENCODER
102 | void save(const ColorRanges *srcRanges, RacOut &rac) const override {
103 | SimpleSymbolCoder, 18> coder(rac);
104 | for (int p=0; pnumPlanes(); p++) {
105 | ColorVal min = bounds[p].first;
106 | ColorVal max = bounds[p].second;
107 | // coder.write_int(0, srcRanges->max(p) - srcRanges->min(p), min - srcRanges->min(p));
108 | // coder.write_int(0, srcRanges->max(p) - min, max - min);
109 | coder.write_int2(srcRanges->min(p), srcRanges->max(p), min);
110 | coder.write_int2(min, srcRanges->max(p), max);
111 | v_printf(5,"[%i:%i..%i]",p,min,max);
112 | }
113 | }
114 |
115 | bool process(const ColorRanges *srcRanges, const Images &images) override {
116 | if (images[0].palette) return false; // skip if the image is already a palette image
117 | bounds.clear();
118 | bool trivialbounds=true;
119 | int nump=srcRanges->numPlanes();
120 | for (int p=0; pmax(p);
122 | ColorVal max = srcRanges->min(p);
123 | for (const Image& image : images)
124 | for (uint32_t r=0; r3 && p<3 && image(3,r,c)==0) continue; // don't take fully transparent pixels into account
127 | ColorVal v = image(p,r,c);
128 | if (v < min) min = v;
129 | if (v > max) max = v;
130 | assert(v <= srcRanges->max(p));
131 | assert(v >= srcRanges->min(p));
132 | }
133 | }
134 | if (min > max) min = max = (min+max)/2; // this can happen if the image is fully transparent
135 | bounds.push_back(std::make_pair(min,max));
136 | if (min > srcRanges->min(p)) trivialbounds=false;
137 | if (max < srcRanges->max(p)) trivialbounds=false;
138 | }
139 | return !trivialbounds;
140 | }
141 | #endif
142 | };
143 |
--------------------------------------------------------------------------------
/src/transform/factory.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "transform.hpp"
4 |
5 | #include "ycocg.hpp"
6 | //#include "yc1c2.hpp"
7 | #include "permute.hpp"
8 | #include "bounds.hpp"
9 | #include "colorbuckets.hpp"
10 | #include "palette.hpp"
11 | #include "palette_A.hpp"
12 | #include "palette_C.hpp"
13 | //#include "palette_CoCg.hpp"
14 | #ifdef SUPPORT_ANIMATION
15 | #include "frameshape.hpp"
16 | #include "framedup.hpp"
17 | #include "framecombine.hpp"
18 | #endif
19 | //#include "dct.hpp"
20 |
21 | template
22 | std::unique_ptr> create_transform(const std::string &desc) {
23 | if (desc == "YCoCg")
24 | return make_unique>();
25 | // use this if you just want to quickly try YC1C2
26 | // return new TransformYCC();
27 | if (desc == "Bounds")
28 | return make_unique>();
29 | if (desc == "PermutePlanes")
30 | return make_unique>();
31 | if (desc == "Color_Buckets")
32 | return make_unique>();
33 | if (desc == "Palette")
34 | return make_unique>();
35 | if (desc == "Palette_Alpha")
36 | return make_unique>();
37 | // if (desc == "Palette_Chroma") // turned out to be useless
38 | // return make_unique>();
39 | if (desc == "Channel_Compact")
40 | return make_unique>();
41 | #ifdef SUPPORT_ANIMATION
42 | if (desc == "Frame_Shape")
43 | return make_unique>();
44 | if (desc == "Duplicate_Frame")
45 | return make_unique>();
46 | if (desc == "Frame_Lookback")
47 | return make_unique>();
48 | #endif
49 | // if (desc == "DCT")
50 | // return make_unique>();
51 | return NULL;
52 | }
53 |
54 | template std::unique_ptr> create_transform(const std::string &desc);
55 | template std::unique_ptr> create_transform(const std::string &desc);
56 | template std::unique_ptr> create_transform(const std::string &desc);
57 |
--------------------------------------------------------------------------------
/src/transform/factory.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "transform.hpp"
4 | #include
5 |
6 | template
7 | std::unique_ptr> create_transform(const std::string &desc);
8 |
--------------------------------------------------------------------------------
/src/transform/framedup.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 |
20 | #pragma once
21 |
22 | #include
23 |
24 | #include "transform.hpp"
25 | #include "../maniac/symbol.hpp"
26 |
27 |
28 |
29 | template
30 | class TransformFrameDup final : public Transform {
31 | protected:
32 | std::vector seen_before;
33 | uint32_t nb;
34 |
35 | bool undo_redo_during_decode() override { return false; }
36 | const ColorRanges *meta(Images& images, const ColorRanges *srcRanges) override {
37 | for (unsigned int fr=0; fr &rac) override {
47 | SimpleSymbolCoder, 18> coder(rac);
48 | seen_before.clear();
49 | seen_before.push_back(-1);
50 | for (unsigned int i=1; i=0) count++; } v_printf(5,"[%i]",count);
52 | return true;
53 | }
54 |
55 | #ifdef HAS_ENCODER
56 | void save(const ColorRanges *, RacOut &rac) const override {
57 | SimpleSymbolCoder, 18> coder(rac);
58 | assert(nb == seen_before.size());
59 | for (unsigned int i=1; i=0) count++; } v_printf(5,"[%i]",count);
61 | }
62 |
63 | bool process(const ColorRanges *srcRanges, const Images &images) override {
64 | int np=srcRanges->numPlanes();
65 | nb = images.size();
66 | seen_before.clear();
67 | seen_before.resize(nb,-1);
68 | bool dupes_found=false;
69 | for (unsigned int fr=1; fr
22 |
23 | #include "transform.hpp"
24 | #include "../maniac/symbol.hpp"
25 |
26 |
27 |
28 | template
29 | class TransformFrameShape final : public Transform {
30 | protected:
31 | std::vector b;
32 | std::vector e;
33 | uint32_t cols;
34 | uint32_t nb;
35 |
36 | bool undo_redo_during_decode() override { return false; }
37 |
38 | const ColorRanges *meta(Images& images, const ColorRanges *srcRanges) override {
39 | uint32_t pos=0;
40 | for (unsigned int fr=1; fr= 0) continue;
43 | for (uint32_t r=0; r &rac) override {
56 | SimpleSymbolCoder, 18> coder(rac);
57 | for (unsigned int i=0; i cols || e[i] < b[i] || e[i] <= 0) {
61 | e_printf("\nError: FRS transform: invalid end column\n");
62 | return false;
63 | }
64 | }
65 | return true;
66 | }
67 |
68 | #if HAS_ENCODER
69 | void save(const ColorRanges *, RacOut &rac) const override {
70 | SimpleSymbolCoder, 18> coder(rac);
71 | assert(nb == b.size());
72 | assert(nb == e.size());
73 | for (unsigned int i=0; inumPlanes();
80 | nb = 0;
81 | cols = images[0].cols();
82 | for (unsigned int fr=1; fr= 0) continue;
85 | nb += image.rows();
86 | for (uint32_t r=0; r3 && image(3,r,c) == 0 && images[fr-1](3,r,c)==0) continue;
90 | for (int p=0; p= b.back(); c--) {
98 | if (image.alpha_zero_special && np>3 && image(3,r,c) == 0 && images[fr-1](3,r,c)==0) continue;
99 | for (int p=0; p
25 | #include
26 |
27 |
28 | class ColorRangesPaletteC final : public ColorRanges {
29 | protected:
30 | const ColorRanges *ranges;
31 | int nb_colors[4];
32 | public:
33 | ColorRangesPaletteC(const ColorRanges *rangesIn, const int nb[4]) : ranges(rangesIn) { for (int i=0; i<4; i++) nb_colors[i] = nb[i]; }
34 | bool isStatic() const override { return true; }
35 | int numPlanes() const override { return ranges->numPlanes(); }
36 |
37 | ColorVal min(FLIF_UNUSED(int p)) const override { return 0; }
38 | ColorVal max(int p) const override { return nb_colors[p]; }
39 | void minmax(const int p, FLIF_UNUSED(const prevPlanes &pp), ColorVal &minv, ColorVal &maxv) const override {
40 | minv=0; maxv=nb_colors[p];
41 | }
42 |
43 | };
44 |
45 |
46 | template
47 | class TransformPaletteC : public Transform {
48 | protected:
49 | std::vector CPalette_vector[4];
50 | std::vector CPalette_inv_vector[4];
51 |
52 | public:
53 | bool init(const ColorRanges *srcRanges) override {
54 | if (srcRanges->numPlanes()>4) return false; // FRA should always be done after CC, this is just to catch bad input
55 | return true;
56 | }
57 |
58 | const ColorRanges *meta(FLIF_UNUSED(Images& images), const ColorRanges *srcRanges) override {
59 | int nb[4] = {};
60 | v_printf(4,"[");
61 | for (int i=0; inumPlanes(); i++) {
62 | nb[i] = CPalette_vector[i].size()-1;
63 | if (i>0) v_printf(4,",");
64 | v_printf(4,"%i",nb[i]);
65 | // if (nb[i] < 64) nb[i] <<= 2;
66 | }
67 | v_printf(4,"]");
68 | return new ColorRangesPaletteC(srcRanges, nb);
69 | }
70 |
71 | void invData(Images& images, FLIF_UNUSED(uint32_t strideCol), FLIF_UNUSED(uint32_t strideRow)) const override {
72 | for (Image& image : images) {
73 |
74 | const uint32_t scaledRows = image.scaledRows();
75 | const uint32_t scaledCols = image.scaledCols();
76 |
77 | for (int p=0; p 64 ? 0 : 2);
81 | image.undo_make_constant_plane(p);
82 | GeneralPlane &plane = image.getPlane(p);
83 | for (uint32_t r=0; r> stretch]);
87 | if (P < 0 || P >= (int) palette_size) P = 0; // might happen on invisible pixels with predictor -H1
88 | assert(P < (int) palette_size);
89 | plane.set(r,c, palette[P]);
90 | }
91 | }
92 | }
93 | }
94 | }
95 |
96 | #if HAS_ENCODER
97 | bool process(const ColorRanges *srcRanges, const Images &images) override {
98 |
99 | if (images[0].palette) return false; // skip if the image is already a palette image
100 |
101 | std::set CPalette;
102 | bool nontrivial=false;
103 | for (int p=0; pnumPlanes(); p++) {
104 | if (p==3) CPalette.insert(0); // ensure that A=0 is still A=0 even if image does not contain zero-alpha pixels
105 | for (const Image& image : images) {
106 | for (uint32_t r=0; rmax(p)-srcRanges->min(p)) nontrivial = true;
113 | // if on all channels, less than 10% of the range can be compacted away, it's probably a bad idea to do the compaction
114 | // since the gain from a smaller RGB range will probably not compensate for the disturbing of the YIQ transform
115 | if ((int)CPalette.size() * 10 <= 9 * (srcRanges->max(p)-srcRanges->min(p))) nontrivial = true;
116 | if (CPalette.size() < 10) {
117 | // add up to 10 shades of gray
118 | ColorVal prev=0;
119 | for (ColorVal c : CPalette) {
120 | if (c > prev+1) CPalette_vector[p].push_back((c+prev)/2);
121 | CPalette_vector[p].push_back(c);
122 | prev=c;
123 | nontrivial=true;
124 | }
125 | } else {
126 | for (ColorVal c : CPalette) CPalette_vector[p].push_back(c);
127 | }
128 | CPalette.clear();
129 | CPalette_inv_vector[p].resize(srcRanges->max(p)+1);
130 | for (unsigned int i=0; i64 ? 0 : 2);
138 | for (uint32_t r=0; r &rac) const override {
150 | SimpleSymbolCoder, 18> coder(rac);
151 | for (int p=0; pnumPlanes(); p++) {
152 | coder.write_int(0, srcRanges->max(p)-srcRanges->min(p), CPalette_vector[p].size()-1);
153 | ColorVal min=srcRanges->min(p);
154 | int remaining=CPalette_vector[p].size()-1;
155 | for (unsigned int i=0; imax(p)-min-remaining, CPalette_vector[p][i]-min);
157 | min = CPalette_vector[p][i]+1;
158 | remaining--;
159 | }
160 | }
161 | }
162 | #endif
163 | bool load(const ColorRanges *srcRanges, RacIn &rac) override {
164 | SimpleSymbolCoder, 18> coder(rac);
165 | for (int p=0; pnumPlanes(); p++) {
166 | unsigned int nb = coder.read_int(0, srcRanges->max(p)-srcRanges->min(p)) + 1;
167 | ColorVal min=srcRanges->min(p);
168 | int remaining = nb-1;
169 | for (unsigned int i=0; imax(p)-min-remaining));
171 | min = CPalette_vector[p][i]+1;
172 | remaining--;
173 | }
174 | }
175 | return true;
176 | }
177 | };
178 |
--------------------------------------------------------------------------------
/src/transform/permute.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 |
20 | #pragma once
21 |
22 | #include "../image/image.hpp"
23 | #include "../image/color_range.hpp"
24 | #include "transform.hpp"
25 |
26 | class ColorRangesPermute final : public ColorRanges {
27 | protected:
28 | const std::vector permutation;
29 | const ColorRanges *ranges;
30 | public:
31 | ColorRangesPermute(const std::vector &perm, const ColorRanges *rangesIn)
32 | : permutation(perm), ranges(rangesIn) { }
33 | bool isStatic() const override { return false; }
34 | int numPlanes() const override { return ranges->numPlanes(); }
35 |
36 | ColorVal min(int p) const override { return ranges->min(permutation[p]); }
37 | ColorVal max(int p) const override { return ranges->max(permutation[p]); }
38 |
39 | };
40 |
41 | class ColorRangesPermuteSubtract final : public ColorRanges {
42 | protected:
43 | const std::vector permutation;
44 | const ColorRanges *ranges;
45 | public:
46 | ColorRangesPermuteSubtract(const std::vector &perm, const ColorRanges *rangesIn)
47 | : permutation(perm), ranges(rangesIn) { }
48 | bool isStatic() const override { return false; }
49 | int numPlanes() const override { return ranges->numPlanes(); }
50 |
51 | ColorVal min(int p) const override { if (p==0 || p>2) return ranges->min(permutation[p]); else return ranges->min(permutation[p])-ranges->max(permutation[0]); }
52 | ColorVal max(int p) const override { if (p==0 || p>2) return ranges->max(permutation[p]); else return ranges->max(permutation[p])-ranges->min(permutation[0]); }
53 | void minmax(const int p, const prevPlanes &pp, ColorVal &minv, ColorVal &maxv) const override {
54 | if (p==0 || p>2) { minv = min(p); maxv = max(p); }
55 | else { minv = ranges->min(permutation[p])-pp[0]; maxv = ranges->max(permutation[p])-pp[0]; }
56 | }
57 |
58 | };
59 |
60 |
61 | template
62 | class TransformPermute : public Transform {
63 | protected:
64 | std::vector permutation;
65 | const ColorRanges *ranges;
66 | bool subtract;
67 |
68 | public:
69 | bool virtual init(const ColorRanges *srcRanges) override {
70 | if (srcRanges->numPlanes() < 3) return false;
71 | if (srcRanges->min(0) < 0 || srcRanges->min(1) < 0 || srcRanges->min(2) < 0) return false; // already did YCoCg
72 | permutation.resize(srcRanges->numPlanes());
73 | ranges = srcRanges;
74 | return true;
75 | }
76 |
77 | const ColorRanges *meta(Images&, const ColorRanges *srcRanges) override {
78 | if (subtract) return new ColorRangesPermuteSubtract(permutation, srcRanges);
79 | else return new ColorRangesPermute(permutation, srcRanges);
80 | }
81 |
82 | #ifdef HAS_ENCODER
83 | void configure(const int setting) override {
84 | subtract = setting;
85 | }
86 | bool process(const ColorRanges *srcRanges, const Images &images) override {
87 | if (images[0].palette) return false; // skip if the image is already a palette image
88 | const int perm[5] = {1,0,2,3,4}; // just always transform RGB to GRB, we can do something more complicated later
89 | for (int p=0; pnumPlanes(); p++) {
90 | permutation[p] = perm[p];
91 | }
92 | return true;
93 | }
94 | void data(Images& images) const override {
95 | ColorVal pixel[5];
96 | for (Image& image : images)
97 | for (uint32_t r=0; rnumPlanes(); p++) pixel[p] = image(p,r,c);
100 | image.set(0,r,c, pixel[permutation[0]]);
101 | if (!subtract) { for (int p=1; pnumPlanes(); p++) image.set(p,r,c, pixel[permutation[p]]); }
102 | else { for (int p=1; p<3 && pnumPlanes(); p++) image.set(p,r,c, pixel[permutation[p]] - pixel[permutation[0]]);
103 | for (int p=3; pnumPlanes(); p++) image.set(p,r,c, pixel[permutation[p]]); }
104 | }
105 | }
106 | }
107 | void save(const ColorRanges *srcRanges, RacOut &rac) const override {
108 | SimpleSymbolCoder, 18> coder(rac);
109 | coder.write_int2(0, 1, subtract);
110 | if (subtract) v_printf(4,"Subtract");
111 | for (int p=0; pnumPlanes(); p++) {
112 | coder.write_int2(0, srcRanges->numPlanes()-1, permutation[p]);
113 | v_printf(5,"[%i->%i]",p,permutation[p]);
114 | }
115 | }
116 | #endif
117 | bool load(const ColorRanges *srcRanges, RacIn &rac) override {
118 | SimpleSymbolCoder, 18> coder(rac);
119 | subtract = coder.read_int2(0, 1);
120 | if (subtract) v_printf(4,"Subtract");
121 | bool from[4] = {false, false, false, false}, to[4] = {false, false, false, false};
122 | for (int p=0; pnumPlanes(); p++) {
123 | permutation[p] = coder.read_int2(0, srcRanges->numPlanes()-1);
124 | v_printf(5,"[%i->%i]",p,permutation[p]);
125 | from[p] = true;
126 | to[permutation[p]] = true;
127 | }
128 | for (int p=0; pnumPlanes(); p++) {
129 | if (!from[p] || !to[p]) {
130 | e_printf("\nNot a valid permutation!\n");
131 | return false;
132 | }
133 | }
134 | return true;
135 | }
136 | #define CLAMP(x,l,u) (x>u?u:(xnumPlanes(); p++) image.undo_make_constant_plane(p);
145 | for (uint32_t r=0; rnumPlanes(); p++) pixel[p] = image(p,r,c);
148 | for (int p=0; pnumPlanes(); p++) image.set(permutation[p],r,c, pixel[p]);
149 | image.set(permutation[0],r,c, pixel[0]);
150 | if (!subtract) { for (int p=1; pnumPlanes(); p++) image.set(permutation[p],r,c, pixel[p]); }
151 | else { for (int p=1; p<3 && pnumPlanes(); p++) image.set(permutation[p],r,c, CLAMP(pixel[p] + pixel[0], ranges->min(permutation[p]), ranges->max(permutation[p])));
152 | for (int p=3; pnumPlanes(); p++) image.set(permutation[p],r,c, pixel[p]); }
153 | }
154 | }
155 | }
156 | }
157 | };
158 |
159 |
--------------------------------------------------------------------------------
/src/transform/transform.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | #pragma once
20 |
21 | #include "../image/image.hpp"
22 | #include "../image/color_range.hpp"
23 | #include "../maniac/rac.hpp"
24 | #include "../flif_config.h"
25 |
26 |
27 | template
28 | class Transform {
29 | protected:
30 |
31 | public:
32 | virtual ~Transform() {};
33 |
34 | // On encode: init, process, save, meta, data,
35 | // On decode: init, load, meta, , invData ( + optional configure anywhere)
36 | // Progressive decode: init, load, meta, , invData, , data,
37 | // , invData, , data,
38 | // ...
39 | // , invData
40 |
41 |
42 | bool virtual init(const ColorRanges *) { return true; }
43 | bool virtual undo_redo_during_decode() { return true; }
44 | void virtual configure(const int) { }
45 | bool virtual load(const ColorRanges *, RacIn &) { return true; };
46 | #ifdef HAS_ENCODER
47 | bool virtual process(const ColorRanges *, const Images &) { return true; };
48 | void virtual save(const ColorRanges *, RacOut &) const {};
49 | void virtual data(Images&) const {}
50 | #endif
51 | const ColorRanges virtual *meta(Images&, const ColorRanges *srcRanges) { return new DupColorRanges(srcRanges); }
52 | void virtual invData(Images&, FLIF_UNUSED(uint32_t strideCol)=1, FLIF_UNUSED(uint32_t strideRow)=1) const {}
53 | bool virtual is_palette_transform() const { return false; }
54 | };
55 |
--------------------------------------------------------------------------------
/src/transform/yc1c2.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | FLIF - Free Lossless Image Format
3 |
4 | Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 |
20 | #pragma once
21 |
22 | #include "../image/image.hpp"
23 | #include "../image/color_range.hpp"
24 | #include "transform.hpp"
25 | #include
26 |
27 | #define clip(x,l,u) if ((x) < (l)) {(x)=(l);} else if ((x) > (u)) {(x)=(u);}
28 |
29 |
30 | class ColorRangesYCC final : public ColorRanges {
31 | protected:
32 | const int maximum;
33 | const ColorRanges *ranges;
34 | public:
35 | ColorRangesYCC(int m, const ColorRanges *rangesIn)
36 | : maximum(m), ranges(rangesIn) {
37 | }
38 | bool isStatic() const { return false; }
39 | int numPlanes() const { return ranges->numPlanes(); }
40 |
41 | ColorVal min(int p) const {
42 | switch(p) {
43 | case 0: return 0;
44 | case 1: return -maximum;
45 | case 2: return -maximum;
46 | default: return ranges->min(p);
47 | };
48 | }
49 | ColorVal max(int p) const {
50 | switch(p) {
51 | case 0: return maximum;
52 | case 1: return maximum;
53 | case 2: return maximum;
54 | default: return ranges->max(p);
55 | };
56 | }
57 |
58 | void minmax(const int p, const prevPlanes &pp, ColorVal &minv, ColorVal &maxv) const {
59 | if (p<3) { minv=min(p); maxv=max(p); return; }
60 | else ranges->minmax(p,pp,minv,maxv);
61 | }
62 | };
63 |
64 |
65 | template
66 | class TransformYCC : public Transform {
67 | protected:
68 | int maximum;
69 | const ColorRanges *ranges;
70 |
71 | public:
72 | bool virtual init(const ColorRanges *srcRanges) override {
73 | if (srcRanges->numPlanes() < 3) return false;
74 | if (srcRanges->min(0) < 0 || srcRanges->min(1) < 0 || srcRanges->min(2) < 0) return false;
75 | if (srcRanges->min(0) == srcRanges->max(0) || srcRanges->min(1) == srcRanges->max(1) || srcRanges->min(2) == srcRanges->max(2)) return false;
76 | maximum = std::max(std::max(srcRanges->max(0), srcRanges->max(1)), srcRanges->max(2));
77 | ranges = srcRanges;
78 | return true;
79 | }
80 |
81 | const ColorRanges *meta(Images&, const ColorRanges *srcRanges) override {
82 | return new ColorRangesYCC(maximum, srcRanges);
83 | }
84 |
85 | #ifdef HAS_ENCODER
86 | void data(Images& images) const override {
87 | ColorVal R,G,B,Y,C1,C2;
88 | for (Image& image : images)
89 | for (uint32_t r=0; rmax(0), ranges->max(1), ranges->max(2)};
109 | for (Image& image : images) {
110 | image.undo_make_constant_plane(0);
111 | image.undo_make_constant_plane(1);
112 | image.undo_make_constant_plane(2);
113 |
114 | const uint32_t scaledRows = image.scaledRows();
115 | const uint32_t scaledCols = image.scaledCols();
116 |
117 | for (uint32_t r=0; r/dev/null >/dev/null
9 | then
10 | echo "FLIF not found, please install FLIF first!"
11 | exit 1
12 | fi
13 | if ! $APNGDIS 2>/dev/null |grep -q APNG
14 | then
15 | echo "APNG Disassembler not found, please install it first!"
16 | echo "sudo apt-get install apngdis"
17 | exit 1
18 | fi
19 |
20 | if [ $# -lt 1 ]
21 | then
22 | echo "Usage: apng2flif input.png [output.flif [flif-options]]"
23 | exit
24 | fi
25 |
26 | IN="$1"
27 | shift
28 |
29 | if [ $# -lt 1 ]
30 | then
31 | OUT="$(dirname "$IN")/$(basename "$IN" .png).flif"
32 | else
33 | OUT="$1"
34 | shift
35 | fi
36 |
37 | echo "Decoding $IN ..."
38 | $APNGDIS "$IN" $TMP_PREFIX >/dev/null
39 | FRAME_DELAY=""
40 | for d in $TMP_PREFIX*.txt
41 | do
42 | . ./$d
43 | FRAME_DELAY="$FRAME_DELAY$((1000 * $delay)),"
44 | done
45 | echo "Encoding $OUT ..."
46 | $FLIF -F$FRAME_DELAY $@ $TMP_PREFIX*.$TMP_FORMAT "$OUT"
47 | rm $TMP_PREFIX*.$TMP_FORMAT
48 | rm $TMP_PREFIX*.txt
49 |
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame01.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame02.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame03.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame04.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame05.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame06.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame07.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame08.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame09.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame10.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame11.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame12.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame13.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame14.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame15.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame16.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame17.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame18.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame19.png
--------------------------------------------------------------------------------
/tools/bouncing_ball_frames/bouncing-ball-frame20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/bouncing_ball_frames/bouncing-ball-frame20.png
--------------------------------------------------------------------------------
/tools/build-libpng.sh:
--------------------------------------------------------------------------------
1 | set -ex
2 |
3 | mkdir ~/build-libpng
4 | cd ~/build-libpng
5 | wget "http://prdownloads.sourceforge.net/libpng/libpng-1.6.28.tar.xz"
6 | tar xf libpng-1.6.28.tar.xz
7 | cd libpng-1.6.28/
8 | ./configure || cat config.log
9 | make install
10 |
--------------------------------------------------------------------------------
/tools/endless_war.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/endless_war.gif
--------------------------------------------------------------------------------
/tools/gif2flif:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | FLIF="flif"
4 | CONVERT="convert"
5 | TMP_PREFIX="gif2flif_tmp_frame"
6 | TMP_FORMAT="png"
7 |
8 | if ! $FLIF 2>/dev/null >/dev/null
9 | then
10 | echo "FLIF not found, please install FLIF first!"
11 | exit 1
12 | fi
13 | if ! $CONVERT -version 2>/dev/null >/dev/null
14 | then
15 | echo "ImageMagick not found, please install it first!"
16 | echo "sudo apt-get install imagemagick"
17 | exit 1
18 | fi
19 |
20 | if [ $# -lt 1 ]
21 | then
22 | echo "Usage: gif2flif input.gif [output.flif [flif-options]]"
23 | exit
24 | fi
25 |
26 | IN="$1"
27 | shift
28 |
29 | if [ $# -lt 1 ]
30 | then
31 | OUT="$(dirname "$IN")/$(basename "$IN" .gif).flif"
32 | else
33 | OUT="$1"
34 | shift
35 | fi
36 |
37 | echo "Decoding $IN ..."
38 | FRAME_DELAY="$($CONVERT -identify -format "%T0," -coalesce "$IN" $TMP_PREFIX%04d.$TMP_FORMAT)"
39 | echo "Encoding $OUT ..."
40 | $FLIF -F "$FRAME_DELAY" $@ $TMP_PREFIX*.$TMP_FORMAT "$OUT"
41 | rm $TMP_PREFIX*.$TMP_FORMAT
42 |
--------------------------------------------------------------------------------
/tools/kodim01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FLIF-hub/FLIF/0074d6fd095d27ce81346aa3fbe9bab59105053e/tools/kodim01.png
--------------------------------------------------------------------------------
/tools/sizes.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | FLIF_FLAGS=""
4 |
5 | make clean
6 |
7 | git reset --hard HEAD > times.log
8 | if [ ! -d "./test_images" ] ; then
9 | echo "Need directory named 'test_images' to contain sample images."
10 | exit 1
11 | fi
12 |
13 | # if "old" already exists for some reason, do NOT work on current branch but bail out
14 | git checkout -b old || exit 2
15 |
16 |
17 |
18 | for i in `seq 1 50`; do
19 | git_head=`git log -1 --format=%h`
20 | # if build fails, make clean and try again
21 | make flif CXXFLAGS="-O3" -j4 || make clean ; make flif CXXFLAGS="-O3" -j4 || (git reset --hard HEAD^1 ; continue)
22 | echo "Run number $i"
23 | mkdir -p test_images/run_${i}
24 | cd test_images
25 | for image in `find . | grep '\.png$'` ; do
26 | ../flif ${FLIF_FLAGS} ${image} run_${i}/${image//png/flif}
27 | done
28 | cd ..
29 | echo "run $i `du -sb test_images/run_${i} | cut -d' ' -f1` $git_head " | tee -a sizes.log
30 | git reset --hard HEAD^1
31 | done
32 |
--------------------------------------------------------------------------------
/tools/test-lossy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -ex
4 |
5 | FLIF=$1
6 | IN=$2
7 | OUTF=$3
8 | OUTP=$4
9 |
10 | runtest() {
11 | local lossyArg=$1
12 | local orderArg=$2
13 |
14 | rm -f ${OUTF} ${OUTP}
15 | ${FLIF} $lossyArg $orderArg "${IN}" "${OUTF}"
16 | ${FLIF} -d ${OUTF} ${OUTP}
17 | test "`compare -metric AE ${IN} ${OUTP} null: 2>&1`" -lt 500000
18 | }
19 |
20 | runtest -I -Q40
21 |
22 | runtest -I -Q0
23 |
24 | runtest -N -Q40
25 |
26 | runtest -N -Q0
27 |
28 |
--------------------------------------------------------------------------------
/tools/test-metadata.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -ex
4 |
5 | FLIF=$1
6 | IN=$2
7 | OUTF=$3
8 | OUTP=$4
9 |
10 | EXIFIN=../tmp-test/in-exif.xmp
11 | EXIFOUT=../tmp-test/out-exif.xmp
12 | EXIFTOOL_OPTIONS="-XMP:*"
13 |
14 | rm -f ${OUTF} ${OUTP} ${EXIFIN} ${EXIFOUT}
15 | ${FLIF} "${IN}" "${OUTF}"
16 | ${FLIF} -d ${OUTF} ${OUTP}
17 | exiftool ${EXIFTOOL_OPTIONS} ${IN} -o ${EXIFIN}
18 | exiftool ${EXIFTOOL_OPTIONS} ${OUTP} -o ${EXIFOUT}
19 | diff ${EXIFIN} ${EXIFOUT}
20 |
21 |
--------------------------------------------------------------------------------
/tools/test-roundtrip.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -ex
4 |
5 | FLIF=$1
6 | IN=$2
7 | OUTF=$3
8 | OUTP=$4
9 |
10 | runtest() {
11 | local encArgs=$1
12 | local decArgs=$2
13 |
14 | rm -f ${OUTF} ${OUTP}
15 | $FLIF $encArgs "${IN}" "${OUTF}"
16 | $FLIF -d $decArgs ${OUTF} ${OUTP}
17 | test "`compare -metric AE ${IN} ${OUTP} null: 2>&1`" = "0"
18 | }
19 |
20 | runtest -I
21 |
22 | runtest -N
23 |
--------------------------------------------------------------------------------
/tools/test-roundtrip_anim.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # compare $1 (base name without .png extension, could be multiple frames) one by one to the rest of the arguments
4 | function check {
5 | one=$1*.png
6 | for c in $one
7 | do
8 | if [[ $(compare -metric mepp $c $2 null: 2>&1) == "0 (0, 0)" ]]
9 | then
10 | #echo "OK-compare (identical decoded images)"
11 | shift
12 | continue
13 | else
14 | echo "BUG DETECTED!!!"
15 | echo "PROBLEM IN FILE $1 : $c is not the same image as $2"
16 | exit 1
17 | fi
18 | done
19 | }
20 |
21 |
22 | set -ex
23 |
24 | FLIF=$1
25 | IN=$2
26 | OUTF=$3
27 |
28 | runtest() {
29 | local encArgs=$1
30 | local decArgs=$2
31 |
32 | rm -f ${OUTF} decoded-test-frame*.pam
33 | $FLIF $encArgs test-frame*.png "${OUTF}"
34 | $FLIF -d $decArgs ${OUTF} decoded-test-frame.pam
35 | check test-frame decoded-test-frame*.pam
36 | rm decoded-test-frame*.pam
37 | }
38 |
39 |
40 | convert -coalesce "${IN}" test-frame%04d.png
41 |
42 | # test a few combinations of encode parameters
43 | runtest -I
44 | runtest -NL0
45 | runtest -SP0
46 | runtest -L50
47 |
48 | rm test-frame*.png
49 |
--------------------------------------------------------------------------------
/tools/test-roundtrip_anim_framedir.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # compare $1 (base name without .png extension, could be multiple frames) one by one to the rest of the arguments
4 | function check {
5 | one=$1*.png
6 | for c in $one
7 | do
8 | if [[ $(compare -metric mepp $c $2 null: 2>&1) == "0 (0, 0)" ]]
9 | then
10 | #echo "OK-compare (identical decoded images)"
11 | shift
12 | continue
13 | else
14 | echo "BUG DETECTED!!!"
15 | echo "PROBLEM IN FILE $1 : $c is not the same image as $2"
16 | exit 1
17 | fi
18 | done
19 | }
20 |
21 |
22 | set -ex
23 |
24 | FLIF=$1
25 | IN=$2
26 | OUTF=$3
27 |
28 | runtest() {
29 | local encArgs=$1
30 | local decArgs=$2
31 |
32 | rm -f ${OUTF} decoded-test-frame*.pam
33 | $FLIF -vv $encArgs ${IN}/*.png "${OUTF}"
34 | $FLIF -vv -d $decArgs ${OUTF} decoded-test-frame.pam
35 | check ${IN}/ decoded-test-frame*.pam
36 | rm decoded-test-frame*.pam
37 | }
38 |
39 |
40 |
41 | # test a few combinations of encode parameters
42 | runtest -I
43 | runtest -NL0
44 | runtest -SP0
45 | runtest -L50
46 |
47 |
--------------------------------------------------------------------------------