1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
|
Table of Contents
=================
* [SAIL Frequently Asked Questions (FAQ)](#sail-frequently-asked-questions-faq)
* [How old is SAIL?](#how-old-is-sail)
* [Is SAIL cross\-platform?](#is-sail-cross-platform)
* [What's the preferred way of installation?](#whats-the-preferred-way-of-installation)
* [Does SAIL support static linking?](#does-sail-support-static-linking)
* [What are the competitors of SAIL?](#what-are-the-competitors-of-sail)
* [Describe the high\-level APIs](#describe-the-high-level-apis)
* [Does SAIL provide simple one\-line APIs?](#does-sail-provide-simple-one-line-apis)
* [In what pixel format do SAIL loading functions output images?](#in-what-pixel-format-do-sail-loading-functions-output-images)
* [What pixel formats can SAIL write?](#what-pixel-formats-can-sail-write)
* [Why does a codec support more pixel formats for writing than sail\_convert can convert to?](#why-does-a-codec-support-more-pixel-formats-for-writing-than-sail_convert-can-convert-to)
* [Does SAIL support animated and multi\-paged images?](#does-sail-support-animated-and-multi-paged-images)
* [Does SAIL support loading from memory?](#does-sail-support-loading-from-memory)
* [How does SAIL support image formats?](#how-does-sail-support-image-formats)
* [Does SAIL preload codecs in the initialization routine?](#does-sail-preload-codecs-in-the-initialization-routine)
* [SAIL\_COMBINE\_CODECS is OFF](#sail_combine_codecs-is-off)
* [SAIL\_COMBINE\_CODECS is ON](#sail_combine_codecs-is-on)
* [How does SAIL look for codecs?](#how-does-sail-look-for-codecs)
* [Conan recipe on any platform](#conan-recipe-on-any-platform)
* [VCPKG port on any platform](#vcpkg-port-on-any-platform)
* [Manually compiled on any platform with SAIL\_COMBINE\_CODECS=ON](#manually-compiled-on-any-platform-with-sail_combine_codecson)
* [Manually compiled on Windows with SAIL\_COMBINE\_CODECS=OFF (the default)](#manually-compiled-on-windows-with-sail_combine_codecsoff-the-default)
* [Manually compiled on Unix (including macOS) SAIL\_COMBINE\_CODECS=OFF (the default)](#manually-compiled-on-unix-including-macos-sail_combine_codecsoff-the-default)
* [How can I point SAIL to my custom codecs?](#how-can-i-point-sail-to-my-custom-codecs)
* [I'd like to reorganize the standard SAIL folder layout on Windows](#id-like-to-reorganize-the-standard-sail-folder-layout-on-windows)
* [Describe the memory management techniques implemented in SAIL](#describe-the-memory-management-techniques-implemented-in-sail)
* [The memory management technique implemented in SAIL](#the-memory-management-technique-implemented-in-sail)
* [Convention to call SAIL functions](#convention-to-call-sail-functions)
* [External pointers stay untouched on error](#external-pointers-stay-untouched-on-error)
* [Always set a pointer to state to NULL (C only)](#always-set-a-pointer-to-state-to-null-c-only)
* [Can I implement an image codec in C\+\+?](#can-i-implement-an-image-codec-in-c)
* [Describe codec info file format](#describe-codec-info-file-format)
* [Can I compile codecs dependencies (like libjpeg) directly into SAIL?](#can-i-compile-codecs-dependencies-like-libjpeg-directly-into-sail)
* [Are there any C/C\+\+ examples?](#are-there-any-cc-examples)
* [Are there any bindings to other programming languages?](#are-there-any-bindings-to-other-programming-languages)
* [How many image formats are you going to implement?](#how-many-image-formats-are-you-going-to-implement)
* [I have problems with include paths with vcpkg without CMake](#i-have-problems-with-include-paths-with-vcpkg-without-cmake)
* [How to embed SAIL as a subproject?](#how-to-embed-sail-as-a-subproject)
* [Does SAIL support big\-endian platforms?](#does-sail-support-big-endian-platforms)
* [I have questions, issues, or proposals](#i-have-questions-issues-or-proposals)
# SAIL Frequently Asked Questions (FAQ)
## How old is SAIL?
SAIL is a rebranded ksquirrel-libs rewritten in C, improved, and enhanced with high-level APIs. Ksquirrel-libs was a set of C++ image codecs
for the KSquirrel image viewer. See [http://ksquirrel.sourceforge.net](http://ksquirrel.sourceforge.net).
Technically, SAIL (ksquirrel-libs) was founded in 2003, making it one of the oldest image decoding libraries.
## Is SAIL cross-platform?
Yes. It's written in pure C11 and is highly portable. However, only Windows, macOS, and Linux platforms
are officially supported. SAIL may or may not compile on other platforms. Pull requests to support additional platforms are highly welcomed.
## What's the preferred way of installation?
- Windows: [Conan](https://conan.io/center/recipes/sail), `vcpkg`
- macOS: [Conan](https://conan.io/center/recipes/sail), `brew`, `vcpkg`
- Linux: native packages if available, [Conan](https://conan.io/center/recipes/sail), `vcpkg`
See [BUILDING](BUILDING.md).
## Does SAIL support static linking?
Yes. Compile with `-DBUILD_SHARED_LIBS=OFF`. This automatically enables `SAIL_COMBINE_CODECS`.
## What are the competitors of SAIL?
- [FreeImage](https://freeimage.sourceforge.io)
- [DevIL](http://openil.sourceforge.net)
- [SDL_Image](https://www.libsdl.org/projects/SDL_image)
- [stb_image](https://github.com/nothings/stb)
- [Boost.GIL](https://www.boost.org/doc/libs/1_68_0/libs/gil/doc/html/index.html)
- [gdk-pixbuf](https://developer.gnome.org/gdk-pixbuf)
- [imlib2](https://docs.enlightenment.org/api/imlib2/html)
- [CImg](https://github.com/dtschump/CImg)
- [WIC (Windows only)](https://docs.microsoft.com/en-us/windows/win32/wic/-wic-about-windows-imaging-codec)
## Describe the high-level APIs
SAIL provides four levels of high-level APIs:
- `Junior`: Simple one-line image loading from file or memory
- `Advanced`: Loading animated/multi-paged images from file or memory
- `Deep diver`: Full control over codec selection, meta data, and loading options
- `Technical diver`: Everything above plus custom I/O sources
## Does SAIL provide simple one-line APIs?
Yes. Use the `junior` API level for simple one-line image loading.
## In what pixel format do SAIL loading functions output images?
SAIL attempts to output a pixel format as close to the source format as possible.
Ideally, it outputs the same pixel format as stored in the image.
For example, SAIL outputs BPP24-BGR images from full-color BMP files without transparency.
Consider using conversion functions from `libsail-manip` for format conversion.
## What pixel formats can SAIL write?
SAIL codecs support as many output pixel formats as possible. SAIL does not convert
pixel formats during save operations. Images are always written as-is.
The list of pixel formats that can be written by SAIL is codec-specific and is publicly available in every
.codec.info file. It can be accessed through `sail_codec_info_from_extension() -> codec_info -> save_features ->
pixel_formats`.
## Why does a codec support more pixel formats for writing than sail_convert can convert to?
SAIL codecs intentionally support more pixel formats for writing than `sail_convert()` can convert to.
This design allows you to write images with pixel formats that come from other sources (like other image
files, cameras, or custom renderers) without losing the original pixel format.
For example, a codec might support writing 32-bit float grayscale images. You can load such an image
from one file and save it to another file preserving the pixel format. However, `sail_convert()` might
not support converting from RGB to this specific format because such conversions are rare and complex.
```
┌─────────────────────────────────────────────────┐
│ Pixel formats a codec can WRITE │
│ (e.g., BPP8, BPP16, BPP24, BPP32-FLOAT, etc.) │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ Pixel formats sail_convert() │ │
│ │ can convert to │ │
│ │ (most common conversions) │ │
│ │ │ │
│ │ [Common conversions like │ │
│ │ RGB → BGR, RGBA → RGB, etc.] │ │
│ └──────────────────────────────────────┘ │
│ │
│ [Exotic formats that can be written as-is │
│ but not converted to: HDR, depth maps, │
│ 32-bit float, uint, etc.] │
└─────────────────────────────────────────────────┘
```
**Workflow example:**
1. Load a TIFF with 32-bit float grayscale (depth map from a camera)
2. Save it to PNG as-is → Not supported, PNG doesn't support this format
3. Save it to OpenEXR as-is → Supported, written without conversion
4. Convert with `sail_convert()` to BPP24-RGB → No such conversion
5. Write your own converter for your specific use case → Then save to any format
This approach provides maximum flexibility while keeping the conversion library focused on
the most common use cases.
## Does SAIL support animated and multi-paged images?
Yes. Continue loading the image file until the loading functions return `SAIL_OK`.
When no more frames are available, the loading functions return `SAIL_ERROR_NO_MORE_FRAMES`.
## Does SAIL support loading from memory?
Yes. SAIL supports loading and saving from files and memory. For technical divers,
custom I/O sources are also supported.
See `sail_start_loading_from_file()`, `sail_start_loading_mem()`, and `sail_start_loading_from_io()`.
## How does SAIL support image formats?
SAIL supports image formats through dynamically loaded codecs. End users never work
with codecs directly; they interact exclusively with the high-level APIs.
## Does SAIL preload codecs in the initialization routine?
### `SAIL_COMBINE_CODECS` is `OFF`
SAIL does not preload codecs in the initialization routine (`sail_init()`). It loads them on demand.
However, you can preload them explicitly with `sail_init_with_flags(SAIL_FLAG_PRELOAD_CODECS)`.
### `SAIL_COMBINE_CODECS` is `ON`
All codecs are loaded on application startup.
## How does SAIL look for codecs?
Codec path search algorithm (first found path wins):
### Conan recipe on any platform
Codecs are combined into a dynamically linked library, so no search is required.
### VCPKG port on any platform
Codecs are combined into a dynamically linked library, so no search is required.
### Manually compiled on any platform with SAIL_COMBINE_CODECS=ON
Codecs are combined into a dynamically linked library, so no search is required.
### Manually compiled on Windows with SAIL_COMBINE_CODECS=OFF (the default)
1. `SAIL_CODECS_PATH` environment variable
2. `<SAIL DEPLOYMENT FOLDER>\lib\sail\codecs`
3. Hardcoded `SAIL_CODECS_PATH` in config.h
### Manually compiled on Unix (including macOS) SAIL_COMBINE_CODECS=OFF (the default)
1. `SAIL_CODECS_PATH` environment variable
2. Hardcoded `SAIL_CODECS_PATH` in config.h
`<FOUND PATH>/lib` is added to `LD_LIBRARY_PATH`.
Additionally, if `SAIL_THIRD_PARTY_CODECS_PATH` is enabled in CMake (the default), the `SAIL_THIRD_PARTY_CODECS_PATH`
environment variable is searched for a list of ';'-separated paths containing third-party codecs.
## How can I point SAIL to my custom codecs?
If `SAIL_THIRD_PARTY_CODECS_PATH` is enabled in CMake (the default), set the `SAIL_THIRD_PARTY_CODECS_PATH` environment variable
to a list of ';'-separated paths containing your custom SAIL codecs.
On Windows, only the `sail.dll` location and `SAIL_THIRD_PARTY_CODECS_PATH/lib` are searched for codec DLL dependencies.
Use the WIN32 API `AddDllDirectory()` to add custom DLL dependency search paths.
On other platforms, `SAIL_THIRD_PARTY_CODECS_PATH/lib` is added to `LD_LIBRARY_PATH`.
If `SAIL_THIRD_PARTY_CODECS_PATH` is `OFF`, custom codec loading is disabled.
## I'd like to reorganize the standard SAIL folder layout on Windows
This is supported. However, with the standard layout, SAIL automatically detects the codec location.
If you reorganize the folder layout, you must specify the new codec location by
setting the `SAIL_CODECS_PATH` environment variable.
## Describe the memory management techniques implemented in SAIL
### The memory management technique implemented in SAIL
Internally, SAIL always cleans up on errors. If you encounter a memory leak on error, please report it.
**C only:** If an error occurs during loading or saving with the `advanced` or deeper API,
the developer must call `sail_stop_loading()` or `sail_stop_saving()` to perform proper cleanup
in the underlying codec. Failure to call these functions will result in memory leaks.
**C++ only:** The C++ binding automatically performs cleanup in `~image_input()` or `~image_output()` destructors.
### Convention to call SAIL functions
Use the `SAIL_TRY()` macro when calling SAIL functions. For cleanup on error,
use the `SAIL_TRY_OR_CLEANUP()` macro.
### External pointers stay untouched on error
External pointers that are allocated or modified by SAIL functions stay untouched on error. For example:
```C
struct sail_image *image = NULL;
SAIL_TRY(sail_alloc_image(&image));
/*
* If sail_alloc_palette_for_data() fails, the palette pointer stays untouched (NULL).
* This code prints NULL value on error.
*/
SAIL_TRY_OR_CLEANUP(sail_alloc_palette_for_data(SAIL_PIXEL_FORMAT_BPP24_RGB, color_count, &image->palette));
/* cleanup */ printf("%p\n", image->palette),
sail_destroy_image(image));
```
Or:
```C
void *state = NULL;
struct sail_image *image = NULL;
SAIL_TRY(sail_start_loading_from_file(..., &state));
/*
* If sail_load_next_frame() fails, the image pointer stays untouched (NULL).
* This code prints NULL value on error.
*/
SAIL_TRY_OR_CLEANUP(sail_load_next_frame(state, &image),
/* cleanup */ printf("%p\n", image),
sail_stop_loading(state));
```
### Always set a pointer to state to NULL (C only)
C loading and saving functions require a local void pointer to state. Always initialize it to NULL before
loading or saving. For example:
```C
void *state = NULL;
SAIL_TRY(sail_start_loading_from_file(..., &state));
SAIL_TRY_OR_CLEANUP(sail_load_next_frame(state, ...),
/* cleanup */ sail_stop_loading(state));
```
## Can I implement an image codec in C++?
Yes. A codec must export a set of public functions for SAIL to recognize and use it.
Theoretically, codecs can be implemented in any programming language that supports C-compatible exports.
## Describe codec info file format
Let's take a hypothetical codec info:
```
# This section describes the codec per se.
#
[codec]
# Codec layout is a set of functions the codec exports. Different layout versions are not compatible.
# libsail supports a single (current) layout version. Cannot be empty.
#
layout=8
# Semantic codec version. Cannot be empty.
#
version=1.0.0
# Codec priority. SAIL uses this property to sort enumerated codecs by priority
# to speed up searches for popular image formats in functions like sail_codec_info_from_path().
#
# HIGHEST = Most popular image formats (e.g., JPEG)
# HIGH = Popular and common image formats (e.g., SVG)
# MEDIUM = Moderately popular formats
# LOW = Rare image formats
# LOWEST = Very rare, highly specific, or ancient image formats
#
priority=MEDIUM
# Short codec name. Must be uppercase letters and numbers only. Cannot be empty.
#
name=ABC
# Codec description. Any human-readable string. Cannot be empty.
#
description=Some ABC Format
# ';'-separated list of hex-encoded magic numbers identifying this image format.
# Can be empty only if the list of file extensions below is not empty.
#
magic-numbers=34 AB
# ';'-separated list of file extensions identifying this image format.
# Can be empty only if the list of magic numbers above is not empty.
#
extensions=abc;bca
# ';'-separated list of MIME types identifying this image format. Can be empty.
#
mime-types=image/abc
# Section of various features describing what the image codec can actually load.
#
[load-features]
# ';'-separated list of features the codec supports for reading.
# Can be empty if the codec cannot load images.
#
# Possible values:
# STATIC - Can load static images.
# ANIMATED - Can load animated images.
# MULTI-PAGED - Can load multi-paged (but not animated) images.
# META-DATA - Can load image metadata (e.g., JPEG comments, EXIF).
# ICCP - Can load embedded ICC profiles.
# SOURCE-IMAGE - Can populate source image information in sail_image.source_image.
#
features=STATIC;META-DATA;INTERLACED;ICCP
# ';'-separated list of codec-specific tuning options. For example,
# disable ABC codec filtering by setting abc-filtering to 0 in load options.
# Tuning option names must start with the codec name to avoid conflicts.
#
# The list of possible values for each tuning option is not available programmatically.
# Each codec must document them in the codec info file.
#
# For example:
# - abc-filtering: Tune filtering. Possible values: 0 (disable), 1 (light), 2 (hard).
#
tuning=abc-filtering
# Section describing features the codec supports for saving.
#
[save-features]
# ';'-separated list of features the codec supports for writing.
# Can be empty if the codec cannot save images.
#
# Possible values:
# STATIC - Can save static images.
# ANIMATED - Can save animated images.
# MULTI-PAGED - Can save multi-paged (but not animated) images.
# META-DATA - Can save image metadata (e.g., JPEG comments, EXIF).
# INTERLACED - Can save interlaced images.
# ICCP - Can save embedded ICC profiles.
#
features=STATIC;META-DATA;INTERLACED;ICCP
# ';'-separated list of codec-specific tuning options. For example,
# disable ABC codec filtering by setting abc-filtering to 0 in save options.
# Tuning option names must start with the codec name to avoid conflicts.
#
# The list of possible values for each tuning option is not available programmatically.
# Each codec must document them in the codec info file.
#
# For example:
# - abc-filtering: Tune filtering. Possible values: 0 (disable), 1 (light), 2 (hard).
#
tuning=abc-filtering
# ';'-separated list of pixel formats the codec can write.
# Can be empty if the codec cannot save images.
#
# Note: SAIL does not convert images during saving. Images are written as-is.
# This example codec accepts and saves 8-bit indexed, 24-bit RGB, and 32-bit RGBA images.
#
pixel-formats=BPP8-INDEXED;BPP24-RGB;BPP32-BGRA
# ';'-separated list of compressions the codec can write. Cannot be empty if the codec
# can save images. If the codec cannot select compressions, specify UNSUPPORTED.
#
compression-types=DEFLATE;RLE
# Default compression to use when no explicit compression is specified
# by the client application. Can be empty if the codec cannot save images.
#
default-compression=DEFLATE
# Minimum compression level. Not used and must be 0 if multiple compressions are supported
# or if the list is empty.
#
# Data type: double. Converted using C function atof().
# Decimal-point character is determined by the current C locale.
#
compression-level-min=1
# Maximum compression level. Not used and must be 0 if multiple compressions are supported
# or if the list is empty.
#
# Data type: double. Converted using C function atof().
# Decimal-point character is determined by the current C locale.
#
compression-level-max=9
# Default compression level to use when no explicit level is specified.
# Not used and must be 0 if multiple compressions are supported or if the list is empty.
# Must be within the min/max range above.
#
# Data type: double. Converted using C function atof().
# Decimal-point character is determined by the current C locale.
#
compression-level-default=6
# Increment/decrement step for compression level. Not used and must be 0 if
# multiple compressions are supported or if the list is empty.
#
# Data type: double. Converted using C function atof().
# Decimal-point character is determined by the current C locale.
#
compression-level-step=1
```
## Can I compile codec dependencies (like libjpeg) directly into SAIL?
Unlike FreeImage, SAIL does not support compiling external dependencies into a single library, and there are no plans to add this feature.
You can achieve this using external build systems like `vcpkg`.
If you prefer compiling SAIL manually as a shared library, compile it against a static vcpkg triplet such as `x64-windows-static`.
For example:
```
# Install vcpkg using the official installation guide into your preferred path.
# For example, into F:/vcpkg.
# Install SAIL in vcpkg just to install all its dependencies
# as static libs. We'll compile SAIL manually later.
cd F:/vcpkg/
vcpkg install sail[all] --triplet x64-windows-static
# Go to the cloned SAIL sources
cd F:/sail/
# Compile SAIL against vcpkg
mkdir build
cd build
cmake -DSAIL_COMBINE_CODECS=ON -DCMAKE_TOOLCHAIN_FILE=F:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static ..
cmake --build . --config Release
```
This way all codecs and their dependencies will be compiled into `sail-codecs.dll`.
## Are there any C/C++ examples?
Yes. See the `examples` directory in the source tree.
## Are there any bindings to other programming languages?
Yes. SAIL currently supports the following language bindings:
1. C++
2. Python
Pull requests to support additional programming languages are highly welcomed.
## How many image formats are you going to implement?
Ksquirrel-libs supported around 60 image formats. Not all of them will be ported. However,
the most popular image formats will be ported from ksquirrel-libs.
## I have problems with include paths with vcpkg without CMake
Add `VcpkgInstalledDir/include/sail` to the project include path.
See https://learn.microsoft.com/en-us/vcpkg/users/buildsystems/msbuild-integration.
## How to embed SAIL as a subproject?
Embedding SAIL is not fully supported. SAIL modifies global CMake variables like `CMAKE_C_FLAGS`,
making embedding not recommended. The recommended approach is to build SAIL separately.
## Does SAIL support big-endian platforms?
No. SAIL currently supports little-endian platforms only.
## I have questions, issues, or proposals
Opening a GitHub [issue](https://github.com/HappySeaFox/sail/issues) is the preferred method
for communication and problem resolution.
Pull requests are always welcome.
|