3rdparty: embeds libsixel

This commit is contained in:
李通洲
2026-09-13 21:45:58 +08:00
parent d796945604
commit 98e9b6eef1
21 changed files with 7654 additions and 0 deletions
+22
View File
@@ -101,6 +101,7 @@ cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR Dragon
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
option(ENABLE_ZLIB "Enable zlib" ON)
option(ENABLE_SIXEL "Enable sixel image logo output (vendored libsixel encoder)" ON)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_TRACER "Build fastfetch with function tracing" OFF)
@@ -1418,6 +1419,21 @@ else()
)
endif()
if(ENABLE_SIXEL)
set(FF_SIXEL_SRC
src/3rdparty/sixel/allocator.c
src/3rdparty/sixel/dither.c
src/3rdparty/sixel/output.c
src/3rdparty/sixel/pixelformat.c
src/3rdparty/sixel/quant.c
src/3rdparty/sixel/status.c
src/3rdparty/sixel/tosixel.c
)
list(APPEND LIBFASTFETCH_SRC ${FF_SIXEL_SRC})
set_source_files_properties(${FF_SIXEL_SRC} PROPERTIES COMPILE_OPTIONS "-Wno-conversion")
endif()
add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
@@ -1993,6 +2009,12 @@ target_include_directories(libfastfetch
PUBLIC ${PROJECT_SOURCE_DIR}/src
)
if(ENABLE_SIXEL)
# src/3rdparty/sixel/*.c include <sixel.h> (angle brackets, so the directory itself
# has to be on the include path)
target_include_directories(libfastfetch PRIVATE ${PROJECT_SOURCE_DIR}/src/3rdparty/sixel)
endif()
target_link_libraries(libfastfetch
PRIVATE ${CMAKE_DL_LIBS}
)
+18
View File
@@ -0,0 +1,18 @@
Copyright (c) 2014-2016 Hayaki Saito
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+13
View File
@@ -0,0 +1,13 @@
src/quant.c is derived from ppmquant, originally by Jef Poskanzer.
Copyright (C) 1989, 1991 by Jef Poskanzer.
Copyright (C) 2001 by Bryan Henderson.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation. This software is provided "as is" without express or
implied warranty.
+49
View File
@@ -0,0 +1,49 @@
"sixel" license (original license)
==================================
src/tosixel.c and src/fromsixel.c are derived from "sixel" original version (2014-3-2)
Package: http://nanno.dip.jp/softlib/man/rlogin/sixel.tar.gz
Unofficial repo: https://github.com/saitoha/sixel
This work is written by kmiya@ culti. He distributes it under very permissive license.
The original license text(in Japanese) is:
```
このプログラム及びソースコードの使用について個人・商用を問わず
ご自由に使用していただいで結構です。
また、配布・転載・紹介もご連絡の必要もありません。
ソースの改変による配布も自由ですが、どのバージョンの改変かを
明記されることを希望します。
バージョン情報が無い場合は、配布物の年月日を明記されることを
希望します。
2014/10/05 kmiya
```
The unofficial translation:
```
Anyone is free to use this program for any purpose,
commercial or non-commercial, without any restriction.
Anyone is free to distribute, copy, publish, or
advertise this software, without any contact.
Anyone is free to distribute with modification of the
source code, but I "hope" that its based version or
date will be written clearly.
2014/10/05 kmiya
```
kmiya also said this is compatible with MIT/BSD/GPL.
+147
View File
@@ -0,0 +1,147 @@
# libsixel (encoder subset, vendored)
Encoder-only subset of [libsixel](https://github.com/saitoha/libsixel) `1.8.7-r2`,
used by `src/logo/image/` to render the `sixel` logo type **on Windows only**.
## Why this is vendored
Neither MSYS2 nor vcpkg packages libsixel, so there is nothing to `dlopen()` or to
link against. The encoder is small and has no external dependencies, so the
necessary files are embedded instead. The intent is to upstream a libsixel package
to MSYS2 later and switch to it; until then this directory is the source of truth.
## Why Windows only
Windows loses ImageMagick entirely — its image backend moves to WIC, which decodes
and scales but cannot *encode* sixel — so it needs an encoder of its own.
On every other platform ImageMagick stays, and it already produces sixel through
its own SIXEL coder. Adding libsixel there would mean a second encoder for a
capability that already works: one more dependency for zero gain. So `ENABLE_SIXEL`
is gated on `WIN32`, and these sources are **not compiled at all** on Linux / macOS /
BSD.
Consequence: sixel bytes differ between Windows (libsixel) and the rest
(ImageMagick). That is deliberate and accepted — see
`doc/windows-image-backend.md` decision 9.
## What was kept
Starting from `sixel_dither_new` / `sixel_dither_initialize` / `sixel_output_new` /
`sixel_encode` and following the dependency closure, only these files are reachable:
| File | Provides |
|---|---|
| `tosixel.c` | `sixel_encode`, `sixel_putc`, `sixel_node_*`, DCS envelope handling |
| `dither.c` / `dither.h` | `sixel_dither_new`, `sixel_dither_initialize`, `sixel_dither_unref` |
| `output.c` / `output.h` | `sixel_output_new`, `sixel_output_unref` |
| `quant.c` / `quant.h` | Median-cut palette construction |
| `pixelformat.c` | `sixel_helper_compute_depth`, `sixel_helper_normalize_pixelformat` |
| `allocator.c` / `allocator.h` | `sixel_allocator_*` |
| `status.c` / `status.h` | `sixel_helper_set_additional_message` |
| `malloc_stub.h` | Included by `allocator.c`; compiles to nothing when `HAVE_MALLOC` |
| `sixel.h` | Public API (upstream `include/sixel.h`) |
## What was removed
Everything else in the upstream tree, in particular:
- **Decoding**: `decoder.c`, `fromsixel.c`, `frompnm.c`, `fromgif.c`, `frame.c`,
`loader.c`, `stb_image.h`, `stb_image_write.*`. Image decoding is done by the
platform backend (WIC on Windows, ImageMagick elsewhere), so libsixel only ever
sees an RGBA8 buffer here.
- **The `sixel_encoder_*` / `sixel_decoder_*` high-level API**: `encoder.c`,
`writer.c`, `tty.c`, `scale.c`. These pull in file I/O, terminal probing and the
loader registry. We call the dither/output/encode trio directly.
- **`rgblookup.h` / `rgblookup.gperf`**: a gperf-generated color-name table used
only by `encoder.c` for `--builtin-palette` parsing.
- **`converters/`** (`img2sixel`, `sixel2png`), **`python/`**, **`tools/`**,
**`tests/`**, **`images/`** (216 test images), and the packaging templates
(`package.json.in.in`, `libsixel.pc.in`).
- **The autotools machinery**: `configure`, `Makefile.in`, `aclocal.m4`, `m4/`,
`ltmain.sh`, `config.h.in`, … See `config.h` below.
- **Six of the nine `LICENSE.*` files**: `LICENSE.images` / `.mesa` / `.pngsuite` /
`.sdump` / `.stb` cover only material that was dropped (test images, the OpenGL
example, the `sdump` tool, stb). The three that remain are the complete set
required by the files above — verified against each file's own header, see
[License](#license).
Result: **20 files / 255 KB**, down from 319 files / 11.3 MB. Note that 8.0 MB of
that 11.3 MB was `images/` fixtures, so the meaningful comparison is code:
`src/` + `include/` went from 50 files / 1.17 MB to 20 files / 255 KB.
## Local modifications
Two deliberate divergences from upstream. Re-apply both when re-syncing.
1. **`sixel.h` — `SIXELAPI` is empty.** Upstream defines it as
`__declspec(dllexport)` on Windows. This subset is compiled into `libfastfetch`
statically rather than into a standalone DLL, so the attribute would (a) add
every libsixel symbol to fastfetch's export table and (b) make `sixel.h`'s
declarations disagree with the ones in `dither.h` / `output.h` / `quant.h` /
`allocator.h`, which do not carry it (clang warns:
`-Wdll-attribute-on-redeclaration`).
2. **`config.h` is hand-written.** Upstream generates it with `configure`. Only
these vendored files read it, and they reference a small fixed set of macros,
so the values are hard-coded. Two things to watch:
- `HAVE_TESTS` must stay **undefined**, not `0`: `sixel.h` gates its test-only
declarations with `#ifdef HAVE_TESTS`, so `#define HAVE_TESTS 0` would still
pull in declarations for functions we do not compile.
- `HAVE_MEMORY_H` / `HAVE_STRING_H` must be `1`. fastfetch builds with
`-Werror=implicit-function-declaration`, so a missing `<memory.h>` /
`<string.h>` include in `pixelformat.c` / `status.c` is a hard error.
The vendored sources are also exempted from `-Wconversion` in `CMakeLists.txt`:
upstream has ~160 implicit int→`unsigned char` narrowing warnings. Everything else
(`-Wall -Wextra` and fastfetch's `-Werror=` set) applies unchanged, and the subset
compiles clean.
## Re-syncing with upstream
```sh
VER=1.8.7-r2
git clone --depth 1 --branch "$VER" https://github.com/saitoha/libsixel /tmp/libsixel
# 1. copy the closure (paths change from src/foo.c to foo.c, include/sixel.h to sixel.h)
for f in tosixel.c dither.c dither.h output.c output.h quant.c quant.h \
pixelformat.c allocator.c allocator.h status.c status.h malloc_stub.h; do
cp "/tmp/libsixel/src/$f" .
done
cp /tmp/libsixel/include/sixel.h .
cp /tmp/libsixel/LICENSE /tmp/libsixel/LICENSE.sixel /tmp/libsixel/LICENSE.pnmcolormap .
# 2. re-apply the two local modifications listed above
# 3. verify
```
Verification (must be 0 diagnostics, and the encoder must emit a DCS-wrapped stream):
```sh
CC=/c/msys64/clang64/bin/cc.exe
FLAGS="-I. -Wall -Wextra -Wconversion -Wno-conversion -Werror=uninitialized \
-Werror=return-type -Werror=vla -Werror=incompatible-pointer-types \
-Werror=implicit-function-declaration -Werror=int-conversion -std=gnu23"
for f in tosixel dither output quant allocator pixelformat status; do
$CC $FLAGS -c $f.c -o /dev/null || echo "FAILED: $f"
done
```
If upstream adds a call from the closure to a new file, the build fails at link
time with an undefined `sixel_*` symbol — add that file and repeat.
## License
MIT-compatible, but three separate notices apply and all three files must be kept.
Mapping verified against each source file's own copyright header:
| File | Applies to |
|---|---|
| `LICENSE` | MIT, Copyright (c) 2014-2016 Hayaki Saito — `dither.c`, `output.c`, `pixelformat.c`, `allocator.c`, `status.c` (their headers say 2014-2018/2019; same MIT terms) |
| `LICENSE.sixel` | `tosixel.c` — derived from kmiya's original `sixel` (2014-3-2), permissive, re-licensed MIT by Hayaki Saito |
| `LICENSE.pnmcolormap` | `quant.c` — derived from `ppmquant` by Jef Poskanzer / Bryan Henderson |
Upstream also ships `LICENSE.images`, `.mesa`, `.pngsuite`, `.sdump` and `.stb`;
none of them cover a file in this subset, so they were not carried over. If a
re-sync ever pulls in a file from the decoder side (`fromgif.c` → `.stb`,
`fromsixel.c` → `.sixel`), re-check this table.
+379
View File
@@ -0,0 +1,379 @@
/*
* Copyright (c) 2014-2018 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
/* STDC_HEADERS */
#include <stdlib.h>
#if HAVE_ASSERT_H
# include <assert.h>
#endif /* HAVE_ASSERT_H */
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#if HAVE_ERRNO_H
# include <errno.h>
#endif /* HAVE_ERRNO_H */
#if HAVE_MEMORY_H
# include <memory.h>
#endif /* HAVE_MEMORY_H */
#include "allocator.h"
#include "malloc_stub.h"
/* create allocator object */
SIXELSTATUS
sixel_allocator_new(
sixel_allocator_t /* out */ **ppallocator, /* allocator object to be created */
sixel_malloc_t /* in */ fn_malloc, /* custom malloc() function */
sixel_calloc_t /* in */ fn_calloc, /* custom calloc() function */
sixel_realloc_t /* in */ fn_realloc, /* custom realloc() function */
sixel_free_t /* in */ fn_free) /* custom free() function */
{
SIXELSTATUS status = SIXEL_FALSE;
if (ppallocator == NULL) {
sixel_helper_set_additional_message(
"sixel_allocator_new: given argument ppallocator is null.");
status = SIXEL_BAD_ARGUMENT;
goto end;
}
if (fn_malloc == NULL) {
fn_malloc = malloc;
}
if (fn_calloc == NULL) {
fn_calloc = calloc;
}
if (fn_realloc == NULL) {
fn_realloc = realloc;
}
if (fn_free == NULL) {
fn_free = free;
}
*ppallocator = fn_malloc(sizeof(sixel_allocator_t));
if (*ppallocator == NULL) {
sixel_helper_set_additional_message(
"sixel_allocator_new: fn_malloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
(*ppallocator)->ref = 1;
(*ppallocator)->fn_malloc = fn_malloc;
(*ppallocator)->fn_calloc = fn_calloc;
(*ppallocator)->fn_realloc = fn_realloc;
(*ppallocator)->fn_free = fn_free;
status = SIXEL_OK;
end:
return status;
}
/* destruct allocator object */
static void
sixel_allocator_destroy(
sixel_allocator_t /* in */ *allocator) /* allocator object to
be destroyed */
{
/* precondition */
assert(allocator);
assert(allocator->fn_free);
allocator->fn_free(allocator);
}
/* increase reference count of allocatort object (thread-unsafe) */
SIXELAPI void
sixel_allocator_ref(
sixel_allocator_t /* in */ *allocator) /* allocator object to be
increment reference counter */
{
/* precondition */
assert(allocator);
/* TODO: be thread safe */
++allocator->ref;
}
/* decrease reference count of output context object (thread-unsafe) */
SIXELAPI void
sixel_allocator_unref(
sixel_allocator_t /* in */ *allocator) /* allocator object to be unreference */
{
/* TODO: be thread safe */
if (allocator) {
assert(allocator->ref > 0);
--allocator->ref;
if (allocator->ref == 0) {
sixel_allocator_destroy(allocator);
}
}
}
/* call custom malloc() */
SIXELAPI void *
sixel_allocator_malloc(
sixel_allocator_t /* in */ *allocator, /* allocator object */
size_t /* in */ n) /* allocation size */
{
/* precondition */
assert(allocator);
assert(allocator->fn_malloc);
if (n == 0) {
sixel_helper_set_additional_message(
"sixel_allocator_malloc: called with n == 0");
return NULL;
}
if (n > SIXEL_ALLOCATE_BYTES_MAX) {
return NULL;
}
return allocator->fn_malloc(n);
}
/* call custom calloc() */
SIXELAPI void *
sixel_allocator_calloc(
sixel_allocator_t /* in */ *allocator, /* allocator object */
size_t /* in */ nelm, /* number of elements */
size_t /* in */ elsize) /* size of element */
{
size_t n;
/* precondition */
assert(allocator);
assert(allocator->fn_calloc);
n = nelm * elsize;
if (n == 0) {
sixel_helper_set_additional_message(
"sixel_allocator_malloc: called with n == 0");
return NULL;
}
if (n > SIXEL_ALLOCATE_BYTES_MAX) {
return NULL;
}
return allocator->fn_calloc(nelm, elsize);
}
/* call custom realloc() */
SIXELAPI void *
sixel_allocator_realloc(
sixel_allocator_t /* in */ *allocator, /* allocator object */
void /* in */ *p, /* existing buffer to be re-allocated */
size_t /* in */ n) /* re-allocation size */
{
/* precondition */
assert(allocator);
assert(allocator->fn_realloc);
if (n == 0) {
sixel_helper_set_additional_message(
"sixel_allocator_malloc: called with n == 0");
return NULL;
}
if (n > SIXEL_ALLOCATE_BYTES_MAX) {
return NULL;
}
return allocator->fn_realloc(p, n);
}
/* call custom free() */
SIXELAPI void
sixel_allocator_free(
sixel_allocator_t /* in */ *allocator, /* allocator object */
void /* in */ *p) /* existing buffer to be freed */
{
/* precondition */
assert(allocator);
assert(allocator->fn_free);
allocator->fn_free(p);
}
#if HAVE_TESTS
volatile int sixel_debug_malloc_counter;
void *
sixel_bad_malloc(size_t size)
{
return sixel_debug_malloc_counter-- == 0 ? NULL: malloc(size);
}
void *
sixel_bad_calloc(size_t count, size_t size)
{
(void) count;
(void) size;
return NULL;
}
void *
sixel_bad_realloc(void *ptr, size_t size)
{
(void) ptr;
(void) size;
return NULL;
}
#endif /* HAVE_TESTS */
#if 0
int
rpl_posix_memalign(void **memptr, size_t alignment, size_t size)
{
#if HAVE_POSIX_MEMALIGN
return posix_memalign(memptr, alignment, size);
#elif HAVE_ALIGNED_ALLOC
*memptr = aligned_alloc(alignment, size);
return *memptr ? 0: ENOMEM;
#elif HAVE_MEMALIGN
*memptr = memalign(alignment, size);
return *memptr ? 0: ENOMEM;
#elif HAVE__ALIGNED_MALLOC
return _aligned_malloc(size, alignment);
#else
# error
#endif /* _MSC_VER */
}
#endif
#if HAVE_TESTS
static int
test1(void)
{
int nret = EXIT_FAILURE;
SIXELSTATUS status;
sixel_allocator_t *allocator = NULL;
status = sixel_allocator_new(NULL, malloc, calloc, realloc, free);
if (status != SIXEL_BAD_ARGUMENT) {
goto error;
}
status = sixel_allocator_new(&allocator, NULL, calloc, realloc, free);
if (SIXEL_FAILED(status)) {
goto error;
}
status = sixel_allocator_new(&allocator, malloc, NULL, realloc, free);
if (SIXEL_FAILED(status)) {
goto error;
}
status = sixel_allocator_new(&allocator, malloc, calloc, NULL, free);
if (SIXEL_FAILED(status)) {
goto error;
}
status = sixel_allocator_new(&allocator, malloc, calloc, realloc, NULL);
if (SIXEL_FAILED(status)) {
goto error;
}
nret = EXIT_SUCCESS;
error:
return nret;
}
static int
test2(void)
{
int nret = EXIT_FAILURE;
SIXELSTATUS status;
sixel_allocator_t *allocator = NULL;
sixel_debug_malloc_counter = 1;
status = sixel_allocator_new(&allocator, sixel_bad_malloc, calloc, realloc, free);
if (status == SIXEL_BAD_ALLOCATION) {
goto error;
}
nret = EXIT_SUCCESS;
error:
return nret;
}
SIXELAPI int
sixel_allocator_tests_main(void)
{
int nret = EXIT_FAILURE;
size_t i;
typedef int (* testcase)(void);
static testcase const testcases[] = {
test1,
test2
};
for (i = 0; i < sizeof(testcases) / sizeof(testcase); ++i) {
nret = testcases[i]();
if (nret != EXIT_SUCCESS) {
goto error;
}
}
nret = EXIT_SUCCESS;
error:
return nret;
}
#endif /* HAVE_TESTS */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2014-2016 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBSIXEL_ALLOCATOR_H
#define LIBSIXEL_ALLOCATOR_H
#include <sixel.h>
struct sixel_allocator {
unsigned int ref; /* reference counter */
sixel_malloc_t fn_malloc;
sixel_calloc_t fn_calloc;
sixel_realloc_t fn_realloc;
sixel_free_t fn_free;
};
#if HAVE_TESTS
int
sixel_allocator_tests_main(void);
#endif
#endif /* LIBSIXEL_ALLOCATOR_H */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+58
View File
@@ -0,0 +1,58 @@
/*
* Minimal hand-written replacement for the autoconf-generated config.h.
*
* Upstream libsixel ships config.h.in and lets `configure` produce config.h.
* We only vendor the encoder-side subset (see README.md), and those files
* reference a small, fixed set of macros, so the values are hard-coded here
* instead of carrying the autotools machinery.
*
* The values below hold for every platform fastfetch targets:
* Windows/MinGW-w64, Linux/glibc, Linux/musl, macOS and the BSDs.
* Re-check this file whenever the vendored subset is re-synced with upstream.
*/
#ifndef LIBSIXEL_CONFIG_H
#define LIBSIXEL_CONFIG_H
/* Standard headers (upstream: AC_CHECK_HEADERS) */
#define HAVE_ASSERT_H 1
#define HAVE_ERRNO_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_LIMITS_H 1
#define HAVE_MATH_H 1
#define HAVE_MEMORY_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_TYPES_H 1
/* libc functions (upstream: AC_CHECK_FUNCS) */
#define HAVE_LDIV 1
#define HAVE_MALLOC 1
#define HAVE_REALLOC 1
/* Byte order of the 32bpp pixel readers in pixelformat.c; 0 = little endian */
#define SWAP_BYTES 0
/*
* Guards the diagnostic pragma push/pop in dither.c. Not needed, and the
* pragma spelling is not portable across the compilers we support.
*/
#define HAVE_DIAGNOSTIC_DEPRECATED_DECLARATIONS 0
/* Verbose quantizer tracing to stderr */
#define HAVE_DEBUG 0
/*
* HAVE_TESTS must stay *undefined* rather than 0: sixel.h gates its test-only
* declarations with `#ifdef HAVE_TESTS`, so defining it to 0 would still pull
* in declarations for functions we do not compile.
*/
#undef HAVE_TESTS
/* Optional image loaders and features; not vendored */
#undef HAVE_GD
#undef HAVE_GDK_PIXBUF2
#undef HAVE_JPEG
#undef HAVE_LIBCURL
#undef HAVE_LIBPNG
#endif /* LIBSIXEL_CONFIG_H */
+918
View File
@@ -0,0 +1,918 @@
/*
* Copyright (c) 2014-2018 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#if HAVE_MATH_H
# include <math.h>
#endif /* HAVE_MATH_H */
#if HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#if HAVE_LIMITS_H
# include <limits.h>
#endif /* HAVE_LIMITS_H */
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif /* HAVE_INTTYPES_H */
#include "dither.h"
#include "quant.h"
#include <sixel.h>
static const unsigned char pal_mono_dark[] = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xff
};
static const unsigned char pal_mono_light[] = {
0xff, 0xff, 0xff, 0x00, 0x00, 0x00
};
static const unsigned char pal_gray_1bit[] = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xff
};
static const unsigned char pal_gray_2bit[] = {
0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff
};
static const unsigned char pal_gray_4bit[] = {
0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33,
0x44, 0x44, 0x44, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77,
0x88, 0x88, 0x88, 0x99, 0x99, 0x99, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb,
0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xee, 0xee, 0xee, 0xff, 0xff, 0xff
};
static const unsigned char pal_gray_8bit[] = {
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b,
0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f,
0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13,
0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17,
0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b,
0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f,
0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23,
0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27,
0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b,
0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f,
0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33,
0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37,
0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b,
0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f,
0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43,
0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47,
0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b,
0x4c, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f,
0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53,
0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57,
0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b,
0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f,
0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63,
0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b,
0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f,
0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73,
0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77,
0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b,
0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f,
0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83,
0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87,
0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b,
0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93,
0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0x9f,
0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3,
0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7,
0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab, 0xab,
0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf,
0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3,
0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7,
0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb,
0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7,
0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf,
0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3,
0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7,
0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb,
0xdc, 0xdc, 0xdc, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf,
0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3,
0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb,
0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7,
0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff
};
static const unsigned char pal_xterm256[] = {
0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00,
0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0,
0x80, 0x80, 0x80, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x87, 0x00, 0x00, 0xaf,
0x00, 0x00, 0xd7, 0x00, 0x00, 0xff, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x5f,
0x00, 0x5f, 0x87, 0x00, 0x5f, 0xaf, 0x00, 0x5f, 0xd7, 0x00, 0x5f, 0xff,
0x00, 0x87, 0x00, 0x00, 0x87, 0x5f, 0x00, 0x87, 0x87, 0x00, 0x87, 0xaf,
0x00, 0x87, 0xd7, 0x00, 0x87, 0xff, 0x00, 0xaf, 0x00, 0x00, 0xaf, 0x5f,
0x00, 0xaf, 0x87, 0x00, 0xaf, 0xaf, 0x00, 0xaf, 0xd7, 0x00, 0xaf, 0xff,
0x00, 0xd7, 0x00, 0x00, 0xd7, 0x5f, 0x00, 0xd7, 0x87, 0x00, 0xd7, 0xaf,
0x00, 0xd7, 0xd7, 0x00, 0xd7, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x5f,
0x00, 0xff, 0x87, 0x00, 0xff, 0xaf, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff,
0x5f, 0x00, 0x00, 0x5f, 0x00, 0x5f, 0x5f, 0x00, 0x87, 0x5f, 0x00, 0xaf,
0x5f, 0x00, 0xd7, 0x5f, 0x00, 0xff, 0x5f, 0x5f, 0x00, 0x5f, 0x5f, 0x5f,
0x5f, 0x5f, 0x87, 0x5f, 0x5f, 0xaf, 0x5f, 0x5f, 0xd7, 0x5f, 0x5f, 0xff,
0x5f, 0x87, 0x00, 0x5f, 0x87, 0x5f, 0x5f, 0x87, 0x87, 0x5f, 0x87, 0xaf,
0x5f, 0x87, 0xd7, 0x5f, 0x87, 0xff, 0x5f, 0xaf, 0x00, 0x5f, 0xaf, 0x5f,
0x5f, 0xaf, 0x87, 0x5f, 0xaf, 0xaf, 0x5f, 0xaf, 0xd7, 0x5f, 0xaf, 0xff,
0x5f, 0xd7, 0x00, 0x5f, 0xd7, 0x5f, 0x5f, 0xd7, 0x87, 0x5f, 0xd7, 0xaf,
0x5f, 0xd7, 0xd7, 0x5f, 0xd7, 0xff, 0x5f, 0xff, 0x00, 0x5f, 0xff, 0x5f,
0x5f, 0xff, 0x87, 0x5f, 0xff, 0xaf, 0x5f, 0xff, 0xd7, 0x5f, 0xff, 0xff,
0x87, 0x00, 0x00, 0x87, 0x00, 0x5f, 0x87, 0x00, 0x87, 0x87, 0x00, 0xaf,
0x87, 0x00, 0xd7, 0x87, 0x00, 0xff, 0x87, 0x5f, 0x00, 0x87, 0x5f, 0x5f,
0x87, 0x5f, 0x87, 0x87, 0x5f, 0xaf, 0x87, 0x5f, 0xd7, 0x87, 0x5f, 0xff,
0x87, 0x87, 0x00, 0x87, 0x87, 0x5f, 0x87, 0x87, 0x87, 0x87, 0x87, 0xaf,
0x87, 0x87, 0xd7, 0x87, 0x87, 0xff, 0x87, 0xaf, 0x00, 0x87, 0xaf, 0x5f,
0x87, 0xaf, 0x87, 0x87, 0xaf, 0xaf, 0x87, 0xaf, 0xd7, 0x87, 0xaf, 0xff,
0x87, 0xd7, 0x00, 0x87, 0xd7, 0x5f, 0x87, 0xd7, 0x87, 0x87, 0xd7, 0xaf,
0x87, 0xd7, 0xd7, 0x87, 0xd7, 0xff, 0x87, 0xff, 0x00, 0x87, 0xff, 0x5f,
0x87, 0xff, 0x87, 0x87, 0xff, 0xaf, 0x87, 0xff, 0xd7, 0x87, 0xff, 0xff,
0xaf, 0x00, 0x00, 0xaf, 0x00, 0x5f, 0xaf, 0x00, 0x87, 0xaf, 0x00, 0xaf,
0xaf, 0x00, 0xd7, 0xaf, 0x00, 0xff, 0xaf, 0x5f, 0x00, 0xaf, 0x5f, 0x5f,
0xaf, 0x5f, 0x87, 0xaf, 0x5f, 0xaf, 0xaf, 0x5f, 0xd7, 0xaf, 0x5f, 0xff,
0xaf, 0x87, 0x00, 0xaf, 0x87, 0x5f, 0xaf, 0x87, 0x87, 0xaf, 0x87, 0xaf,
0xaf, 0x87, 0xd7, 0xaf, 0x87, 0xff, 0xaf, 0xaf, 0x00, 0xaf, 0xaf, 0x5f,
0xaf, 0xaf, 0x87, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xd7, 0xaf, 0xaf, 0xff,
0xaf, 0xd7, 0x00, 0xaf, 0xd7, 0x5f, 0xaf, 0xd7, 0x87, 0xaf, 0xd7, 0xaf,
0xaf, 0xd7, 0xd7, 0xaf, 0xd7, 0xff, 0xaf, 0xff, 0x00, 0xaf, 0xff, 0x5f,
0xaf, 0xff, 0x87, 0xaf, 0xff, 0xaf, 0xaf, 0xff, 0xd7, 0xaf, 0xff, 0xff,
0xd7, 0x00, 0x00, 0xd7, 0x00, 0x5f, 0xd7, 0x00, 0x87, 0xd7, 0x00, 0xaf,
0xd7, 0x00, 0xd7, 0xd7, 0x00, 0xff, 0xd7, 0x5f, 0x00, 0xd7, 0x5f, 0x5f,
0xd7, 0x5f, 0x87, 0xd7, 0x5f, 0xaf, 0xd7, 0x5f, 0xd7, 0xd7, 0x5f, 0xff,
0xd7, 0x87, 0x00, 0xd7, 0x87, 0x5f, 0xd7, 0x87, 0x87, 0xd7, 0x87, 0xaf,
0xd7, 0x87, 0xd7, 0xd7, 0x87, 0xff, 0xd7, 0xaf, 0x00, 0xd7, 0xaf, 0x5f,
0xd7, 0xaf, 0x87, 0xd7, 0xaf, 0xaf, 0xd7, 0xaf, 0xd7, 0xd7, 0xaf, 0xff,
0xd7, 0xd7, 0x00, 0xd7, 0xd7, 0x5f, 0xd7, 0xd7, 0x87, 0xd7, 0xd7, 0xaf,
0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xff, 0xd7, 0xff, 0x00, 0xd7, 0xff, 0x5f,
0xd7, 0xff, 0x87, 0xd7, 0xff, 0xaf, 0xd7, 0xff, 0xd7, 0xd7, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0x00, 0x5f, 0xff, 0x00, 0x87, 0xff, 0x00, 0xaf,
0xff, 0x00, 0xd7, 0xff, 0x00, 0xff, 0xff, 0x5f, 0x00, 0xff, 0x5f, 0x5f,
0xff, 0x5f, 0x87, 0xff, 0x5f, 0xaf, 0xff, 0x5f, 0xd7, 0xff, 0x5f, 0xff,
0xff, 0x87, 0x00, 0xff, 0x87, 0x5f, 0xff, 0x87, 0x87, 0xff, 0x87, 0xaf,
0xff, 0x87, 0xd7, 0xff, 0x87, 0xff, 0xff, 0xaf, 0x00, 0xff, 0xaf, 0x5f,
0xff, 0xaf, 0x87, 0xff, 0xaf, 0xaf, 0xff, 0xaf, 0xd7, 0xff, 0xaf, 0xff,
0xff, 0xd7, 0x00, 0xff, 0xd7, 0x5f, 0xff, 0xd7, 0x87, 0xff, 0xd7, 0xaf,
0xff, 0xd7, 0xd7, 0xff, 0xd7, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x5f,
0xff, 0xff, 0x87, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xff,
0x08, 0x08, 0x08, 0x12, 0x12, 0x12, 0x1c, 0x1c, 0x1c, 0x26, 0x26, 0x26,
0x30, 0x30, 0x30, 0x3a, 0x3a, 0x3a, 0x44, 0x44, 0x44, 0x4e, 0x4e, 0x4e,
0x58, 0x58, 0x58, 0x62, 0x62, 0x62, 0x6c, 0x6c, 0x6c, 0x76, 0x76, 0x76,
0x80, 0x80, 0x80, 0x8a, 0x8a, 0x8a, 0x94, 0x94, 0x94, 0x9e, 0x9e, 0x9e,
0xa8, 0xa8, 0xa8, 0xb2, 0xb2, 0xb2, 0xbc, 0xbc, 0xbc, 0xc6, 0xc6, 0xc6,
0xd0, 0xd0, 0xd0, 0xda, 0xda, 0xda, 0xe4, 0xe4, 0xe4, 0xee, 0xee, 0xee,
};
/*
* VT340 undocumented behavior regarding the color palette reported
* by Vertis Sidus(@vrtsds):
* it loads the first fifteen colors as 1 through 15, and loads the
* sixteenth color as 0.
*/
static const unsigned char pal_vt340_mono[] = {
/* 1 Gray-2 */ 13 * 255 / 100, 13 * 255 / 100, 13 * 255 / 100,
/* 2 Gray-4 */ 26 * 255 / 100, 26 * 255 / 100, 26 * 255 / 100,
/* 3 Gray-6 */ 40 * 255 / 100, 40 * 255 / 100, 40 * 255 / 100,
/* 4 Gray-1 */ 6 * 255 / 100, 6 * 255 / 100, 6 * 255 / 100,
/* 5 Gray-3 */ 20 * 255 / 100, 20 * 255 / 100, 20 * 255 / 100,
/* 6 Gray-5 */ 33 * 255 / 100, 33 * 255 / 100, 33 * 255 / 100,
/* 7 White 7 */ 46 * 255 / 100, 46 * 255 / 100, 46 * 255 / 100,
/* 8 Black 0 */ 0 * 255 / 100, 0 * 255 / 100, 0 * 255 / 100,
/* 9 Gray-2 */ 13 * 255 / 100, 13 * 255 / 100, 13 * 255 / 100,
/* 10 Gray-4 */ 26 * 255 / 100, 26 * 255 / 100, 26 * 255 / 100,
/* 11 Gray-6 */ 40 * 255 / 100, 40 * 255 / 100, 40 * 255 / 100,
/* 12 Gray-1 */ 6 * 255 / 100, 6 * 255 / 100, 6 * 255 / 100,
/* 13 Gray-3 */ 20 * 255 / 100, 20 * 255 / 100, 20 * 255 / 100,
/* 14 Gray-5 */ 33 * 255 / 100, 33 * 255 / 100, 33 * 255 / 100,
/* 15 White 7 */ 46 * 255 / 100, 46 * 255 / 100, 46 * 255 / 100,
/* 0 Black */ 0 * 255 / 100, 0 * 255 / 100, 0 * 255 / 100,
};
static const unsigned char pal_vt340_color[] = {
/* 1 Blue */ 20 * 255 / 100, 20 * 255 / 100, 80 * 255 / 100,
/* 2 Red */ 80 * 255 / 100, 13 * 255 / 100, 13 * 255 / 100,
/* 3 Green */ 20 * 255 / 100, 80 * 255 / 100, 20 * 255 / 100,
/* 4 Magenta */ 80 * 255 / 100, 20 * 255 / 100, 80 * 255 / 100,
/* 5 Cyan */ 20 * 255 / 100, 80 * 255 / 100, 80 * 255 / 100,
/* 6 Yellow */ 80 * 255 / 100, 80 * 255 / 100, 20 * 255 / 100,
/* 7 Gray 50% */ 53 * 255 / 100, 53 * 255 / 100, 53 * 255 / 100,
/* 8 Gray 25% */ 26 * 255 / 100, 26 * 255 / 100, 26 * 255 / 100,
/* 9 Blue* */ 33 * 255 / 100, 33 * 255 / 100, 60 * 255 / 100,
/* 10 Red* */ 60 * 255 / 100, 26 * 255 / 100, 26 * 255 / 100,
/* 11 Green* */ 33 * 255 / 100, 60 * 255 / 100, 33 * 255 / 100,
/* 12 Magenta* */ 60 * 255 / 100, 33 * 255 / 100, 60 * 255 / 100,
/* 13 Cyan* */ 33 * 255 / 100, 60 * 255 / 100, 60 * 255 / 100,
/* 14 Yellow* */ 60 * 255 / 100, 60 * 255 / 100, 33 * 255 / 100,
/* 15 Gray 75% */ 80 * 255 / 100, 80 * 255 / 100, 80 * 255 / 100,
/* 0 Black */ 0 * 255 / 100, 0 * 255 / 100, 0 * 255 / 100,
};
/* create dither context object */
SIXELAPI SIXELSTATUS
sixel_dither_new(
sixel_dither_t /* out */ **ppdither, /* dither object to be created */
int /* in */ ncolors, /* required colors */
sixel_allocator_t /* in */ *allocator) /* allocator, null if you use
default allocator */
{
SIXELSTATUS status = SIXEL_FALSE;
size_t headsize;
size_t datasize;
size_t wholesize;
int quality_mode;
/* ensure given pointer is not null */
if (ppdither == NULL) {
sixel_helper_set_additional_message(
"sixel_dither_new: ppdither is null.");
status = SIXEL_BAD_ARGUMENT;
goto end;
}
if (allocator == NULL) {
status = sixel_allocator_new(&allocator, NULL, NULL, NULL, NULL);
if (SIXEL_FAILED(status)) {
*ppdither = NULL;
goto end;
}
} else {
sixel_allocator_ref(allocator);
}
if (ncolors < 0) {
ncolors = SIXEL_PALETTE_MAX;
quality_mode = SIXEL_QUALITY_HIGHCOLOR;
} else {
if (ncolors > SIXEL_PALETTE_MAX) {
status = SIXEL_BAD_INPUT;
goto end;
} else if (ncolors < 1) {
status = SIXEL_BAD_INPUT;
sixel_helper_set_additional_message(
"sixel_dither_new: palette colors must be more than 0");
goto end;
}
quality_mode = SIXEL_QUALITY_LOW;
}
headsize = sizeof(sixel_dither_t);
datasize = (size_t)(ncolors * 3);
wholesize = headsize + datasize;
*ppdither = (sixel_dither_t *)sixel_allocator_malloc(allocator, wholesize);
if (*ppdither == NULL) {
sixel_allocator_unref(allocator);
sixel_helper_set_additional_message(
"sixel_dither_new: sixel_allocator_malloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
(*ppdither)->ref = 1;
(*ppdither)->palette = (unsigned char*)(*ppdither + 1);
(*ppdither)->cachetable = NULL;
(*ppdither)->reqcolors = ncolors;
(*ppdither)->ncolors = ncolors;
(*ppdither)->origcolors = (-1);
(*ppdither)->keycolor = (-1);
(*ppdither)->optimized = 0;
(*ppdither)->optimize_palette = 0;
(*ppdither)->complexion = 1;
(*ppdither)->bodyonly = 0;
(*ppdither)->method_for_largest = SIXEL_LARGE_NORM;
(*ppdither)->method_for_rep = SIXEL_REP_CENTER_BOX;
(*ppdither)->method_for_diffuse = SIXEL_DIFFUSE_FS;
(*ppdither)->quality_mode = quality_mode;
(*ppdither)->pixelformat = SIXEL_PIXELFORMAT_RGB888;
(*ppdither)->allocator = allocator;
status = SIXEL_OK;
end:
return status;
}
/* create dither context object (deprecated) */
SIXELAPI sixel_dither_t *
sixel_dither_create(
int /* in */ ncolors)
{
SIXELSTATUS status = SIXEL_FALSE;
sixel_dither_t *dither = NULL;
status = sixel_dither_new(&dither, ncolors, NULL);
if (SIXEL_FAILED(status)) {
goto end;
}
end:
return dither;
}
SIXELAPI void
sixel_dither_destroy(
sixel_dither_t /* in */ *dither)
{
sixel_allocator_t *allocator;
if (dither) {
allocator = dither->allocator;
sixel_allocator_free(allocator, dither->cachetable);
dither->cachetable = NULL;
sixel_allocator_free(allocator, dither);
sixel_allocator_unref(allocator);
}
}
SIXELAPI void
sixel_dither_ref(
sixel_dither_t /* in */ *dither)
{
/* TODO: be thread safe */
++dither->ref;
}
SIXELAPI void
sixel_dither_unref(
sixel_dither_t /* in */ *dither)
{
/* TODO: be thread safe */
if (dither != NULL && --dither->ref == 0) {
sixel_dither_destroy(dither);
}
}
SIXELAPI sixel_dither_t *
sixel_dither_get(
int /* in */ builtin_dither)
{
SIXELSTATUS status = SIXEL_FALSE;
unsigned char *palette;
int ncolors;
int keycolor;
sixel_dither_t *dither = NULL;
switch (builtin_dither) {
case SIXEL_BUILTIN_MONO_DARK:
ncolors = 2;
palette = (unsigned char *)pal_mono_dark;
keycolor = 0;
break;
case SIXEL_BUILTIN_MONO_LIGHT:
ncolors = 2;
palette = (unsigned char *)pal_mono_light;
keycolor = 0;
break;
case SIXEL_BUILTIN_XTERM16:
ncolors = 16;
palette = (unsigned char *)pal_xterm256;
keycolor = (-1);
break;
case SIXEL_BUILTIN_XTERM256:
ncolors = 256;
palette = (unsigned char *)pal_xterm256;
keycolor = (-1);
break;
case SIXEL_BUILTIN_VT340_MONO:
ncolors = 16;
palette = (unsigned char *)pal_vt340_mono;
keycolor = (-1);
break;
case SIXEL_BUILTIN_VT340_COLOR:
ncolors = 16;
palette = (unsigned char *)pal_vt340_color;
keycolor = (-1);
break;
case SIXEL_BUILTIN_G1:
ncolors = 2;
palette = (unsigned char *)pal_gray_1bit;
keycolor = (-1);
break;
case SIXEL_BUILTIN_G2:
ncolors = 4;
palette = (unsigned char *)pal_gray_2bit;
keycolor = (-1);
break;
case SIXEL_BUILTIN_G4:
ncolors = 16;
palette = (unsigned char *)pal_gray_4bit;
keycolor = (-1);
break;
case SIXEL_BUILTIN_G8:
ncolors = 256;
palette = (unsigned char *)pal_gray_8bit;
keycolor = (-1);
break;
default:
goto end;
}
status = sixel_dither_new(&dither, ncolors, NULL);
if (SIXEL_FAILED(status)) {
dither = NULL;
goto end;
}
dither->palette = palette;
dither->keycolor = keycolor;
dither->optimized = 1;
dither->optimize_palette = 0;
end:
return dither;
}
static void
sixel_dither_set_method_for_largest(
sixel_dither_t /* in */ *dither,
int /* in */ method_for_largest)
{
if (method_for_largest == SIXEL_LARGE_AUTO) {
method_for_largest = SIXEL_LARGE_NORM;
}
dither->method_for_largest = method_for_largest;
}
static void
sixel_dither_set_method_for_rep(
sixel_dither_t /* in */ *dither,
int /* in */ method_for_rep)
{
if (method_for_rep == SIXEL_REP_AUTO) {
method_for_rep = SIXEL_REP_CENTER_BOX;
}
dither->method_for_rep = method_for_rep;
}
static void
sixel_dither_set_quality_mode(
sixel_dither_t /* in */ *dither,
int /* in */ quality_mode)
{
if (quality_mode == SIXEL_QUALITY_AUTO) {
if (dither->ncolors <= 8) {
quality_mode = SIXEL_QUALITY_HIGH;
} else {
quality_mode = SIXEL_QUALITY_LOW;
}
}
dither->quality_mode = quality_mode;
}
SIXELAPI SIXELSTATUS
sixel_dither_initialize(
sixel_dither_t /* in */ *dither,
unsigned char /* in */ *data,
int /* in */ width,
int /* in */ height,
int /* in */ pixelformat,
int /* in */ method_for_largest,
int /* in */ method_for_rep,
int /* in */ quality_mode)
{
unsigned char *buf = NULL;
unsigned char *normalized_pixels = NULL;
unsigned char *input_pixels;
SIXELSTATUS status = SIXEL_FALSE;
/* ensure dither object is not null */
if (dither == NULL) {
sixel_helper_set_additional_message(
"sixel_dither_new: dither is null.");
status = SIXEL_BAD_ARGUMENT;
goto end;
}
/* increment ref count */
sixel_dither_ref(dither);
sixel_dither_set_pixelformat(dither, pixelformat);
switch (pixelformat) {
case SIXEL_PIXELFORMAT_RGB888:
input_pixels = data;
break;
default:
/* normalize pixelformat */
normalized_pixels
= (unsigned char *)sixel_allocator_malloc(dither->allocator, (size_t)(width * height * 3));
if (normalized_pixels == NULL) {
sixel_helper_set_additional_message(
"sixel_dither_initialize: sixel_allocator_malloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
status = sixel_helper_normalize_pixelformat(
normalized_pixels,
&pixelformat,
data,
pixelformat,
width,
height);
if (SIXEL_FAILED(status)) {
goto end;
}
input_pixels = normalized_pixels;
break;
}
sixel_dither_set_method_for_largest(dither, method_for_largest);
sixel_dither_set_method_for_rep(dither, method_for_rep);
sixel_dither_set_quality_mode(dither, quality_mode);
status = sixel_quant_make_palette(&buf,
input_pixels,
(unsigned int)(width * height * 3),
SIXEL_PIXELFORMAT_RGB888,
(unsigned int)dither->reqcolors,
(unsigned int *)&dither->ncolors,
(unsigned int *)&dither->origcolors,
dither->method_for_largest,
dither->method_for_rep,
dither->quality_mode,
dither->allocator);
if (SIXEL_FAILED(status)) {
goto end;
}
memcpy(dither->palette, buf, (size_t)(dither->ncolors * 3));
dither->optimized = 1;
if (dither->origcolors <= dither->ncolors) {
dither->method_for_diffuse = SIXEL_DIFFUSE_NONE;
}
sixel_quant_free_palette(buf, dither->allocator);
status = SIXEL_OK;
end:
free(normalized_pixels);
/* decrement ref count */
sixel_dither_unref(dither);
return status;
}
/* set diffusion type, choose from enum methodForDiffuse */
SIXELAPI void
sixel_dither_set_diffusion_type(
sixel_dither_t /* in */ *dither,
int /* in */ method_for_diffuse)
{
if (method_for_diffuse == SIXEL_DIFFUSE_AUTO) {
if (dither->ncolors > 16) {
method_for_diffuse = SIXEL_DIFFUSE_FS;
} else {
method_for_diffuse = SIXEL_DIFFUSE_ATKINSON;
}
}
dither->method_for_diffuse = method_for_diffuse;
}
/* get number of palette colors */
SIXELAPI int
sixel_dither_get_num_of_palette_colors(
sixel_dither_t /* in */ *dither)
{
return dither->ncolors;
}
/* get number of histogram colors */
SIXELAPI int
sixel_dither_get_num_of_histogram_colors(
sixel_dither_t /* in */ *dither) /* dither context object */
{
return dither->origcolors;
}
/* typoed: remained for keeping compatibility */
SIXELAPI int
sixel_dither_get_num_of_histgram_colors(
sixel_dither_t /* in */ *dither) /* dither context object */
{
return sixel_dither_get_num_of_histogram_colors(dither);
}
/* get palette */
SIXELAPI unsigned char *
sixel_dither_get_palette(
sixel_dither_t /* in */ *dither) /* dither context object */
{
return dither->palette;
}
/* set palette */
SIXELAPI void
sixel_dither_set_palette(
sixel_dither_t /* in */ *dither, /* dither context object */
unsigned char /* in */ *palette)
{
memcpy(dither->palette, palette, (size_t)(dither->ncolors * 3));
}
/* set the factor of complexion color correcting */
SIXELAPI void
sixel_dither_set_complexion_score(
sixel_dither_t /* in */ *dither, /* dither context object */
int /* in */ score) /* complexion score (>= 1) */
{
dither->complexion = score;
}
/* set whether omitting palette difinition */
SIXELAPI void
sixel_dither_set_body_only(
sixel_dither_t /* in */ *dither, /* dither context object */
int /* in */ bodyonly) /* 0: output palette section
1: do not output palette section */
{
dither->bodyonly = bodyonly;
}
/* set whether optimize palette size */
SIXELAPI void
sixel_dither_set_optimize_palette(
sixel_dither_t /* in */ *dither, /* dither context object */
int /* in */ do_opt) /* 0: optimize palette size
1: don't optimize palette size */
{
dither->optimize_palette = do_opt;
}
/* set pixelformat */
SIXELAPI void
sixel_dither_set_pixelformat(
sixel_dither_t /* in */ *dither, /* dither context object */
int /* in */ pixelformat) /* one of enum pixelFormat */
{
dither->pixelformat = pixelformat;
}
/* set transparent */
SIXELAPI void
sixel_dither_set_transparent(
sixel_dither_t /* in */ *dither, /* dither context object */
int /* in */ transparent) /* transparent color index */
{
dither->keycolor = transparent;
}
/* set transparent */
SIXELAPI sixel_index_t *
sixel_dither_apply_palette(
sixel_dither_t /* in */ *dither,
unsigned char /* in */ *pixels,
int /* in */ width,
int /* in */ height)
{
SIXELSTATUS status = SIXEL_FALSE;
size_t bufsize;
sixel_index_t *dest = NULL;
int ncolors;
unsigned char *normalized_pixels = NULL;
unsigned char *input_pixels;
/* ensure dither object is not null */
if (dither == NULL) {
sixel_helper_set_additional_message(
"sixel_dither_apply_palette: dither is null.");
status = SIXEL_BAD_ARGUMENT;
goto end;
}
sixel_dither_ref(dither);
bufsize = (size_t)(width * height) * sizeof(sixel_index_t);
dest = (sixel_index_t *)sixel_allocator_malloc(dither->allocator, bufsize);
if (dest == NULL) {
sixel_helper_set_additional_message(
"sixel_dither_new: sixel_allocator_malloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
/* if quality_mode is full, do not use palette caching */
if (dither->quality_mode == SIXEL_QUALITY_FULL) {
dither->optimized = 0;
}
if (dither->cachetable == NULL && dither->optimized) {
if (dither->palette != pal_mono_dark && dither->palette != pal_mono_light) {
dither->cachetable = (unsigned short *)sixel_allocator_calloc(dither->allocator,
(size_t)(1 << 3 * 5),
sizeof(unsigned short));
if (dither->cachetable == NULL) {
sixel_helper_set_additional_message(
"sixel_dither_new: sixel_allocator_calloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
}
}
if (dither->pixelformat != SIXEL_PIXELFORMAT_RGB888) {
/* normalize pixelformat */
normalized_pixels
= (unsigned char *)sixel_allocator_malloc(dither->allocator, (size_t)(width * height * 3));
if (normalized_pixels == NULL) {
sixel_helper_set_additional_message(
"sixel_dither_new: sixel_allocator_malloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
status = sixel_helper_normalize_pixelformat(normalized_pixels,
&dither->pixelformat,
pixels, dither->pixelformat,
width, height);
if (SIXEL_FAILED(status)) {
goto end;
}
input_pixels = normalized_pixels;
} else {
input_pixels = pixels;
}
status = sixel_quant_apply_palette(dest,
input_pixels,
width, height, 3,
dither->palette,
dither->ncolors,
dither->method_for_diffuse,
dither->optimized,
dither->optimize_palette,
dither->complexion,
dither->cachetable,
&ncolors,
dither->allocator);
if (SIXEL_FAILED(status)) {
free(dest);
dest = NULL;
goto end;
}
dither->ncolors = ncolors;
end:
free(normalized_pixels);
sixel_dither_unref(dither);
return dest;
}
#if HAVE_TESTS
static int
test1(void)
{
sixel_dither_t *dither = NULL;
int nret = EXIT_FAILURE;
#if HAVE_DIAGNOSTIC_DEPRECATED_DECLARATIONS
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
dither = sixel_dither_create(2);
#if HAVE_DIAGNOSTIC_DEPRECATED_DECLARATIONS
# pragma GCC diagnostic pop
#endif
if (dither == NULL) {
goto error;
}
sixel_dither_ref(dither);
sixel_dither_unref(dither);
nret = EXIT_SUCCESS;
error:
sixel_dither_unref(dither);
return nret;
}
static int
test2(void)
{
sixel_dither_t *dither = NULL;
int colors;
int nret = EXIT_FAILURE;
#if HAVE_DIAGNOSTIC_DEPRECATED_DECLARATIONS
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
dither = sixel_dither_create(INT_MAX);
#if HAVE_DIAGNOSTIC_DEPRECATED_DECLARATIONS
# pragma GCC diagnostic pop
#endif
if (dither == NULL) {
goto error;
}
sixel_dither_set_body_only(dither, 1);
colors = sixel_dither_get_num_of_histogram_colors(dither);
if (colors != -1) {
goto error;
}
nret = EXIT_SUCCESS;
error:
sixel_dither_unref(dither);
return nret;
}
SIXELAPI int
sixel_dither_tests_main(void)
{
int nret = EXIT_FAILURE;
size_t i;
typedef int (* testcase)(void);
static testcase const testcases[] = {
test1,
test2,
};
for (i = 0; i < sizeof(testcases) / sizeof(testcase); ++i) {
nret = testcases[i]();
if (nret != EXIT_SUCCESS) {
goto error;
}
}
nret = EXIT_SUCCESS;
error:
return nret;
}
#endif /* HAVE_TESTS */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+78
View File
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2014-2016 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBSIXEL_DITHER_H
#define LIBSIXEL_DITHER_H
#include <sixel.h>
/* dither context object */
struct sixel_dither {
unsigned int ref; /* reference counter */
unsigned char *palette; /* palette definition */
unsigned short *cachetable; /* cache table */
int reqcolors; /* requested colors */
int ncolors; /* active colors */
int origcolors; /* original colors */
int optimized; /* pixel is 15bpp compressable */
int optimize_palette; /* minimize palette size */
int complexion; /* for complexion correction */
int bodyonly; /* do not output palette section if true */
int method_for_largest; /* method for finding the largest dimention
for splitting */
int method_for_rep; /* method for choosing a color from the box */
int method_for_diffuse; /* method for diffusing */
int quality_mode; /* quality of histogram */
int keycolor; /* background color */
int pixelformat; /* pixelformat for internal processing */
sixel_allocator_t *allocator; /* allocator */
};
#ifdef __cplusplus
extern "C" {
#endif
/* apply palette */
sixel_index_t *
sixel_dither_apply_palette(struct sixel_dither /* in */ *dither,
unsigned char /* in */ *pixels,
int /* in */ width,
int /* in */ height);
#if HAVE_TESTS
int
sixel_frame_tests_main(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* LIBSIXEL_DITHER_H */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2014-2016 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MALLOC_STUB_H
#define MALLOC_STUB_H
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#if !HAVE_MALLOC
void * rpl_malloc(size_t n);
#endif /* !HAVE_MALLOC */
#if !HAVE_REALLOC
void * rpl_realloc(void *p, size_t n);
#endif /* !HAVE_REALLOC */
#if 0
int rpl_posix_memalign(void **memptr, size_t alignment, size_t size);
#endif
#endif /* MALLOC_STUB_H */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+210
View File
@@ -0,0 +1,210 @@
/*
* Copyright (c) 2014-2019 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
/* STDC_HEADERS */
# include <stdio.h>
# include <stdlib.h>
#if HAVE_ASSERT_H
# include <assert.h>
#endif /* HAVE_ASSERT_H */
#include <sixel.h>
#include "output.h"
/* create new output context object */
SIXELAPI SIXELSTATUS
sixel_output_new(
sixel_output_t /* out */ **output,
sixel_write_function /* in */ fn_write,
void /* in */ *priv,
sixel_allocator_t /* in */ *allocator)
{
SIXELSTATUS status = SIXEL_FALSE;
size_t size;
if (allocator == NULL) {
status = sixel_allocator_new(&allocator, NULL, NULL, NULL, NULL);
if (SIXEL_FAILED(status)) {
goto end;
}
} else {
sixel_allocator_ref(allocator);
}
size = sizeof(sixel_output_t) + SIXEL_OUTPUT_PACKET_SIZE * 2;
*output = (sixel_output_t *)sixel_allocator_malloc(allocator, size);
if (*output == NULL) {
sixel_helper_set_additional_message(
"sixel_output_new: sixel_allocator_malloc() failed.");
status = SIXEL_BAD_ALLOCATION;
goto end;
}
(*output)->ref = 1;
(*output)->has_8bit_control = 0;
(*output)->has_sdm_glitch = 0;
(*output)->has_gri_arg_limit = 1;
(*output)->skip_dcs_envelope = 0;
(*output)->palette_type = SIXEL_PALETTETYPE_AUTO;
(*output)->fn_write = fn_write;
(*output)->save_pixel = 0;
(*output)->save_count = 0;
(*output)->active_palette = (-1);
(*output)->node_top = NULL;
(*output)->node_free = NULL;
(*output)->priv = priv;
(*output)->pos = 0;
(*output)->penetrate_multiplexer = 0;
(*output)->encode_policy = SIXEL_ENCODEPOLICY_AUTO;
(*output)->allocator = allocator;
status = SIXEL_OK;
end:
return status;
}
/* deprecated: create an output object */
SIXELAPI sixel_output_t *
sixel_output_create(sixel_write_function fn_write, void *priv)
{
SIXELSTATUS status = SIXEL_FALSE;
sixel_output_t *output = NULL;
status = sixel_output_new(&output, fn_write, priv, NULL);
if (SIXEL_FAILED(status)) {
goto end;
}
end:
return output;
}
/* destroy output context object */
SIXELAPI void
sixel_output_destroy(sixel_output_t *output)
{
sixel_allocator_t *allocator;
if (output) {
allocator = output->allocator;
sixel_allocator_free(allocator, output);
sixel_allocator_unref(allocator);
}
}
/* increase reference count of output context object (thread-unsafe) */
SIXELAPI void
sixel_output_ref(sixel_output_t *output)
{
/* TODO: be thread-safe */
++output->ref;
}
/* decrease reference count of output context object (thread-unsafe) */
SIXELAPI void
sixel_output_unref(sixel_output_t *output)
{
/* TODO: be thread-safe */
if (output) {
assert(output->ref > 0);
output->ref--;
if (output->ref == 0) {
sixel_output_destroy(output);
}
}
}
/* get 8bit output mode which indicates whether it uses C1 control characters */
SIXELAPI int
sixel_output_get_8bit_availability(sixel_output_t *output)
{
return output->has_8bit_control;
}
/* set 8bit output mode state */
SIXELAPI void
sixel_output_set_8bit_availability(sixel_output_t *output, int availability)
{
output->has_8bit_control = availability;
}
/* set whether limit arguments of DECGRI('!') to 255 */
SIXELAPI void
sixel_output_set_gri_arg_limit(
sixel_output_t /* in */ *output, /* output context */
int /* in */ value) /* 0: don't limit arguments of DECGRI
1: limit arguments of DECGRI to 255 */
{
output->has_gri_arg_limit = value;
}
/* set GNU Screen penetration feature enable or disable */
SIXELAPI void
sixel_output_set_penetrate_multiplexer(sixel_output_t *output, int penetrate)
{
output->penetrate_multiplexer = penetrate;
}
/* set whether we skip DCS envelope */
SIXELAPI void
sixel_output_set_skip_dcs_envelope(sixel_output_t *output, int skip)
{
output->skip_dcs_envelope = skip;
}
/* set palette type: RGB or HLS */
SIXELAPI void
sixel_output_set_palette_type(sixel_output_t *output, int palettetype)
{
output->palette_type = palettetype;
}
/* set encodeing policy: auto, fast or size */
SIXELAPI void
sixel_output_set_encode_policy(sixel_output_t *output, int encode_policy)
{
output->encode_policy = encode_policy;
}
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+91
View File
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2014-2016 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBSIXEL_OUTPUT_H
#define LIBSIXEL_OUTPUT_H
typedef struct sixel_node {
struct sixel_node *next;
int pal;
int sx;
int mx;
char *map;
} sixel_node_t;
struct sixel_output {
int ref;
sixel_allocator_t *allocator;
/* compatiblity flags */
/* 0: 7bit terminal,
* 1: 8bit terminal */
unsigned char has_8bit_control;
/* 0: the terminal has sixel scrolling
* 1: the terminal does not have sixel scrolling */
unsigned char has_sixel_scrolling;
/* 1: the argument of repeat introducer(DECGRI) is not limitted
0: the argument of repeat introducer(DECGRI) is limitted 255 */
unsigned char has_gri_arg_limit;
/* 0: DECSDM set (CSI ? 80 h) enables sixel scrolling
1: DECSDM set (CSI ? 80 h) disables sixel scrolling */
unsigned char has_sdm_glitch;
/* 0: do not skip DCS envelope
* 1: skip DCS envelope */
unsigned char skip_dcs_envelope;
/* PALETTETYPE_AUTO: select palette type automatically
* PALETTETYPE_HLS : HLS color space
* PALETTETYPE_RGB : RGB color space */
unsigned char palette_type;
sixel_write_function fn_write;
int save_pixel;
int save_count;
int active_palette;
sixel_node_t *node_top;
sixel_node_t *node_free;
int penetrate_multiplexer;
int encode_policy;
void *priv;
int pos;
unsigned char buffer[1];
};
#endif /* LIBSIXEL_OUTPUT_H */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+725
View File
@@ -0,0 +1,725 @@
/*
* Copyright (c) 2014-2019 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
/* STDC_HEADERS */
#include <stdio.h>
#include <stdlib.h>
#if HAVE_MEMORY_H
# include <memory.h>
#endif /* HAVE_MEMORY_H */
#include <sixel.h>
static void
get_rgb(unsigned char const *data,
int const pixelformat,
int depth,
unsigned char *r,
unsigned char *g,
unsigned char *b)
{
unsigned int pixels = 0;
#if SWAP_BYTES
unsigned int low;
unsigned int high;
#endif
int count = 0;
while (count < depth) {
pixels = *(data + count) | (pixels << 8);
count++;
}
/* TODO: we should swap bytes (only necessary on LSByte first hardware?) */
#if SWAP_BYTES
if (depth == 2) {
low = pixels & 0xff;
high = (pixels >> 8) & 0xff;
pixels = (low << 8) | high;
}
#endif
switch (pixelformat) {
case SIXEL_PIXELFORMAT_RGB555:
*r = ((pixels >> 10) & 0x1f) << 3;
*g = ((pixels >> 5) & 0x1f) << 3;
*b = ((pixels >> 0) & 0x1f) << 3;
break;
case SIXEL_PIXELFORMAT_RGB565:
*r = ((pixels >> 11) & 0x1f) << 3;
*g = ((pixels >> 5) & 0x3f) << 2;
*b = ((pixels >> 0) & 0x1f) << 3;
break;
case SIXEL_PIXELFORMAT_RGB888:
*r = (pixels >> 16) & 0xff;
*g = (pixels >> 8) & 0xff;
*b = (pixels >> 0) & 0xff;
break;
case SIXEL_PIXELFORMAT_BGR555:
*r = ((pixels >> 0) & 0x1f) << 3;
*g = ((pixels >> 5) & 0x1f) << 3;
*b = ((pixels >> 10) & 0x1f) << 3;
break;
case SIXEL_PIXELFORMAT_BGR565:
*r = ((pixels >> 0) & 0x1f) << 3;
*g = ((pixels >> 5) & 0x3f) << 2;
*b = ((pixels >> 11) & 0x1f) << 3;
break;
case SIXEL_PIXELFORMAT_BGR888:
*r = (pixels >> 0) & 0xff;
*g = (pixels >> 8) & 0xff;
*b = (pixels >> 16) & 0xff;
break;
case SIXEL_PIXELFORMAT_RGBA8888:
*r = (pixels >> 24) & 0xff;
*g = (pixels >> 16) & 0xff;
*b = (pixels >> 8) & 0xff;
break;
case SIXEL_PIXELFORMAT_ARGB8888:
*r = (pixels >> 16) & 0xff;
*g = (pixels >> 8) & 0xff;
*b = (pixels >> 0) & 0xff;
break;
case SIXEL_PIXELFORMAT_BGRA8888:
*r = (pixels >> 8) & 0xff;
*g = (pixels >> 16) & 0xff;
*b = (pixels >> 24) & 0xff;
break;
case SIXEL_PIXELFORMAT_ABGR8888:
*r = (pixels >> 0) & 0xff;
*g = (pixels >> 8) & 0xff;
*b = (pixels >> 16) & 0xff;
break;
case SIXEL_PIXELFORMAT_GA88:
*r = *g = *b = (pixels >> 8) & 0xff;
break;
case SIXEL_PIXELFORMAT_G8:
case SIXEL_PIXELFORMAT_AG88:
*r = *g = *b = pixels & 0xff;
break;
default:
*r = *g = *b = 0;
break;
}
}
SIXELAPI int
sixel_helper_compute_depth(int pixelformat)
{
int depth = (-1); /* unknown */
switch (pixelformat) {
case SIXEL_PIXELFORMAT_ARGB8888:
case SIXEL_PIXELFORMAT_RGBA8888:
case SIXEL_PIXELFORMAT_ABGR8888:
case SIXEL_PIXELFORMAT_BGRA8888:
depth = 4;
break;
case SIXEL_PIXELFORMAT_RGB888:
case SIXEL_PIXELFORMAT_BGR888:
depth = 3;
break;
case SIXEL_PIXELFORMAT_RGB555:
case SIXEL_PIXELFORMAT_RGB565:
case SIXEL_PIXELFORMAT_BGR555:
case SIXEL_PIXELFORMAT_BGR565:
case SIXEL_PIXELFORMAT_AG88:
case SIXEL_PIXELFORMAT_GA88:
depth = 2;
break;
case SIXEL_PIXELFORMAT_G1:
case SIXEL_PIXELFORMAT_G2:
case SIXEL_PIXELFORMAT_G4:
case SIXEL_PIXELFORMAT_G8:
case SIXEL_PIXELFORMAT_PAL1:
case SIXEL_PIXELFORMAT_PAL2:
case SIXEL_PIXELFORMAT_PAL4:
case SIXEL_PIXELFORMAT_PAL8:
depth = 1;
break;
default:
break;
}
return depth;
}
static void
expand_rgb(unsigned char *dst,
unsigned char const *src,
int width, int height,
int pixelformat, int depth)
{
int x;
int y;
int dst_offset;
int src_offset;
unsigned char r, g, b;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
src_offset = depth * (y * width + x);
dst_offset = 3 * (y * width + x);
get_rgb(src + src_offset, pixelformat, depth, &r, &g, &b);
*(dst + dst_offset + 0) = r;
*(dst + dst_offset + 1) = g;
*(dst + dst_offset + 2) = b;
}
}
}
static SIXELSTATUS
expand_palette(unsigned char *dst, unsigned char const *src,
int width, int height, int const pixelformat)
{
SIXELSTATUS status = SIXEL_FALSE;
int x;
int y;
int i;
int bpp; /* bit per plane */
switch (pixelformat) {
case SIXEL_PIXELFORMAT_PAL1:
case SIXEL_PIXELFORMAT_G1:
bpp = 1;
break;
case SIXEL_PIXELFORMAT_PAL2:
case SIXEL_PIXELFORMAT_G2:
bpp = 2;
break;
case SIXEL_PIXELFORMAT_PAL4:
case SIXEL_PIXELFORMAT_G4:
bpp = 4;
break;
case SIXEL_PIXELFORMAT_PAL8:
case SIXEL_PIXELFORMAT_G8:
for (i = 0; i < width * height; ++i, ++src) {
*dst++ = *src;
}
status = SIXEL_OK;
goto end;
default:
status = SIXEL_BAD_ARGUMENT;
sixel_helper_set_additional_message(
"expand_palette: invalid pixelformat.");
goto end;
}
#if HAVE_DEBUG
fprintf(stderr, "expanding PAL%d to PAL8...\n", bpp);
#endif
for (y = 0; y < height; ++y) {
for (x = 0; x < width * bpp / 8; ++x) {
for (i = 0; i < 8 / bpp; ++i) {
*dst++ = *src >> (8 / bpp - 1 - i) * bpp & ((1 << bpp) - 1);
}
src++;
}
x = width - x * 8 / bpp;
if (x > 0) {
for (i = 0; i < x; ++i) {
*dst++ = *src >> (8 - (i + 1) * bpp) & ((1 << bpp) - 1);
}
src++;
}
}
status = SIXEL_OK;
end:
return status;
}
SIXELAPI SIXELSTATUS
sixel_helper_normalize_pixelformat(
unsigned char /* out */ *dst, /* destination buffer */
int /* out */ *dst_pixelformat, /* converted pixelformat */
unsigned char const /* in */ *src, /* source pixels */
int /* in */ src_pixelformat, /* format of source image */
int /* in */ width, /* width of source image */
int /* in */ height) /* height of source image */
{
SIXELSTATUS status = SIXEL_FALSE;
switch (src_pixelformat) {
case SIXEL_PIXELFORMAT_G8:
expand_rgb(dst, src, width, height, src_pixelformat, 1);
*dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
break;
case SIXEL_PIXELFORMAT_RGB565:
case SIXEL_PIXELFORMAT_RGB555:
case SIXEL_PIXELFORMAT_BGR565:
case SIXEL_PIXELFORMAT_BGR555:
case SIXEL_PIXELFORMAT_GA88:
case SIXEL_PIXELFORMAT_AG88:
expand_rgb(dst, src, width, height, src_pixelformat, 2);
*dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
break;
case SIXEL_PIXELFORMAT_RGB888:
case SIXEL_PIXELFORMAT_BGR888:
expand_rgb(dst, src, width, height, src_pixelformat, 3);
*dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
break;
case SIXEL_PIXELFORMAT_RGBA8888:
case SIXEL_PIXELFORMAT_ARGB8888:
case SIXEL_PIXELFORMAT_BGRA8888:
case SIXEL_PIXELFORMAT_ABGR8888:
expand_rgb(dst, src, width, height, src_pixelformat, 4);
*dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
break;
case SIXEL_PIXELFORMAT_PAL1:
case SIXEL_PIXELFORMAT_PAL2:
case SIXEL_PIXELFORMAT_PAL4:
*dst_pixelformat = SIXEL_PIXELFORMAT_PAL8;
status = expand_palette(dst, src, width, height, src_pixelformat);
if (SIXEL_FAILED(status)) {
goto end;
}
break;
case SIXEL_PIXELFORMAT_G1:
case SIXEL_PIXELFORMAT_G2:
case SIXEL_PIXELFORMAT_G4:
*dst_pixelformat = SIXEL_PIXELFORMAT_G8;
status = expand_palette(dst, src, width, height, src_pixelformat);
if (SIXEL_FAILED(status)) {
goto end;
}
break;
case SIXEL_PIXELFORMAT_PAL8:
memcpy(dst, src, (size_t)(width * height));
*dst_pixelformat = src_pixelformat;
break;
default:
status = SIXEL_BAD_ARGUMENT;
goto end;
}
status = SIXEL_OK;
end:
return status;
}
#if HAVE_TESTS
static int
test1(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_RGB888;
unsigned char src[] = { 0x46, 0xf3, 0xe5 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if ((dst[0] << 16 | dst[1] << 8 | dst[2]) != (src[0] << 16 | src[1] << 8 | src[2])) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test1");
return nret;
}
static int
test2(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_RGB555;
unsigned char src[] = { 0x47, 0x9c };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if ((dst[0] >> 3 << 10 | dst[1] >> 3 << 5 | dst[2] >> 3) != (src[0] << 8 | src[1])) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test2");
return nret;
}
static int
test3(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_RGB565;
unsigned char src[] = { 0x47, 0x9c };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if ((dst[0] >> 3 << 11 | dst[1] >> 2 << 5 | dst[2] >> 3) != (src[0] << 8 | src[1])) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test3");
return nret;
}
static int
test4(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_BGR888;
unsigned char src[] = { 0x46, 0xf3, 0xe5 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if ((dst[2] << 16 | dst[1] << 8 | dst[0]) != (src[0] << 16 | src[1] << 8 | src[2])) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test4");
return nret;
}
static int
test5(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_BGR555;
unsigned char src[] = { 0x23, 0xc8 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if ((dst[2] >> 3 << 10 | dst[1] >> 3 << 5 | dst[0] >> 3) != (src[0] << 8 | src[1])) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test5");
return nret;
}
static int
test6(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_BGR565;
unsigned char src[] = { 0x47, 0x88 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if ((dst[2] >> 3 << 11 | dst[1] >> 2 << 5 | dst[0] >> 3) != (src[0] << 8 | src[1])) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test6");
return nret;
}
static int
test7(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_AG88;
unsigned char src[] = { 0x47, 0x88 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if (dst[0] != src[1]) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test7");
return nret;
}
static int
test8(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_GA88;
unsigned char src[] = { 0x47, 0x88 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if (dst[0] != src[0]) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test8");
return nret;
}
static int
test9(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_RGBA8888;
unsigned char src[] = { 0x46, 0xf3, 0xe5, 0xf0 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if (dst[0] != src[0]) {
goto error;
}
if (dst[1] != src[1]) {
goto error;
}
if (dst[2] != src[2]) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test8");
return nret;
}
static int
test10(void)
{
unsigned char dst[3];
int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
int src_pixelformat = SIXEL_PIXELFORMAT_ARGB8888;
unsigned char src[] = { 0x46, 0xf3, 0xe5, 0xf0 };
int ret = 0;
int nret = EXIT_FAILURE;
ret = sixel_helper_normalize_pixelformat(dst,
&dst_pixelformat,
src,
src_pixelformat,
1,
1);
if (ret != 0) {
goto error;
}
if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
goto error;
}
if (dst[0] != src[1]) {
goto error;
}
if (dst[1] != src[2]) {
goto error;
}
if (dst[2] != src[3]) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test8");
return nret;
}
SIXELAPI int
sixel_pixelformat_tests_main(void)
{
int nret = EXIT_FAILURE;
size_t i;
typedef int (* testcase)(void);
static testcase const testcases[] = {
test1,
test2,
test3,
test4,
test5,
test6,
test7,
test8,
test9,
test10,
};
for (i = 0; i < sizeof(testcases) / sizeof(testcase); ++i) {
nret = testcases[i]();
if (nret != EXIT_SUCCESS) {
goto error;
}
}
nret = EXIT_SUCCESS;
error:
return nret;
}
#endif /* HAVE_TESTS */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+1549
View File
File diff suppressed because it is too large Load Diff
+90
View File
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2014-2016 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBSIXEL_QUANT_H
#define LIBSIXEL_QUANT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sixel.h>
/* choose colors using median-cut method */
SIXELSTATUS
sixel_quant_make_palette(
unsigned char /* out */ **result,
unsigned const char /* in */ *data, /* data for sampling */
unsigned int /* in */ length, /* data size */
int /* in */ pixelformat,
unsigned int /* in */ reqcolors,
unsigned int /* in */ *ncolors,
unsigned int /* in */ *origcolors,
int /* in */ methodForLargest,
int /* in */ methodForRep,
int /* in */ qualityMode,
sixel_allocator_t /* in */ *allocator);
/* apply color palette into specified pixel buffers */
SIXELSTATUS
sixel_quant_apply_palette(
sixel_index_t /* out */ *result,
unsigned char /* in */ *data,
int /* in */ width,
int /* in */ height,
int /* in */ pixelformat,
unsigned char /* in */ *palette,
int /* in */ reqcolor,
int const /* in */ methodForDiffuse,
int /* in */ foptimize,
int /* in */ foptimize_palette,
int /* in */ complexion,
unsigned short /* in */ *cachetable,
int /* in */ *ncolor,
sixel_allocator_t /* in */ *allocator);
/* deallocate specified palette */
void
sixel_quant_free_palette(
unsigned char /* in */ *data,
sixel_allocator_t /* in */ *allocator);
#if HAVE_TESTS
int
sixel_quant_tests_main(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* LIBSIXEL_QUANT_H */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+6
View File
@@ -0,0 +1,6 @@
{
"home": "https://github.com/saitoha/libsixel",
"license": "MIT ( embed in source )",
"version": "1.8.7-r2",
"author": "Hayaki Saito"
}
+1173
View File
File diff suppressed because it is too large Load Diff
+355
View File
@@ -0,0 +1,355 @@
/*
* Copyright (c) 2014-2018 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
/* STDC_HEADERS */
#include <stdio.h>
#include <stdlib.h>
#if HAVE_MEMORY_H
# include <memory.h>
#endif /* HAVE_MEMORY_H */
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_ERRNO_H
# include <errno.h>
#endif /* HAVE_ERRNO_H */
#ifdef HAVE_LIBCURL
# include <curl/curl.h>
#endif /* HAVE_LIBCURL */
#include <sixel.h>
#include "status.h"
#define SIXEL_MESSAGE_OK ("succeeded")
#define SIXEL_MESSAGE_FALSE ("unexpected error (SIXEL_FALSE)");
#define SIXEL_MESSAGE_UNEXPECTED ("unexpected error")
#define SIXEL_MESSAGE_INTERRUPTED ("interrupted by a signal")
#define SIXEL_MESSAGE_BAD_ALLOCATION ("runtime error: bad allocation error")
#define SIXEL_MESSAGE_BAD_ARGUMENT ("runtime error: bad argument detected")
#define SIXEL_MESSAGE_BAD_INPUT ("runtime error: bad input detected")
#define SIXEL_MESSAGE_BAD_INTEGER_OVERFLOW ("runtime error: integer overflow")
#define SIXEL_MESSAGE_RUNTIME_ERROR ("runtime error")
#define SIXEL_MESSAGE_LOGIC_ERROR ("logic error")
#define SIXEL_MESSAGE_NOT_IMPLEMENTED ("feature error: not implemented")
#define SIXEL_MESSAGE_FEATURE_ERROR ("feature error")
#define SIXEL_MESSAGE_STBI_ERROR ("stb_image error")
#define SIXEL_MESSAGE_STBIW_ERROR ("stb_image_write error")
#define SIXEL_MESSAGE_JPEG_ERROR ("libjpeg error")
#define SIXEL_MESSAGE_PNG_ERROR ("libpng error")
#define SIXEL_MESSAGE_GDK_ERROR ("GDK error")
#define SIXEL_MESSAGE_GD_ERROR ("GD error")
static char g_buffer[1024] = { 0x0 };
/* set detailed error message (thread-unsafe) */
SIXELAPI void
sixel_helper_set_additional_message(
const char /* in */ *message /* error message */
)
{
size_t len;
if (message == 0)
return;
len = strlen(message);
memcpy(g_buffer, message, len < sizeof(g_buffer) ? len: sizeof(g_buffer) - 1);
g_buffer[sizeof(g_buffer) - 1] = 0;
}
/* get detailed error message (thread-unsafe) */
SIXELAPI char const *
sixel_helper_get_additional_message(void)
{
return g_buffer;
}
/* convert error status code int formatted string */
SIXELAPI char const *
sixel_helper_format_error(
SIXELSTATUS /* in */ status /* status code */
)
{
static char buffer[1024];
char const *error_string;
char *p;
size_t len;
switch (status & 0x1000) {
case SIXEL_OK:
switch (status) {
case SIXEL_INTERRUPTED:
error_string = SIXEL_MESSAGE_INTERRUPTED;
break;
case SIXEL_OK:
default:
error_string = SIXEL_MESSAGE_OK;
break;
}
break;
case SIXEL_FALSE:
switch (status & 0x1f00) {
case SIXEL_RUNTIME_ERROR:
switch (status) {
case SIXEL_BAD_ALLOCATION:
error_string = SIXEL_MESSAGE_BAD_ALLOCATION;
break;
case SIXEL_BAD_ARGUMENT:
error_string = SIXEL_MESSAGE_BAD_ARGUMENT;
break;
case SIXEL_BAD_INPUT:
error_string = SIXEL_MESSAGE_BAD_INPUT;
break;
case SIXEL_BAD_INTEGER_OVERFLOW:
error_string = SIXEL_MESSAGE_BAD_INTEGER_OVERFLOW;
break;
default:
error_string = SIXEL_MESSAGE_RUNTIME_ERROR;
break;
}
break;
case SIXEL_LOGIC_ERROR:
error_string = SIXEL_MESSAGE_LOGIC_ERROR;
break;
case SIXEL_FEATURE_ERROR:
switch (status) {
case SIXEL_NOT_IMPLEMENTED:
error_string = SIXEL_MESSAGE_NOT_IMPLEMENTED;
break;
default:
error_string = SIXEL_MESSAGE_FEATURE_ERROR;
break;
}
break;
case SIXEL_LIBC_ERROR:
p = strerror(errno);
len = strlen(p) + 1;
memcpy(buffer, p, len < sizeof(buffer) ? len: sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = 0;
error_string = buffer;
break;
#ifdef HAVE_LIBCURL
case SIXEL_CURL_ERROR:
error_string = curl_easy_strerror(status & 0xff);
break;
#endif
#ifdef HAVE_JPEG
case SIXEL_JPEG_ERROR:
error_string = SIXEL_MESSAGE_JPEG_ERROR;
break;
#endif
#ifdef HAVE_LIBPNG
case SIXEL_PNG_ERROR:
error_string = SIXEL_MESSAGE_PNG_ERROR;
break;
#endif
#ifdef HAVE_GDK_PIXBUF2
case SIXEL_GDK_ERROR:
error_string = SIXEL_MESSAGE_GDK_ERROR;
break;
#endif
#ifdef HAVE_GD
case SIXEL_GD_ERROR:
error_string = SIXEL_MESSAGE_GD_ERROR;
break;
#endif
case SIXEL_STBI_ERROR:
error_string = SIXEL_MESSAGE_STBI_ERROR;
break;
case SIXEL_STBIW_ERROR:
error_string = SIXEL_MESSAGE_STBIW_ERROR;
break;
case SIXEL_FALSE:
error_string = SIXEL_MESSAGE_FALSE;
break;
default:
error_string = SIXEL_MESSAGE_UNEXPECTED;
break;
}
break;
default:
error_string = SIXEL_MESSAGE_UNEXPECTED;
break;
}
return error_string;
}
#if HAVE_TESTS
static int
test1(void)
{
int nret = EXIT_FAILURE;
char const *message;
message = sixel_helper_format_error(SIXEL_OK);
if (strcmp(message, SIXEL_MESSAGE_OK) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_INTERRUPTED);
if (strcmp(message, SIXEL_MESSAGE_INTERRUPTED) != 0) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test1");
return nret;
}
static int
test2(void)
{
int nret = EXIT_FAILURE;
char const *message;
message = sixel_helper_format_error(SIXEL_BAD_ALLOCATION);
if (strcmp(message, SIXEL_MESSAGE_BAD_ALLOCATION) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_BAD_ARGUMENT);
if (strcmp(message, SIXEL_MESSAGE_BAD_ARGUMENT) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_BAD_INPUT);
if (strcmp(message, SIXEL_MESSAGE_BAD_INPUT) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_RUNTIME_ERROR);
if (strcmp(message, SIXEL_MESSAGE_RUNTIME_ERROR) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_LOGIC_ERROR);
if (strcmp(message, SIXEL_MESSAGE_LOGIC_ERROR) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_NOT_IMPLEMENTED);
if (strcmp(message, SIXEL_MESSAGE_NOT_IMPLEMENTED) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_FEATURE_ERROR);
if (strcmp(message, SIXEL_MESSAGE_FEATURE_ERROR) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_LIBC_ERROR);
if (strcmp(message, SIXEL_MESSAGE_UNEXPECTED) == 0) {
goto error;
}
#ifdef HAVE_LIBCURL
message = sixel_helper_format_error(SIXEL_CURL_ERROR);
if (strcmp(message, SIXEL_MESSAGE_UNEXPECTED) == 0) {
goto error;
}
#endif
#if HAVE_JPEG
message = sixel_helper_format_error(SIXEL_JPEG_ERROR);
if (strcmp(message, SIXEL_MESSAGE_JPEG_ERROR) != 0) {
goto error;
}
#endif
#if HAVE_LIBPNG
message = sixel_helper_format_error(SIXEL_PNG_ERROR);
if (strcmp(message, SIXEL_MESSAGE_PNG_ERROR) != 0) {
goto error;
}
#endif
#if HAVE_GD
message = sixel_helper_format_error(SIXEL_GD_ERROR);
if (strcmp(message, SIXEL_MESSAGE_GD_ERROR) != 0) {
goto error;
}
#endif
#if HAVE_GDK_PIXBUF2
message = sixel_helper_format_error(SIXEL_GDK_ERROR);
if (strcmp(message, SIXEL_MESSAGE_GDK_ERROR) != 0) {
goto error;
}
#endif
message = sixel_helper_format_error(SIXEL_STBI_ERROR);
if (strcmp(message, SIXEL_MESSAGE_STBI_ERROR) != 0) {
goto error;
}
message = sixel_helper_format_error(SIXEL_STBIW_ERROR);
if (strcmp(message, SIXEL_MESSAGE_STBIW_ERROR) != 0) {
goto error;
}
return EXIT_SUCCESS;
error:
perror("test2");
return nret;
}
SIXELAPI int
sixel_status_tests_main(void)
{
int nret = EXIT_FAILURE;
size_t i;
typedef int (* testcase)(void);
static testcase const testcases[] = {
test1,
test2,
};
for (i = 0; i < sizeof(testcases) / sizeof(testcase); ++i) {
nret = testcases[i]();
if (nret != EXIT_SUCCESS) {
goto error;
}
}
nret = EXIT_SUCCESS;
error:
return nret;
}
#endif /* HAVE_TESTS */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2014-2016 Hayaki Saito
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBSIXEL_STATUS_H
#define LIBSIXEL_STATUS_H
#ifdef __cplusplus
extern "C" {
#endif
#if HAVE_TESTS
int
sixel_status_tests_main(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* LIBSIXEL_STATUS_H */
/* emacs Local Variables: */
/* emacs mode: c */
/* emacs tab-width: 4 */
/* emacs indent-tabs-mode: nil */
/* emacs c-basic-offset: 4 */
/* emacs End: */
/* vim: set expandtab ts=4 sts=4 sw=4 : */
/* EOF */
+1627
View File
File diff suppressed because it is too large Load Diff