Initial commit

master 1.0.1
Gillian B. 3 months ago
commit d740a726ee
  1. 24
      Examples.md
  2. 29
      FAQ.md
  3. 238
      INSTALL.md
  4. 22
      LICENSE
  5. 139
      Makefile
  6. 113
      README.md
  7. BIN
      img/gfx1.png
  8. BIN
      img/gfx2.png
  9. BIN
      img/gfx3.png
  10. BIN
      img/logo-128px.png
  11. 40
      img/logo.svg
  12. BIN
      img/opng_header.png
  13. BIN
      img/sleepyhollow.txt.png
  14. 78
      man/octapng.1
  15. 45
      man/octapng.1.ronn
  16. 8
      src/crc.c
  17. 7
      src/crc.h
  18. 224
      src/dec.c
  19. 240
      src/enc.c
  20. 246
      src/ioe.c
  21. 44
      src/ioe.h
  22. 94
      src/octapng.c
  23. 40
      src/opng.h
  24. 25
      src/opngthis.h
  25. 354
      src/parg.c
  26. 192
      src/parg.h
  27. 25
      src/ver.c

@ -0,0 +1,24 @@
# oPNG examples
Below are some examples of files in different formats after being converted to oPNGs.
* [*The Legend of Sleepy Hollow*](https://www.gutenberg.org/ebooks/41) by Washington Irving (.txt) \[89 KiB\]
![](https://inspirats.com/images/2022/05/20/sleepyhollow.txt.png)
* [*Programming from the Ground Up*](https://savannah.nongnu.org/projects/pgubook) by Jonathan Bartlett (.pdf) \[1.3 MiB\]
![](https://inspirats.com/images/2022/05/20/pgubook.pdf.png)
* [*Sylenth Creation*](https://freesound.org/people/Georgke/sounds/237414/) by George Tripels (.ogg) \[1.2 MiB\]
![](https://inspirats.com/images/2022/05/20/sylenth.ogg.png)
* [Excerpt from *Big Buck Bunny* (2008)](https://www.youtube.com/watch?v=aqz-KE-bpKQ) by the Blender Institute (.webm) \[646 KiB\]
![](https://inspirats.com/images/2022/05/20/bigbuckbunny.webm.png)
* [Lite XL v2.0.5](https://github.com/lite-xl/lite-xl) for Windows (.zip) \[1.4 MiB\]
![](https://inspirats.com/images/2022/05/20/lite-xl.zip.png)

@ -0,0 +1,29 @@
# octaPNG FAQ
### What is this?
octaPNG is a tool for encoding any file into a regular PNG image by simply writing the file's binary data as colored pixels, and decoding by reversing this process. I refer to PNG images created by this tool as "oPNGs".
### Why use it?
Images in general are easily transferable across the web, and a growing number of websites allow their users to upload PNG images, so why not explore the possibility of PNGs holding different types of data?
Consider the following scenario: you're on an internet forum and want to quickly share a small ZIP file with other users. Normally you'd have to visit an external file hosting website, log into it, upload your ZIP, wait for the upload process to finish, receive a link, return to the forum you were on, post the link and hope it doesn't get caught by spam filters... That is, if the forum allows posting external links to begin with!
With octaPNG you'd only have to encode your ZIP into a PNG then post it directly on the forum, like you would with any other image. That's it.
### Is it dangerous?
An oPNG in and of itself is not dangerous, after all it's just a colored image like any other, however it can potentially be dangerous if it's holding malicious data. Think of it like an unmarked package you got in the mail; it *may* contain a [letter bomb](https://en.wikipedia.org/wiki/Letter_bomb) but it remains harmless as long as it's not opened... The catch here is that you'll never know what's inside the package *until* you open it.
Unlike other "data vessels" such as ZIP archives and ISO disc images, oPNGs fly under the radar of antivirus software and are not even reported as suspicious. For example the infamous [ZIP bomb](https://en.wikipedia.org/wiki/Zip_bomb) [42.zip](https://www.unforgettable.dk/) is successfully [detected as malicious](https://www.virustotal.com/gui/url/eb5d4b7d331317f453c62557662ffe4549980d7ee1f6eeb7b7598d52a0548d81) by VirusTotal, but after being encoded into an oPNG [it is not](https://www.virustotal.com/gui/url/d9c0a6d6aad1e52fc66bb7c33774bd9410a51005c3be0b678fcb2ee007b279b4).
Know the risks before decoding an oPNG.
### How much data can you fit?
A single oPNG can hold up to about 4 GB of data, naturally the larger your file is the larger the dimensions of the resulting image. Practically though you'll be storing data that's around 50 MB and under.
### Is the data encrypted?
No, oPNGs store data as-is so it can be recovered by anyone with a copy of octaPNG. If you want your data to be encrypted store it in an encrypted archive first then encode that into an oPNG.

@ -0,0 +1,238 @@
# Compiling octaPNG from source
octaPNG is written to be as portable as possible in order to compile on any system with minimal dependencies, using only one Makefile that accepts command line options. Compilation will yield a single statically-linked binary that can be moved and used from anywhere.
## Dependencies
* GCC
* Make
* libpng
* zlib
* pkg-config (optional)
## Compiling under Linux and \*BSD
These steps are for compiling under Linux, \*BSD, or any POSIX-compliant OS using Make.
1. Install `gcc`, `make`, `pkg-config`, and the development libraries for `libpng` and `zlib` from your package manager. For example on Ubuntu you can install them using this command:
```sh
sudo apt install build-essential libpng-dev zlib1g-dev pkg-config
```
1. Open a terminal window in the octaPNG source directory (e.g. `octapng-master` ).
1. Run
```sh
make
```
or if compiling without `pkg-config` run
```sh
make nopc
```
1. To install octaPNG (to default prefix `/usr/local` ) run:
```sh
make install
```
## Compiling under Windows
### Online
These steps are for compiling under a supported version of Windows with internet access using MSYS2 and MinGW-w64.
1. Install [MSYS2](https://www.msys2.org/). You should now have the directory `C:\msys64`
1. Run the MSYS2 shell at `C:\msys64\msys2_shell.bat` and a terminal window will open.
1. Run
```sh
pacman -Syuu
```
to install any available MSYS2 updates. Repeat this step until there are no more updates.
1. Run
```sh
pacman -S \
mingw64/mingw-w64-x86_64-gcc \
mingw64/mingw-w64-x86_64-make \
mingw64/mingw-w64-x86_64-libpng \
mingw64/mingw-w64-x86_64-zlib \
mingw64/mingw-w64-x86_64-pkg-config
```
to install all dependencies.
1. Place the octaPNG source directory into `C:\msys64\home\USERNAME` where `USERNAME` is your Windows user name. You should now have the directory `C:\msys64\home\USERNAME\octapng-master` or similar.
1. Close the MSYS2 shell, run the MinGW shell at `C:\msys64\mingw64.exe` or `C:\msys64\mingw64_shell.bat` and a terminal window will open.
1. Run
```sh
cd octapng-master
mingw32-make
```
If that doesn't work, run
```sh
mingw32-make CCPRFX="x86_64-w64-mingw32-"
```
### Offline
These steps are essentially the same as those for online compilation except they'll work for any Windows version without internet access, by downloading all the necessary files beforehand. If online compilation didn't work try offline compilation.
1. Download the MSYS2 installer \[[32-bit](https://repo.msys2.org/distrib/i686/) / [64-bit](https://repo.msys2.org/distrib/x86_64/)\], the MinGW-w64 archive \[[32-bit](https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/) / [64-bit](https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/)\], the pre-built libpng \[[32-bit](https://repo.msys2.org/mingw/mingw32/mingw-w64-i686-libpng-1.6.37-6-any.pkg.tar.zst) / [64-bit](https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-libpng-1.6.37-6-any.pkg.tar.zst)\] and zlib \[[32-bit](https://repo.msys2.org/mingw/mingw32/mingw-w64-i686-zlib-1.2.12-1-any.pkg.tar.zst) / [64-bit](https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-zlib-1.2.12-1-any.pkg.tar.zst)\] archives, the pkg-config archive \[[32-bit](https://repo.msys2.org/mingw/mingw32/mingw-w64-i686-pkg-config-0.29.2-3-any.pkg.tar.zst) / [64-bit](https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-pkg-config-0.29.2-3-any.pkg.tar.zst)\], and the ZSTD command line tool \[[32-bit](https://git.creepercreep.fr/attachments/4c901eda-7cd3-46d6-8e9e-274e3b14576d) / [64-bit](https://git.creepercreep.fr/attachments/5a767fdd-67a3-478b-9c57-f55bd4a6cd2b)\].
1. Install MSYS2. You should now have the directory `C:\msys64`
1. Extract the MinGW-w64 archive into `C:\msys64` . You should now have the directory `C:\msys64\mingw64`
1. Place the octaPNG source directory, the libpng and zlib archives, the pkg-config archive, and the ZSTD tool renamed as `zstd.exe` into `C:\msys64\home\USERNAME` where `USERNAME` is your Windows user name. You should now have the directory `C:\msys64\home\USERNAME\octapng-master` or similar.
1. Run the MSYS2 shell at `C:\msys64\msys2_shell.bat` and a terminal window will open.
1. Run
```sh
./zstd -d --rm *.zst
for f in *.tar*; do bsdtar -xvf "$f"; done
```
and you'll find the directory `C:\msys64\home\USERNAME\mingw64` is created.
1. Merge this directory with the one inside `C:\msys64`
1. Close the MSYS2 shell, run the MinGW shell at `C:\msys64\mingw64.exe` or `C:\msys64\mingw64_shell.bat` and a terminal window will open.
1. Run
```sh
cd octapng-master
mingw32-make
```
If that doesn't work, run
```sh
mingw32-make CCPRFX="x86_64-w64-mingw32-"
```
### 32-bit Windows
To compile under a 32-bit version of Windows follow the same steps for online or offline compilation, with the following changes:
* The MSYS2 directory will be `C:\msys32`
* The MinGW directory will be `C:\msys32\mingw32`
* The MinGW shell will be named `mingw32.exe` or `mingw32_shell.bat`
* The command to install all dependencies using the MSYS2 shell will be
```sh
pacman -S \
mingw32/mingw-w64-i686-gcc \
mingw32/mingw-w64-i686-make \
mingw32/mingw-w64-i686-libpng \
mingw32/mingw-w64-i686-zlib \
mingw32/mingw-w64-i686-pkg-config
```
* The compilation command will be
```sh
mingw32-make CCPRFX="i686-w64-mingw32-"
```
## Compiling under other systems
Any system containing...
* An ANSI C compiler
* A POSIX-compliant Make tool
* The needed development libraries (preferably with pkg-config)
...should allow compiling the octaPNG source without issue. The Makefile accepts a myriad of command line options that you can use to fine-tune the compilation process, familiarize yourself with them by reading the full option list or the examples below. Avoid editing the Makefile by hand, if your use case isn't covered please [report an issue](https://git.creepercreep.fr/gillian885/octaPNG/issues).
## Makefile options
The available `make` command line options are listed at the top of the Makefile exactly as they are on this page, view them anytime using your favorite text editor or run `make help` from a POSIX shell.
See also the examples below.
```makefile
--- USAGE
make [OPTIONS] [TARGETS]
--- OPTIONS
builddir=BUILDDIR Compiled binary path. (default=.)
exename=EXENAME Compiled binary name. (default=octapng)
exeprfx=EXEPRFX Compiled binary prefix.
exesufx=EXESUFX Compiled binary extension.
objsufx=OBJSUFX Compiled object extension. (default=.o)
prefix=PREFIX Installation path. (default=/usr/local)
bindir=BINDIR Installed binary path. (default=PREFIX/bin)
mandir=MANDIR Installed manuals path. (default=PREFIX/share/man)
man1dir=MAN1DIR Installed man1 path. (default=MANDIR/man1)
warnings=... Additional warning flags.
cflags=... Additional general compiler flags.
ldflags=... Additional general linker flags.
cflibs=... Additional library compiler flags.
ldlibs=... Additional library linker flags.
--- ADVANCED OPTIONS
CC=... Compiler command. (default=gcc)
CCPRFX=... Compiler command prefix.
WARNINGS=... Overwrite warning flags.
CFLAGS=... Overwrite general compiler flags.
LDFLAGS=... Overwrite general linker flags.
CFLIBS=... Overwrite library compiler flags.
LDLIBS=... Overwrite library linker flags.
CFLIBS_NOPC=... Overwrite library compiler flags for
targets `nopc` and `nopc_basic`.
LDLIBS_NOPC=... Overwrite library linker flags for
targets `nopc` and `nopc_basic`.
--- TARGETS
all Compile program. (default)
nopc Compile program without `pkg-config`.
nopc_basic Compile program without `pkg-config` in
non-POSIX environments. (ignores BUILDDIR)
clean Delete compiled program.
install Install compiled program into PREFIX.
uninstall Delete installed program from PREFIX.
```
### Examples
```sh
# compile program into a `build` directory, then install into prefix `/usr`
make builddir=build
make builddir=build install prefix=/usr
# uninstall program from prefix `/usr`
make uninstall prefix=/usr
# compile on 64-bit Windows using the full MinGW-w64 command prefix, and use
# `.exe` as the binary extension
mingw32-make CCPFX="x86_64-w64-mingw32-" exesufx=".exe"
# compile a dynamically-linked binary with debug symbols and no optimization
make LDFLAGS="" cflags="-g -O0"
# compile without `pkg-config` and specify additional search paths
make nopc cflibs="-I/opt/include -L/opt/lib"
# compile without `pkg-config` or any POSIX tools, manually overwrite search
# paths and library link flags
nmake nopc_basic CFLIBS_NOPC="-Iinclude" LDLIBS_NOPC="libpng16.a zlib.a"
# compile a binary named `foo-octapng-bar` and store name inside binary
make exename="foo-octapng-bar"
# compile a binary named `foo-octapng-bar` but don't store name inside binary
make exeprfx="foo-" exesufx="-bar"
```

@ -0,0 +1,22 @@
zlib License
Copyright (C) 2022 Gillian Bates
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

@ -0,0 +1,139 @@
### OCTAPNG MAKEFILE ###
.POSIX:
#.
#. --- USAGE
#.
#. make [OPTIONS] [TARGETS]
#.
#. --- OPTIONS
#.
#. builddir=BUILDDIR Compiled binary path. (default=.)
#. exename=EXENAME Compiled binary name. (default=octapng)
#. exeprfx=EXEPRFX Compiled binary prefix.
#. exesufx=EXESUFX Compiled binary extension.
#. objsufx=OBJSUFX Compiled object extension. (default=.o)
#.
#. prefix=PREFIX Installation path. (default=/usr/local)
#. bindir=BINDIR Installed binary path. (default=PREFIX/bin)
#. mandir=MANDIR Installed manuals path. (default=PREFIX/share/man)
#. man1dir=MAN1DIR Installed man1 path. (default=MANDIR/man1)
#.
#. warnings=... Additional warning flags.
#. cflags=... Additional general compiler flags.
#. ldflags=... Additional general linker flags.
#. cflibs=... Additional library compiler flags.
#. ldlibs=... Additional library linker flags.
#.
#. --- ADVANCED OPTIONS
#.
#. CC=... Compiler command. (default=gcc)
#. CCPRFX=... Compiler command prefix.
#.
#. WARNINGS=... Overwrite warning flags.
#. CFLAGS=... Overwrite general compiler flags.
#. LDFLAGS=... Overwrite general linker flags.
#. CFLIBS=... Overwrite library compiler flags.
#. LDLIBS=... Overwrite library linker flags.
#.
#. CFLIBS_NOPC=... Overwrite library compiler flags for
#. targets `nopc` and `nopc_basic`.
#. LDLIBS_NOPC=... Overwrite library linker flags for
#. targets `nopc` and `nopc_basic`.
#.
#. --- TARGETS
#.
#. all Compile program. (default)
#. nopc Compile program without `pkg-config`.
#. nopc_basic Compile program without `pkg-config` in
#. non-POSIX environments. (ignores BUILDDIR)
#.
#. clean Delete compiled program.
#. install Install compiled program into PREFIX.
#. uninstall Delete installed program from PREFIX.
#.
### OPTIONS ###
# build files & dirs
builddir=.
exename=octapng
exeprfx=
exesufx=
objsufx=.o
# install dirs
prefix=/usr/local
bindir=$(prefix)/bin
mandir=$(prefix)/share/man
man1dir=$(mandir)/man1
# compiler
CC=gcc
CCPRFX=
# compilation flags
WARNINGS=-W -Wall -Wconversion -Wshadow -Wcast-qual -Wwrite-strings $(warnings)
CFLAGS=-ansi -pedantic -O1 $(cflags)
LDFLAGS=-static $(ldflags)
# library flags
CFLIBS=`pkg-config --cflags libpng zlib` $(cflibs)
LDLIBS=`pkg-config --libs libpng zlib` -lm $(ldlibs)
CFLIBS_NOPC=-Iinclude -Llib $(cflibs)
LDLIBS_NOPC=-lpng -lz -lm $(ldlibs)
### INTERNAL VARS ###
# source
srcdir=src
CFILES=$(srcdir)/octapng.c $(srcdir)/parg.c \
$(srcdir)/enc.c $(srcdir)/dec.c $(srcdir)/ioe.c \
$(srcdir)/crc.c $(srcdir)/ver.c
HFILES=$(srcdir)/opng.h $(srcdir)/opngthis.h \
$(srcdir)/ioe.h $(srcdir)/crc.h $(srcdir)/parg.h
# misc
EXENAME=$(exeprfx)$(exename)$(exesufx)
EXE=$(builddir)/$(EXENAME)
COMMONFLAGS=$(WARNINGS) $(CFLAGS) $(LDFLAGS)
MAN1NAME=octapng.1
MAN1=man/$(MAN1NAME)
### TARGETS ###
all: $(EXE)
$(EXE): $(CFILES)
@mkdir -p $(builddir)
$(CCPRFX)$(CC) $(COMMONFLAGS) $(CFLIBS) \
-o $@ -DEXENAME=\"$(exename)\" $(CFILES) $(LDLIBS)
nopc: $(CFILES)
@mkdir -p $(builddir)
$(CCPRFX)$(CC) $(COMMONFLAGS) $(CFLIBS_NOPC) \
-o $(EXE) -DEXENAME=\"$(exename)\" $(CFILES) $(LDLIBS_NOPC)
nopc_basic: $(CFILES)
$(CCPRFX)$(CC) $(COMMONFLAGS) $(CFLIBS_NOPC) \
-o $(EXENAME) -DEXENAME=\"$(exename)\" $(CFILES) $(LDLIBS_NOPC)
clean:
rm -f $(EXE)
install: all
@mkdir -p "$(bindir)"
@mkdir -p "$(man1dir)"
cp -t "$(bindir)" $(EXE)
cp -t "$(man1dir)" $(MAN1)
uninstall:
rm -f "$(bindir)/$(EXENAME)"
rm -f "$(man1dir)/$(MAN1NAME)"
help:
@cat Makefile | grep "#\."

@ -0,0 +1,113 @@
![](img/logo-128px.png)
# octaPNG
![](https://img.shields.io/badge/made_with-C-lightgray?style=flat-square) ![](https://img.shields.io/badge/license-zlib-blue?style=flat-square) [![](https://img.shields.io/badge/%BB-download-brightgreen?style=flat-square&logo=windowsxp&logoColor=white)](https://psychicdebugging.com/gillian885/octaPNG/releases) [![](https://img.shields.io/badge/%BB-download-brightgreen?style=flat-square&logo=debian&logoColor=white)](https://git.creepercreep.fr/gillian885/octaPNG/releases)
#### *Convert any file into a PNG and back!*
## Description
**octaPNG** is a tool for encoding any file into a regular PNG image by simply writing the file's binary data as colored pixels, and decoding by reversing this process. I refer to PNG images created by this tool as "**oPNGs**".
The codebase is written in portable ANSI C (C89) and depends on the libraries [`libpng`](http://www.libpng.org/pub/png/libpng.html) and [`zlib`](https://zlib.net/). Currently there's only a command line version of octaPNG, however a graphical (GUI) version is planned.
Read the [FAQ](FAQ.md).
### Example
Here's [*The Legend of Sleepy Hollow*](https://www.gutenberg.org/files/41/41-0.txt) by Washington Irving encoded into an oPNG:
![](img/sleepyhollow.txt.png "sleepyhollow.txt.png [174x175]")
See more examples on [this page](Examples.md).
## How It Works
octaPNG operates in two modes; encoding and decoding. Encoding involves writing an input file into an oPNG, and decoding involves reading the oPNG to recreate the original input file. The whole process is lossless, an oPNG always stores a byte-for-byte identical copy of whatever data you encode into it.
During the encoding process, octaPNG creates a blank PNG image and writes into it a few pixels that constitute the oPNG "header", these "header pixels" contain information about the input file so it may be decoded correctly later. The pixels are divided as follows:
```
_______________________________________
| Pixel | Byte* | Description |
|¯¯¯¯¯¯¯|¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| 0 | 0 | oPNG version. |
| |_______|______________________|
| | 1 | |
|_______| 2 | Binary data size in |
| | 3 | bytes, big endian |
| 1 | 4 | order. |
| |_______|______________________|
|_______| 5 | |
| | 6 | CRC32 sum of the |
| 2 | 7 | binary data, big |
| | 8 | endian order. |
________|_______|______________________|
```
\* *Assuming 1 byte = 8 bits (1 octet)*
After the "header pixels" are written, octaPNG writes the input file itself. The file is read as a stream of bytes where every 3 bytes of data are treated as an RGB color triplet and written to the image as a pixel, until the entire file is written. If there are still "empty" pixels remaining in the image they get filled with dummy data as padding.
![](img/opng_header.png)
Decoding is the reverse of the encoding process; the oPNG "header pixels" are read first, then the data pixels are read as bytes and written into a new file, while padding pixels are skipped... To ensure the original input file has been recreated correctly, a [CRC32](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) checksum is calculated for the newly-decoded file and compared against the checksum stored in the oPNG "header". If both checksums match then the decoded file is indeed identical to the original input file, if not then the file may have been corrupted.
Both encode and decode operations are zero-copy, meaning data is progressively read from / written to disk and *not* kept in memory. Only a PNG row buffer is kept.
## Getting Started
Pre-built binaries for Windows and Linux are available on the [releases page](https://git.creepercreep.fr/gillian885/octaPNG/releases) for users to download. The binaries are self-contained and require no installation, simply download and run.
To compile from source see the [INSTALL.md](INSTALL.md) file.
### Usage
To encode a file, open a command prompt or terminal window and run:
```
octapng -e file.zip
```
To decode an oPNG run:
```
octapng -d file.zip.png
```
### Guidelines
To prevent oPNG corruption please take note of the following guidelines.
#### *You should not...*
* Distort (e.g. crop, stretch, scale) an oPNG
* Add your own graphics on, above, or to the left/right of an oPNG
* Convert an oPNG from the PNG format to a lossy image format such as JPEG or GIF
* Change the bit depth of an oPNG
* Add transparency to an oPNG
* Make an oPNG interlaced
#### *You may...*
* Extend the canvas size of an oPNG from the bottom to add your own graphics (e.g. icons or logos) if you like, provided you do **not** overlap the oPNG's original pixels.
Some examples of acceptable graphics placement:
|![](img/gfx1.png)|![](img/gfx2.png)|![](img/gfx3.png)|
|:--:|:--:|:--:|
## Roadmap
`[*]` Encoding binary data into a PNG image
`[*]` Decoding binary data from a PNG image
`[*]` Verifying binary data integrity using CRC32
`[ ]` Creating GUI version
`[ ]` Supporting interlaced PNG images
## License
octaPNG is licensed under the [zlib License](LICENSE).
Licenses for the used libraries: [libpng](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt), [zlib](https://zlib.net/zlib_license.html), [parg](https://github.com/jibsen/parg/blob/master/COPYING)

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,40 @@
<svg
width="500"
height="500"
viewBox="0 0 132.29166 132.29167"
version="1.1"
id="svg75161"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs75158">
<rect
x="97.722538"
y="110.79102"
width="654.24472"
height="454.09441"
id="rect82594" />
<rect
x="97.722538"
y="110.79102"
width="654.24472"
height="454.09441"
id="rect6944" />
</defs>
<g
id="layer1">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.612994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill"
id="rect1239"
width="173.80211"
height="304.18555"
x="631.44995"
y="-133.0392"
transform="matrix(0.76116257,0,0,0.4349045,-480.63606,57.859348)" />
<path
id="path6946-3"
style="font-weight:bold;font-size:100px;line-height:1.25;font-family:'Libre Barcode 39';-inkscape-font-specification:'Libre Barcode 39 Bold';white-space:pre;shape-inside:url(#rect6944);display:inline;fill:#000000;stroke-width:1"
d="M 59.322266,0 V 500 H 84.746094 V 0 Z m 50.847654,0 v 217.69531 a 49.999999,49.999999 0 0 1 25.42383,-15.85547 V 0 Z m 50.84766,0 v 201.66016 a 49.999999,49.999999 0 0 1 25.42383,16.03515 V 0 Z M 262.71094,0 V 301.10938 A 74.999998,74.999998 0 0 0 250,300 74.999998,74.999998 0 0 0 186.44141,335.30273 v -52.99804 a 49.999999,49.999999 0 0 1 -25.42383,15.85547 V 500 h 25.42383 V 414.69727 A 74.999998,74.999998 0 0 0 250,450 74.999998,74.999998 0 0 0 262.71094,448.79297 V 500 h 76.27148 V 298.16016 A 49.999999,49.999999 0 0 1 301.69531,250 49.999999,49.999999 0 0 1 338.98242,201.83984 V 0 Z M 364.40625,0 V 201.66016 A 49.999999,49.999999 0 0 1 401.69336,250 49.999999,49.999999 0 0 1 364.40625,298.16016 V 500 h 76.27148 V 0 Z M 148.30664,225 a 24.999999,24.999999 0 0 0 -25,25 24.999999,24.999999 0 0 0 25,25 24.999999,24.999999 0 0 0 25,-25 24.999999,24.999999 0 0 0 -25,-25 z m 203.38672,0 a 24.999999,24.999999 0 0 0 -25,25 24.999999,24.999999 0 0 0 25,25 24.999999,24.999999 0 0 0 25,-25 24.999999,24.999999 0 0 0 -25,-25 z M 110.16992,282.30469 V 500 h 25.42383 V 298.16016 A 49.999999,49.999999 0 0 1 110.16992,282.30469 Z M 250,337.5 A 37.499999,37.499999 0 0 1 287.5,375 37.499999,37.499999 0 0 1 250,412.5 37.499999,37.499999 0 0 1 212.5,375 37.499999,37.499999 0 0 1 250,337.5 Z"
transform="scale(0.26458333)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@ -0,0 +1,78 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "OCTAPNG" "1" "May 2022" "Gillian B." "octaPNG Manual"
.
.SH "NAME"
\fBoctapng\fR \- convert any file into a PNG and back
.
.SH "SYNOPSIS"
\fBoctapng\fR [\fB\-y\fR|\fBn\fR] \fB\-e\fR \fIFILE\fR [\fIFILE\fR\.\.\.]
.
.br
\fBoctapng\fR [\fB\-y\fR|\fBn\fR] \fB\-d\fR \fIFILE\.PNG\fR [\fIFILE\.PNG\fR\.\.\.]
.
.br
.
.SH "DESCRIPTION"
\fBoctaPNG\fR is a tool for encoding any file into a regular PNG image
.
.br
by simply writing the file\'s binary data as colored pixels, and
.
.br
decoding by reversing this process\. I refer to PNG images created
.
.br
by this tool as "\fBoPNGs\fR"\.
.
.SH "MODES"
.
.TP
\fB\-e\fR \fIFILE\fR [\fIFILE\fR\.\.\.]
\fBE\fRncode one or more files each into an oPNG\.
.
.br
Output images retain the input file names with an added
.
.br
\fI\.png\fR suffix\.
.
.TP
\fB\-d\fR \fIFILE\.PNG\.\.\.\fR [\fIFILE\.PNG\fR\.\.\.]
\fBD\fRecode one or more oPNGs into their original files\.
.
.br
Output files retain the input file names but the \fI\.png\fR
.
.br
suffix is removed\. If no \fI\.png\fR suffix is present an
.
.br
underscore (\fI_\fR) is appended instead\.
.
.SH "OPTIONS"
.
.TP
\fB\-n\fR
Skip existing output files, don\'t overwrite\. \fB(default)\fR
.
.br
Must be placed before the \fBMODE\fR flag\.
.
.TP
\fB\-y\fR
Overwrite existing output files\.
.
.br
Must be placed before the \fBMODE\fR flag\.
.
.TP
\fB\-h\fR
Display help screen and exit\.
.
.SH "COPYRIGHT"
Copyright (C) 2022 Gillian Bates
.
.br
octaPNG is licensed under the \fIzlib License\fR

@ -0,0 +1,45 @@
octapng(1) -- convert any file into a PNG and back
==================================================
## SYNOPSIS
`octapng` [`-y`|`n`] `-e` *FILE* [*FILE*...]<br>
`octapng` [`-y`|`n`] `-d` *FILE.PNG* [*FILE.PNG*...]<br>
## DESCRIPTION
**octaPNG** is a tool for encoding any file into a regular PNG image
by simply writing the file's binary data as colored pixels, and
decoding by reversing this process. I refer to PNG images created
by this tool as "**oPNGs**".
## MODES
* `-e` *FILE* [*FILE*...]:
**E**ncode one or more files each into an oPNG.
Output images retain the input file names with an added
*.png* suffix.
* `-d` *FILE.PNG...* [*FILE.PNG*...]:
**D**ecode one or more oPNGs into their original files.
Output files retain the input file names but the *.png*
suffix is removed. If no *.png* suffix is present an
underscore (*_*) is appended instead.
## OPTIONS
* `-n`:
Skip existing output files, don't overwrite. **(default)**
Must be placed before the **MODE** flag.
* `-y`:
Overwrite existing output files.
Must be placed before the **MODE** flag.
* `-h`:
Display help screen and exit.
## COPYRIGHT
Copyright (C) 2022 Gillian Bates
octaPNG is licensed under the *zlib License*

@ -0,0 +1,8 @@
#include <zlib.h>
#include "crc.h"
unsigned long
crc_byte(unsigned long crc, unsigned char *c)
{
return crc32(crc, c, 1);
}

@ -0,0 +1,7 @@
/*** exposing only the crc32 function from zlib ***/
#ifndef OPNG_CRC_H
#define OPNG_CRC_H
unsigned long crc_byte(unsigned long, unsigned char*);
#endif

@ -0,0 +1,224 @@
#include <stdio.h> /* printf, fprintf */
#include <string.h> /* strlen, strcat, strcpy */
#include "opng.h"
#include "opngthis.h"
#include "ioe.h"
#include "crc.h"
static int r_opng(opng*);
static int invalid_in(opng*);
static int invalid_out(opng*);
static int r_png_hdr(opng*);
static int r_opng_hdr(opng*);
/* read a single byte from a PNG */
#define R_PNG_BYTE(UCHAR,OPNG) R_PNG_BYTE_((UCHAR),(OPNG))
#define R_PNG_BYTE_(C,O) { \
if (O.ib%(O.width*3) == 0) \
png_read_row(O.png_ptr, O.row, NULL); \
C = O.row[O.ib++%(O.width*3)]; \
}
/* decode a file from a PNG image */
int
opng_dec(const char *fin_s, int overwri)
{
opng this = {
NULL, NULL,
"", "",
0UL, 0UL,
0UL, 0UL,
0UL, 0UL, 0UL,
0UL, 0UL,
NULL, NULL,
{0},
0
};
this.fin_s = fin_s;
this.overwri = overwri;
return r_opng(&this);
}
/* read an oPNG */
static int
r_opng(opng *this)
{
int err = 0;
unsigned char c;
if (OVERWRI)
echo_opng_err(OPNG_ERR_I_OVERWRION, this);
/* check I/O validity */
if ((err = invalid_in(this))) return err;
if ((err = invalid_out(this))) return err;
/* verify PNG header, verify oPNG "header"
open files */
FIN = fopen(FIN_S, "rb");
if ((err = r_png_hdr(this)) ||
(err = r_opng_hdr(this)) )
{
fclose(FIN);
return err;
}
FOUT = fopen(FOUT_S, "wb");
/* start r/w */
while (IB<FOUT_B) {
R_PNG_BYTE(c, *this);
putc(c, FOUT);
FOUT_CRC = crc_byte(FOUT_CRC, &c);
}
/* close files */
fclose(FIN);
fclose(FOUT);
/* verify checksum */
echo_info("Successfully decoded: \"%s\"\n", FOUT_S);
if (FIN_CRC == FOUT_CRC)
echo_info("CRC32 is %lx\n", FOUT_CRC);
else
echo_opng_err(OPNG_ERR_O_BADCRC, this);
return err;
}
/* check if input is valid */
static int
invalid_in(opng *this)
{
int err = 0;
unsigned long png_b = 0;
if (strlen(FIN_S)+1 > OPNG_MAX_FNAME) /* account for `_` */
return err = echo_opng_err(OPNG_ERR_I_LONGPATH, this);
FIN = fopen(FIN_S, "rb");
if (!FIN)
return err = echo_opng_err(OPNG_ERR_I_NOINPUT, this);
fseek(FIN, 0L, SEEK_END);
png_b = (unsigned long) ftell(FIN);
fclose(FIN);
if (!png_b)
err = echo_opng_err(OPNG_ERR_I_ZEROINPUT, this);
else if (png_b>OPNG_MAX_FSIZE)
err = echo_opng_err(OPNG_ERR_I_HUGEINPUT, this);
return err;
}
/* check if output is valid TODO use strlcpy
S/E: output filename */
static int
invalid_out(opng *this)
{
int err = 0;
size_t len;
strcpy(FOUT_S, FIN_S);
len = strlen(FOUT_S);
/* a.png, foobar --> a, foobar_ */
if (len>4) {
if (streq(FOUT_S+len-4, ".png"))
FOUT_S[len-4] = '\0';
else strcat(FOUT_S,"_");
}
/* .png, file --> .png_, file_ */
else strcat(FOUT_S,"_");
/* con, com1 --> con_, com1_ */
if (invalid_ntfs_name(FOUT_S))
strcat(FOUT_S,"_");
FOUT = fopen(FOUT_S, "rb");
if (!FOUT) goto writable;
fseek(FOUT, 0L, SEEK_END);
len = (size_t) ftell(FOUT);
fclose(FOUT);
if (!len) goto writable;
else err = echo_opng_err(OPNG_ERR_I_OUTEXISTS, this);
if (!OVERWRI) goto end;
writable:
FOUT = fopen(FOUT_S, "wb");
if (!FOUT)
return err = echo_opng_err(OPNG_ERR_I_OUTNONWRI, this);
fclose(FOUT);
end:
return err;
}
/* read PNG header
S/E: PNG pointers, width & height */
static int
r_png_hdr(opng *this)
{
int err = 0;
unsigned char header[8];
fread(header, 1, 8, FIN);
if (png_sig_cmp(header, 0, 8))
return err = echo_opng_err(OPNG_ERR_P_NOHDR, this);
PNG_PTR = png_create_read_struct(
PNG_LIBPNG_VER_STRING, NULL, NULL, NULL
);
if (!PNG_PTR)
return err = echo_opng_err(OPNG_ERR_I_WPNGFAIL, this);
INF_PTR = png_create_info_struct(PNG_PTR);
if (!INF_PTR)
return err = echo_opng_err(OPNG_ERR_I_WPNGFAIL, this);
if (setjmp(png_jmpbuf(PNG_PTR)))
return err = echo_opng_err(OPNG_ERR_I_WPNGFAIL, this);
png_init_io(PNG_PTR, FIN);
png_set_sig_bytes(PNG_PTR, 8);
png_read_info(PNG_PTR, INF_PTR);
if (png_get_color_type(PNG_PTR, INF_PTR) != PNG_COLOR_TYPE_RGB)
return err = echo_opng_err(OPNG_ERR_P_NOTRGB, this);
if (png_get_bit_depth(PNG_PTR, INF_PTR) != 8)
return err = echo_opng_err(OPNG_ERR_P_NOT8BIT, this);
if (png_get_interlace_type(PNG_PTR, INF_PTR) != PNG_INTERLACE_NONE)
return err = echo_opng_err(OPNG_ERR_P_INTERLACE, this);
WIDTH = (unsigned long) png_get_image_width(PNG_PTR, INF_PTR);
HEIGHT = (unsigned long) png_get_image_height(PNG_PTR, INF_PTR);
if (WIDTH*HEIGHT <= 9)
return err = echo_opng_err(OPNG_ERR_P_TINYAREA, this);
return err;
}
/* read opng "header pixels"
S/E: input & output filesizes, input CRC */
static int
r_opng_hdr(opng *this)
{
int i, err = 0;
unsigned char c;
R_PNG_BYTE(c, *this);
if (c>OPNG_VERSION)
return err = echo_opng_err(OPNG_ERR_O_BADVER, this);
for (i=0; i<4; ++i) {
R_PNG_BYTE(c, *this);
FIN_B = (FIN_B<<8) | c;
}
FOUT_B = FIN_B+OPNG_HDR_B;
if (FOUT_B>WIDTH*HEIGHT*3)
return err = echo_opng_err(OPNG_ERR_O_BADFSIZE, this);
for (i=0; i<4; ++i) {
R_PNG_BYTE(c, *this);
FIN_CRC = (FIN_CRC<<8) | c;
}
return err;
}

@ -0,0 +1,240 @@
#include <stdio.h> /* printf, fprintf */
#include <string.h> /* strlen, strcat, strcpy */
#include "opng.h"
#include "opngthis.h"
#include "ioe.h"
#include "crc.h"
static int w_opng(opng*);
static int invalid_in(opng*);
static int invalid_out(opng*);
static void calc_crc(opng*);
static void calc_wxh(opng*);
static int w_png_hdr(opng*);
static void w_opng_hdr(opng*);
/* accumulate bytes in row buffer, then if it's full flush it */
#define W_PNG_BYTE(UCHAR,OPNG) W_PNG_BYTE_((UCHAR),(OPNG))
#define W_PNG_BYTE_(C,O) { \
O.row[O.ib%(O.width*3)] = (png_byte) C; \
if (++O.ib%(O.width*3) == 0) \
png_write_row(O.png_ptr, O.row); \
}
/* encode a file as a PNG image */
int
opng_enc(const char *fin_s, int overwri)
{
opng this = {
NULL, NULL,
"", "",
0UL, 0UL,
0UL, 0UL,
0UL, 0UL, 0UL,
0UL, 0UL,
NULL, NULL,
{0},
0
};
this.fin_s = fin_s;
this.overwri = overwri;
return w_opng(&this);
}
/* write an oPNG */
static int
w_opng(opng *this)
{
int c, err = 0;
/* check input validity, generate I/O params */
if ((err = invalid_in(this))) return err;
if ((err = invalid_out(this))) return err;
calc_crc(this);
calc_wxh(this);
/* open files for I/O, write PNG header,
write oPNG "header pixels" */
FOUT = fopen(FOUT_S, "wb");
if ((err = w_png_hdr(this))) {
fclose(FOUT);
return err;
}
w_opng_hdr(this);
FIN = fopen(FIN_S, "rb");
/* write binary data as pixels */
while ((c=getc(FIN)) != EOF)
W_PNG_BYTE((unsigned char) c, *this);
/* flush remaining half-full row if any,
then terminate PNG */
if (IB < WIDTH*HEIGHT*3-1)
png_write_row(PNG_PTR, ROW);
png_write_end(PNG_PTR, INF_PTR);
/* close files */
fclose(FIN);
fclose(FOUT);
/* print stats */
echo_info(
"Successfully encoded: \"%s\"\n", FIN_S
);
echo_info(
"%ld + %d = %ld B (%ldpx) in %ldx%ld = %ldpx\n",
FIN_B, OPNG_HDR_B, FOUT_B, FOUT_P,
WIDTH, HEIGHT, WIDTH*HEIGHT
);
echo_info("CRC32 is %lx\n", FIN_CRC);
return err;
}
/* check if input is valid
S/E: input & output filesizes */
static int
invalid_in(opng *this)
{
int err = 0;
if (strlen(FIN_S)+4 > OPNG_MAX_FNAME) /* account for `.png` */
return err = echo_opng_err(OPNG_ERR_I_LONGPATH, this);
FIN = fopen(FIN_S, "rb");
if (!FIN)
return err = echo_opng_err(OPNG_ERR_I_NOINPUT, this);
fseek(FIN, 0L, SEEK_END);
FIN_B = (unsigned long) ftell(FIN);
FOUT_B = FIN_B+OPNG_HDR_B;
fclose(FIN);
if (!FIN_B)
err = echo_opng_err(OPNG_ERR_I_ZEROINPUT, this);
else if (FIN_B>OPNG_MAX_FSIZE)
err = echo_opng_err(OPNG_ERR_I_HUGEINPUT, this);
return err;
}
/* check if output is valid TODO use strlcpy
S/E: output filename */
static int
invalid_out(opng *this)
{
int err = 0;
size_t len;
strcpy(FOUT_S, FIN_S);
strcat(FOUT_S, ".png");
FOUT = fopen(FOUT_S, "rb");
if (!FOUT) goto writable;
fseek(FOUT, 0L, SEEK_END);
len = (size_t) ftell(FOUT);
fclose(FOUT);
if (!len) goto writable;
else err = echo_opng_err(OPNG_ERR_I_OUTEXISTS, this);
if (!OVERWRI) goto end;
writable:
FOUT = fopen(FOUT_S, "wb");
if (!FOUT)
return err = echo_opng_err(OPNG_ERR_I_OUTNONWRI, this);
fclose(FOUT);
end:
return err;
}
/* calculate CRC32 for input file
S/E: input CRC */
static void
calc_crc(opng *this)
{
int c;
FIN = fopen(FIN_S, "rb");
while ((c=getc(FIN)) != EOF)
FIN_CRC = crc_byte(FIN_CRC, (unsigned char *)&c);
fclose(FIN);
if (!FIN_CRC) {
echo_opng_err(OPNG_ERR_I_CRCFAIL, this);
FIN_CRC = 0xFFFFFFFF;
}
}
/* calculate output PNG dimensions
S/E: input & output pixelsize, width & height */
static void
calc_wxh(opng *this)
{
int i;
float fin_pf, fout_pf, r; /* sqrt guess */
/* calculate total data pixels (rounded up)
(1 colored pixel = 3 bytes) */
fin_pf = (float) FIN_B / 3;
FIN_P = (unsigned long) (fin_pf+0.9F);
fout_pf = (float) FOUT_B / 3;
FOUT_P = (unsigned long) (fout_pf+0.9F);
/* find the width for a roughly square image
using a hacky (inaccurate!) square root function
then calculate height rounded up */
r = fout_pf/64;
for (i=0; i<8; ++i)
r = (r+fout_pf/r)/2;
WIDTH = (r<OPNG_MINWIDTH) ? OPNG_MINWIDTH : (unsigned long) (r+0.5F);
HEIGHT = (FOUT_P + WIDTH-1) / WIDTH;
}
/* write PNG header
S/E: PNG pointers */
static int
w_png_hdr(opng *this)
{
PNG_PTR = png_create_write_struct(
PNG_LIBPNG_VER_STRING, NULL, NULL, NULL
);
if (!PNG_PTR)
return echo_opng_err(OPNG_ERR_I_WPNGFAIL, this);
INF_PTR = png_create_info_struct(PNG_PTR);
if (!INF_PTR)
return echo_opng_err(OPNG_ERR_I_WPNGFAIL, this);
if (setjmp(png_jmpbuf(PNG_PTR)))
return echo_opng_err(OPNG_ERR_I_WPNGFAIL, this);
png_init_io(PNG_PTR, FOUT);
png_set_IHDR(
PNG_PTR, INF_PTR,
(png_uint_32)WIDTH, (png_uint_32)HEIGHT, 8,
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
);
png_set_filter(PNG_PTR, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
png_write_info(PNG_PTR, INF_PTR);
return 0;
}
/* write oPNG "header pixels" */
static void
w_opng_hdr(opng *this)
{
W_PNG_BYTE((unsigned char) OPNG_VERSION, *this);
W_PNG_BYTE((unsigned char) (FIN_B>>24 & 0xFF), *this);
W_PNG_BYTE((unsigned char) (FIN_B>>16 & 0xFF), *this);
W_PNG_BYTE((unsigned char) (FIN_B>> 8 & 0xFF), *this);
W_PNG_BYTE((unsigned char) (FIN_B>> 0 & 0xFF), *this);
W_PNG_BYTE((unsigned char) (FIN_CRC>>24 & 0xFF), *this);
W_PNG_BYTE((unsigned char) (FIN_CRC>>16 & 0xFF), *this);
W_PNG_BYTE((unsigned char) (FIN_CRC>> 8 & 0xFF), *this);
W_PNG_BYTE((unsigned char) (FIN_CRC>> 0 & 0xFF), *this);
}

@ -0,0 +1,246 @@
#include <stdio.h> /* printf, fprintf, vfprintf */
#include <string.h> /* strlen, strcat, strcpy */
#include <ctype.h> /* tolower */
#include <stdarg.h> /* va_list */
#include "opng.h"
#include "opngthis.h"
#include "ioe.h"
static const char *reserved[22] = {
"CON", "PRN" , "AUX" , "NUL" , "COM1", "COM2",
"COM3", "COM4", "COM5", "COM6", "COM7", "COM8",
"COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5",
"LPT6", "LPT7", "LPT8", "LPT9"
};
/* case-insensitive string comparison
returns 1 if equal, 0 otherwise */
int
streq(const char *a, const char *b)
{
if (!a || !b) /* NULL strings */
return 0;
/* segfault on non-null-terminated strings! */
for (;; a++, b++) {
if (tolower((unsigned char)*a) != tolower((unsigned char)*b))
return 0;
else if (*a=='\0' && *a==*b)
return 1;
}
return 0;
}
/* invalid NTFS filename checker */
int
invalid_ntfs_name(const char *s)
{
int i;
size_t len = strlen(s);
if (s[len-1] == '.' || s[len-1] == ' ')
return 1;
/* unneeded, untested */
/*for (i=0; i<len; i++) {
switch(s[i]) {
case '<':
case '>':
case ':':
case '"':
case '/':
case '\':
case '|':
case '?':
case '*':
return 1;
default:
continue;
}
}*/
if (len != 3 && len != 4)
return 0;
for (i=0; i<22; i++) {
if (streq(s,reserved[i]))
return 1;
}
return 0;
}
#define ECHO(S,A) { \
vfprintf(stderr,S,A); \
}
#define ECHO_(S) { \
fprintf(stderr,S); \
}
void
echo_info(const char *s, ...)
{
va_list argp;
va_start(argp, s);
ECHO_("[INFO] ");
ECHO(s,argp);
va_end(argp);
}
void
echo_warn(const char *s, ...)
{
va_list argp;
va_start(argp, s);
ECHO_("[WARNING] ");
ECHO(s,argp);
va_end(argp);
}
void
echo_erro(const char *s, ...)
{
va_list argp;
va_start(argp, s);
ECHO_("[ERROR] ");
ECHO(s,argp);
va_end(argp);
}
int
echo_opng_err(int e, opng* this)
{
switch(e) {
/*** I/O ***/
case OPNG_ERR_SUCCESS:
break;
case OPNG_ERR_I_OVERWRION:
echo_warn(
"Overwrite mode is ON\n"
);
break;
case OPNG_ERR_I_LONGPATH:
echo_erro(
"Filename too long: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_I_NOINPUT:
echo_erro(
"File doesn't exist or is inaccessible: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_I_HUGEINPUT:
echo_erro(
"Filesize too large (%.2f GB): \"%s\"\n",
(double)FIN_B/1e9F, FIN_S
);
echo_info(
"Maximum filesize is %.2f GB\n",
OPNG_MAX_FSIZE
);
break;
case OPNG_ERR_I_ZEROINPUT:
echo_erro(
"File is empty: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_I_CRCFAIL:
echo_warn(
"Couldn't calculate CRC32 sum for: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_I_OUTEXISTS:
if (OVERWRI) {
echo_warn(
"File already exists, overwriting: \"%s\"\n",
FIN_S
);
e = 0; /* no error if we're overwriting */
}
else {
echo_warn(
"File already exists, skipping: \"%s\"\n",
FIN_S
);
echo_info(
"To enable overwrite mode add `-y` before `-e` or `-d`\n"
);
}
break;
case OPNG_ERR_I_OUTNONWRI:
echo_erro(
"File is non-writable: \"%s\"\n",
FOUT_S
);
break;
case OPNG_ERR_I_WPNGFAIL:
echo_erro(
"Couldn't open PNG for writing: \"%s\"\n",
FOUT_S
);
break;
/*** PNG header ***/
case OPNG_ERR_P_NOHDR:
echo_erro(
"Invalid PNG file header: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_P_NOTRGB:
echo_erro(
"PNG color type is not RGB: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_P_NOT8BIT:
echo_erro(
"PNG bit depth is not 8: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_P_INTERLACE:
echo_erro(
"PNG is interlaced, deinterlacing is not supported: \"%s\"\n",
FIN_S
);
break;
case OPNG_ERR_P_TINYAREA:
echo_erro(
"PNG dimensions are too small, this is not an oPNG: \"%s\"\n",
FIN_S
);
break;
/*** oPNG "header" ***/
case OPNG_ERR_O_BADVER:
echo_erro(
"oPNG version is not supported (%d): \"%s\"\n",
ROW[0], FIN_S
);
break;
case OPNG_ERR_O_BADFSIZE:
echo_erro(
"Filesize in oPNG header is too large for this image (%d B),"
" oPNG may be corrupted: \"%s\"\n",
FIN_B, FIN_S
);
break;
case OPNG_ERR_O_BADCRC:
echo_warn(
"CRC32 sum in oPNG header doesn't match file"
" (%lx =/= %lx), oPNG may be corrupted: \"%s\"\n",
FIN_CRC, FOUT_CRC, FIN_S
);
break;
default: