Metadata-Version: 2.1
Name: jpeglib
Version: 0.4.5
Summary: Low-level loader of JPEG DCT coefficients, based on libjpeg.
Home-page: UNKNOWN
Author: Martin Beneš
Author-email: martinbenes1996@gmail.com
License: MPL
Keywords: dct-coefficients,dct,jpeg,jpg
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Other Audience
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: C
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Topic :: Education
Classifier: Topic :: Multimedia
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Topic :: Scientific/Engineering :: Image Recognition
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Description-Content-Type: text/markdown

# Stegojpeg

A low-level JPEG loader for acquiring DCT coefficients and quantization tables. It uses *libjpeg* for reading of the JPEG format.

## Setup

Package `stegojpeg` is developed for Python3. Install using pip (or pip3) with

```bash
pip3 install stegojpeg
```

For now, `libjpeg` is linked dynamically and hence must be installed manually.
If the pip command fails on *jpeglib.h: No such file or directory*, `libjpeg` is missing.

```bash
apt-get install libjpeg-dev # ubuntu
brew install jpeg # mac
```

<!--For MacOS M1, I had to manually create symlinks of *libjpeg.dylib* in /usr/local/lib and add /opt/homebrew/bin to /etc/paths.-->

## Usage

There is a file `input.jpeg` of dimensions H x W. Get its DCT (*discrete cosine transform*) coefficients and quantization matrices in numpy tensor with

```python
import stegojpeg
im = stegojpeg.JPEG("input.jpeg") # load metadata
Y,CbCr,qt = im.read_dct() # load data
```

We receive three values

* **Luminance DCT coefficients** as numpy array of shape (1,H/8,W/8,8,8)
* **Chrominance DCT coefficients** as numpy array of shape (2,H/8/2,W/8/2,8,8) for subsampling 4:2:2
* **Quantization tables** as numpy array of shape (3,8,8)

DCT coefficients are commonly used to embed a steganographic message to. Once done, create a file with modified DCT with

```python
im.write_dct("output.jpeg", Y, CbCr) # write data
```

Read the spatial representation of `input.jpeg` with

```python
im = stegojpeg.JPEG("input.jpeg")
spatial = im.read_spatial()
```

The reading can be parameterized with spatial color space, dithering mode, dct method and various boolean flags.
For not-specified parameters, default of libjpeg is used. 

```python
spatial = im.read_spatial(
  out_color_space = "JCS_GRAYSCALE", # color space of output
  dither_mode     = "JDITHER_FS",    # dithering mode
  dct_method      = "JDCT_FLOAT",    # dct method
  flags           = ["DO_FANCY_UPSAMPLING", "DO_BLOCK_SMOOTHING"] # flags to be set true
)
```

Writing of a spatial representation is done with

```python
im.write_spatial("output.jpeg", spatial)
```

If you do not specify the second parameter, the original source data is used.

Similarly to reading there are parameters for writing that you can use.
Based on the source of libjpeg default, if not specified.

```python
im.write_spatial(
  "output.jpeg",
  spatial,
  in_color_space   = "JCS_RGB",    # color space of input
  dct_method       = "JDCT_ISLOW", # dct method
  samp_factor      = (2,1,1),      # sampling factor
  quality          = 75,           # compression quality
  smoothing_factor = 0,            # smoothing factor
  flags            = ["QUANTIZE_COLORS","WRITE_JFIF_HEADER"]
)
```



## Dependencies and platforms

Tested on MacOS and Linux. There is a [known bug](https://stackoverflow.com/questions/49299905/error-lnk2001-unresolved-external-symbol-pyinit) which is planned to be fixed in the future.

For the installation you need

* C compiler (gcc, clang)
* [libjpeg](http://libjpeg.sourceforge.net/) + properly configured environment (so compiler & linker can find it)

## Future extensions

* **Static linking of libjpeg** = libjpeg will be distributed with the stegojpeg and linked statically. The arguments pro are
  * Removal of the external dependency.
  * Manual control of the libjpeg version. Ability to select in runtime.

* **Possible to make changes in quantization tables** = for now modifications are only possible on DCT coefficients

* **Independence on source file** = to write matrices you need the object you used for reading, because metadata are copied. I would like this to be independent, so the writing is state-less and the memory can be released

```python
import stegojpeg
with stegojpeg.JPEG("input.jpeg") as im:
    Y,CbCr,qt = im.read_dct() # read DCT

    # modify here
    
    im.write_dct("output.jpeg", Y, CbCr) # write DCT

# load RGB
import numpy as np
from PIL import Image
im1 = np.array(Image.open("input.jpeg")) # original
im2 = np.array(Image.open("output.jpeg")) # modified
```

* **Fix Windows installation** = make sure the library can be installed on Windows

## Credits

Developed by [Martin Benes](https://github.com/martinbenes1996).

