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
//! Rust bindings for TurboJPEG, which provides simple and fast operations for JPEG images:
//!
//! - [Compression][compress()]: encode images into JPEG.
//! - [Decompression][decompress()]: decode JPEGs into pixels.
//! - [Lossless transformations][transform()]: apply basic geometric transformations (rotate, mirror,
//! ...) without going through decompression and compression, so that the image does not lose
//! quality.
//! - [Decompression into YUV][decompress_to_yuv()]: decode JPEG into YUV (YCbCr), without
//! performing the color transform into RGB.
//!
//! # Integration with image-rs (version 0.24)
//! 
//! To easily encode and decode images from the [`image`][image-rs] crate (version 0.24), please
//! enable the optional dependency `"image"` of this crate in your `Cargo.toml`. Then you can use
//! the functions [`decompress_image()`][crate::decompress_image] and
//! [`compress_image()`][crate::compress_image]:
//! 
//! ```
//! # #[cfg(feature = "image")] {
//! // read JPEG data from file
//! let jpeg_data = std::fs::read("examples/parrots.jpg")?;
//!
//! // decompress `jpeg_data` into an `image::RgbImage`
//! let image: image::RgbImage = turbojpeg::decompress_image(&jpeg_data)?;
//!
//! // compress `image` into JPEG with quality 95 and 2x2 chrominance subsampling
//! let jpeg_data = turbojpeg::compress_image(&image, 95, turbojpeg::Subsamp::Sub2x2)?;
//!
//! # }
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
//! 
//! This crate supports these specializations of [`image::ImageBuffer`]:
//! 
//! - [`image::RgbImage`]
//! - [`image::RgbaImage`] (JPEG does not support alpha channel, so alpha is ignored when encoding
//! and set to 255 when decoding)
//! - [`image::GrayImage`]
//! 
//! [image-rs]: https://docs.rs/image/*/image/index.html
//!
//! # The [`Image`] type
//!
//! For more advanced usage of TurboJPEG, you will need to use the [`Image`] type. This is a simple
//! struct that contains the geometry of the image (width, height and pitch/stride), pixel format
//! (such as RGB, ABGR or grayscale) and the pixel data itself.
//!
//! [`Image`] is parameterized by the pixel data container, so you will use `Image<&[u8]>` as input
//! argument for compression, `Image<&out [u8]>` as output argument for decompression, and you may
//! also find `Image<Vec<u8>>` useful as an owned container of image data in you application.
//!
//! # Operations
//!
//! - **Decompress** images from JPEG using [`decompress()`] or [`Decompressor`].
//! - **Compress** images into JPEG using [`compress()`] or [`Compressor`].
//! - **Transform** images without recompression using [`transform()`] or [`Transformer`]. The
//! transformations are described in the [`Transform`] struct.
//! - **Read header** of JPEG image to get its size without decompression using
//! [`Decompressor::read_header()`] or [`read_header()`].
//! - **Decompress** images **into YUV** using [`decompress_to_yuv()`] or [`Decompressor`].
//! - **Compress** images **from YUV** using [`compress_yuv()`] or [`Compressor`].
//! 
//! # The [`OutputBuf`] and [`OwnedBuf`] types
//!
//! During compression, we need to write the produced JPEG data into some memory buffer. You have
//! two options:
//!
//! - Write the data into a mutable slice (`&mut [u8]`) that you already allocated and initialized.
//! This has the disadvantage that you must allocate all memory up front, so you need to make the
//! buffer very large to ensure that it can hold the compressed image even in the worst case, when
//! the compression does not reduce the image size at all. You will also need to initialize the
//! memory to comply with the Rust safety requirements.
//!
//! - Write the data into a memory buffer managed by TurboJPEG. This has the advantage that
//! TurboJPEG can automatically resize the buffer, so we don't have to conservatively allocate and
//! initialize a large chunk of memory, but we can let TurboJPEG grow the buffer as needed. This
//! kind of buffer is exposed as the [`OwnedBuf`].
//!
//! To handle both of these cases, this crate provides the [`OutputBuf`] type, which can hold
//! either a `&mut [u8]` or an `OwnedBuf`.
//!
//! # Features
//!
//! - `image`: enables the optional dependency on the [`image`][image-rs] crate.
//! - `pkg-config`: uses pkg-config to find the `libturbojpeg` library.
//! - `bindgen`: uses [bindgen] to generate the `libturbojpeg` bindings.
//!
//! [bindgen]: https://rust-lang.github.io/rust-bindgen/
#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]

pub extern crate turbojpeg_sys as raw;
pub extern crate libc;
#[cfg(feature = "image")]
pub extern crate image as image;

mod buf;
mod common;
mod compress;
mod decompress;
mod handle;
mod image_internal;
mod transform;
pub use self::buf::{OwnedBuf, OutputBuf};
pub use self::common::{PixelFormat, Subsamp, Colorspace, Result, Error};
pub use self::compress::{Compressor, compress, compress_yuv, compressed_buf_len};
pub use self::decompress::{Decompressor, DecompressHeader, decompress, read_header, decompress_to_yuv, yuv_pixels_len};
pub use self::image_internal::{Image, YuvImage};
pub use self::transform::{Transformer, Transform, TransformOp, TransformCrop, transform};

#[cfg(feature = "image")]
mod image_rs;
#[cfg(feature = "image")]
pub use self::image_rs::{JpegPixel, compress_image, decompress_image};