├── .gitignore ├── .gitlab-ci.yml ├── .readthedocs.yaml ├── LICENSE ├── README.md ├── build.py ├── doc ├── Makefile └── source │ ├── _static │ ├── torchjpeg-logo.png │ └── torchjpeg-logo.xcf │ ├── api │ ├── index.rst │ ├── torchjpeg.codec.rst │ ├── torchjpeg.data.rst │ ├── torchjpeg.dct.rst │ ├── torchjpeg.metrics.rst │ └── torchjpeg.quantization.rst │ ├── conf.py │ ├── dct_and_color.md │ ├── dct_rw.md │ ├── index.md │ ├── metrics_and_losses.md │ └── quantization.md ├── examples ├── color_test.py ├── compress.py ├── decompress.py ├── grayscale.py ├── ident.py └── quantize.py ├── poetry.lock ├── pyproject.toml ├── src ├── libjpeg │ ├── Makefile.am │ ├── Makefile.in │ ├── README │ ├── aclocal.m4 │ ├── ar-lib │ ├── cderror.h │ ├── cdjpeg.c │ ├── cdjpeg.h │ ├── change.log │ ├── cjpeg.1 │ ├── cjpeg.c │ ├── ckconfig.c │ ├── coderules.txt │ ├── compile │ ├── config.guess │ ├── config.sub │ ├── configure │ ├── configure.ac │ ├── depcomp │ ├── djpeg.1 │ ├── djpeg.c │ ├── example.c │ ├── filelist.txt │ ├── install-sh │ ├── install.txt │ ├── jaricom.c │ ├── jcapimin.c │ ├── jcapistd.c │ ├── jcarith.c │ ├── jccoefct.c │ ├── jccolor.c │ ├── jcdctmgr.c │ ├── jchuff.c │ ├── jcinit.c │ ├── jcmainct.c │ ├── jcmarker.c │ ├── jcmaster.c │ ├── jcomapi.c │ ├── jconfig.bcc │ ├── jconfig.cfg │ ├── jconfig.dj │ ├── jconfig.mac │ ├── jconfig.manx │ ├── jconfig.mc6 │ ├── jconfig.sas │ ├── jconfig.st │ ├── jconfig.txt │ ├── jconfig.vc │ ├── jconfig.vms │ ├── jconfig.wat │ ├── jcparam.c │ ├── jcprepct.c │ ├── jcsample.c │ ├── jctrans.c │ ├── jdapimin.c │ ├── jdapistd.c │ ├── jdarith.c │ ├── jdatadst.c │ ├── jdatasrc.c │ ├── jdcoefct.c │ ├── jdcolor.c │ ├── jdct.h │ ├── jddctmgr.c │ ├── jdhuff.c │ ├── jdinput.c │ ├── jdmainct.c │ ├── jdmarker.c │ ├── jdmaster.c │ ├── jdmerge.c │ ├── jdpostct.c │ ├── jdsample.c │ ├── jdtrans.c │ ├── jerror.c │ ├── jerror.h │ ├── jfdctflt.c │ ├── jfdctfst.c │ ├── jfdctint.c │ ├── jidctflt.c │ ├── jidctfst.c │ ├── jidctint.c │ ├── jinclude.h │ ├── jmemansi.c │ ├── jmemdos.c │ ├── jmemdosa.asm │ ├── jmemmac.c │ ├── jmemmgr.c │ ├── jmemname.c │ ├── jmemnobs.c │ ├── jmemsys.h │ ├── jmorecfg.h │ ├── jpegint.h │ ├── jpeglib.h │ ├── jpegtran.1 │ ├── jpegtran.c │ ├── jquant1.c │ ├── jquant2.c │ ├── jutils.c │ ├── jversion.h │ ├── libjpeg.map │ ├── libjpeg.pc.in │ ├── libjpeg.txt │ ├── ltmain.sh │ ├── makcjpeg.st │ ├── makdjpeg.st │ ├── makeadsw.vc6 │ ├── makeasln.v16 │ ├── makecdep.vc6 │ ├── makecdsp.vc6 │ ├── makecfil.v16 │ ├── makecmak.vc6 │ ├── makecvcx.v16 │ ├── makeddep.vc6 │ ├── makeddsp.vc6 │ ├── makedfil.v16 │ ├── makedmak.vc6 │ ├── makedvcx.v16 │ ├── makefile.ansi │ ├── makefile.b32 │ ├── makefile.bcc │ ├── makefile.dj │ ├── makefile.manx │ ├── makefile.mc6 │ ├── makefile.mms │ ├── makefile.sas │ ├── makefile.unix │ ├── makefile.vc │ ├── makefile.vms │ ├── makefile.vs │ ├── makefile.wat │ ├── makejdep.vc6 │ ├── makejdsp.vc6 │ ├── makejdsw.vc6 │ ├── makejfil.v16 │ ├── makejmak.vc6 │ ├── makejsln.v16 │ ├── makejvcx.v16 │ ├── makeproj.mac │ ├── makerdep.vc6 │ ├── makerdsp.vc6 │ ├── makerfil.v16 │ ├── makermak.vc6 │ ├── makervcx.v16 │ ├── maketdep.vc6 │ ├── maketdsp.vc6 │ ├── maketfil.v16 │ ├── maketmak.vc6 │ ├── maketvcx.v16 │ ├── makewdep.vc6 │ ├── makewdsp.vc6 │ ├── makewfil.v16 │ ├── makewmak.vc6 │ ├── makewvcx.v16 │ ├── makljpeg.st │ ├── maktjpeg.st │ ├── makvms.opt │ ├── missing │ ├── rdbmp.c │ ├── rdcolmap.c │ ├── rdgif.c │ ├── rdjpgcom.1 │ ├── rdjpgcom.c │ ├── rdppm.c │ ├── rdrle.c │ ├── rdswitch.c │ ├── rdtarga.c │ ├── structure.txt │ ├── testimg.bmp │ ├── testimg.gif │ ├── testimg.jpg │ ├── testimg.ppm │ ├── testimgp.jpg │ ├── testorig.jpg │ ├── testprog.jpg │ ├── transupp.c │ ├── transupp.h │ ├── usage.txt │ ├── wizard.txt │ ├── wrbmp.c │ ├── wrgif.c │ ├── wrjpgcom.1 │ ├── wrjpgcom.c │ ├── wrppm.c │ ├── wrrle.c │ └── wrtarga.c └── torchjpeg │ ├── __init__.py │ ├── codec │ ├── __init__.py │ └── codec_ops.cpp │ ├── data │ ├── __init__.py │ ├── folder_of_jpeg_dataset.py │ ├── image_list.py │ ├── jpeg_quantized_dataset.py │ ├── transforms │ │ └── __init__.py │ └── unlabeled_image_folder.py │ ├── dct │ ├── __init__.py │ ├── _block.py │ ├── _color.py │ ├── _nn.py │ ├── _stats.py │ └── stats │ │ ├── __init__.py │ │ ├── color.pt │ │ └── grayscale.pt │ ├── metrics │ ├── __init__.py │ ├── _psnr.py │ ├── _psnrb.py │ ├── _size.py │ └── _ssim.py │ └── quantization │ ├── __init__.py │ ├── _quantize.py │ └── ijg.py ├── tasks.py ├── test ├── __init__.py ├── e2e │ └── __init__.py ├── import │ ├── __init__.py │ └── test_import.py └── unit │ ├── __init__.py │ └── test_dct.py └── version.py /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .vscode 3 | build 4 | dist 5 | *.egg-info 6 | __pycache__ 7 | *.so 8 | .mypy_cache 9 | .pytest_cache 10 | .coverage 11 | coverage.xml 12 | src/libjpeg 13 | .python-version -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - dependency cache 3 | - code quality 4 | - test 5 | - build 6 | - deploy 7 | 8 | build-venv: 9 | image: python:$PYVER 10 | stage: dependency cache 11 | variables: 12 | CC: ccache gcc 13 | CCACHE_DIR: $CI_PROJECT_DIR/.ccache 14 | script: 15 | - apt-get update 16 | - apt-get -y install ccache 17 | - ccache -z 18 | - python -m venv --copies .venv 19 | - source .venv/bin/activate 20 | - pip install --upgrade pip 21 | - pip install "poetry==1.5.1" 22 | - poetry install --no-root 23 | - poetry run python build.py 24 | - ccache -s 25 | parallel: 26 | matrix: 27 | - PYVER: ["3.8", "3.9", "3.10", "3.11"] 28 | cache: 29 | key: 30 | files: 31 | - poetry.lock 32 | - src/libjpeg/jversion.h 33 | prefix: ${PYVER} 34 | paths: 35 | - .venv/ 36 | - src/libjpeg 37 | - $CI_PROJECT_DIR/.ccache 38 | rules: 39 | - when: always 40 | 41 | # Code quality 42 | .cq-base: 43 | image: python:3.11 44 | stage: code quality 45 | before_script: 46 | - source .venv/bin/activate 47 | needs: 48 | - build-venv 49 | cache: 50 | key: 51 | files: 52 | - poetry.lock 53 | - src/libjpeg/jversion.h 54 | prefix: "3.11" 55 | paths: 56 | - .venv/ 57 | - src/libjpeg 58 | policy: pull 59 | rules: 60 | - when: always 61 | 62 | lint: 63 | extends: .cq-base 64 | script: 65 | - poetry install 66 | - poetry run pylint torchjpeg 67 | - poetry run pylint test 68 | - poetry run pylint examples 69 | - poetry run pylint ./*.py 70 | 71 | type-check: 72 | extends: .cq-base 73 | script: 74 | - poetry run mypy src/torchjpeg 75 | - poetry run mypy test 76 | - poetry run mypy examples 77 | - poetry run mypy ./*.py 78 | 79 | imports-sorted: 80 | extends: .cq-base 81 | script: 82 | - poetry run isort . --check 83 | 84 | style: 85 | extends: .cq-base 86 | script: 87 | - poetry run black . --check 88 | 89 | dco: 90 | extends: .cq-base 91 | script: 92 | - poetry run invoke dco 93 | 94 | # Tests 95 | test: 96 | image: python:$PYVER 97 | stage: test 98 | parallel: 99 | matrix: 100 | - PYVER: ["3.8", "3.9", "3.10", "3.11"] 101 | before_script: 102 | - source .venv/bin/activate 103 | - poetry install 104 | script: 105 | - poetry run pytest test/import --junitxml=import.xml --cov-report xml 106 | - poetry run pytest test/unit --junitxml=unit.xml --cov-report xml 107 | #- poetry run pytest test/e2e 108 | artifacts: 109 | reports: 110 | coverage_report: 111 | coverage_format: cobertura 112 | path: coverage.xml 113 | junit: 114 | - import.xml 115 | - unit.xml 116 | needs: 117 | - build-venv 118 | cache: 119 | key: 120 | files: 121 | - poetry.lock 122 | - src/libjpeg/jversion.h 123 | prefix: ${PYVER} 124 | paths: 125 | - .venv/ 126 | - src/libjpeg 127 | policy: pull 128 | coverage: '/^TOTAL.+?(\d+\%)$/' 129 | rules: 130 | - when: always 131 | 132 | # Build wheels 133 | build-wheel: 134 | image: quay.io/pypa/manylinux_2_28_x86_64 135 | stage: build 136 | variables: 137 | PYBIN: /opt/python/$PYVER/bin 138 | parallel: 139 | matrix: 140 | - PYVER: [cp38-cp38, cp39-cp39, cp310-cp310, cp311-cp311] 141 | script: 142 | - yum install util-linux 143 | - ${PYBIN}/pip install poetry==1.5.1 144 | - ${PYBIN}/poetry run pip install "dunamai==1.15.0" "torch==2.0.0" 145 | - ${PYBIN}/poetry version $(${PYBIN}/poetry run python version.py) 146 | - ${PYBIN}/poetry build 147 | - rename manylinux_2_28 manylinux2014 dist/* 148 | needs: [] 149 | dependencies: [] 150 | artifacts: 151 | paths: 152 | - dist/ 153 | - pyproject.toml 154 | rules: 155 | - when: always 156 | 157 | # Deploy 158 | pypi: 159 | stage: deploy 160 | image: python:3.11 161 | script: 162 | - pip install "poetry==1.5.1" 163 | - poetry publish --username __token__ --password ${pypi_push_key} 164 | rules: 165 | - if: "$CI_COMMIT_TAG" 166 | when: on_success 167 | - if: "$BUILD_OFFICIAL" 168 | when: on_success 169 | dependencies: 170 | - build-wheel 171 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: ubuntu-22.04 5 | tools: 6 | python: "3.11" 7 | jobs: 8 | post_install: 9 | - pip install poetry 10 | - poetry config virtualenvs.create false 11 | - poetry install --with doc 12 | 13 | sphinx: 14 | configuration: doc/source/conf.py 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Max Ehrlich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TorchJPEG 2 | 3 | [![pipeline status](https://gitlab.com/torchjpeg/torchjpeg/badges/master/pipeline.svg)](https://gitlab.com/torchjpeg/torchjpeg/-/commits/master) 4 | [![coverage report](https://gitlab.com/torchjpeg/torchjpeg/badges/master/coverage.svg)](https://gitlab.com/torchjpeg/torchjpeg/-/commits/master) 5 | [![PyPI](https://img.shields.io/pypi/v/torchjpeg)](https://pypi.org/project/torchjpeg/) 6 | [![License](https://img.shields.io/badge/license-MIT-blue)](https://gitlab.com/Queuecumber/torchjpeg/-/blob/master/LICENSE) 7 | 8 | This package contains a C++ extension for pytorch that interfaces with libjpeg to allow for manipulation of low-level JPEG data. 9 | By using libjpeg, quantization results are guaranteed to be consistent with other applications, like image viewers or MATLAB, 10 | which use libjpeg to compress and decompress images. This is useful because JPEG images can be effected by round-off 11 | errors or slight differences in the decompression procedure. Besides this, this library can be used to read and write 12 | DCT coefficients, functionality which is not available from other python interfaces. 13 | 14 | Besides this, the library includes many utilities related to JPEG compression, many of which are written using native pytorch code meaning 15 | they can be differentiated or GPU accelerated. The library currently includes packages related to the DCT, quantization, metrics, and dataset 16 | transformations. 17 | 18 | ## LIBJPEG 19 | 20 | Currently builds against: `libjpeg-9d`. libjpeg is statically linked during the build process. See [http://www.ijg.org/files/](http://www.ijg.org/files/) for libjpeg source. 21 | The full libjpeg source is included with the torchjpeg source code and will be built during the install process (for a source or sdist install). 22 | 23 | ## Install 24 | 25 | Packages are hosted on [pypi](https://pypi.org/project/torchjpeg/). Install using pip, note that only Linux builds are supported at the moment. 26 | 27 | ``` 28 | pip install torchjpeg 29 | ``` 30 | 31 | If there is demand for builds on other platforms it may happen in the future. Also note that the wheel is intended to be compatible with manylinux2014 32 | which means it should work on modern Linux systems, however, because of they way pytorch works, we can't actually build it using all of the manylinux2014 33 | tools. So compliance is not guaranteed and YMMV. 34 | 35 | ```{warning} 36 | torchjpeg is currently in pre-beta development and consists mostly of converted research code. The public facing API, including any and all names of 37 | parameters and functions, is subject to change at any time. We follow semver for versioning and will adhere to that before making and breaking 38 | changes. 39 | ``` 40 | 41 | ## Citation 42 | 43 | If you use our code in a publication, we ask that you cite the following paper ([bibtex](http://softmax.me/bibtex/ehrlich2020quantization.txt)): 44 | 45 | > Max Ehrlich, Larry Davis, Ser-Nam Lim, and Abhinav Shrivastava. "Quantization Guided JPEG Artifact Correction." In Proceedings of the European Conference on Computer Vision, 2020 -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=missing-function-docstring 2 | import pathlib 3 | from subprocess import check_call 4 | 5 | from torch.utils.cpp_extension import BuildExtension, CppExtension 6 | 7 | 8 | def build_libjpeg(): 9 | check_call("cd src/libjpeg && ./configure --enable-static --with-pic && make", shell=True) 10 | 11 | 12 | def build(setup_kwargs): 13 | build_libjpeg() 14 | 15 | libjpeg_dir = pathlib.Path(__file__).parent.absolute() / "src" / "libjpeg" 16 | 17 | setup_kwargs.update( 18 | { 19 | "ext_modules": [ 20 | CppExtension( 21 | "torchjpeg.codec._codec_ops", 22 | [ 23 | "src/torchjpeg/codec/codec_ops.cpp", 24 | ], 25 | include_dirs=[str(libjpeg_dir)], 26 | extra_objects=[str(libjpeg_dir / ".libs" / "libjpeg.a")], 27 | extra_compile_args=["-std=c++17"], 28 | ) 29 | ], 30 | "cmdclass": {"build_ext": BuildExtension}, 31 | } 32 | ) 33 | 34 | 35 | if __name__ == "__main__": 36 | build_libjpeg() 37 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= poetry run sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /doc/source/_static/torchjpeg-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/doc/source/_static/torchjpeg-logo.png -------------------------------------------------------------------------------- /doc/source/_static/torchjpeg-logo.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/doc/source/_static/torchjpeg-logo.xcf -------------------------------------------------------------------------------- /doc/source/api/index.rst: -------------------------------------------------------------------------------- 1 | torchjpeg 2 | --------- 3 | 4 | .. automodule:: torchjpeg 5 | :members: 6 | :undoc-members: 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | 11 | torchjpeg.codec 12 | torchjpeg.dct 13 | torchjpeg.metrics 14 | torchjpeg.quantization 15 | torchjpeg.data 16 | -------------------------------------------------------------------------------- /doc/source/api/torchjpeg.codec.rst: -------------------------------------------------------------------------------- 1 | torchjpeg.codec 2 | =============== 3 | 4 | Low-level Codec Operations 5 | -------------------------- 6 | 7 | .. automodule:: torchjpeg.codec 8 | :members: 9 | :undoc-members: 10 | -------------------------------------------------------------------------------- /doc/source/api/torchjpeg.data.rst: -------------------------------------------------------------------------------- 1 | torchjpeg.data 2 | ==================== 3 | 4 | Dataset and Data Processing 5 | --------------------------- 6 | 7 | .. automodule:: torchjpeg.data 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | 13 | Transforms 14 | ---------- 15 | 16 | .. automodule:: torchjpeg.data.transforms 17 | :members: 18 | :undoc-members: 19 | :show-inheritance: 20 | -------------------------------------------------------------------------------- /doc/source/api/torchjpeg.dct.rst: -------------------------------------------------------------------------------- 1 | torchjpeg.dct 2 | ============= 3 | 4 | DCT 5 | --- 6 | 7 | .. automodule:: torchjpeg.dct 8 | :members: 9 | :undoc-members: -------------------------------------------------------------------------------- /doc/source/api/torchjpeg.metrics.rst: -------------------------------------------------------------------------------- 1 | torchjpeg.metrics 2 | ================= 3 | 4 | Metrics 5 | ------- 6 | 7 | .. automodule:: torchjpeg.metrics 8 | :members: 9 | :undoc-members: 10 | -------------------------------------------------------------------------------- /doc/source/api/torchjpeg.quantization.rst: -------------------------------------------------------------------------------- 1 | torchjpeg.quantization 2 | ====================== 3 | 4 | General Quantization 5 | -------------------- 6 | 7 | .. automodule:: torchjpeg.quantization 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | IJG (libjpeg) Compatible Quantization 13 | ------------------------------------- 14 | 15 | .. automodule:: torchjpeg.quantization.ijg 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: -------------------------------------------------------------------------------- /doc/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = "torchjpeg" 21 | copyright = "2020, Max Ehrlich" 22 | author = "Max Ehrlich" 23 | 24 | # -- General configuration --------------------------------------------------- 25 | 26 | # Add any Sphinx extension module names here, as strings. They can be 27 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 28 | # ones. 29 | extensions = [ 30 | "sphinx.ext.autodoc", 31 | "sphinx.ext.autosummary", 32 | "sphinx.ext.doctest", 33 | "sphinx.ext.intersphinx", 34 | "sphinx.ext.todo", 35 | "sphinx.ext.napoleon", 36 | "sphinx.ext.viewcode", 37 | "sphinxcontrib.katex", 38 | "sphinx.ext.intersphinx", 39 | "myst_parser", 40 | ] 41 | 42 | intersphinx_mapping = { 43 | "python": ("https://docs.python.org/3", None), 44 | "numpy": ("https://numpy.org/doc/stable", None), 45 | "pytorch": ("https://pytorch.org/docs/stable", None), 46 | } 47 | 48 | # Add any paths that contain templates here, relative to this directory. 49 | templates_path = ["_templates"] 50 | 51 | # List of patterns, relative to source directory, that match files and 52 | # directories to ignore when looking for source files. 53 | # This pattern also affects html_static_path and html_extra_path. 54 | exclude_patterns = [] 55 | 56 | 57 | # -- Options for HTML output ------------------------------------------------- 58 | 59 | # The theme to use for HTML and HTML Help pages. See the documentation for 60 | # a list of builtin themes. 61 | # 62 | html_theme = "sphinx_book_theme" 63 | 64 | html_title = "TorchJPEG" 65 | html_copy_source = True 66 | html_sourcelink_suffix = "" 67 | 68 | html_logo = "_static/torchjpeg-logo.png" 69 | html_favicon = "_static/torchjpeg-logo.png" 70 | html_theme_options = {"repository_url": "https://gitlab.com/torchjpeg/torchjpeg", "use_repository_button": True, "use_issues_button": True, "expand_sections": ["api/index"]} 71 | 72 | # Add any paths that contain custom static files (such as style sheets) here, 73 | # relative to this directory. They are copied after the builtin static files, 74 | # so a file named "default.css" will overwrite the builtin "default.css". 75 | html_static_path = ["_static"] 76 | -------------------------------------------------------------------------------- /doc/source/dct_and_color.md: -------------------------------------------------------------------------------- 1 | # DCT Coefficients and Color Transforms -------------------------------------------------------------------------------- /doc/source/index.md: -------------------------------------------------------------------------------- 1 | ```{include} ../../README.md 2 | ``` 3 | 4 | ## Documentation 5 | 6 | The documentation is split into two parts. In the first part we discuss useful tasks that can be performed with the libjpeg functions. In the second part, we provide a packge reference in the form of generated API documentation. This part is also available as python docstrings. The latest documentation is always available at [https://torchjpeg.readthedocs.io](https://torchjpeg.readthedocs.io). 7 | 8 | ```{toctree} 9 | --- 10 | maxdepth: 1 11 | caption: Common Tasks 12 | --- 13 | dct_rw 14 | metrics_and_losses 15 | quantization 16 | dct_and_color 17 | ``` 18 | 19 | ```{toctree} 20 | --- 21 | maxdepth: 2 22 | caption: Package Reference 23 | --- 24 | api/index 25 | ``` -------------------------------------------------------------------------------- /doc/source/metrics_and_losses.md: -------------------------------------------------------------------------------- 1 | # Metrics and Loss Functions 2 | 3 | The {py:mod}`torchjpeg.metrics` package provides useful metrics for evaluating JPEGs. In general, these metrics are differentiable and can be used as loss functions. Note that {py:func}`torchjpeg.metrics.size` is the only 4 | metric which is not differentiable. It returns the size in bytes of a JPEG compressed image given the image pixels. 5 | 6 | ## JPEG Quality Evaluation 7 | 8 | We provide three metrics for evaluating the visual quality of JPEG images: {py:func}`torchjpeg.metrics.psnr`, {py:func}`torchjpeg.metrics.psnrb`, and {py:func}`torchjpeg.metrics.ssim`. While these metrics are good attempts at 9 | quantifying the visual quality of an image, they are known to be imperfect. However, reporting all three of these metrics consistently is a good way to show that a particular method improves visual quality with respect to another method. 10 | 11 | ```{note} 12 | For a more objective measure of image quality, it may be necessary to carry out a user study or rely on a metric such as the [FID score](https://arxiv.org/abs/1706.08500). 13 | ``` 14 | 15 | PSNR and PSNR-B are both measured in decibels and SSIM is unitless. To compute the quality of a JPEG image, code like the following can be used: 16 | 17 | ```{code-block} python 18 | --- 19 | linenos: yes 20 | emphasize-lines: '10,11,12' 21 | --- 22 | from PIL import Image 23 | from torchvision.transforms.functional import to_tensor 24 | 25 | from torchjpeg.metrics import psnr, psnrb, ssim 26 | 27 | 28 | image = to_tensor(Image.open('input.png')) 29 | jpeg = to_tensor(Image.open('input.jpg')) 30 | 31 | p = psnr(jpeg, image) 32 | b = psnrb(jpeg, image) 33 | s = ssim(jpeg, image) 34 | 35 | print(f'PSNR: {p}db, PSNR-B: {b}db, SSIM: {s}') 36 | ``` 37 | 38 | For PSNR-B, the order of the arguments is extremely important. The JPEG must be passed in the first argument because the blocking-effect-factor is only computed on the degraded image. Passing the arguments 39 | in reverse order will result in a very low BEF and therefore an artificially good score on PSNR-B. We have seen people make this mistake before. The BEF can be computed without PSNR-B using the function {py:func}`torchjpeg.metrics.blocking_effect_factor`. This takes a single image as input, so it is considered an "objective measure of blockiness". 40 | 41 | For SSIM, we have hard coded some JPEG specific settings. These are based on the evaluation procedure of [ARCNN](http://mmlab.ie.cuhk.edu.hk/projects/ARCNN.html) a seminal work in JPEG artifact correction. Instead of 42 | the customary $11 \times 11$ gaussian window, it uses an $8 \times 8$ uniform averaging window. For a general use SSIM library, we recommend [pytorch-msssim](https://github.com/VainF/pytorch-msssim) which includes multi-scale 43 | SSIM. 44 | 45 | ## Loss Functions 46 | 47 | Since the quality metrics are differentiable they can be used as loss functions. There is one major caveat to this: they measure quality so the objective should be maximized and not minimized. 48 | 49 | ```{warning} 50 | In general, we do not recommend using 51 | PSNR as a loss function, since it should be equivalent to minimizing the $l_2$ error of the image. PSNR-B has a similar issue, it may be a better idea to minimize BEF ({py:func}`torchjpeg.metrics.blocking_effect_factor`), the "objective measure of blockiness" used by PNSR-B. 52 | ``` 53 | 54 | For SSIM, there are two ways to construct a loss function: 55 | 56 | ```{code-block} python 57 | --- 58 | linenos: yes 59 | --- 60 | 61 | from torchjpeg.metrics import ssim 62 | 63 | def ssim_loss_a(jpeg, target): 64 | return -ssim(jpeg, target) 65 | 66 | def ssim_loss_b(jpeg, target): 67 | return 1 - ssim(jpeg, target) 68 | ``` 69 | 70 | In other words you can either minimize the negative SSIM or minimize 1 - ssim, since SSIM is in [0, 1]. The first option is slightly simpler while the second is more interpretable, but the result (gradient) should be the same. 71 | 72 | ## Size Metric 73 | 74 | The {py:func}`torchjpeg.metrics.size` metric gives the size in bytes of a JPEG as it would be stored on disk. It takes as input an image, either a PIL image or a pytorch tensor of shape $C \times H \times W$ (pixels in [0, 1]) and 75 | compresses it using PIL. The function also accepts `kwargs` to pass to PIL. You can use these kwargs to pass quality or custom quantization matrices. The return value is a single dimensional tensor containing the size in bytes of the 76 | JPEG as it would be stored on disk, and a tensor containing the decompressed pixels. 77 | 78 | To use the size metric with a quality: 79 | 80 | ```{code-block} python 81 | --- 82 | linenos: yes 83 | emphasize-lines: '9' 84 | --- 85 | from PIL import Image 86 | from torchvision.transforms.functional import to_tensor 87 | 88 | from torchjpeg.metrics import size 89 | 90 | 91 | im = to_tensor(Image.open('input.png')) 92 | 93 | sizes = [size(im, quality=q)[0] for q in range(0, 101)] 94 | print(sizes) 95 | ``` 96 | 97 | This code prints the size of an image for all 101 JPEG quality levels. 98 | 99 | To use the size metric with a quantization matrix, pass two 64 dimensional lists of integers made from flattening the quantization matrices in row-major order: 100 | 101 | ```{code-block} python 102 | --- 103 | linenos: yes 104 | emphasize-lines: '12' 105 | --- 106 | from PIL import Image 107 | from torchvision.transforms.functional import to_tensor 108 | 109 | from torchjpeg.metrics import size 110 | 111 | 112 | im = to_tensor(Image.open('input.png')) 113 | 114 | qm_l = [1] * 64 115 | qm_c = [1] * 64 116 | 117 | size_q100, _ = size(im, qtables=[qm_l, qm_c]) 118 | print(size_q100) 119 | ``` 120 | 121 | Which prints the size of an image at quality 100 using the quanitzation matrix for quality 100 explicitly (all ones). 122 | -------------------------------------------------------------------------------- /doc/source/quantization.md: -------------------------------------------------------------------------------- 1 | # Quantizing DCT Coefficients 2 | 3 | The {py:mod}`torchjpeg.quantization` package provides routines for quantizing DCT coefficients, including performing IJG (libjpeg) compatible quantization by implementing their quality to quantization matrix algorithm. The 4 | functions are entirely written in pytorch and can be differentiated adn GPU accelerated. This is in contrast to the {py:func}`torchjpeg.codec.quantize_at_quality` function which uses the libjpeg C API. Both have advantages and 5 | disadvantages. Here we discuss only {py:mod}`torchjpeg.quantization`. 6 | 7 | ## General Quantization 8 | 9 | The two functions {py:func}`torchjpeg.quantization.quantize_multichannel` and {py:func}`torchjpeg.quantization.dequantize_multichannel` implement the general case quantization. These funcions take a batch of DCT coefficients (shape $N \times 3 \times H \times W$) and quantization matrices of shape $1 \times 2 \times 8 \times 8$ and returns quantized coefficients for each image in the batch. This function also applies chroma subsampling. If chroma subsampling is not desired, then the single channel versions {py:func}`torchjpeg.quantization.quantize` and {py:func}`torchjpeg.quantization.dequantize` can be used instead. 10 | 11 | ```{note} 12 | While the quantization function is fully differentiable, because of the rounding function, the gradient will not be useful. The rounding function can be overridden using the `round_func` parameter to an approximation to true rounding which provides more useful gradient. It defaults to {py:func}`torch.round`. 13 | ``` 14 | 15 | ## IJG Quantization 16 | 17 | For differentiable libjpeg compatible quantization, use the {py:mod}`torchjpeg.quantization.ijg` package. The analog to the previous sections discussion are the functions {py:func}`torchjpeg.quantization.ijg.quantize_at_quality` and{py:func}`torchjpeg.quantization.ijg.dequantize_at_quality`. These functions take a batch of DCT coefficients (of a single channel) and a scalar quality in [0, 100] and quantize and dequantize the coefficients respectively. The parameter `table` allows the selection of either the 'luma' table for y channels or the 'chroma' table for color channels. -------------------------------------------------------------------------------- /examples/color_test.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from PIL import Image 4 | from torchvision.transforms.functional import to_pil_image, to_tensor 5 | 6 | from torchjpeg.dct import to_rgb, to_ycbcr 7 | 8 | parser = argparse.ArgumentParser("Tests the color conversion functions") 9 | parser.add_argument("input", help="Input image, should be lossless") 10 | args = parser.parse_args() 11 | 12 | im = to_tensor(Image.open(args.input)) 13 | 14 | if im.shape[0] > 3: 15 | im = im[:3] 16 | 17 | to_pil_image(to_rgb(to_ycbcr(im, data_range=1.0), data_range=1.0)).save("1_range.png") 18 | to_pil_image(to_rgb(to_ycbcr(im * 255, data_range=255), data_range=255) / 255).save("255_range.png") 19 | to_pil_image(to_rgb(to_ycbcr(im * 255, data_range=255) / 255, data_range=1.0)).save("255_1_range.png") 20 | to_pil_image(to_rgb(to_ycbcr(im, data_range=1.0) * 255, data_range=255) / 255).save("1_255_range.png") 21 | -------------------------------------------------------------------------------- /examples/compress.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from PIL import Image 4 | from torchvision.transforms.functional import to_tensor 5 | 6 | import torchjpeg.codec 7 | 8 | parser = argparse.ArgumentParser("Tests the pytorch DCT loader by reading and image, quantizing its pixels, and writing the DCT coefficients to a JPEG") 9 | parser.add_argument("input", help="Input image, should be lossless") 10 | parser.add_argument("output", help="Output image, must be a JPEG") 11 | parser.add_argument("quality", type=int, help="Output quality on the 0-100 scale") 12 | parser.add_argument("color_samp_factor_vertical", type=int, nargs="?", default=2, help="Vertical chroma subsampling factor. Defaults to 2.") 13 | parser.add_argument("color_samp_factor_horizontal", type=int, nargs="?", default=2, help="Horizontal chroma subsampling factor. Defaults to 2.") 14 | args = parser.parse_args() 15 | 16 | im = to_tensor(Image.open(args.input)) 17 | 18 | if im.shape[0] > 3: 19 | im = im[:3] 20 | 21 | dimensions, quantization, Y_coefficients, CbCr_coefficients = torchjpeg.codec.quantize_at_quality(im, args.quality, args.color_samp_factor_vertical, args.color_samp_factor_horizontal) 22 | torchjpeg.codec.write_coefficients(args.output, dimensions, quantization, Y_coefficients, CbCr_coefficients) 23 | -------------------------------------------------------------------------------- /examples/decompress.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from torchvision.transforms.functional import to_pil_image 4 | 5 | import torchjpeg.codec 6 | 7 | parser = argparse.ArgumentParser("Tests the pytorch DCT loader by using it along with a custom DCT routine to decompress a JPEG") 8 | parser.add_argument("input", help="Input image, must be a JPEG") 9 | parser.add_argument("output", help="Output image, should be lossless for best results") 10 | args = parser.parse_args() 11 | 12 | dimensions, quantization, Y_coefficients, CbCr_coefficients = torchjpeg.codec.read_coefficients(args.input) 13 | spatial = torchjpeg.codec.reconstruct_full_image(Y_coefficients, quantization, CbCr_coefficients, dimensions) 14 | 15 | to_pil_image(spatial).save(args.output) 16 | -------------------------------------------------------------------------------- /examples/grayscale.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import torchjpeg.codec 4 | 5 | parser = argparse.ArgumentParser("Losslessly converts a JPEG to grayscale by dropping the Cb and Cr channels without requantizing") 6 | parser.add_argument("input", help="Input image, must be a JPEG") 7 | parser.add_argument("output", help="Output image, must be a JPEG") 8 | args = parser.parse_args() 9 | 10 | dimensions, quantization, Y_coefficients, CbCr_coefficients = torchjpeg.codec.read_coefficients(args.input) 11 | torchjpeg.codec.write_coefficients(args.output, dimensions, quantization, Y_coefficients) 12 | -------------------------------------------------------------------------------- /examples/ident.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import torchjpeg.codec 4 | 5 | parser = argparse.ArgumentParser("Tests the pytorch DCT loader by reading quantized DCT coefficients from a JPEG then writing them unchanged") 6 | parser.add_argument("input", help="Input image, must be a JPEG") 7 | parser.add_argument("output", help="Output image, must be a JPEG") 8 | args = parser.parse_args() 9 | 10 | dimensions, quantization, Y_coefficients, CbCr_coefficients = torchjpeg.codec.read_coefficients(args.input) 11 | torchjpeg.codec.write_coefficients(args.output, dimensions, quantization, Y_coefficients, CbCr_coefficients) 12 | -------------------------------------------------------------------------------- /examples/quantize.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from PIL import Image 4 | from torchvision.transforms.functional import to_pil_image, to_tensor 5 | 6 | import torchjpeg.codec 7 | 8 | parser = argparse.ArgumentParser("Tests the pytorch DCT quantizer by quantizing an input image") 9 | parser.add_argument("input", help="Input image, should be lossless for best results") 10 | parser.add_argument("output", help="Output image, should be lossless for best results") 11 | parser.add_argument("quality", type=int, help="Output quality on the 0-100 scale") 12 | args = parser.parse_args() 13 | 14 | im = Image.open(args.input) 15 | im_tensor = to_tensor(im) 16 | 17 | if im_tensor.shape[0] > 3: 18 | im_tensor = im_tensor[:3] 19 | 20 | dimensions, quantization, Y_coefficients, CbCr_coefficients = torchjpeg.codec.quantize_at_quality(im_tensor, args.quality) 21 | spatial = torchjpeg.codec.reconstruct_full_image(Y_coefficients, quantization, CbCr_coefficients, dimensions) 22 | 23 | to_pil_image(spatial).save(args.output) 24 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | 3 | name = "torchjpeg" 4 | version = "0.0.0" # This is a placeholder, version is set by the CI during build 5 | description = "Utilities for JPEG data access and manipulation in pytorch" 6 | authors = [ 7 | "Max Ehrlich" 8 | ] 9 | 10 | license = "MIT" 11 | readme = "README.md" 12 | 13 | homepage = "https://torchjpeg.readthedocs.io" 14 | repository = "https://gitlab.com/torchjpeg/torchjpeg" 15 | documentation = "https://torchjpeg.readthedocs.io" 16 | 17 | 18 | classifiers = [ 19 | "Programming Language :: Python", 20 | "Programming Language :: Python :: 3.8", 21 | "Programming Language :: Python :: 3.9", 22 | "Programming Language :: Python :: 3.10", 23 | "Programming Language :: Python :: 3.11", 24 | "Programming Language :: Python :: 3 :: Only", 25 | "Programming Language :: C++", 26 | "License :: OSI Approved :: MIT License", 27 | "Operating System :: POSIX :: Linux", 28 | "Development Status :: 3 - Alpha" 29 | ] 30 | 31 | 32 | include = ["src/libjpeg/*"] 33 | 34 | [tool.poetry.build] 35 | 36 | script = "build.py" 37 | generate-setup-file = true 38 | 39 | [tool.poetry.dependencies] 40 | 41 | python = ">= 3.8, < 4.0" 42 | 43 | torch = ">= 2.0.0, < 2.0.1" 44 | torchvision = ">= 0.15.1, < 0.15.2" 45 | 46 | Pillow = ">=7.2.0" 47 | 48 | [tool.poetry.group.dev.dependencies] 49 | 50 | dunamai = "^1.15.0" 51 | 52 | invoke = "^2.1.2" 53 | colorama = "^0.4.3" 54 | 55 | black = { version = "^22.3.0", python = ">=3.8 <4.0" } 56 | isort = "^5.5.2" 57 | 58 | mypy = "1.3.0" 59 | pylint = "2.17.4" 60 | 61 | pytest = "^6.0.0" 62 | 63 | coverage = "^5.2.1" 64 | pytest-cov = "^2.10.0" 65 | 66 | virtualenv = "20.23.0" 67 | setuptools = "67.8.0" 68 | 69 | [tool.poetry.group.doc.dependencies] 70 | sphinx = ">=2,<3" 71 | sphinxcontrib-katex = "^0.8.6" 72 | pydocstyle = "^5.0.2" 73 | sphinx-book-theme = "^0.0.34" 74 | myst-parser = "^0.9.1" 75 | jinja2 = "<3.1" 76 | 77 | [tool.black] 78 | 79 | line-length = 1000 80 | target-version = ["py38", "py39", "py310", "py311"] 81 | 82 | [tool.pylint.master] 83 | 84 | init-hook='import sys; sys.path.append("src")' 85 | 86 | unsafe-load-any-extension = true 87 | 88 | [tool.pylint.messages_control] 89 | 90 | # line-too-ling: I don't beleive in line length limits 91 | # trailing-whitespace: triggers on docstrings which is unimportant (black probably fixes this for code) 92 | # invalid-name: often use names from equations which can be considered invalid 93 | # mising-module-docstring: many modules have a single function which contains a docstring 94 | # wrong-import-order: isort takes care of this 95 | # not-callable: https://github.com/pytorch/pytorch/pull/25093 96 | # unsubscriptable-object: https://github.com/PyCQA/pylint/issues/3882 97 | disable = """, 98 | line-too-long, 99 | trailing-whitespace, 100 | invalid-name, 101 | missing-module-docstring, 102 | wrong-import-order, 103 | not-callable 104 | """ 105 | 106 | [tool.pylint.typecheck] 107 | 108 | generated-members = "numpy.*,torch.*" 109 | 110 | [tool.pytest.ini_options] 111 | 112 | addopts = "--cov=torchjpeg --cov-report term --cov-append" 113 | 114 | [tool.mypy] 115 | 116 | ignore_missing_imports = true 117 | no_implicit_optional = true 118 | check_untyped_defs = true 119 | 120 | [tool.isort] 121 | 122 | profile = "black" 123 | line_length = 1000 124 | 125 | [build-system] 126 | 127 | requires = [ 128 | "poetry-core", 129 | "torch==2.0.0", 130 | ] 131 | build-backend = "poetry.core.masonry.api" -------------------------------------------------------------------------------- /src/libjpeg/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | # 3 | # Automake Makefile for the JPEG library 4 | # 5 | # This file is written by Bob Friesenhahn, Guido Vollbeding 6 | # 7 | 8 | # Sources to build library 9 | LIBSOURCES = jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c \ 10 | jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \ 11 | jcomapi.c jcparam.c jcprepct.c jcsample.c jctrans.c jdapimin.c \ 12 | jdapistd.c jdarith.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \ 13 | jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \ 14 | jdmerge.c jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c \ 15 | jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jquant1.c \ 16 | jquant2.c jutils.c jmemmgr.c @MEMORYMGR@.c 17 | 18 | # System dependent sources 19 | SYSDEPSOURCES = jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c 20 | 21 | # Headers which are installed to support the library 22 | INSTINCLUDES = jerror.h jmorecfg.h jpeglib.h 23 | 24 | # Headers which are not installed 25 | OTHERINCLUDES = cderror.h cdjpeg.h jdct.h jinclude.h jmemsys.h jpegint.h \ 26 | jversion.h transupp.h 27 | 28 | # Manual pages (Automake uses 'MANS' for itself) 29 | DISTMANS= cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 wrjpgcom.1 30 | 31 | # Other documentation files 32 | DOCS= README install.txt usage.txt wizard.txt example.c libjpeg.txt \ 33 | structure.txt coderules.txt filelist.txt change.log 34 | 35 | # Makefiles for various systems 36 | MKFILES= configure Makefile.in makefile.ansi makefile.unix makefile.b32 \ 37 | makefile.bcc makefile.mc6 makefile.dj makefile.wat makefile.vc \ 38 | makefile.vs makejdsw.vc6 makeadsw.vc6 makejdep.vc6 makejdsp.vc6 \ 39 | makejmak.vc6 makecdep.vc6 makecdsp.vc6 makecmak.vc6 makeddep.vc6 \ 40 | makeddsp.vc6 makedmak.vc6 maketdep.vc6 maketdsp.vc6 maketmak.vc6 \ 41 | makerdep.vc6 makerdsp.vc6 makermak.vc6 makewdep.vc6 makewdsp.vc6 \ 42 | makewmak.vc6 makejsln.v16 makeasln.v16 makejvcx.v16 makejfil.v16 \ 43 | makecvcx.v16 makecfil.v16 makedvcx.v16 makedfil.v16 maketvcx.v16 \ 44 | maketfil.v16 makervcx.v16 makerfil.v16 makewvcx.v16 makewfil.v16 \ 45 | makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st maktjpeg.st \ 46 | makefile.manx makefile.sas makefile.mms makefile.vms makvms.opt 47 | 48 | # Configuration files 49 | CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ 50 | jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ 51 | jconfig.vms 52 | 53 | # Support scripts for configure 54 | CONFIGUREFILES= config.guess config.sub install-sh ltmain.sh depcomp \ 55 | missing ar-lib 56 | 57 | # Miscellaneous support files 58 | OTHERFILES= jconfig.txt ckconfig.c jmemdosa.asm libjpeg.map libjpeg.pc.in 59 | 60 | # Test support files 61 | TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.bmp testimg.jpg \ 62 | testprog.jpg testimgp.jpg 63 | 64 | # libtool libraries to build 65 | lib_LTLIBRARIES = libjpeg.la 66 | 67 | # Library sources for libjpeg.la 68 | libjpeg_la_SOURCES = $(LIBSOURCES) 69 | 70 | # LDFLAGS for libjpeg.la 71 | libjpeg_la_LDFLAGS = -no-undefined \ 72 | -version-info $(JPEG_LIB_VERSION) 73 | 74 | if HAVE_LD_VERSION_SCRIPT 75 | libjpeg_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libjpeg.map 76 | endif 77 | 78 | # Executables to build 79 | bin_PROGRAMS = cjpeg djpeg jpegtran rdjpgcom wrjpgcom 80 | 81 | # Executable sources & libs 82 | cjpeg_SOURCES = cjpeg.c rdppm.c rdgif.c rdtarga.c rdrle.c rdbmp.c \ 83 | rdswitch.c cdjpeg.c 84 | cjpeg_LDADD = libjpeg.la 85 | djpeg_SOURCES = djpeg.c wrppm.c wrgif.c wrtarga.c wrrle.c wrbmp.c \ 86 | rdcolmap.c cdjpeg.c 87 | djpeg_LDADD = libjpeg.la 88 | jpegtran_SOURCES = jpegtran.c rdswitch.c cdjpeg.c transupp.c 89 | jpegtran_LDADD = libjpeg.la 90 | rdjpgcom_SOURCES = rdjpgcom.c 91 | wrjpgcom_SOURCES = wrjpgcom.c 92 | 93 | # Manual pages to install 94 | man_MANS = $(DISTMANS) 95 | 96 | # Headers to install 97 | include_HEADERS = $(INSTINCLUDES) 98 | 99 | # Other distributed headers 100 | noinst_HEADERS = $(OTHERINCLUDES) 101 | 102 | # Other distributed files 103 | EXTRA_DIST = $(DOCS) $(DISTMANS) $(MKFILES) $(CONFIGFILES) $(SYSDEPSOURCES) \ 104 | $(OTHERFILES) $(TESTFILES) 105 | 106 | # pkg-config file 107 | pkgconfigdir = $(libdir)/pkgconfig 108 | nodist_pkgconfig_DATA = libjpeg.pc 109 | 110 | # Files to be cleaned 111 | CLEANFILES = testout.ppm testout.gif testout.bmp testout.jpg testoutp.ppm \ 112 | testoutp.jpg testoutt.jpg 113 | 114 | # Install jconfig.h 115 | install-data-local: 116 | $(mkinstalldirs) $(DESTDIR)$(includedir) 117 | $(INSTALL_HEADER) jconfig.h $(DESTDIR)$(includedir)/jconfig.h 118 | 119 | # Uninstall jconfig.h 120 | uninstall-local: 121 | rm -f $(DESTDIR)$(includedir)/jconfig.h 122 | 123 | # Run tests 124 | test: check-local 125 | check-local: 126 | rm -f testout* 127 | ./djpeg -dct int -ppm -outfile testout.ppm $(srcdir)/testorig.jpg 128 | ./djpeg -dct int -gif -outfile testout.gif $(srcdir)/testorig.jpg 129 | ./djpeg -dct int -bmp -colors 256 -outfile testout.bmp $(srcdir)/testorig.jpg 130 | ./cjpeg -dct int -outfile testout.jpg $(srcdir)/testimg.ppm 131 | ./djpeg -dct int -ppm -outfile testoutp.ppm $(srcdir)/testprog.jpg 132 | ./cjpeg -dct int -progressive -opt -outfile testoutp.jpg $(srcdir)/testimg.ppm 133 | ./jpegtran -outfile testoutt.jpg $(srcdir)/testprog.jpg 134 | cmp $(srcdir)/testimg.ppm testout.ppm 135 | cmp $(srcdir)/testimg.gif testout.gif 136 | cmp $(srcdir)/testimg.bmp testout.bmp 137 | cmp $(srcdir)/testimg.jpg testout.jpg 138 | cmp $(srcdir)/testimg.ppm testoutp.ppm 139 | cmp $(srcdir)/testimgp.jpg testoutp.jpg 140 | cmp $(srcdir)/testorig.jpg testoutt.jpg 141 | -------------------------------------------------------------------------------- /src/libjpeg/ar-lib: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for Microsoft lib.exe 3 | 4 | me=ar-lib 5 | scriptversion=2012-03-01.08; # UTC 6 | 7 | # Copyright (C) 2010-2018 Free Software Foundation, Inc. 8 | # Written by Peter Rosin . 9 | # 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | # This file is maintained in Automake, please report 29 | # bugs to or send patches to 30 | # . 31 | 32 | 33 | # func_error message 34 | func_error () 35 | { 36 | echo "$me: $1" 1>&2 37 | exit 1 38 | } 39 | 40 | file_conv= 41 | 42 | # func_file_conv build_file 43 | # Convert a $build file to $host form and store it in $file 44 | # Currently only supports Windows hosts. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv in 65 | mingw) 66 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 67 | ;; 68 | cygwin) 69 | file=`cygpath -m "$file" || echo "$file"` 70 | ;; 71 | wine) 72 | file=`winepath -w "$file" || echo "$file"` 73 | ;; 74 | esac 75 | ;; 76 | esac 77 | } 78 | 79 | # func_at_file at_file operation archive 80 | # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE 81 | # for each of them. 82 | # When interpreting the content of the @FILE, do NOT use func_file_conv, 83 | # since the user would need to supply preconverted file names to 84 | # binutils ar, at least for MinGW. 85 | func_at_file () 86 | { 87 | operation=$2 88 | archive=$3 89 | at_file_contents=`cat "$1"` 90 | eval set x "$at_file_contents" 91 | shift 92 | 93 | for member 94 | do 95 | $AR -NOLOGO $operation:"$member" "$archive" || exit $? 96 | done 97 | } 98 | 99 | case $1 in 100 | '') 101 | func_error "no command. Try '$0 --help' for more information." 102 | ;; 103 | -h | --h*) 104 | cat < /* to declare isupper(), tolower() */ 14 | #ifdef NEED_SIGNAL_CATCHER 15 | #include /* to declare signal() */ 16 | #endif 17 | #ifdef USE_SETMODE 18 | #include /* to declare setmode()'s parameter macros */ 19 | /* If you have setmode() but not , just delete this line: */ 20 | #include /* to declare setmode() */ 21 | #endif 22 | 23 | 24 | /* 25 | * Signal catcher to ensure that temporary files are removed before aborting. 26 | * NB: for Amiga Manx C this is actually a global routine named _abort(); 27 | * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus... 28 | */ 29 | 30 | #ifdef NEED_SIGNAL_CATCHER 31 | 32 | static j_common_ptr sig_cinfo; 33 | 34 | void /* must be global for Manx C */ 35 | signal_catcher (int signum) 36 | { 37 | if (sig_cinfo != NULL) { 38 | if (sig_cinfo->err != NULL) /* turn off trace output */ 39 | sig_cinfo->err->trace_level = 0; 40 | jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */ 41 | } 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | 46 | GLOBAL(void) 47 | enable_signal_catcher (j_common_ptr cinfo) 48 | { 49 | sig_cinfo = cinfo; 50 | #ifdef SIGINT /* not all systems have SIGINT */ 51 | signal(SIGINT, signal_catcher); 52 | #endif 53 | #ifdef SIGTERM /* not all systems have SIGTERM */ 54 | signal(SIGTERM, signal_catcher); 55 | #endif 56 | } 57 | 58 | #endif 59 | 60 | 61 | /* 62 | * Optional progress monitor: display a percent-done figure on stderr. 63 | */ 64 | 65 | #ifdef PROGRESS_REPORT 66 | 67 | METHODDEF(void) 68 | progress_monitor (j_common_ptr cinfo) 69 | { 70 | cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress; 71 | int total_passes = prog->pub.total_passes + prog->total_extra_passes; 72 | int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit); 73 | 74 | if (percent_done != prog->percent_done) { 75 | prog->percent_done = percent_done; 76 | if (total_passes > 1) { 77 | fprintf(stderr, "\rPass %d/%d: %3d%% ", 78 | prog->pub.completed_passes + prog->completed_extra_passes + 1, 79 | total_passes, percent_done); 80 | } else { 81 | fprintf(stderr, "\r %3d%% ", percent_done); 82 | } 83 | fflush(stderr); 84 | } 85 | } 86 | 87 | 88 | GLOBAL(void) 89 | start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress) 90 | { 91 | /* Enable progress display, unless trace output is on */ 92 | if (cinfo->err->trace_level == 0) { 93 | progress->pub.progress_monitor = progress_monitor; 94 | progress->completed_extra_passes = 0; 95 | progress->total_extra_passes = 0; 96 | progress->percent_done = -1; 97 | cinfo->progress = &progress->pub; 98 | } 99 | } 100 | 101 | 102 | GLOBAL(void) 103 | end_progress_monitor (j_common_ptr cinfo) 104 | { 105 | /* Clear away progress display */ 106 | if (cinfo->err->trace_level == 0) { 107 | fprintf(stderr, "\r \r"); 108 | fflush(stderr); 109 | } 110 | } 111 | 112 | #endif 113 | 114 | 115 | /* 116 | * Case-insensitive matching of possibly-abbreviated keyword switches. 117 | * keyword is the constant keyword (must be lower case already), 118 | * minchars is length of minimum legal abbreviation. 119 | */ 120 | 121 | GLOBAL(boolean) 122 | keymatch (char * arg, const char * keyword, int minchars) 123 | { 124 | register int ca, ck; 125 | register int nmatched = 0; 126 | 127 | while ((ca = *arg++) != '\0') { 128 | if ((ck = *keyword++) == '\0') 129 | return FALSE; /* arg longer than keyword, no good */ 130 | if (isupper(ca)) /* force arg to lcase (assume ck is already) */ 131 | ca = tolower(ca); 132 | if (ca != ck) 133 | return FALSE; /* no good */ 134 | nmatched++; /* count matched characters */ 135 | } 136 | /* reached end of argument; fail if it's too short for unique abbrev */ 137 | if (nmatched < minchars) 138 | return FALSE; 139 | return TRUE; /* A-OK */ 140 | } 141 | 142 | 143 | /* 144 | * Routines to establish binary I/O mode for stdin and stdout. 145 | * Non-Unix systems often require some hacking to get out of text mode. 146 | */ 147 | 148 | GLOBAL(FILE *) 149 | read_stdin (void) 150 | { 151 | FILE * input_file = stdin; 152 | 153 | #ifdef USE_SETMODE /* need to hack file mode? */ 154 | setmode(fileno(stdin), O_BINARY); 155 | #endif 156 | #ifdef USE_FDOPEN /* need to re-open in binary mode? */ 157 | if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { 158 | fprintf(stderr, "Cannot reopen stdin\n"); 159 | exit(EXIT_FAILURE); 160 | } 161 | #endif 162 | return input_file; 163 | } 164 | 165 | 166 | GLOBAL(FILE *) 167 | write_stdout (void) 168 | { 169 | FILE * output_file = stdout; 170 | 171 | #ifdef USE_SETMODE /* need to hack file mode? */ 172 | setmode(fileno(stdout), O_BINARY); 173 | #endif 174 | #ifdef USE_FDOPEN /* need to re-open in binary mode? */ 175 | if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { 176 | fprintf(stderr, "Cannot reopen stdout\n"); 177 | exit(EXIT_FAILURE); 178 | } 179 | #endif 180 | return output_file; 181 | } 182 | -------------------------------------------------------------------------------- /src/libjpeg/cdjpeg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cdjpeg.h 3 | * 4 | * Copyright (C) 1994-1997, Thomas G. Lane. 5 | * Modified 2019 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file contains common declarations for the sample applications 10 | * cjpeg and djpeg. It is NOT used by the core JPEG library. 11 | */ 12 | 13 | #define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ 14 | #define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ 15 | #include "jinclude.h" 16 | #include "jpeglib.h" 17 | #include "jerror.h" /* get library error codes too */ 18 | #include "cderror.h" /* get application-specific error codes */ 19 | 20 | 21 | /* 22 | * Object interface for cjpeg's source file decoding modules 23 | */ 24 | 25 | typedef struct cjpeg_source_struct * cjpeg_source_ptr; 26 | 27 | struct cjpeg_source_struct { 28 | JMETHOD(void, start_input, (j_compress_ptr cinfo, 29 | cjpeg_source_ptr sinfo)); 30 | JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, 31 | cjpeg_source_ptr sinfo)); 32 | JMETHOD(void, finish_input, (j_compress_ptr cinfo, 33 | cjpeg_source_ptr sinfo)); 34 | 35 | FILE *input_file; 36 | 37 | JSAMPARRAY buffer; 38 | JDIMENSION buffer_height; 39 | }; 40 | 41 | 42 | /* 43 | * Object interface for djpeg's output file encoding modules 44 | */ 45 | 46 | typedef struct djpeg_dest_struct * djpeg_dest_ptr; 47 | 48 | struct djpeg_dest_struct { 49 | /* start_output is called after jpeg_start_decompress finishes. 50 | * The color map will be ready at this time, if one is needed. 51 | */ 52 | JMETHOD(void, start_output, (j_decompress_ptr cinfo, 53 | djpeg_dest_ptr dinfo)); 54 | /* Emit the specified number of pixel rows from the buffer. */ 55 | JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, 56 | djpeg_dest_ptr dinfo, 57 | JDIMENSION rows_supplied)); 58 | /* Finish up at the end of the image. */ 59 | JMETHOD(void, finish_output, (j_decompress_ptr cinfo, 60 | djpeg_dest_ptr dinfo)); 61 | 62 | /* Target file spec; filled in by djpeg.c after object is created. */ 63 | FILE * output_file; 64 | 65 | /* Output pixel-row buffer. Created by module init or start_output. 66 | * Width is cinfo->output_width * cinfo->output_components; 67 | * height is buffer_height. 68 | */ 69 | JSAMPARRAY buffer; 70 | JDIMENSION buffer_height; 71 | }; 72 | 73 | 74 | /* 75 | * cjpeg/djpeg may need to perform extra passes to convert to or from 76 | * the source/destination file format. The JPEG library does not know 77 | * about these passes, but we'd like them to be counted by the progress 78 | * monitor. We use an expanded progress monitor object to hold the 79 | * additional pass count. 80 | */ 81 | 82 | struct cdjpeg_progress_mgr { 83 | struct jpeg_progress_mgr pub; /* fields known to JPEG library */ 84 | int completed_extra_passes; /* extra passes completed */ 85 | int total_extra_passes; /* total extra */ 86 | /* last printed percentage stored here to avoid multiple printouts */ 87 | int percent_done; 88 | }; 89 | 90 | typedef struct cdjpeg_progress_mgr * cd_progress_ptr; 91 | 92 | 93 | /* Short forms of external names for systems with brain-damaged linkers. */ 94 | 95 | #ifdef NEED_SHORT_EXTERNAL_NAMES 96 | #define jinit_read_bmp jIRdBMP 97 | #define jinit_write_bmp jIWrBMP 98 | #define jinit_read_gif jIRdGIF 99 | #define jinit_write_gif jIWrGIF 100 | #define jinit_read_ppm jIRdPPM 101 | #define jinit_write_ppm jIWrPPM 102 | #define jinit_read_rle jIRdRLE 103 | #define jinit_write_rle jIWrRLE 104 | #define jinit_read_targa jIRdTarga 105 | #define jinit_write_targa jIWrTarga 106 | #define read_quant_tables RdQTables 107 | #define read_scan_script RdScnScript 108 | #define set_quality_ratings SetQRates 109 | #define set_quant_slots SetQSlots 110 | #define set_sample_factors SetSFacts 111 | #define read_color_map RdCMap 112 | #define enable_signal_catcher EnSigCatcher 113 | #define start_progress_monitor StProgMon 114 | #define end_progress_monitor EnProgMon 115 | #define read_stdin RdStdin 116 | #define write_stdout WrStdout 117 | #endif /* NEED_SHORT_EXTERNAL_NAMES */ 118 | 119 | /* Module selection routines for I/O modules. */ 120 | 121 | EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); 122 | EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, 123 | boolean is_os2)); 124 | EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); 125 | EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo, 126 | boolean is_lzw)); 127 | EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); 128 | EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); 129 | EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); 130 | EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); 131 | EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); 132 | EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); 133 | 134 | /* cjpeg support routines (in rdswitch.c) */ 135 | 136 | EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, 137 | boolean force_baseline)); 138 | EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); 139 | EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, 140 | boolean force_baseline)); 141 | EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); 142 | EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); 143 | 144 | /* djpeg support routines (in rdcolmap.c) */ 145 | 146 | EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); 147 | 148 | /* common support routines (in cdjpeg.c) */ 149 | 150 | EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); 151 | EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, 152 | cd_progress_ptr progress)); 153 | EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); 154 | EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); 155 | EXTERN(FILE *) read_stdin JPP((void)); 156 | EXTERN(FILE *) write_stdout JPP((void)); 157 | 158 | /* miscellaneous useful macros */ 159 | 160 | #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ 161 | #define READ_BINARY "r" 162 | #define WRITE_BINARY "w" 163 | #else 164 | #ifdef VMS /* VMS is very nonstandard */ 165 | #define READ_BINARY "rb", "ctx=stm" 166 | #define WRITE_BINARY "wb", "ctx=stm" 167 | #else /* standard ANSI-compliant case */ 168 | #define READ_BINARY "rb" 169 | #define WRITE_BINARY "wb" 170 | #endif 171 | #endif 172 | 173 | #ifndef EXIT_FAILURE /* define exit() codes if not provided */ 174 | #define EXIT_FAILURE 1 175 | #endif 176 | #ifndef EXIT_SUCCESS 177 | #ifdef VMS 178 | #define EXIT_SUCCESS 1 /* VMS is very nonstandard */ 179 | #else 180 | #define EXIT_SUCCESS 0 181 | #endif 182 | #endif 183 | #ifndef EXIT_WARNING 184 | #ifdef VMS 185 | #define EXIT_WARNING 1 /* VMS is very nonstandard */ 186 | #else 187 | #define EXIT_WARNING 2 188 | #endif 189 | #endif 190 | -------------------------------------------------------------------------------- /src/libjpeg/coderules.txt: -------------------------------------------------------------------------------- 1 | IJG JPEG LIBRARY: CODING RULES 2 | 3 | Copyright (C) 1991-1996, Thomas G. Lane. 4 | This file is part of the Independent JPEG Group's software. 5 | For conditions of distribution and use, see the accompanying README file. 6 | 7 | 8 | Since numerous people will be contributing code and bug fixes, it's important 9 | to establish a common coding style. The goal of using similar coding styles 10 | is much more important than the details of just what that style is. 11 | 12 | In general we follow the recommendations of "Recommended C Style and Coding 13 | Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and 14 | Brader). This document is available in the IJG FTP archive (see 15 | jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl). 16 | 17 | Block comments should be laid out thusly: 18 | 19 | /* 20 | * Block comments in this style. 21 | */ 22 | 23 | We indent statements in K&R style, e.g., 24 | if (test) { 25 | then-part; 26 | } else { 27 | else-part; 28 | } 29 | with two spaces per indentation level. (This indentation convention is 30 | handled automatically by GNU Emacs and many other text editors.) 31 | 32 | Multi-word names should be written in lower case with underscores, e.g., 33 | multi_word_name (not multiWordName). Preprocessor symbols and enum constants 34 | are similar but upper case (MULTI_WORD_NAME). Names should be unique within 35 | the first fifteen characters. (On some older systems, global names must be 36 | unique within six characters. We accommodate this without cluttering the 37 | source code by using macros to substitute shorter names.) 38 | 39 | We use function prototypes everywhere; we rely on automatic source code 40 | transformation to feed prototype-less C compilers. Transformation is done 41 | by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript). 42 | ansi2knr is not very bright, so it imposes a format requirement on function 43 | declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions 44 | should be written in the following style: 45 | 46 | LOCAL(int *) 47 | function_name (int a, char *b) 48 | { 49 | code... 50 | } 51 | 52 | Note that each function definition must begin with GLOBAL(type), LOCAL(type), 53 | or METHODDEF(type). These macros expand to "static type" or just "type" as 54 | appropriate. They provide a readable indication of the routine's usage and 55 | can readily be changed for special needs. (For instance, special linkage 56 | keywords can be inserted for use in Windows DLLs.) 57 | 58 | ansi2knr does not transform method declarations (function pointers in 59 | structs). We handle these with a macro JMETHOD, defined as 60 | #ifdef HAVE_PROTOTYPES 61 | #define JMETHOD(type,methodname,arglist) type (*methodname) arglist 62 | #else 63 | #define JMETHOD(type,methodname,arglist) type (*methodname) () 64 | #endif 65 | which is used like this: 66 | struct function_pointers { 67 | JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp)); 68 | JMETHOD(void, term_entropy_encoder, (void)); 69 | }; 70 | Note the set of parentheses surrounding the parameter list. 71 | 72 | A similar solution is used for forward and external function declarations 73 | (see the EXTERN and JPP macros). 74 | 75 | If the code is to work on non-ANSI compilers, we cannot rely on a prototype 76 | declaration to coerce actual parameters into the right types. Therefore, use 77 | explicit casts on actual parameters whenever the actual parameter type is not 78 | identical to the formal parameter. Beware of implicit conversions to "int". 79 | 80 | It seems there are some non-ANSI compilers in which the sizeof() operator 81 | is defined to return int, yet size_t is defined as long. Needless to say, 82 | this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(), 83 | so that the result is guaranteed to be of type size_t. 84 | 85 | 86 | The JPEG library is intended to be used within larger programs. Furthermore, 87 | we want it to be reentrant so that it can be used by applications that process 88 | multiple images concurrently. The following rules support these requirements: 89 | 90 | 1. Avoid direct use of file I/O, "malloc", error report printouts, etc; 91 | pass these through the common routines provided. 92 | 93 | 2. Minimize global namespace pollution. Functions should be declared static 94 | wherever possible. (Note that our method-based calling conventions help this 95 | a lot: in many modules only the initialization function will ever need to be 96 | called directly, so only that function need be externally visible.) All 97 | global function names should begin with "jpeg_", and should have an 98 | abbreviated name (unique in the first six characters) substituted by macro 99 | when NEED_SHORT_EXTERNAL_NAMES is set. 100 | 101 | 3. Don't use global variables; anything that must be used in another module 102 | should be in the common data structures. 103 | 104 | 4. Don't use static variables except for read-only constant tables. Variables 105 | that should be private to a module can be placed into private structures (see 106 | the system architecture document, structure.txt). 107 | 108 | 5. Source file names should begin with "j" for files that are part of the 109 | library proper; source files that are not part of the library, such as cjpeg.c 110 | and djpeg.c, do not begin with "j". Keep source file names to eight 111 | characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep 112 | compression and decompression code in separate source files --- some 113 | applications may want only one half of the library. 114 | 115 | Note: these rules (particularly #4) are not followed religiously in the 116 | modules that are used in cjpeg/djpeg but are not part of the JPEG library 117 | proper. Those modules are not really intended to be used in other 118 | applications. 119 | -------------------------------------------------------------------------------- /src/libjpeg/jaricom.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jaricom.c 3 | * 4 | * Developed 1997-2011 by Guido Vollbeding. 5 | * This file is part of the Independent JPEG Group's software. 6 | * For conditions of distribution and use, see the accompanying README file. 7 | * 8 | * This file contains probability estimation tables for common use in 9 | * arithmetic entropy encoding and decoding routines. 10 | * 11 | * This data represents Table D.3 in the JPEG spec (D.2 in the draft), 12 | * ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81, and Table 24 13 | * in the JBIG spec, ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82. 14 | */ 15 | 16 | #define JPEG_INTERNALS 17 | #include "jinclude.h" 18 | #include "jpeglib.h" 19 | 20 | /* The following #define specifies the packing of the four components 21 | * into the compact INT32 representation. 22 | * Note that this formula must match the actual arithmetic encoder 23 | * and decoder implementation. The implementation has to be changed 24 | * if this formula is changed. 25 | * The current organization is leaned on Markus Kuhn's JBIG 26 | * implementation (jbig_tab.c). 27 | */ 28 | 29 | #define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) 30 | 31 | const INT32 jpeg_aritab[113+1] = { 32 | /* 33 | * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS 34 | */ 35 | V( 0, 0x5a1d, 1, 1, 1 ), 36 | V( 1, 0x2586, 14, 2, 0 ), 37 | V( 2, 0x1114, 16, 3, 0 ), 38 | V( 3, 0x080b, 18, 4, 0 ), 39 | V( 4, 0x03d8, 20, 5, 0 ), 40 | V( 5, 0x01da, 23, 6, 0 ), 41 | V( 6, 0x00e5, 25, 7, 0 ), 42 | V( 7, 0x006f, 28, 8, 0 ), 43 | V( 8, 0x0036, 30, 9, 0 ), 44 | V( 9, 0x001a, 33, 10, 0 ), 45 | V( 10, 0x000d, 35, 11, 0 ), 46 | V( 11, 0x0006, 9, 12, 0 ), 47 | V( 12, 0x0003, 10, 13, 0 ), 48 | V( 13, 0x0001, 12, 13, 0 ), 49 | V( 14, 0x5a7f, 15, 15, 1 ), 50 | V( 15, 0x3f25, 36, 16, 0 ), 51 | V( 16, 0x2cf2, 38, 17, 0 ), 52 | V( 17, 0x207c, 39, 18, 0 ), 53 | V( 18, 0x17b9, 40, 19, 0 ), 54 | V( 19, 0x1182, 42, 20, 0 ), 55 | V( 20, 0x0cef, 43, 21, 0 ), 56 | V( 21, 0x09a1, 45, 22, 0 ), 57 | V( 22, 0x072f, 46, 23, 0 ), 58 | V( 23, 0x055c, 48, 24, 0 ), 59 | V( 24, 0x0406, 49, 25, 0 ), 60 | V( 25, 0x0303, 51, 26, 0 ), 61 | V( 26, 0x0240, 52, 27, 0 ), 62 | V( 27, 0x01b1, 54, 28, 0 ), 63 | V( 28, 0x0144, 56, 29, 0 ), 64 | V( 29, 0x00f5, 57, 30, 0 ), 65 | V( 30, 0x00b7, 59, 31, 0 ), 66 | V( 31, 0x008a, 60, 32, 0 ), 67 | V( 32, 0x0068, 62, 33, 0 ), 68 | V( 33, 0x004e, 63, 34, 0 ), 69 | V( 34, 0x003b, 32, 35, 0 ), 70 | V( 35, 0x002c, 33, 9, 0 ), 71 | V( 36, 0x5ae1, 37, 37, 1 ), 72 | V( 37, 0x484c, 64, 38, 0 ), 73 | V( 38, 0x3a0d, 65, 39, 0 ), 74 | V( 39, 0x2ef1, 67, 40, 0 ), 75 | V( 40, 0x261f, 68, 41, 0 ), 76 | V( 41, 0x1f33, 69, 42, 0 ), 77 | V( 42, 0x19a8, 70, 43, 0 ), 78 | V( 43, 0x1518, 72, 44, 0 ), 79 | V( 44, 0x1177, 73, 45, 0 ), 80 | V( 45, 0x0e74, 74, 46, 0 ), 81 | V( 46, 0x0bfb, 75, 47, 0 ), 82 | V( 47, 0x09f8, 77, 48, 0 ), 83 | V( 48, 0x0861, 78, 49, 0 ), 84 | V( 49, 0x0706, 79, 50, 0 ), 85 | V( 50, 0x05cd, 48, 51, 0 ), 86 | V( 51, 0x04de, 50, 52, 0 ), 87 | V( 52, 0x040f, 50, 53, 0 ), 88 | V( 53, 0x0363, 51, 54, 0 ), 89 | V( 54, 0x02d4, 52, 55, 0 ), 90 | V( 55, 0x025c, 53, 56, 0 ), 91 | V( 56, 0x01f8, 54, 57, 0 ), 92 | V( 57, 0x01a4, 55, 58, 0 ), 93 | V( 58, 0x0160, 56, 59, 0 ), 94 | V( 59, 0x0125, 57, 60, 0 ), 95 | V( 60, 0x00f6, 58, 61, 0 ), 96 | V( 61, 0x00cb, 59, 62, 0 ), 97 | V( 62, 0x00ab, 61, 63, 0 ), 98 | V( 63, 0x008f, 61, 32, 0 ), 99 | V( 64, 0x5b12, 65, 65, 1 ), 100 | V( 65, 0x4d04, 80, 66, 0 ), 101 | V( 66, 0x412c, 81, 67, 0 ), 102 | V( 67, 0x37d8, 82, 68, 0 ), 103 | V( 68, 0x2fe8, 83, 69, 0 ), 104 | V( 69, 0x293c, 84, 70, 0 ), 105 | V( 70, 0x2379, 86, 71, 0 ), 106 | V( 71, 0x1edf, 87, 72, 0 ), 107 | V( 72, 0x1aa9, 87, 73, 0 ), 108 | V( 73, 0x174e, 72, 74, 0 ), 109 | V( 74, 0x1424, 72, 75, 0 ), 110 | V( 75, 0x119c, 74, 76, 0 ), 111 | V( 76, 0x0f6b, 74, 77, 0 ), 112 | V( 77, 0x0d51, 75, 78, 0 ), 113 | V( 78, 0x0bb6, 77, 79, 0 ), 114 | V( 79, 0x0a40, 77, 48, 0 ), 115 | V( 80, 0x5832, 80, 81, 1 ), 116 | V( 81, 0x4d1c, 88, 82, 0 ), 117 | V( 82, 0x438e, 89, 83, 0 ), 118 | V( 83, 0x3bdd, 90, 84, 0 ), 119 | V( 84, 0x34ee, 91, 85, 0 ), 120 | V( 85, 0x2eae, 92, 86, 0 ), 121 | V( 86, 0x299a, 93, 87, 0 ), 122 | V( 87, 0x2516, 86, 71, 0 ), 123 | V( 88, 0x5570, 88, 89, 1 ), 124 | V( 89, 0x4ca9, 95, 90, 0 ), 125 | V( 90, 0x44d9, 96, 91, 0 ), 126 | V( 91, 0x3e22, 97, 92, 0 ), 127 | V( 92, 0x3824, 99, 93, 0 ), 128 | V( 93, 0x32b4, 99, 94, 0 ), 129 | V( 94, 0x2e17, 93, 86, 0 ), 130 | V( 95, 0x56a8, 95, 96, 1 ), 131 | V( 96, 0x4f46, 101, 97, 0 ), 132 | V( 97, 0x47e5, 102, 98, 0 ), 133 | V( 98, 0x41cf, 103, 99, 0 ), 134 | V( 99, 0x3c3d, 104, 100, 0 ), 135 | V( 100, 0x375e, 99, 93, 0 ), 136 | V( 101, 0x5231, 105, 102, 0 ), 137 | V( 102, 0x4c0f, 106, 103, 0 ), 138 | V( 103, 0x4639, 107, 104, 0 ), 139 | V( 104, 0x415e, 103, 99, 0 ), 140 | V( 105, 0x5627, 105, 106, 1 ), 141 | V( 106, 0x50e7, 108, 107, 0 ), 142 | V( 107, 0x4b85, 109, 103, 0 ), 143 | V( 108, 0x5597, 110, 109, 0 ), 144 | V( 109, 0x504f, 111, 107, 0 ), 145 | V( 110, 0x5a10, 110, 111, 1 ), 146 | V( 111, 0x5522, 112, 109, 0 ), 147 | V( 112, 0x59eb, 112, 111, 1 ), 148 | /* 149 | * This last entry is used for fixed probability estimate of 0.5 150 | * as suggested in Section 10.3 Table 5 of ITU-T Rec. T.851. 151 | */ 152 | V( 113, 0x5a1d, 113, 113, 0 ) 153 | }; 154 | -------------------------------------------------------------------------------- /src/libjpeg/jcapistd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jcapistd.c 3 | * 4 | * Copyright (C) 1994-1996, Thomas G. Lane. 5 | * Modified 2013 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file contains application interface code for the compression half 10 | * of the JPEG library. These are the "standard" API routines that are 11 | * used in the normal full-compression case. They are not used by a 12 | * transcoding-only application. Note that if an application links in 13 | * jpeg_start_compress, it will end up linking in the entire compressor. 14 | * We thus must separate this file from jcapimin.c to avoid linking the 15 | * whole compression library into a transcoder. 16 | */ 17 | 18 | #define JPEG_INTERNALS 19 | #include "jinclude.h" 20 | #include "jpeglib.h" 21 | 22 | 23 | /* 24 | * Compression initialization. 25 | * Before calling this, all parameters and a data destination must be set up. 26 | * 27 | * We require a write_all_tables parameter as a failsafe check when writing 28 | * multiple datastreams from the same compression object. Since prior runs 29 | * will have left all the tables marked sent_table=TRUE, a subsequent run 30 | * would emit an abbreviated stream (no tables) by default. This may be what 31 | * is wanted, but for safety's sake it should not be the default behavior: 32 | * programmers should have to make a deliberate choice to emit abbreviated 33 | * images. Therefore the documentation and examples should encourage people 34 | * to pass write_all_tables=TRUE; then it will take active thought to do the 35 | * wrong thing. 36 | */ 37 | 38 | GLOBAL(void) 39 | jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) 40 | { 41 | if (cinfo->global_state != CSTATE_START) 42 | ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); 43 | 44 | if (write_all_tables) 45 | jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ 46 | 47 | /* (Re)initialize error mgr and destination modules */ 48 | (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); 49 | (*cinfo->dest->init_destination) (cinfo); 50 | /* Perform master selection of active modules */ 51 | jinit_compress_master(cinfo); 52 | /* Set up for the first pass */ 53 | (*cinfo->master->prepare_for_pass) (cinfo); 54 | /* Ready for application to drive first pass through jpeg_write_scanlines 55 | * or jpeg_write_raw_data. 56 | */ 57 | cinfo->next_scanline = 0; 58 | cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); 59 | } 60 | 61 | 62 | /* 63 | * Write some scanlines of data to the JPEG compressor. 64 | * 65 | * The return value will be the number of lines actually written. 66 | * This should be less than the supplied num_lines only in case that 67 | * the data destination module has requested suspension of the compressor, 68 | * or if more than image_height scanlines are passed in. 69 | * 70 | * Note: we warn about excess calls to jpeg_write_scanlines() since 71 | * this likely signals an application programmer error. However, 72 | * excess scanlines passed in the last valid call are *silently* ignored, 73 | * so that the application need not adjust num_lines for end-of-image 74 | * when using a multiple-scanline buffer. 75 | */ 76 | 77 | GLOBAL(JDIMENSION) 78 | jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, 79 | JDIMENSION num_lines) 80 | { 81 | JDIMENSION row_ctr, rows_left; 82 | 83 | if (cinfo->global_state != CSTATE_SCANNING) 84 | ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); 85 | if (cinfo->next_scanline >= cinfo->image_height) 86 | WARNMS(cinfo, JWRN_TOO_MUCH_DATA); 87 | 88 | /* Call progress monitor hook if present */ 89 | if (cinfo->progress != NULL) { 90 | cinfo->progress->pass_counter = (long) cinfo->next_scanline; 91 | cinfo->progress->pass_limit = (long) cinfo->image_height; 92 | (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); 93 | } 94 | 95 | /* Give master control module another chance if this is first call to 96 | * jpeg_write_scanlines. This lets output of the frame/scan headers be 97 | * delayed so that application can write COM, etc, markers between 98 | * jpeg_start_compress and jpeg_write_scanlines. 99 | */ 100 | if (cinfo->master->call_pass_startup) 101 | (*cinfo->master->pass_startup) (cinfo); 102 | 103 | /* Ignore any extra scanlines at bottom of image. */ 104 | rows_left = cinfo->image_height - cinfo->next_scanline; 105 | if (num_lines > rows_left) 106 | num_lines = rows_left; 107 | 108 | row_ctr = 0; 109 | (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); 110 | cinfo->next_scanline += row_ctr; 111 | return row_ctr; 112 | } 113 | 114 | 115 | /* 116 | * Alternate entry point to write raw data. 117 | * Processes exactly one iMCU row per call, unless suspended. 118 | */ 119 | 120 | GLOBAL(JDIMENSION) 121 | jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, 122 | JDIMENSION num_lines) 123 | { 124 | JDIMENSION lines_per_iMCU_row; 125 | 126 | if (cinfo->global_state != CSTATE_RAW_OK) 127 | ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); 128 | if (cinfo->next_scanline >= cinfo->image_height) { 129 | WARNMS(cinfo, JWRN_TOO_MUCH_DATA); 130 | return 0; 131 | } 132 | 133 | /* Call progress monitor hook if present */ 134 | if (cinfo->progress != NULL) { 135 | cinfo->progress->pass_counter = (long) cinfo->next_scanline; 136 | cinfo->progress->pass_limit = (long) cinfo->image_height; 137 | (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); 138 | } 139 | 140 | /* Give master control module another chance if this is first call to 141 | * jpeg_write_raw_data. This lets output of the frame/scan headers be 142 | * delayed so that application can write COM, etc, markers between 143 | * jpeg_start_compress and jpeg_write_raw_data. 144 | */ 145 | if (cinfo->master->call_pass_startup) 146 | (*cinfo->master->pass_startup) (cinfo); 147 | 148 | /* Verify that at least one iMCU row has been passed. */ 149 | lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; 150 | if (num_lines < lines_per_iMCU_row) 151 | ERREXIT(cinfo, JERR_BUFFER_SIZE); 152 | 153 | /* Directly compress the row. */ 154 | if (! (*cinfo->coef->compress_data) (cinfo, data)) { 155 | /* If compressor did not consume the whole row, suspend processing. */ 156 | return 0; 157 | } 158 | 159 | /* OK, we processed one iMCU row. */ 160 | cinfo->next_scanline += lines_per_iMCU_row; 161 | return lines_per_iMCU_row; 162 | } 163 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.bcc: -------------------------------------------------------------------------------- 1 | /* jconfig.bcc --- jconfig.h for Borland C (Turbo C) on MS-DOS or OS/2. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #ifdef __MSDOS__ 15 | #define NEED_FAR_POINTERS /* for small or medium memory model */ 16 | #endif 17 | #undef NEED_SHORT_EXTERNAL_NAMES 18 | #undef INCOMPLETE_TYPES_BROKEN /* this assumes you have -w-stu in CFLAGS */ 19 | 20 | #ifdef JPEG_INTERNALS 21 | 22 | #undef RIGHT_SHIFT_IS_UNSIGNED 23 | 24 | #ifdef __MSDOS__ 25 | #define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ 26 | #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ 27 | #define USE_FMEM /* Borland has _fmemcpy() and _fmemset() */ 28 | #endif 29 | 30 | #endif /* JPEG_INTERNALS */ 31 | 32 | #ifdef JPEG_CJPEG_DJPEG 33 | 34 | #define BMP_SUPPORTED /* BMP image file format */ 35 | #define GIF_SUPPORTED /* GIF image file format */ 36 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 37 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 38 | #define TARGA_SUPPORTED /* Targa image file format */ 39 | 40 | #define TWO_FILE_COMMANDLINE 41 | #define USE_SETMODE /* Borland has setmode() */ 42 | #ifdef __MSDOS__ 43 | #define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ 44 | #endif 45 | #undef DONT_USE_B_MODE 46 | #undef PROGRESS_REPORT /* optional */ 47 | 48 | #endif /* JPEG_CJPEG_DJPEG */ 49 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.cfg: -------------------------------------------------------------------------------- 1 | /* jconfig.cfg --- source file edited by configure script */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #undef HAVE_PROTOTYPES 5 | #undef HAVE_UNSIGNED_CHAR 6 | #undef HAVE_UNSIGNED_SHORT 7 | #undef void 8 | #undef const 9 | #undef CHAR_IS_UNSIGNED 10 | #undef HAVE_STDDEF_H 11 | #undef HAVE_STDLIB_H 12 | #undef HAVE_LOCALE_H 13 | #undef NEED_BSD_STRINGS 14 | #undef NEED_SYS_TYPES_H 15 | #undef NEED_FAR_POINTERS 16 | #undef NEED_SHORT_EXTERNAL_NAMES 17 | /* Define this if you get warnings about undefined structures. */ 18 | #undef INCOMPLETE_TYPES_BROKEN 19 | 20 | /* Define "boolean" as unsigned char, not enum, on Windows systems. */ 21 | #ifdef _WIN32 22 | #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ 23 | typedef unsigned char boolean; 24 | #endif 25 | #ifndef FALSE /* in case these macros already exist */ 26 | #define FALSE 0 /* values of boolean */ 27 | #endif 28 | #ifndef TRUE 29 | #define TRUE 1 30 | #endif 31 | #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ 32 | #endif 33 | 34 | #ifdef JPEG_INTERNALS 35 | 36 | #undef RIGHT_SHIFT_IS_UNSIGNED 37 | #undef INLINE 38 | /* These are for configuring the JPEG memory manager. */ 39 | #undef DEFAULT_MAX_MEM 40 | #undef NO_MKTEMP 41 | 42 | #endif /* JPEG_INTERNALS */ 43 | 44 | #ifdef JPEG_CJPEG_DJPEG 45 | 46 | #define BMP_SUPPORTED /* BMP image file format */ 47 | #define GIF_SUPPORTED /* GIF image file format */ 48 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 49 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 50 | #define TARGA_SUPPORTED /* Targa image file format */ 51 | 52 | #undef TWO_FILE_COMMANDLINE 53 | #undef NEED_SIGNAL_CATCHER 54 | #undef DONT_USE_B_MODE 55 | 56 | /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ 57 | #undef PROGRESS_REPORT 58 | 59 | #endif /* JPEG_CJPEG_DJPEG */ 60 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.dj: -------------------------------------------------------------------------------- 1 | /* jconfig.dj --- jconfig.h for DJGPP (Delorie's GNU C port) on MS-DOS. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #undef NEED_FAR_POINTERS /* DJGPP uses flat 32-bit addressing */ 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #undef INCOMPLETE_TYPES_BROKEN 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #endif /* JPEG_INTERNALS */ 23 | 24 | #ifdef JPEG_CJPEG_DJPEG 25 | 26 | #define BMP_SUPPORTED /* BMP image file format */ 27 | #define GIF_SUPPORTED /* GIF image file format */ 28 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 29 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 30 | #define TARGA_SUPPORTED /* Targa image file format */ 31 | 32 | #undef TWO_FILE_COMMANDLINE /* optional */ 33 | #define USE_SETMODE /* Needed to make one-file style work in DJGPP */ 34 | #undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ 35 | #undef DONT_USE_B_MODE 36 | #undef PROGRESS_REPORT /* optional */ 37 | 38 | #endif /* JPEG_CJPEG_DJPEG */ 39 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.mac: -------------------------------------------------------------------------------- 1 | /* jconfig.mac --- jconfig.h for CodeWarrior on Apple Macintosh */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #undef NEED_FAR_POINTERS 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #undef INCOMPLETE_TYPES_BROKEN 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #define USE_MAC_MEMMGR /* Define this if you use jmemmac.c */ 23 | 24 | #define ALIGN_TYPE long /* Needed for 680x0 Macs */ 25 | 26 | #endif /* JPEG_INTERNALS */ 27 | 28 | #ifdef JPEG_CJPEG_DJPEG 29 | 30 | #define BMP_SUPPORTED /* BMP image file format */ 31 | #define GIF_SUPPORTED /* GIF image file format */ 32 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 33 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 34 | #define TARGA_SUPPORTED /* Targa image file format */ 35 | 36 | #define USE_CCOMMAND /* Command line reader for Macintosh */ 37 | #define TWO_FILE_COMMANDLINE /* Binary I/O thru stdin/stdout doesn't work */ 38 | 39 | #undef NEED_SIGNAL_CATCHER 40 | #undef DONT_USE_B_MODE 41 | #undef PROGRESS_REPORT /* optional */ 42 | 43 | #endif /* JPEG_CJPEG_DJPEG */ 44 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.manx: -------------------------------------------------------------------------------- 1 | /* jconfig.manx --- jconfig.h for Amiga systems using Manx Aztec C ver 5.x. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #undef NEED_FAR_POINTERS 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #undef INCOMPLETE_TYPES_BROKEN 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ 23 | 24 | #define SHORTxSHORT_32 /* produces better DCT code with Aztec C */ 25 | 26 | #endif /* JPEG_INTERNALS */ 27 | 28 | #ifdef JPEG_CJPEG_DJPEG 29 | 30 | #define BMP_SUPPORTED /* BMP image file format */ 31 | #define GIF_SUPPORTED /* GIF image file format */ 32 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 33 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 34 | #define TARGA_SUPPORTED /* Targa image file format */ 35 | 36 | #define TWO_FILE_COMMANDLINE 37 | #define NEED_SIGNAL_CATCHER 38 | #undef DONT_USE_B_MODE 39 | #undef PROGRESS_REPORT /* optional */ 40 | 41 | #define signal_catcher _abort /* hack for Aztec C naming requirements */ 42 | 43 | #endif /* JPEG_CJPEG_DJPEG */ 44 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.mc6: -------------------------------------------------------------------------------- 1 | /* jconfig.mc6 --- jconfig.h for Microsoft C on MS-DOS, version 6.00A & up. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #define NEED_FAR_POINTERS /* for small or medium memory model */ 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #undef INCOMPLETE_TYPES_BROKEN 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ 23 | 24 | #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ 25 | 26 | #define USE_FMEM /* Microsoft has _fmemcpy() and _fmemset() */ 27 | 28 | #define NEED_FHEAPMIN /* far heap management routines are broken */ 29 | 30 | #define SHORTxLCONST_32 /* enable compiler-specific DCT optimization */ 31 | /* Note: the above define is known to improve the code with Microsoft C 6.00A. 32 | * I do not know whether it is good for later compiler versions. 33 | * Please report any info on this point to jpeg-info@jpegclub.org. 34 | */ 35 | 36 | #endif /* JPEG_INTERNALS */ 37 | 38 | #ifdef JPEG_CJPEG_DJPEG 39 | 40 | #define BMP_SUPPORTED /* BMP image file format */ 41 | #define GIF_SUPPORTED /* GIF image file format */ 42 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 43 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 44 | #define TARGA_SUPPORTED /* Targa image file format */ 45 | 46 | #define TWO_FILE_COMMANDLINE 47 | #define USE_SETMODE /* Microsoft has setmode() */ 48 | #define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ 49 | #undef DONT_USE_B_MODE 50 | #undef PROGRESS_REPORT /* optional */ 51 | 52 | #endif /* JPEG_CJPEG_DJPEG */ 53 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.sas: -------------------------------------------------------------------------------- 1 | /* jconfig.sas --- jconfig.h for Amiga systems using SAS C 6.0 and up. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #undef NEED_FAR_POINTERS 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #undef INCOMPLETE_TYPES_BROKEN 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ 23 | 24 | #define NO_MKTEMP /* SAS C doesn't have mktemp() */ 25 | 26 | #define SHORTxSHORT_32 /* produces better DCT code with SAS C */ 27 | 28 | #endif /* JPEG_INTERNALS */ 29 | 30 | #ifdef JPEG_CJPEG_DJPEG 31 | 32 | #define BMP_SUPPORTED /* BMP image file format */ 33 | #define GIF_SUPPORTED /* GIF image file format */ 34 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 35 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 36 | #define TARGA_SUPPORTED /* Targa image file format */ 37 | 38 | #define TWO_FILE_COMMANDLINE 39 | #define NEED_SIGNAL_CATCHER 40 | #undef DONT_USE_B_MODE 41 | #undef PROGRESS_REPORT /* optional */ 42 | 43 | #endif /* JPEG_CJPEG_DJPEG */ 44 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.st: -------------------------------------------------------------------------------- 1 | /* jconfig.st --- jconfig.h for Atari ST/STE/TT using Pure C or Turbo C. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #undef NEED_FAR_POINTERS 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #define INCOMPLETE_TYPES_BROKEN /* suppress undefined-structure warnings */ 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #define ALIGN_TYPE long /* apparently double is a weird size? */ 23 | 24 | #endif /* JPEG_INTERNALS */ 25 | 26 | #ifdef JPEG_CJPEG_DJPEG 27 | 28 | #define BMP_SUPPORTED /* BMP image file format */ 29 | #define GIF_SUPPORTED /* GIF image file format */ 30 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 31 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 32 | #define TARGA_SUPPORTED /* Targa image file format */ 33 | 34 | #define TWO_FILE_COMMANDLINE /* optional -- undef if you like Unix style */ 35 | /* Note: if you undef TWO_FILE_COMMANDLINE, you may need to define 36 | * USE_SETMODE. Some Atari compilers require it, some do not. 37 | */ 38 | #define NEED_SIGNAL_CATCHER /* needed if you use jmemname.c */ 39 | #undef DONT_USE_B_MODE 40 | #undef PROGRESS_REPORT /* optional */ 41 | 42 | #endif /* JPEG_CJPEG_DJPEG */ 43 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * jconfig.txt 3 | * 4 | * Copyright (C) 1991-1994, Thomas G. Lane. 5 | * Modified 2009-2013 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file documents the configuration options that are required to 10 | * customize the JPEG software for a particular system. 11 | * 12 | * The actual configuration options for a particular installation are stored 13 | * in jconfig.h. On many machines, jconfig.h can be generated automatically 14 | * or copied from one of the "canned" jconfig files that we supply. But if 15 | * you need to generate a jconfig.h file by hand, this file tells you how. 16 | * 17 | * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. 18 | * EDIT A COPY NAMED JCONFIG.H. 19 | */ 20 | 21 | 22 | /* 23 | * These symbols indicate the properties of your machine or compiler. 24 | * #define the symbol if yes, #undef it if no. 25 | */ 26 | 27 | /* Does your compiler support function prototypes? 28 | * (If not, you also need to use ansi2knr, see install.txt) 29 | */ 30 | #define HAVE_PROTOTYPES 31 | 32 | /* Does your compiler support the declaration "unsigned char" ? 33 | * How about "unsigned short" ? 34 | */ 35 | #define HAVE_UNSIGNED_CHAR 36 | #define HAVE_UNSIGNED_SHORT 37 | 38 | /* Define "void" as "char" if your compiler doesn't know about type void. 39 | * NOTE: be sure to define void such that "void *" represents the most general 40 | * pointer type, e.g., that returned by malloc(). 41 | */ 42 | /* #define void char */ 43 | 44 | /* Define "const" as empty if your compiler doesn't know the "const" keyword. 45 | */ 46 | /* #define const */ 47 | 48 | /* Define this if an ordinary "char" type is unsigned. 49 | * If you're not sure, leaving it undefined will work at some cost in speed. 50 | * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. 51 | */ 52 | #undef CHAR_IS_UNSIGNED 53 | 54 | /* Define this if your system has an ANSI-conforming file. 55 | */ 56 | #define HAVE_STDDEF_H 57 | 58 | /* Define this if your system has an ANSI-conforming file. 59 | */ 60 | #define HAVE_STDLIB_H 61 | 62 | /* Define this if your system does not have an ANSI/SysV , 63 | * but does have a BSD-style . 64 | */ 65 | #undef NEED_BSD_STRINGS 66 | 67 | /* Define this if your system does not provide typedef size_t in any of the 68 | * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in 69 | * instead. 70 | */ 71 | #undef NEED_SYS_TYPES_H 72 | 73 | /* For 80x86 machines, you need to define NEED_FAR_POINTERS, 74 | * unless you are using a large-data memory model or 80386 flat-memory mode. 75 | * On less brain-damaged CPUs this symbol must not be defined. 76 | * (Defining this symbol causes large data structures to be referenced through 77 | * "far" pointers and to be allocated with a special version of malloc.) 78 | */ 79 | #undef NEED_FAR_POINTERS 80 | 81 | /* Define this if your linker needs global names to be unique in less 82 | * than the first 15 characters. 83 | */ 84 | #undef NEED_SHORT_EXTERNAL_NAMES 85 | 86 | /* Although a real ANSI C compiler can deal perfectly well with pointers to 87 | * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI 88 | * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, 89 | * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you 90 | * actually get "missing structure definition" warnings or errors while 91 | * compiling the JPEG code. 92 | */ 93 | #undef INCOMPLETE_TYPES_BROKEN 94 | 95 | /* Define "boolean" as unsigned char, not enum, on Windows systems. 96 | */ 97 | #ifdef _WIN32 98 | #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ 99 | typedef unsigned char boolean; 100 | #endif 101 | #ifndef FALSE /* in case these macros already exist */ 102 | #define FALSE 0 /* values of boolean */ 103 | #endif 104 | #ifndef TRUE 105 | #define TRUE 1 106 | #endif 107 | #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ 108 | #endif 109 | 110 | 111 | /* 112 | * The following options affect code selection within the JPEG library, 113 | * but they don't need to be visible to applications using the library. 114 | * To minimize application namespace pollution, the symbols won't be 115 | * defined unless JPEG_INTERNALS has been defined. 116 | */ 117 | 118 | #ifdef JPEG_INTERNALS 119 | 120 | /* Define this if your compiler implements ">>" on signed values as a logical 121 | * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, 122 | * which is the normal and rational definition. 123 | */ 124 | #undef RIGHT_SHIFT_IS_UNSIGNED 125 | 126 | 127 | #endif /* JPEG_INTERNALS */ 128 | 129 | 130 | /* 131 | * The remaining options do not affect the JPEG library proper, 132 | * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). 133 | * Other applications can ignore these. 134 | */ 135 | 136 | #ifdef JPEG_CJPEG_DJPEG 137 | 138 | /* These defines indicate which image (non-JPEG) file formats are allowed. */ 139 | 140 | #define BMP_SUPPORTED /* BMP image file format */ 141 | #define GIF_SUPPORTED /* GIF image file format */ 142 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 143 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 144 | #define TARGA_SUPPORTED /* Targa image file format */ 145 | 146 | /* Define this if you want to name both input and output files on the command 147 | * line, rather than using stdout and optionally stdin. You MUST do this if 148 | * your system can't cope with binary I/O to stdin/stdout. See comments at 149 | * head of cjpeg.c or djpeg.c. 150 | */ 151 | #undef TWO_FILE_COMMANDLINE 152 | 153 | /* Define this if your system needs explicit cleanup of temporary files. 154 | * This is crucial under MS-DOS, where the temporary "files" may be areas 155 | * of extended memory; on most other systems it's not as important. 156 | */ 157 | #undef NEED_SIGNAL_CATCHER 158 | 159 | /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). 160 | * This is necessary on systems that distinguish text files from binary files, 161 | * and is harmless on most systems that don't. If you have one of the rare 162 | * systems that complains about the "b" spec, define this symbol. 163 | */ 164 | #undef DONT_USE_B_MODE 165 | 166 | /* Define this if you want percent-done progress reports from cjpeg/djpeg. 167 | */ 168 | #undef PROGRESS_REPORT 169 | 170 | 171 | #endif /* JPEG_CJPEG_DJPEG */ 172 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.vc: -------------------------------------------------------------------------------- 1 | /* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 9x or NT. */ 2 | /* This file also works for Borland C++ 32-bit (bcc32) on Windows 9x or NT. */ 3 | /* see jconfig.txt for explanations */ 4 | 5 | #define HAVE_PROTOTYPES 6 | #define HAVE_UNSIGNED_CHAR 7 | #define HAVE_UNSIGNED_SHORT 8 | /* #define void char */ 9 | /* #define const */ 10 | #undef CHAR_IS_UNSIGNED 11 | #define HAVE_STDDEF_H 12 | #define HAVE_STDLIB_H 13 | #undef NEED_BSD_STRINGS 14 | #undef NEED_SYS_TYPES_H 15 | #undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ 16 | #undef NEED_SHORT_EXTERNAL_NAMES 17 | #undef INCOMPLETE_TYPES_BROKEN 18 | 19 | /* Define "boolean" as unsigned char, not enum, per Windows custom */ 20 | #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ 21 | typedef unsigned char boolean; 22 | #endif 23 | #ifndef FALSE /* in case these macros already exist */ 24 | #define FALSE 0 /* values of boolean */ 25 | #endif 26 | #ifndef TRUE 27 | #define TRUE 1 28 | #endif 29 | #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ 30 | 31 | 32 | #ifdef JPEG_INTERNALS 33 | 34 | #undef RIGHT_SHIFT_IS_UNSIGNED 35 | 36 | #endif /* JPEG_INTERNALS */ 37 | 38 | #ifdef JPEG_CJPEG_DJPEG 39 | 40 | #define BMP_SUPPORTED /* BMP image file format */ 41 | #define GIF_SUPPORTED /* GIF image file format */ 42 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 43 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 44 | #define TARGA_SUPPORTED /* Targa image file format */ 45 | 46 | #define TWO_FILE_COMMANDLINE /* optional */ 47 | #define USE_SETMODE /* Microsoft has setmode() */ 48 | #undef NEED_SIGNAL_CATCHER 49 | #undef DONT_USE_B_MODE 50 | #undef PROGRESS_REPORT /* optional */ 51 | 52 | #endif /* JPEG_CJPEG_DJPEG */ 53 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.vms: -------------------------------------------------------------------------------- 1 | /* jconfig.vms --- jconfig.h for use on Digital VMS. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #undef CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #undef NEED_FAR_POINTERS 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #undef INCOMPLETE_TYPES_BROKEN 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #endif /* JPEG_INTERNALS */ 23 | 24 | #ifdef JPEG_CJPEG_DJPEG 25 | 26 | #define BMP_SUPPORTED /* BMP image file format */ 27 | #define GIF_SUPPORTED /* GIF image file format */ 28 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 29 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 30 | #define TARGA_SUPPORTED /* Targa image file format */ 31 | 32 | #define TWO_FILE_COMMANDLINE /* Needed on VMS */ 33 | #undef NEED_SIGNAL_CATCHER 34 | #undef DONT_USE_B_MODE 35 | #undef PROGRESS_REPORT /* optional */ 36 | 37 | #endif /* JPEG_CJPEG_DJPEG */ 38 | -------------------------------------------------------------------------------- /src/libjpeg/jconfig.wat: -------------------------------------------------------------------------------- 1 | /* jconfig.wat --- jconfig.h for Watcom C/C++ on MS-DOS or OS/2. */ 2 | /* see jconfig.txt for explanations */ 3 | 4 | #define HAVE_PROTOTYPES 5 | #define HAVE_UNSIGNED_CHAR 6 | #define HAVE_UNSIGNED_SHORT 7 | /* #define void char */ 8 | /* #define const */ 9 | #define CHAR_IS_UNSIGNED 10 | #define HAVE_STDDEF_H 11 | #define HAVE_STDLIB_H 12 | #undef NEED_BSD_STRINGS 13 | #undef NEED_SYS_TYPES_H 14 | #undef NEED_FAR_POINTERS /* Watcom uses flat 32-bit addressing */ 15 | #undef NEED_SHORT_EXTERNAL_NAMES 16 | #undef INCOMPLETE_TYPES_BROKEN 17 | 18 | #ifdef JPEG_INTERNALS 19 | 20 | #undef RIGHT_SHIFT_IS_UNSIGNED 21 | 22 | #endif /* JPEG_INTERNALS */ 23 | 24 | #ifdef JPEG_CJPEG_DJPEG 25 | 26 | #define BMP_SUPPORTED /* BMP image file format */ 27 | #define GIF_SUPPORTED /* GIF image file format */ 28 | #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ 29 | #undef RLE_SUPPORTED /* Utah RLE image file format */ 30 | #define TARGA_SUPPORTED /* Targa image file format */ 31 | 32 | #undef TWO_FILE_COMMANDLINE /* optional */ 33 | #define USE_SETMODE /* Needed to make one-file style work in Watcom */ 34 | #undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ 35 | #undef DONT_USE_B_MODE 36 | #undef PROGRESS_REPORT /* optional */ 37 | 38 | #endif /* JPEG_CJPEG_DJPEG */ 39 | -------------------------------------------------------------------------------- /src/libjpeg/jdtrans.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jdtrans.c 3 | * 4 | * Copyright (C) 1995-1997, Thomas G. Lane. 5 | * Modified 2000-2009 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file contains library routines for transcoding decompression, 10 | * that is, reading raw DCT coefficient arrays from an input JPEG file. 11 | * The routines in jdapimin.c will also be needed by a transcoder. 12 | */ 13 | 14 | #define JPEG_INTERNALS 15 | #include "jinclude.h" 16 | #include "jpeglib.h" 17 | 18 | 19 | /* Forward declarations */ 20 | LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); 21 | 22 | 23 | /* 24 | * Read the coefficient arrays from a JPEG file. 25 | * jpeg_read_header must be completed before calling this. 26 | * 27 | * The entire image is read into a set of virtual coefficient-block arrays, 28 | * one per component. The return value is a pointer to the array of 29 | * virtual-array descriptors. These can be manipulated directly via the 30 | * JPEG memory manager, or handed off to jpeg_write_coefficients(). 31 | * To release the memory occupied by the virtual arrays, call 32 | * jpeg_finish_decompress() when done with the data. 33 | * 34 | * An alternative usage is to simply obtain access to the coefficient arrays 35 | * during a buffered-image-mode decompression operation. This is allowed 36 | * after any jpeg_finish_output() call. The arrays can be accessed until 37 | * jpeg_finish_decompress() is called. (Note that any call to the library 38 | * may reposition the arrays, so don't rely on access_virt_barray() results 39 | * to stay valid across library calls.) 40 | * 41 | * Returns NULL if suspended. This case need be checked only if 42 | * a suspending data source is used. 43 | */ 44 | 45 | GLOBAL(jvirt_barray_ptr *) 46 | jpeg_read_coefficients (j_decompress_ptr cinfo) 47 | { 48 | if (cinfo->global_state == DSTATE_READY) { 49 | /* First call: initialize active modules */ 50 | transdecode_master_selection(cinfo); 51 | cinfo->global_state = DSTATE_RDCOEFS; 52 | } 53 | if (cinfo->global_state == DSTATE_RDCOEFS) { 54 | /* Absorb whole file into the coef buffer */ 55 | for (;;) { 56 | int retcode; 57 | /* Call progress monitor hook if present */ 58 | if (cinfo->progress != NULL) 59 | (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); 60 | /* Absorb some more input */ 61 | retcode = (*cinfo->inputctl->consume_input) (cinfo); 62 | if (retcode == JPEG_SUSPENDED) 63 | return NULL; 64 | if (retcode == JPEG_REACHED_EOI) 65 | break; 66 | /* Advance progress counter if appropriate */ 67 | if (cinfo->progress != NULL && 68 | (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { 69 | if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { 70 | /* startup underestimated number of scans; ratchet up one scan */ 71 | cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; 72 | } 73 | } 74 | } 75 | /* Set state so that jpeg_finish_decompress does the right thing */ 76 | cinfo->global_state = DSTATE_STOPPING; 77 | } 78 | /* At this point we should be in state DSTATE_STOPPING if being used 79 | * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access 80 | * to the coefficients during a full buffered-image-mode decompression. 81 | */ 82 | if ((cinfo->global_state == DSTATE_STOPPING || 83 | cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { 84 | return cinfo->coef->coef_arrays; 85 | } 86 | /* Oops, improper usage */ 87 | ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); 88 | return NULL; /* keep compiler happy */ 89 | } 90 | 91 | 92 | /* 93 | * Master selection of decompression modules for transcoding. 94 | * This substitutes for jdmaster.c's initialization of the full decompressor. 95 | */ 96 | 97 | LOCAL(void) 98 | transdecode_master_selection (j_decompress_ptr cinfo) 99 | { 100 | /* This is effectively a buffered-image operation. */ 101 | cinfo->buffered_image = TRUE; 102 | 103 | /* Compute output image dimensions and related values. */ 104 | jpeg_core_output_dimensions(cinfo); 105 | 106 | /* Entropy decoding: either Huffman or arithmetic coding. */ 107 | if (cinfo->arith_code) 108 | jinit_arith_decoder(cinfo); 109 | else { 110 | jinit_huff_decoder(cinfo); 111 | } 112 | 113 | /* Always get a full-image coefficient buffer. */ 114 | jinit_d_coef_controller(cinfo, TRUE); 115 | 116 | /* We can now tell the memory manager to allocate virtual arrays. */ 117 | (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); 118 | 119 | /* Initialize input side of decompressor to consume first scan. */ 120 | (*cinfo->inputctl->start_input_pass) (cinfo); 121 | 122 | /* Initialize progress monitoring. */ 123 | if (cinfo->progress != NULL) { 124 | int nscans; 125 | /* Estimate number of scans to set pass_limit. */ 126 | if (cinfo->progressive_mode) { 127 | /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ 128 | nscans = 2 + 3 * cinfo->num_components; 129 | } else if (cinfo->inputctl->has_multiple_scans) { 130 | /* For a nonprogressive multiscan file, estimate 1 scan per component. */ 131 | nscans = cinfo->num_components; 132 | } else { 133 | nscans = 1; 134 | } 135 | cinfo->progress->pass_counter = 0L; 136 | cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; 137 | cinfo->progress->completed_passes = 0; 138 | cinfo->progress->total_passes = 1; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/libjpeg/jfdctflt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jfdctflt.c 3 | * 4 | * Copyright (C) 1994-1996, Thomas G. Lane. 5 | * Modified 2003-2017 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file contains a floating-point implementation of the 10 | * forward DCT (Discrete Cosine Transform). 11 | * 12 | * This implementation should be more accurate than either of the integer 13 | * DCT implementations. However, it may not give the same results on all 14 | * machines because of differences in roundoff behavior. Speed will depend 15 | * on the hardware's floating point capacity. 16 | * 17 | * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT 18 | * on each column. Direct algorithms are also available, but they are 19 | * much more complex and seem not to be any faster when reduced to code. 20 | * 21 | * This implementation is based on Arai, Agui, and Nakajima's algorithm for 22 | * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in 23 | * Japanese, but the algorithm is described in the Pennebaker & Mitchell 24 | * JPEG textbook (see REFERENCES section in file README). The following code 25 | * is based directly on figure 4-8 in P&M. 26 | * While an 8-point DCT cannot be done in less than 11 multiplies, it is 27 | * possible to arrange the computation so that many of the multiplies are 28 | * simple scalings of the final outputs. These multiplies can then be 29 | * folded into the multiplications or divisions by the JPEG quantization 30 | * table entries. The AA&N method leaves only 5 multiplies and 29 adds 31 | * to be done in the DCT itself. 32 | * The primary disadvantage of this method is that with a fixed-point 33 | * implementation, accuracy is lost due to imprecise representation of the 34 | * scaled quantization values. However, that problem does not arise if 35 | * we use floating point arithmetic. 36 | */ 37 | 38 | #define JPEG_INTERNALS 39 | #include "jinclude.h" 40 | #include "jpeglib.h" 41 | #include "jdct.h" /* Private declarations for DCT subsystem */ 42 | 43 | #ifdef DCT_FLOAT_SUPPORTED 44 | 45 | 46 | /* 47 | * This module is specialized to the case DCTSIZE = 8. 48 | */ 49 | 50 | #if DCTSIZE != 8 51 | Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ 52 | #endif 53 | 54 | 55 | /* 56 | * Perform the forward DCT on one block of samples. 57 | * 58 | * cK represents cos(K*pi/16). 59 | */ 60 | 61 | GLOBAL(void) 62 | jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col) 63 | { 64 | FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; 65 | FAST_FLOAT tmp10, tmp11, tmp12, tmp13; 66 | FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; 67 | FAST_FLOAT *dataptr; 68 | JSAMPROW elemptr; 69 | int ctr; 70 | 71 | /* Pass 1: process rows. */ 72 | 73 | dataptr = data; 74 | for (ctr = 0; ctr < DCTSIZE; ctr++) { 75 | elemptr = sample_data[ctr] + start_col; 76 | 77 | /* Load data into workspace */ 78 | tmp0 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7])); 79 | tmp7 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7])); 80 | tmp1 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6])); 81 | tmp6 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6])); 82 | tmp2 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5])); 83 | tmp5 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5])); 84 | tmp3 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4])); 85 | tmp4 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4])); 86 | 87 | /* Even part */ 88 | 89 | tmp10 = tmp0 + tmp3; /* phase 2 */ 90 | tmp13 = tmp0 - tmp3; 91 | tmp11 = tmp1 + tmp2; 92 | tmp12 = tmp1 - tmp2; 93 | 94 | /* Apply unsigned->signed conversion. */ 95 | dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ 96 | dataptr[4] = tmp10 - tmp11; 97 | 98 | z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ 99 | dataptr[2] = tmp13 + z1; /* phase 5 */ 100 | dataptr[6] = tmp13 - z1; 101 | 102 | /* Odd part */ 103 | 104 | tmp10 = tmp4 + tmp5; /* phase 2 */ 105 | tmp11 = tmp5 + tmp6; 106 | tmp12 = tmp6 + tmp7; 107 | 108 | /* The rotator is modified from fig 4-8 to avoid extra negations. */ 109 | z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ 110 | z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ 111 | z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ 112 | z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ 113 | 114 | z11 = tmp7 + z3; /* phase 5 */ 115 | z13 = tmp7 - z3; 116 | 117 | dataptr[5] = z13 + z2; /* phase 6 */ 118 | dataptr[3] = z13 - z2; 119 | dataptr[1] = z11 + z4; 120 | dataptr[7] = z11 - z4; 121 | 122 | dataptr += DCTSIZE; /* advance pointer to next row */ 123 | } 124 | 125 | /* Pass 2: process columns. */ 126 | 127 | dataptr = data; 128 | for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { 129 | tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; 130 | tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; 131 | tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; 132 | tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; 133 | tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; 134 | tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; 135 | tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; 136 | tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; 137 | 138 | /* Even part */ 139 | 140 | tmp10 = tmp0 + tmp3; /* phase 2 */ 141 | tmp13 = tmp0 - tmp3; 142 | tmp11 = tmp1 + tmp2; 143 | tmp12 = tmp1 - tmp2; 144 | 145 | dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ 146 | dataptr[DCTSIZE*4] = tmp10 - tmp11; 147 | 148 | z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ 149 | dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ 150 | dataptr[DCTSIZE*6] = tmp13 - z1; 151 | 152 | /* Odd part */ 153 | 154 | tmp10 = tmp4 + tmp5; /* phase 2 */ 155 | tmp11 = tmp5 + tmp6; 156 | tmp12 = tmp6 + tmp7; 157 | 158 | /* The rotator is modified from fig 4-8 to avoid extra negations. */ 159 | z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ 160 | z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ 161 | z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ 162 | z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ 163 | 164 | z11 = tmp7 + z3; /* phase 5 */ 165 | z13 = tmp7 - z3; 166 | 167 | dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ 168 | dataptr[DCTSIZE*3] = z13 - z2; 169 | dataptr[DCTSIZE*1] = z11 + z4; 170 | dataptr[DCTSIZE*7] = z11 - z4; 171 | 172 | dataptr++; /* advance pointer to next column */ 173 | } 174 | } 175 | 176 | #endif /* DCT_FLOAT_SUPPORTED */ 177 | -------------------------------------------------------------------------------- /src/libjpeg/jinclude.h: -------------------------------------------------------------------------------- 1 | /* 2 | * jinclude.h 3 | * 4 | * Copyright (C) 1991-1994, Thomas G. Lane. 5 | * Modified 2017 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file exists to provide a single place to fix any problems with 10 | * including the wrong system include files. (Common problems are taken 11 | * care of by the standard jconfig symbols, but on really weird systems 12 | * you may have to edit this file.) 13 | * 14 | * NOTE: this file is NOT intended to be included by applications using the 15 | * JPEG library. Most applications need only include jpeglib.h. 16 | */ 17 | 18 | 19 | /* Include auto-config file to find out which system include files we need. */ 20 | 21 | #include "jconfig.h" /* auto configuration options */ 22 | #define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ 23 | 24 | /* 25 | * We need the NULL macro and size_t typedef. 26 | * On an ANSI-conforming system it is sufficient to include . 27 | * Otherwise, we get them from or ; we may have to 28 | * pull in as well. 29 | * Note that the core JPEG library does not require ; 30 | * only the default error handler and data source/destination modules do. 31 | * But we must pull it in because of the references to FILE in jpeglib.h. 32 | * You can remove those references if you want to compile without . 33 | */ 34 | 35 | #ifdef HAVE_STDDEF_H 36 | #include 37 | #endif 38 | 39 | #ifdef HAVE_STDLIB_H 40 | #include 41 | #endif 42 | 43 | #ifdef NEED_SYS_TYPES_H 44 | #include 45 | #endif 46 | 47 | #include 48 | 49 | /* 50 | * We need memory copying and zeroing functions, plus strncpy(). 51 | * ANSI and System V implementations declare these in . 52 | * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). 53 | * Some systems may declare memset and memcpy in . 54 | * 55 | * NOTE: we assume the size parameters to these functions are of type size_t. 56 | * Change the casts in these macros if not! 57 | */ 58 | 59 | #ifdef NEED_BSD_STRINGS 60 | 61 | #include 62 | #define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) 63 | #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) 64 | 65 | #else /* not BSD, assume ANSI/SysV string lib */ 66 | 67 | #include 68 | #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) 69 | #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) 70 | 71 | #endif 72 | 73 | /* 74 | * In ANSI C, and indeed any rational implementation, size_t is also the 75 | * type returned by sizeof(). However, it seems there are some irrational 76 | * implementations out there, in which sizeof() returns an int even though 77 | * size_t is defined as long or unsigned long. To ensure consistent results 78 | * we always use this SIZEOF() macro in place of using sizeof() directly. 79 | */ 80 | 81 | #define SIZEOF(object) ((size_t) sizeof(object)) 82 | 83 | /* 84 | * The modules that use fread() and fwrite() always invoke them through 85 | * these macros. On some systems you may need to twiddle the argument casts. 86 | * CAUTION: argument order is different from underlying functions! 87 | * 88 | * Furthermore, macros are provided for fflush() and ferror() in order 89 | * to facilitate adaption by applications using an own FILE class. 90 | */ 91 | 92 | #define JFREAD(file,buf,sizeofbuf) \ 93 | ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) 94 | #define JFWRITE(file,buf,sizeofbuf) \ 95 | ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) 96 | #define JFFLUSH(file) fflush(file) 97 | #define JFERROR(file) ferror(file) 98 | -------------------------------------------------------------------------------- /src/libjpeg/jmemansi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jmemansi.c 3 | * 4 | * Copyright (C) 1992-1996, Thomas G. Lane. 5 | * This file is part of the Independent JPEG Group's software. 6 | * For conditions of distribution and use, see the accompanying README file. 7 | * 8 | * This file provides a simple generic implementation of the system- 9 | * dependent portion of the JPEG memory manager. This implementation 10 | * assumes that you have the ANSI-standard library routine tmpfile(). 11 | * Also, the problem of determining the amount of memory available 12 | * is shoved onto the user. 13 | */ 14 | 15 | #define JPEG_INTERNALS 16 | #include "jinclude.h" 17 | #include "jpeglib.h" 18 | #include "jmemsys.h" /* import the system-dependent declarations */ 19 | 20 | #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ 21 | extern void * malloc JPP((size_t size)); 22 | extern void free JPP((void *ptr)); 23 | #endif 24 | 25 | #ifndef SEEK_SET /* pre-ANSI systems may not define this; */ 26 | #define SEEK_SET 0 /* if not, assume 0 is correct */ 27 | #endif 28 | 29 | 30 | /* 31 | * Memory allocation and freeing are controlled by the regular library 32 | * routines malloc() and free(). 33 | */ 34 | 35 | GLOBAL(void *) 36 | jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) 37 | { 38 | return (void *) malloc(sizeofobject); 39 | } 40 | 41 | GLOBAL(void) 42 | jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) 43 | { 44 | free(object); 45 | } 46 | 47 | 48 | /* 49 | * "Large" objects are treated the same as "small" ones. 50 | * NB: although we include FAR keywords in the routine declarations, 51 | * this file won't actually work in 80x86 small/medium model; at least, 52 | * you probably won't be able to process useful-size images in only 64KB. 53 | */ 54 | 55 | GLOBAL(void FAR *) 56 | jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) 57 | { 58 | return (void FAR *) malloc(sizeofobject); 59 | } 60 | 61 | GLOBAL(void) 62 | jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) 63 | { 64 | free(object); 65 | } 66 | 67 | 68 | /* 69 | * This routine computes the total memory space available for allocation. 70 | * It's impossible to do this in a portable way; our current solution is 71 | * to make the user tell us (with a default value set at compile time). 72 | * If you can actually get the available space, it's a good idea to subtract 73 | * a slop factor of 5% or so. 74 | */ 75 | 76 | #ifndef DEFAULT_MAX_MEM /* so can override from makefile */ 77 | #define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ 78 | #endif 79 | 80 | GLOBAL(long) 81 | jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, 82 | long max_bytes_needed, long already_allocated) 83 | { 84 | return cinfo->mem->max_memory_to_use - already_allocated; 85 | } 86 | 87 | 88 | /* 89 | * Backing store (temporary file) management. 90 | * Backing store objects are only used when the value returned by 91 | * jpeg_mem_available is less than the total space needed. You can dispense 92 | * with these routines if you have plenty of virtual memory; see jmemnobs.c. 93 | */ 94 | 95 | 96 | METHODDEF(void) 97 | read_backing_store (j_common_ptr cinfo, backing_store_ptr info, 98 | void FAR * buffer_address, 99 | long file_offset, long byte_count) 100 | { 101 | if (fseek(info->temp_file, file_offset, SEEK_SET)) 102 | ERREXIT(cinfo, JERR_TFILE_SEEK); 103 | if (JFREAD(info->temp_file, buffer_address, byte_count) 104 | != (size_t) byte_count) 105 | ERREXIT(cinfo, JERR_TFILE_READ); 106 | } 107 | 108 | 109 | METHODDEF(void) 110 | write_backing_store (j_common_ptr cinfo, backing_store_ptr info, 111 | void FAR * buffer_address, 112 | long file_offset, long byte_count) 113 | { 114 | if (fseek(info->temp_file, file_offset, SEEK_SET)) 115 | ERREXIT(cinfo, JERR_TFILE_SEEK); 116 | if (JFWRITE(info->temp_file, buffer_address, byte_count) 117 | != (size_t) byte_count) 118 | ERREXIT(cinfo, JERR_TFILE_WRITE); 119 | } 120 | 121 | 122 | METHODDEF(void) 123 | close_backing_store (j_common_ptr cinfo, backing_store_ptr info) 124 | { 125 | fclose(info->temp_file); 126 | /* Since this implementation uses tmpfile() to create the file, 127 | * no explicit file deletion is needed. 128 | */ 129 | } 130 | 131 | 132 | /* 133 | * Initial opening of a backing-store object. 134 | * 135 | * This version uses tmpfile(), which constructs a suitable file name 136 | * behind the scenes. We don't have to use info->temp_name[] at all; 137 | * indeed, we can't even find out the actual name of the temp file. 138 | */ 139 | 140 | GLOBAL(void) 141 | jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, 142 | long total_bytes_needed) 143 | { 144 | if ((info->temp_file = tmpfile()) == NULL) 145 | ERREXITS(cinfo, JERR_TFILE_CREATE, ""); 146 | info->read_backing_store = read_backing_store; 147 | info->write_backing_store = write_backing_store; 148 | info->close_backing_store = close_backing_store; 149 | } 150 | 151 | 152 | /* 153 | * These routines take care of any system-dependent initialization and 154 | * cleanup required. 155 | */ 156 | 157 | GLOBAL(long) 158 | jpeg_mem_init (j_common_ptr cinfo) 159 | { 160 | return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ 161 | } 162 | 163 | GLOBAL(void) 164 | jpeg_mem_term (j_common_ptr cinfo) 165 | { 166 | /* no work */ 167 | } 168 | -------------------------------------------------------------------------------- /src/libjpeg/jmemnobs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * jmemnobs.c 3 | * 4 | * Copyright (C) 1992-1996, Thomas G. Lane. 5 | * Modified 2019 by Guido Vollbeding. 6 | * This file is part of the Independent JPEG Group's software. 7 | * For conditions of distribution and use, see the accompanying README file. 8 | * 9 | * This file provides a really simple implementation of the system- 10 | * dependent portion of the JPEG memory manager. This implementation 11 | * assumes that no backing-store files are needed: all required space 12 | * can be obtained from malloc(). 13 | * This is very portable in the sense that it'll compile on almost anything, 14 | * but you'd better have lots of main memory (or virtual memory) if you want 15 | * to process big images. 16 | * Note that the max_memory_to_use option is respected by this implementation. 17 | */ 18 | 19 | #define JPEG_INTERNALS 20 | #include "jinclude.h" 21 | #include "jpeglib.h" 22 | #include "jmemsys.h" /* import the system-dependent declarations */ 23 | 24 | #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ 25 | extern void * malloc JPP((size_t size)); 26 | extern void free JPP((void *ptr)); 27 | #endif 28 | 29 | 30 | /* 31 | * Memory allocation and freeing are controlled by the regular library 32 | * routines malloc() and free(). 33 | */ 34 | 35 | GLOBAL(void *) 36 | jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) 37 | { 38 | return (void *) malloc(sizeofobject); 39 | } 40 | 41 | GLOBAL(void) 42 | jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) 43 | { 44 | free(object); 45 | } 46 | 47 | 48 | /* 49 | * "Large" objects are treated the same as "small" ones. 50 | * NB: although we include FAR keywords in the routine declarations, 51 | * this file won't actually work in 80x86 small/medium model; at least, 52 | * you probably won't be able to process useful-size images in only 64KB. 53 | */ 54 | 55 | GLOBAL(void FAR *) 56 | jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) 57 | { 58 | return (void FAR *) malloc(sizeofobject); 59 | } 60 | 61 | GLOBAL(void) 62 | jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) 63 | { 64 | free(object); 65 | } 66 | 67 | 68 | /* 69 | * This routine computes the total memory space available for allocation. 70 | */ 71 | 72 | GLOBAL(long) 73 | jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, 74 | long max_bytes_needed, long already_allocated) 75 | { 76 | if (cinfo->mem->max_memory_to_use) 77 | return cinfo->mem->max_memory_to_use - already_allocated; 78 | 79 | /* Here we say, "we got all you want bud!" */ 80 | return max_bytes_needed; 81 | } 82 | 83 | 84 | /* 85 | * Backing store (temporary file) management. 86 | * Since jpeg_mem_available always promised the moon, 87 | * this should never be called and we can just error out. 88 | */ 89 | 90 | GLOBAL(void) 91 | jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, 92 | long total_bytes_needed) 93 | { 94 | ERREXIT(cinfo, JERR_NO_BACKING_STORE); 95 | } 96 | 97 | 98 | /* 99 | * These routines take care of any system-dependent initialization and 100 | * cleanup required. Here, there isn't any. 101 | */ 102 | 103 | GLOBAL(long) 104 | jpeg_mem_init (j_common_ptr cinfo) 105 | { 106 | return 0; /* just set max_memory_to_use to 0 */ 107 | } 108 | 109 | GLOBAL(void) 110 | jpeg_mem_term (j_common_ptr cinfo) 111 | { 112 | /* no work */ 113 | } 114 | -------------------------------------------------------------------------------- /src/libjpeg/jversion.h: -------------------------------------------------------------------------------- 1 | /* 2 | * jversion.h 3 | * 4 | * Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding. 5 | * This file is part of the Independent JPEG Group's software. 6 | * For conditions of distribution and use, see the accompanying README file. 7 | * 8 | * This file contains software version identification. 9 | */ 10 | 11 | 12 | #define JVERSION "9d 12-Jan-2020" 13 | 14 | #define JCOPYRIGHT "Copyright (C) 2020, Thomas G. Lane, Guido Vollbeding" 15 | -------------------------------------------------------------------------------- /src/libjpeg/libjpeg.map: -------------------------------------------------------------------------------- 1 | LIBJPEG_9.0 { 2 | global: 3 | *; 4 | }; 5 | -------------------------------------------------------------------------------- /src/libjpeg/libjpeg.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libjpeg 7 | Description: Reads and writes JPEG files 8 | Version: @JPEG_LIB_VERSION_MAJOR@.@JPEG_LIB_VERSION_MINOR@.0 9 | Libs: -L${libdir} -ljpeg 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /src/libjpeg/makcjpeg.st: -------------------------------------------------------------------------------- 1 | ; Project file for Independent JPEG Group's software 2 | ; 3 | ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. 4 | ; Thanks to Frank Moehle, B. Setzepfandt, and Guido Vollbeding. 5 | ; 6 | ; To use this file, rename it to cjpeg.prj. 7 | ; If you are using Turbo C, change filenames beginning with "pc..." to "tc..." 8 | ; Read installation instructions before trying to make the program! 9 | ; 10 | ; 11 | ; * * * Output file * * * 12 | cjpeg.ttp 13 | ; 14 | ; * * * COMPILER OPTIONS * * * 15 | .C[-P] ; absolute calls 16 | .C[-M] ; and no string merging, folks 17 | .C[-w-cln] ; no "constant is long" warnings 18 | .C[-w-par] ; no "parameter xxxx unused" 19 | .C[-w-rch] ; no "unreachable code" 20 | .C[-wsig] ; warn if significant digits may be lost 21 | = 22 | ; * * * * List of modules * * * * 23 | pcstart.o 24 | cjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,jversion.h) 25 | cdjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 26 | rdswitch.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 27 | rdppm.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 28 | rdgif.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 29 | rdtarga.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 30 | rdbmp.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 31 | rdrle.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 32 | libjpeg.lib ; built by libjpeg.prj 33 | pcfltlib.lib ; floating point library 34 | ; the float library can be omitted if you've turned off DCT_FLOAT_SUPPORTED 35 | pcstdlib.lib ; standard library 36 | pcextlib.lib ; extended library 37 | -------------------------------------------------------------------------------- /src/libjpeg/makdjpeg.st: -------------------------------------------------------------------------------- 1 | ; Project file for Independent JPEG Group's software 2 | ; 3 | ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. 4 | ; Thanks to Frank Moehle, B. Setzepfandt, and Guido Vollbeding. 5 | ; 6 | ; To use this file, rename it to djpeg.prj. 7 | ; If you are using Turbo C, change filenames beginning with "pc..." to "tc..." 8 | ; Read installation instructions before trying to make the program! 9 | ; 10 | ; 11 | ; * * * Output file * * * 12 | djpeg.ttp 13 | ; 14 | ; * * * COMPILER OPTIONS * * * 15 | .C[-P] ; absolute calls 16 | .C[-M] ; and no string merging, folks 17 | .C[-w-cln] ; no "constant is long" warnings 18 | .C[-w-par] ; no "parameter xxxx unused" 19 | .C[-w-rch] ; no "unreachable code" 20 | .C[-wsig] ; warn if significant digits may be lost 21 | = 22 | ; * * * * List of modules * * * * 23 | pcstart.o 24 | djpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,jversion.h) 25 | cdjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 26 | rdcolmap.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 27 | wrppm.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 28 | wrgif.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 29 | wrtarga.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 30 | wrbmp.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 31 | wrrle.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 32 | libjpeg.lib ; built by libjpeg.prj 33 | pcfltlib.lib ; floating point library 34 | ; the float library can be omitted if you've turned off DCT_FLOAT_SUPPORTED 35 | pcstdlib.lib ; standard library 36 | pcextlib.lib ; extended library 37 | -------------------------------------------------------------------------------- /src/libjpeg/makeadsw.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makeadsw.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makeasln.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makeasln.v16 -------------------------------------------------------------------------------- /src/libjpeg/makecdep.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makecdep.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makecdsp.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makecdsp.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makecfil.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makecfil.v16 -------------------------------------------------------------------------------- /src/libjpeg/makecmak.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makecmak.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makecvcx.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makecvcx.v16 -------------------------------------------------------------------------------- /src/libjpeg/makeddep.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makeddep.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makeddsp.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makeddsp.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makedfil.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makedfil.v16 -------------------------------------------------------------------------------- /src/libjpeg/makedmak.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makedmak.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makedvcx.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makedvcx.v16 -------------------------------------------------------------------------------- /src/libjpeg/makefile.vms: -------------------------------------------------------------------------------- 1 | $! Makefile for Independent JPEG Group's software 2 | $! 3 | $! This is a command procedure for Digital VMS systems that do not have MMS. 4 | $! It builds the JPEG software by brute force, recompiling everything whether 5 | $! or not it is necessary. It then runs the basic self-test. 6 | $! Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu) 7 | $! and Tim Bell (tbell@netcom.com) for their help. 8 | $! 9 | $! Read installation instructions before running this!! 10 | $! 11 | $ If F$Mode () .eqs. "INTERACTIVE" 12 | $ Then 13 | $ VERIFY = F$Verify (0) 14 | $ Else 15 | $ VERIFY = F$Verify (1) 16 | $ EndIf 17 | $ On Control_Y Then GoTo End 18 | $ On Error Then GoTo End 19 | $ 20 | $ If F$GetSyi ("HW_MODEL") .gt. 1023 21 | $ Then 22 | $ OPT = "" 23 | $ Else 24 | $ OPT = ",Sys$Disk:[]makvms.opt/Option" 25 | $ EndIf 26 | $ 27 | $ DoCompile := CC /NoDebug /Optimize /NoList 28 | $! 29 | $ DoCompile jaricom.c 30 | $ DoCompile jcapimin.c 31 | $ DoCompile jcapistd.c 32 | $ DoCompile jcarith.c 33 | $ DoCompile jctrans.c 34 | $ DoCompile jcparam.c 35 | $ DoCompile jdatadst.c 36 | $ DoCompile jcinit.c 37 | $ DoCompile jcmaster.c 38 | $ DoCompile jcmarker.c 39 | $ DoCompile jcmainct.c 40 | $ DoCompile jcprepct.c 41 | $ DoCompile jccoefct.c 42 | $ DoCompile jccolor.c 43 | $ DoCompile jcsample.c 44 | $ DoCompile jchuff.c 45 | $ DoCompile jcdctmgr.c 46 | $ DoCompile jfdctfst.c 47 | $ DoCompile jfdctflt.c 48 | $ DoCompile jfdctint.c 49 | $ DoCompile jdapimin.c 50 | $ DoCompile jdapistd.c 51 | $ DoCompile jdarith.c 52 | $ DoCompile jdtrans.c 53 | $ DoCompile jdatasrc.c 54 | $ DoCompile jdmaster.c 55 | $ DoCompile jdinput.c 56 | $ DoCompile jdmarker.c 57 | $ DoCompile jdhuff.c 58 | $ DoCompile jdmainct.c 59 | $ DoCompile jdcoefct.c 60 | $ DoCompile jdpostct.c 61 | $ DoCompile jddctmgr.c 62 | $ DoCompile jidctfst.c 63 | $ DoCompile jidctflt.c 64 | $ DoCompile jidctint.c 65 | $ DoCompile jdsample.c 66 | $ DoCompile jdcolor.c 67 | $ DoCompile jquant1.c 68 | $ DoCompile jquant2.c 69 | $ DoCompile jdmerge.c 70 | $ DoCompile jcomapi.c 71 | $ DoCompile jutils.c 72 | $ DoCompile jerror.c 73 | $ DoCompile jmemmgr.c 74 | $ DoCompile jmemnobs.c 75 | $! 76 | $ Library /Create libjpeg.olb jaricom.obj,jcapimin.obj,jcapistd.obj, - 77 | jcarith.obj,jctrans.obj,jcparam.obj,jdatadst.obj,jcinit.obj, - 78 | jcmaster.obj,jcmarker.obj,jcmainct.obj,jcprepct.obj,jccoefct.obj, - 79 | jccolor.obj,jcsample.obj,jchuff.obj,jcdctmgr.obj,jfdctfst.obj, - 80 | jfdctflt.obj,jfdctint.obj,jdapimin.obj,jdapistd.obj,jdarith.obj, - 81 | jdtrans.obj,jdatasrc.obj,jdmaster.obj,jdinput.obj,jdmarker.obj, - 82 | jdhuff.obj,jdmainct.obj,jdcoefct.obj,jdpostct.obj,jddctmgr.obj, - 83 | jidctfst.obj,jidctflt.obj,jidctint.obj,jdsample.obj,jdcolor.obj, - 84 | jquant1.obj,jquant2.obj,jdmerge.obj,jcomapi.obj,jutils.obj, - 85 | jerror.obj,jmemmgr.obj,jmemnobs.obj 86 | $! 87 | $ DoCompile cjpeg.c 88 | $ DoCompile rdppm.c 89 | $ DoCompile rdgif.c 90 | $ DoCompile rdtarga.c 91 | $ DoCompile rdrle.c 92 | $ DoCompile rdbmp.c 93 | $ DoCompile rdswitch.c 94 | $ DoCompile cdjpeg.c 95 | $! 96 | $ Link /NoMap /Executable = cjpeg.exe cjpeg.obj,rdppm.obj,rdgif.obj, - 97 | rdtarga.obj,rdrle.obj,rdbmp.obj,rdswitch.obj,cdjpeg.obj,libjpeg.olb/Library'OPT' 98 | $! 99 | $ DoCompile djpeg.c 100 | $ DoCompile wrppm.c 101 | $ DoCompile wrgif.c 102 | $ DoCompile wrtarga.c 103 | $ DoCompile wrrle.c 104 | $ DoCompile wrbmp.c 105 | $ DoCompile rdcolmap.c 106 | $ DoCompile cdjpeg.c 107 | $! 108 | $ Link /NoMap /Executable = djpeg.exe djpeg.obj,wrppm.obj,wrgif.obj, - 109 | wrtarga.obj,wrrle.obj,wrbmp.obj,rdcolmap.obj,cdjpeg.obj,libjpeg.olb/Library'OPT' 110 | $! 111 | $ DoCompile jpegtran.c 112 | $ DoCompile rdswitch.c 113 | $ DoCompile cdjpeg.c 114 | $ DoCompile transupp.c 115 | $! 116 | $ Link /NoMap /Executable = jpegtran.exe jpegtran.obj,rdswitch.obj, - 117 | cdjpeg.obj,transupp.obj,libjpeg.olb/Library'OPT' 118 | $! 119 | $ DoCompile rdjpgcom.c 120 | $ Link /NoMap /Executable = rdjpgcom.exe rdjpgcom.obj'OPT' 121 | $! 122 | $ DoCompile wrjpgcom.c 123 | $ Link /NoMap /Executable = wrjpgcom.exe wrjpgcom.obj'OPT' 124 | $! 125 | $! Run the self-test 126 | $! 127 | $ mcr sys$disk:[]djpeg -dct int -ppm -outfile testout.ppm testorig.jpg 128 | $ mcr sys$disk:[]djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg 129 | $ mcr sys$disk:[]cjpeg -dct int -outfile testout.jpg testimg.ppm 130 | $ mcr sys$disk:[]djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg 131 | $ mcr sys$disk:[]cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm 132 | $ mcr sys$disk:[]jpegtran -outfile testoutt.jpg testprog.jpg 133 | $ Backup /Compare/Log testimg.ppm testout.ppm 134 | $ Backup /Compare/Log testimg.bmp testout.bmp 135 | $ Backup /Compare/Log testimg.jpg testout.jpg 136 | $ Backup /Compare/Log testimg.ppm testoutp.ppm 137 | $ Backup /Compare/Log testimgp.jpg testoutp.jpg 138 | $ Backup /Compare/Log testorig.jpg testoutt.jpg 139 | $! 140 | $End: 141 | $ If Verify Then Set Verify 142 | $ Exit 143 | -------------------------------------------------------------------------------- /src/libjpeg/makejdep.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makejdep.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makejdsp.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makejdsp.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makejdsw.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makejdsw.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makejfil.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makejfil.v16 -------------------------------------------------------------------------------- /src/libjpeg/makejmak.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makejmak.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makejsln.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makejsln.v16 -------------------------------------------------------------------------------- /src/libjpeg/makejvcx.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makejvcx.v16 -------------------------------------------------------------------------------- /src/libjpeg/makerdep.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makerdep.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makerdsp.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makerdsp.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makerfil.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makerfil.v16 -------------------------------------------------------------------------------- /src/libjpeg/makermak.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makermak.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makervcx.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makervcx.v16 -------------------------------------------------------------------------------- /src/libjpeg/maketdep.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/maketdep.vc6 -------------------------------------------------------------------------------- /src/libjpeg/maketdsp.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/maketdsp.vc6 -------------------------------------------------------------------------------- /src/libjpeg/maketfil.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/maketfil.v16 -------------------------------------------------------------------------------- /src/libjpeg/maketmak.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/maketmak.vc6 -------------------------------------------------------------------------------- /src/libjpeg/maketvcx.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/maketvcx.v16 -------------------------------------------------------------------------------- /src/libjpeg/makewdep.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makewdep.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makewdsp.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makewdsp.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makewfil.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makewfil.v16 -------------------------------------------------------------------------------- /src/libjpeg/makewmak.vc6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makewmak.vc6 -------------------------------------------------------------------------------- /src/libjpeg/makewvcx.v16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/makewvcx.v16 -------------------------------------------------------------------------------- /src/libjpeg/makljpeg.st: -------------------------------------------------------------------------------- 1 | ; Project file for Independent JPEG Group's software 2 | ; 3 | ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. 4 | ; Thanks to Frank Moehle, B. Setzepfandt, and Guido Vollbeding. 5 | ; 6 | ; To use this file, rename it to libjpeg.prj. 7 | ; Read installation instructions before trying to make the program! 8 | ; 9 | ; 10 | ; * * * Output file * * * 11 | libjpeg.lib 12 | ; 13 | ; * * * COMPILER OPTIONS * * * 14 | .C[-P] ; absolute calls 15 | .C[-M] ; and no string merging, folks 16 | .C[-w-cln] ; no "constant is long" warnings 17 | .C[-w-par] ; no "parameter xxxx unused" 18 | .C[-w-rch] ; no "unreachable code" 19 | .C[-wsig] ; warn if significant digits may be lost 20 | .L[-J] ; link new Obj-format (so we get a library) 21 | = 22 | ; * * * * List of modules * * * * 23 | jaricom.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 24 | jcapimin.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 25 | jcapistd.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 26 | jcarith.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 27 | jccoefct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 28 | jccolor.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 29 | jcdctmgr.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 30 | jchuff.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 31 | jcinit.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 32 | jcmainct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 33 | jcmarker.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 34 | jcmaster.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 35 | jcomapi.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 36 | jcparam.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 37 | jcprepct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 38 | jcsample.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 39 | jctrans.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 40 | jdapimin.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 41 | jdapistd.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 42 | jdarith.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 43 | jdatadst.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h) 44 | jdatasrc.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h) 45 | jdcoefct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 46 | jdcolor.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 47 | jddctmgr.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 48 | jdhuff.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 49 | jdinput.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 50 | jdmainct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 51 | jdmarker.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 52 | jdmaster.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 53 | jdmerge.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 54 | jdpostct.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 55 | jdsample.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 56 | jdtrans.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 57 | jerror.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jversion.h,jerror.h) 58 | jfdctflt.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 59 | jfdctfst.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 60 | jfdctint.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 61 | jidctflt.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 62 | jidctfst.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 63 | jidctint.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jdct.h) 64 | jquant1.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 65 | jquant2.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 66 | jutils.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h) 67 | jmemmgr.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jmemsys.h) 68 | jmemansi.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,jmemsys.h) 69 | -------------------------------------------------------------------------------- /src/libjpeg/maktjpeg.st: -------------------------------------------------------------------------------- 1 | ; Project file for Independent JPEG Group's software 2 | ; 3 | ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. 4 | ; Thanks to Frank Moehle, B. Setzepfandt, and Guido Vollbeding. 5 | ; 6 | ; To use this file, rename it to jpegtran.prj. 7 | ; If you are using Turbo C, change filenames beginning with "pc..." to "tc..." 8 | ; Read installation instructions before trying to make the program! 9 | ; 10 | ; 11 | ; * * * Output file * * * 12 | jpegtran.ttp 13 | ; 14 | ; * * * COMPILER OPTIONS * * * 15 | .C[-P] ; absolute calls 16 | .C[-M] ; and no string merging, folks 17 | .C[-w-cln] ; no "constant is long" warnings 18 | .C[-w-par] ; no "parameter xxxx unused" 19 | .C[-w-rch] ; no "unreachable code" 20 | .C[-wsig] ; warn if significant digits may be lost 21 | = 22 | ; * * * * List of modules * * * * 23 | pcstart.o 24 | jpegtran.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,transupp.h,jversion.h) 25 | cdjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 26 | rdswitch.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) 27 | transupp.c (jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jpegint.h,jerror.h,transupp.h) 28 | libjpeg.lib ; built by libjpeg.prj 29 | pcstdlib.lib ; standard library 30 | pcextlib.lib ; extended library 31 | -------------------------------------------------------------------------------- /src/libjpeg/makvms.opt: -------------------------------------------------------------------------------- 1 | ! A pointer to the VAX/VMS C Run-Time Shareable Library. 2 | ! This file is needed by makefile.mms and makefile.vms, 3 | ! but only for the older VAX C compiler. DEC C does not need it. 4 | Sys$Library:VAXCRTL.EXE /Share 5 | -------------------------------------------------------------------------------- /src/libjpeg/rdjpgcom.1: -------------------------------------------------------------------------------- 1 | .TH RDJPGCOM 1 "13 September 2013" 2 | .SH NAME 3 | rdjpgcom \- display text comments from a JPEG file 4 | .SH SYNOPSIS 5 | .B rdjpgcom 6 | [ 7 | .B \-raw 8 | ] 9 | [ 10 | .B \-verbose 11 | ] 12 | [ 13 | .I filename 14 | ] 15 | .LP 16 | .SH DESCRIPTION 17 | .LP 18 | .B rdjpgcom 19 | reads the named JPEG/JFIF file, or the standard input if no file is named, 20 | and prints any text comments found in the file on the standard output. 21 | .PP 22 | The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file. 23 | Although the standard doesn't actually define what COM blocks are for, they 24 | are widely used to hold user-supplied text strings. This lets you add 25 | annotations, titles, index terms, etc to your JPEG files, and later retrieve 26 | them as text. COM blocks do not interfere with the image stored in the JPEG 27 | file. The maximum size of a COM block is 64K, but you can have as many of 28 | them as you like in one JPEG file. 29 | .SH OPTIONS 30 | .TP 31 | .B \-raw 32 | Normally 33 | .B rdjpgcom 34 | escapes non-printable characters in comments, for security reasons. 35 | This option avoids that. 36 | .PP 37 | .B \-verbose 38 | Causes 39 | .B rdjpgcom 40 | to also display the JPEG image dimensions. 41 | .PP 42 | Switch names may be abbreviated, and are not case sensitive. 43 | .SH HINTS 44 | .B rdjpgcom 45 | does not depend on the IJG JPEG library. Its source code is intended as an 46 | illustration of the minimum amount of code required to parse a JPEG file 47 | header correctly. 48 | .PP 49 | In 50 | .B \-verbose 51 | mode, 52 | .B rdjpgcom 53 | will also attempt to print the contents of any "APP12" markers as text. 54 | Some digital cameras produce APP12 markers containing useful textual 55 | information. If you like, you can modify the source code to print 56 | other APPn marker types as well. 57 | .SH SEE ALSO 58 | .BR cjpeg (1), 59 | .BR djpeg (1), 60 | .BR jpegtran (1), 61 | .BR wrjpgcom (1) 62 | .SH AUTHOR 63 | Independent JPEG Group 64 | -------------------------------------------------------------------------------- /src/libjpeg/testimg.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/testimg.bmp -------------------------------------------------------------------------------- /src/libjpeg/testimg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/testimg.gif -------------------------------------------------------------------------------- /src/libjpeg/testimg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/testimg.jpg -------------------------------------------------------------------------------- /src/libjpeg/testimg.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/testimg.ppm -------------------------------------------------------------------------------- /src/libjpeg/testimgp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/testimgp.jpg -------------------------------------------------------------------------------- /src/libjpeg/testorig.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/testorig.jpg -------------------------------------------------------------------------------- /src/libjpeg/testprog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/libjpeg/testprog.jpg -------------------------------------------------------------------------------- /src/libjpeg/wrjpgcom.1: -------------------------------------------------------------------------------- 1 | .TH WRJPGCOM 1 "15 June 1995" 2 | .SH NAME 3 | wrjpgcom \- insert text comments into a JPEG file 4 | .SH SYNOPSIS 5 | .B wrjpgcom 6 | [ 7 | .B \-replace 8 | ] 9 | [ 10 | .BI \-comment " text" 11 | ] 12 | [ 13 | .BI \-cfile " name" 14 | ] 15 | [ 16 | .I filename 17 | ] 18 | .LP 19 | .SH DESCRIPTION 20 | .LP 21 | .B wrjpgcom 22 | reads the named JPEG/JFIF file, or the standard input if no file is named, 23 | and generates a new JPEG/JFIF file on standard output. A comment block is 24 | added to the file. 25 | .PP 26 | The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file. 27 | Although the standard doesn't actually define what COM blocks are for, they 28 | are widely used to hold user-supplied text strings. This lets you add 29 | annotations, titles, index terms, etc to your JPEG files, and later retrieve 30 | them as text. COM blocks do not interfere with the image stored in the JPEG 31 | file. The maximum size of a COM block is 64K, but you can have as many of 32 | them as you like in one JPEG file. 33 | .PP 34 | .B wrjpgcom 35 | adds a COM block, containing text you provide, to a JPEG file. 36 | Ordinarily, the COM block is added after any existing COM blocks; but you 37 | can delete the old COM blocks if you wish. 38 | .SH OPTIONS 39 | Switch names may be abbreviated, and are not case sensitive. 40 | .TP 41 | .B \-replace 42 | Delete any existing COM blocks from the file. 43 | .TP 44 | .BI \-comment " text" 45 | Supply text for new COM block on command line. 46 | .TP 47 | .BI \-cfile " name" 48 | Read text for new COM block from named file. 49 | .PP 50 | If you have only one line of comment text to add, you can provide it on the 51 | command line with 52 | .BR \-comment . 53 | The comment text must be surrounded with quotes so that it is treated as a 54 | single argument. Longer comments can be read from a text file. 55 | .PP 56 | If you give neither 57 | .B \-comment 58 | nor 59 | .BR \-cfile , 60 | then 61 | .B wrjpgcom 62 | will read the comment text from standard input. (In this case an input image 63 | file name MUST be supplied, so that the source JPEG file comes from somewhere 64 | else.) You can enter multiple lines, up to 64KB worth. Type an end-of-file 65 | indicator (usually control-D) to terminate the comment text entry. 66 | .PP 67 | .B wrjpgcom 68 | will not add a COM block if the provided comment string is empty. Therefore 69 | \fB\-replace \-comment ""\fR can be used to delete all COM blocks from a file. 70 | .SH EXAMPLES 71 | .LP 72 | Add a short comment to in.jpg, producing out.jpg: 73 | .IP 74 | .B wrjpgcom \-c 75 | \fI"View of my back yard" in.jpg 76 | .B > 77 | .I out.jpg 78 | .PP 79 | Attach a long comment previously stored in comment.txt: 80 | .IP 81 | .B wrjpgcom 82 | .I in.jpg 83 | .B < 84 | .I comment.txt 85 | .B > 86 | .I out.jpg 87 | .PP 88 | or equivalently 89 | .IP 90 | .B wrjpgcom 91 | .B -cfile 92 | .I comment.txt 93 | .B < 94 | .I in.jpg 95 | .B > 96 | .I out.jpg 97 | .SH SEE ALSO 98 | .BR cjpeg (1), 99 | .BR djpeg (1), 100 | .BR jpegtran (1), 101 | .BR rdjpgcom (1) 102 | .SH AUTHOR 103 | Independent JPEG Group 104 | -------------------------------------------------------------------------------- /src/torchjpeg/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | torchjpeg 3 | ==================================== 4 | torchjpeg provides an API for accessing low-level JPEG related constructs directly from pytorch. 5 | """ 6 | -------------------------------------------------------------------------------- /src/torchjpeg/codec/__init__.py: -------------------------------------------------------------------------------- 1 | r""" 2 | Provides access to low-level JPEG operations using libjpeg. 3 | By using libjpeg directly, coefficients can be loaded or saved to JPEG files directly with needing to be recomputed. 4 | In addtion to the C++ implemented low-level operations, two python convenience functions are exported that can decode the ressulting coefficients to pixels. 5 | """ 6 | from typing import Optional 7 | 8 | import torch 9 | from torch import Tensor 10 | from torch.nn.functional import interpolate 11 | 12 | from torchjpeg.dct import block_idct, deblockify, double_nn_dct, to_rgb 13 | 14 | from ._codec_ops import * # pylint: disable=import-error 15 | 16 | __all__ = ["read_coefficients", "write_coefficients", "quantize_at_quality", "pixels_for_channel", "reconstruct_full_image"] # pylint: disable=undefined-all-variable 17 | 18 | 19 | def pixels_for_channel(channel: Tensor, quantization: Tensor, crop: Optional[Tensor] = None) -> Tensor: 20 | r""" 21 | Converts a single channel of quantized DCT coefficients into pixels. 22 | 23 | Args 24 | ---------- 25 | channel : torch.Tensor 26 | A :math:`\left(1, \frac{H}{8}, \frac{W}{8}, 8, 8 \right)` Tensor of quantized DCT coefficients. 27 | quantization : torch.Tensor 28 | An (8, 8) Tensor of the quantization matrix that was used to quantize :code:`channel`. 29 | crop : torch.Tensor 30 | An optional (2) Tensor of containing the `$\left(H, W \right)$` original sizes of the image channel stored in :code:`channel`. The pixel result will be cropped to this size. 31 | 32 | Returns 33 | ------- 34 | torch.Tensor 35 | A :math:`\left(H, W \right)` Tensor containing the pixel values of the channel in [0, 1] 36 | 37 | Note 38 | ----- 39 | This function takes inputs in the same format as returned by :py:func:`read_coefficients` separated into a single channel. 40 | """ 41 | dequantized = channel.float() * quantization.float() 42 | 43 | s = block_idct(dequantized) + 128 44 | s = s.view(1, 1, s.shape[1] * s.shape[2], 8, 8) 45 | s = deblockify(s, (channel.shape[1] * 8, channel.shape[2] * 8)) 46 | s = s.squeeze() 47 | 48 | if crop is not None: 49 | s = s[: int(crop[0]), : int(crop[1])] 50 | 51 | return s 52 | 53 | 54 | def reconstruct_full_image(y_coefficients: Tensor, quantization: Tensor, cbcr_coefficients: Optional[Tensor] = None, crop: Optional[Tensor] = None) -> Tensor: 55 | r""" 56 | Converts quantized DCT coefficients into an image. 57 | 58 | This function is designed to work on the output of :py:func:`read_coefficients` and py:func:`quantize_at_quality`. Note that the color channel coefficients 59 | will be upsampled by 2 as chroma subsampling is currently assumed. If the image is color, it will be converted from YCbCr to RGB. 60 | 61 | Parameters 62 | ---------- 63 | y_coefficients : torch.Tensor 64 | A :math:`\left(1, \frac{H}{8}, \frac{W}{8}, 8, 8 \right)` Tensor of quantized Y channel DCT coefficients. 65 | quantization : torch.Tensor 66 | A :math:`\left(C, 8, 8 \right)` Tensor of quantization matrices for each channel. 67 | cbcr_coefficients : Optional[torch.Tensor] 68 | A :math:`\left(2, \frac{H}{8}, \frac{W}{8}, 8, 8 \right)` Tensor of quantized color channel DCT coeffcients. 69 | crop : Optional[torch.Tensor] 70 | A :math:`\left(C, 2 \right)` Tensor containing the :math:`\left(H, W \right)` dimensions of the image that produced the given DCT coefficients, the pixel result will be cropped to this size. 71 | 72 | Returns 73 | ------- 74 | torch.Tensor 75 | A :math:`\left(C, H, W \right)` Tensor containing the image pixels in pytorch format (normalized to [0, 1]) 76 | """ 77 | y = pixels_for_channel(y_coefficients, quantization[0], crop[0] if crop is not None else None) 78 | 79 | if cbcr_coefficients is not None: 80 | cb = pixels_for_channel(cbcr_coefficients[0:1], quantization[1], crop[1] if crop is not None else None) 81 | cr = pixels_for_channel(cbcr_coefficients[1:2], quantization[2], crop[2] if crop is not None else None) 82 | 83 | cb = interpolate(cb.unsqueeze(0).unsqueeze(0), y.shape, mode="nearest") 84 | cr = interpolate(cr.unsqueeze(0).unsqueeze(0), y.shape, mode="nearest") 85 | 86 | out = torch.cat([y.unsqueeze(0).unsqueeze(0), cb, cr], dim=1) 87 | out = to_rgb(out).squeeze() 88 | else: 89 | out = y 90 | 91 | return out.clamp(0, 255) / 255.0 92 | -------------------------------------------------------------------------------- /src/torchjpeg/data/__init__.py: -------------------------------------------------------------------------------- 1 | from .folder_of_jpeg_dataset import FolderOfJpegDataset 2 | from .image_list import ImageList, crop_batch 3 | from .jpeg_quantized_dataset import JPEGQuantizedDataset 4 | from .unlabeled_image_folder import UnlabeledImageFolder 5 | 6 | __all__ = ["ImageList", "crop_batch", "JPEGQuantizedDataset", "FolderOfJpegDataset", "UnlabeledImageFolder"] 7 | -------------------------------------------------------------------------------- /src/torchjpeg/data/folder_of_jpeg_dataset.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from typing import Sequence, Tuple, Union 3 | 4 | import torch 5 | from torch import Tensor 6 | 7 | import torchjpeg.codec 8 | from torchjpeg.dct import Stats 9 | 10 | from .image_list import ImageList 11 | from .jpeg_quantized_dataset import _prep_coefficients 12 | 13 | 14 | class FolderOfJpegDataset(torch.utils.data.Dataset): 15 | """ 16 | Loads coefficents from a folder of JPEG without any labels. For each image, it returns the format of :py:func:`torchjpeg.codec.read_coefficients`. The 17 | images must be actualy JPEG files (stored as JPEGs) for this to work. The relative path to the JPEG file will be returned along with the coefficients. The 18 | coefficients themselves are not guaranteed to be the same size, use the collate function to collate these into a batched Tensor by adding padding. 19 | 20 | Args: 21 | path (Path): The path to load images from 22 | stats (Stats): DCT stats to use to normalize the coefficients 23 | extensions (List[str]): The JPEG file extensions to search for 24 | """ 25 | 26 | def __init__(self, path: Union[str, Path], stats: Stats, extensions: Sequence[str] = [".jpg", ".jpeg", ".JPEG"]): 27 | # pylint: disable=dangerous-default-value 28 | if isinstance(path, str): 29 | path = Path(path) 30 | 31 | self.path = path 32 | self.stats = stats 33 | 34 | if path.is_dir(): 35 | self.images = list(filter(lambda p: p.suffix in extensions, path.glob("**/*"))) 36 | else: 37 | self.images = [path] 38 | 39 | def __len__(self): 40 | return len(self.images) 41 | 42 | def __getitem__(self, idx): 43 | image = self.images[idx] 44 | 45 | dim, quantization, Y_coefficients, CbCr_coefficients = torchjpeg.codec.read_coefficients(str(image)) # type: ignore 46 | 47 | y_dequantized, cbcr_dequantized, y_q, c_q = _prep_coefficients(quantization, Y_coefficients, CbCr_coefficients, self.stats) 48 | 49 | return y_dequantized.squeeze(0), cbcr_dequantized.squeeze(0), y_q.unsqueeze(0), c_q.unsqueeze(0), image.relative_to(self.path), dim[0] 50 | 51 | @staticmethod 52 | def collate(batch_list: Sequence[Tuple[Tensor, Tensor, Tensor, Tensor, Path, Tensor]]) -> Tuple[Tensor, Tensor, Tensor, Tensor, Sequence[Path], Tensor]: 53 | """ 54 | Custom collate function which works for return values from this dataset. Adds padding to the images so that they can be stored in a single tensor 55 | 56 | Args: 57 | batch_list: Output from this dataset 58 | 59 | Returns: 60 | Batch with each input collated into single tensors 61 | """ 62 | y_coefs = [] 63 | cbcr_coefs = [] 64 | 65 | yqs = torch.stack([b[2] for b in batch_list]) 66 | cqs = torch.stack([b[3] for b in batch_list]) 67 | sizes = torch.stack([b[5] for b in batch_list]) 68 | 69 | paths = [b[4] for b in batch_list] 70 | 71 | for b in batch_list: 72 | y_coefs.append(b[0]) 73 | cbcr_coefs.append(b[1]) 74 | 75 | y_coefs_t = ImageList.from_tensors(y_coefs).tensor 76 | cbcr_coefs_t = ImageList.from_tensors(cbcr_coefs).tensor 77 | 78 | return y_coefs_t, cbcr_coefs_t, yqs, cqs, paths, sizes 79 | -------------------------------------------------------------------------------- /src/torchjpeg/data/image_list.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from typing import Any, List, Sequence, Tuple 4 | 5 | import torch 6 | from torch import Tensor 7 | from torch.nn import functional as F 8 | 9 | 10 | class ImageList: 11 | """ 12 | Structure that holds a list of images (of possibly 13 | varying sizes) as a single tensor. 14 | This works by padding the images to the same size, 15 | and storing in a field the original sizes of each image 16 | 17 | Attributes: 18 | image_sizes (list[tuple[int, int]]): each tuple is (h, w) 19 | 20 | Note: 21 | This class was taken from detectron2 (https://github.com/facebookresearch/detectron2/blob/master/detectron2/structures/image_list.py) with 22 | a small modification to the padding function which preserves gradients and some small fixes for linting and type checking. 23 | Otherwise the class and its documentation of unchanged. 24 | """ 25 | 26 | def __init__(self, tensor: torch.Tensor, image_sizes: List[Tuple[int, int]]): 27 | """ 28 | Arguments: 29 | tensor (Tensor): of shape (N, H, W) or (N, C_1, ..., C_K, H, W) where K >= 1 30 | image_sizes (list[tuple[int, int]]): Each tuple is (h, w). It can 31 | be smaller than (H, W) due to padding. 32 | """ 33 | self.tensor = tensor 34 | self.image_sizes = image_sizes 35 | 36 | def __len__(self) -> int: 37 | return len(self.image_sizes) 38 | 39 | def __getitem__(self, idx) -> torch.Tensor: 40 | """ 41 | Access the individual image in its original size. 42 | 43 | Args: 44 | idx: int or slice 45 | 46 | Returns: 47 | Tensor: an image of shape (H, W) or (C_1, ..., C_K, H, W) where K >= 1 48 | """ 49 | size = self.image_sizes[idx] 50 | return self.tensor[idx, ..., : size[0], : size[1]] 51 | 52 | @torch.jit.unused 53 | def to(self, *args: Any, **kwargs: Any) -> "ImageList": 54 | """ 55 | Implements the device API for ImageLists by copying the underyling storage to the target device 56 | 57 | Args: 58 | All arguments are forwarded to the underlying tensor storage :py:func:`torch.Tensor.to` 59 | 60 | Returns: 61 | ImageList: The imagelist object on the new device 62 | """ 63 | cast_tensor = self.tensor.to(*args, **kwargs) 64 | return ImageList(cast_tensor, self.image_sizes) 65 | 66 | @property 67 | def device(self) -> torch.device: 68 | """ 69 | Implements the device API for ImageLists by returning the underlying device 70 | 71 | Returns: 72 | torch.device: The device that the underlying tensor storage resides on 73 | """ 74 | return self.tensor.device 75 | 76 | @staticmethod 77 | # https://github.com/pytorch/pytorch/issues/39308 78 | @torch.jit.unused 79 | def from_tensors( 80 | tensors: Sequence[torch.Tensor], 81 | size_divisibility: int = 0, 82 | pad_value: float = 0.0, 83 | ) -> "ImageList": 84 | """ 85 | Args: 86 | tensors: a tuple or list of `torch.Tensors`, each of shape (Hi, Wi) or 87 | (C_1, ..., C_K, Hi, Wi) where K >= 1. The Tensors will be padded 88 | to the same shape with `pad_value`. 89 | size_divisibility (int): If `size_divisibility > 0`, add padding to ensure 90 | the common height and width is divisible by `size_divisibility`. 91 | This depends on the model and many models need a divisibility of 32. 92 | pad_value (float): value to pad 93 | 94 | Returns: 95 | an `ImageList`. 96 | """ 97 | assert len(tensors) > 0 98 | assert isinstance(tensors, (tuple, list)) 99 | for t in tensors: 100 | assert isinstance(t, torch.Tensor), type(t) 101 | assert t.shape[1:-2] == tensors[0].shape[1:-2], t.shape 102 | # per dimension maximum (H, W) or (C_1, ..., C_K, H, W) where K >= 1 among all tensors 103 | max_size = ( 104 | # In tracing mode, x.shape[i] is Tensor, and should not be converted 105 | # to int: this will cause the traced graph to have hard-coded shapes. 106 | # Instead we should make max_size a Tensor that depends on these tensors. 107 | # Using torch.stack twice seems to be the best way to convert 108 | # list[list[ScalarTensor]] to a Tensor 109 | torch.stack([torch.stack([torch.as_tensor(dim) for dim in size]) for size in [tuple(img.shape) for img in tensors]]) 110 | .max(0) 111 | .values 112 | ) 113 | 114 | if size_divisibility > 1: 115 | stride = size_divisibility 116 | # the last two dims are H,W, both subject to divisibility requirement 117 | max_size = torch.cat([max_size[:-2], (max_size[-2:] + (stride - 1)) // stride * stride]) 118 | 119 | image_sizes = [(int(im.shape[-2]), int(im.shape[-1])) for im in tensors] 120 | 121 | if len(tensors) == 1: 122 | # This seems slightly (2%) faster. 123 | image_size = image_sizes[0] 124 | padding_size = [ 125 | 0, 126 | int(max_size[-1] - image_size[1]), 127 | 0, 128 | int(max_size[-2] - image_size[0]), 129 | ] 130 | if all(x == 0 for x in padding_size): # https://github.com/pytorch/pytorch/issues/31734 131 | batched_imgs = tensors[0].unsqueeze(0) 132 | else: 133 | padded = F.pad(tensors[0], padding_size, value=pad_value) 134 | batched_imgs = padded.unsqueeze_(0) 135 | else: 136 | # max_size can be a tensor in tracing mode, therefore use tuple() 137 | batched_imgs = [] 138 | for i, img in enumerate(tensors): 139 | image_size = image_sizes[i] 140 | padding_size = [ 141 | 0, 142 | int(max_size[-1] - image_size[1]), 143 | 0, 144 | int(max_size[-2] - image_size[0]), 145 | ] 146 | 147 | padded = F.pad(img, padding_size, value=pad_value) 148 | batched_imgs.append(padded) 149 | 150 | batched_imgs = torch.stack(batched_imgs) 151 | 152 | return ImageList(batched_imgs.contiguous(), image_sizes) 153 | 154 | 155 | def crop_batch(batch: Tensor, sizes: Tensor) -> Sequence[Tensor]: 156 | """ 157 | Crops a batch of images to their original size, removing any padding 158 | 159 | Args: 160 | batch (Tensor): A batch of shape :math:`(N, C, H, W)` of images which may have been padded either by JPEG or to make them the same size 161 | sizes (Tensor): A tensor of shape :math:`(N, M)` where the height and width of image `i` respecively are stored at position `[i, -1]` and `[i, -2]`. 162 | 163 | Returns: 164 | Sequence of Tensors: A list of the cropped images, potentially all with different sizes. 165 | """ 166 | return [batch[i, :, : int(sizes[i, -2]), : int(sizes[i, -1])] for i in range(len(batch))] 167 | -------------------------------------------------------------------------------- /src/torchjpeg/data/transforms/__init__.py: -------------------------------------------------------------------------------- 1 | from io import BytesIO 2 | from random import randint 3 | from typing import Tuple 4 | 5 | from PIL import Image 6 | 7 | 8 | class YChannel: 9 | r""" 10 | Converts a tensor with a color image in [0, 1] to the Y channel using ITU-R BT.601 conversion 11 | 12 | Warning: 13 | This is **not** equivalent to the Y channel of a color image that would be used by JPEG, the result 14 | is in [16, 240] following the ITU-R BT.601 standard before normalization. This is useful for certian JPEG artifact correction 15 | algorithms due to some questionable evaluation choices by that community. The result **is** normalized to :math:`\left[\frac{16}{255},\frac{240}{255}\right]` 16 | before being returned. 17 | """ 18 | 19 | def __init__(self): 20 | pass 21 | 22 | def __call__(self, tensor): 23 | if tensor.shape[0] == 3: 24 | tensor = tensor * 255 25 | tensor = 16.0 + tensor[0, :, :] * 65.481 / 255.0 + tensor[1, :, :] * 128.553 / 255.0 + tensor[2, :, :] * 24.966 / 255.0 26 | tensor = tensor.unsqueeze(0).round() / 255.0 27 | 28 | return tensor 29 | 30 | def __repr__(self): 31 | return self.__class__.__name__ + "()" 32 | 33 | 34 | class YCbCr: 35 | r""" 36 | Converts a PIL image to YCbCr color space 37 | 38 | Note: 39 | PIL follows the JPEG YCbCr color conversion giving a result in [0, 255]. 40 | """ 41 | 42 | def __init__(self): 43 | pass 44 | 45 | def __call__(self, pil_image): 46 | return pil_image.convert("YCbCr") 47 | 48 | def __repr__(self): 49 | return self.__class__.__name__ + "()" 50 | 51 | 52 | class RandomJPEG: 53 | r""" 54 | Applies JPEG compression on a PIL at a random quality. 55 | 56 | Args: 57 | quality_range (Tuple[int, int]): The quality range to choose from, inclusive on both ends. 58 | An integer in this range will be chosen at random and will be used as the compression quality setting. 59 | """ 60 | 61 | def __init__(self, quality_range: Tuple[int, int] = (0, 100)) -> None: 62 | self.quality_range = quality_range 63 | 64 | def __call__(self, pil_image): 65 | q = randint(*self.quality_range) 66 | with BytesIO() as f: 67 | pil_image.save(f, format="jpeg", quality=q) 68 | f.seek(0) 69 | output = Image.open(f) 70 | output.load() 71 | 72 | return output 73 | 74 | def __repr__(self): 75 | return f"{self.__class__.__name__} ({self.quality_range})" 76 | -------------------------------------------------------------------------------- /src/torchjpeg/data/unlabeled_image_folder.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from typing import Any, Callable, Optional, Sequence, Union 3 | 4 | import torch 5 | from PIL import Image 6 | 7 | 8 | class UnlabeledImageFolder(torch.utils.data.Dataset): 9 | """ 10 | Dataset loading a folder of unlabeled images recursively. The images are loaded using PIL and otherwise unchanged, add a transform to turn them into Tensors 11 | 12 | Args: 13 | path (Path): The path to load recursively from 14 | extensions (List[str]): The image extensions to look for 15 | transform: Any transform to apply to the images after loading them 16 | """ 17 | 18 | def __init__(self, path: Union[str, Path], extensions: Sequence[str] = [".bmp", ".png", ".jpg", ".ppm", ".pgm"], transform: Optional[Callable] = None) -> None: 19 | # pylint: disable=dangerous-default-value 20 | if isinstance(path, str): 21 | path = Path(path) 22 | 23 | self.path = path 24 | self.images = list(filter(lambda p: p.suffix in extensions, path.glob("**/*"))) 25 | self.transform = transform 26 | 27 | def __len__(self) -> int: 28 | return len(self.images) 29 | 30 | def __getitem__(self, idx) -> Any: 31 | im_path = self.images[idx] 32 | 33 | with open(im_path, "rb") as f: 34 | im = Image.open(f) 35 | im.load() 36 | 37 | if self.transform is not None: 38 | im = self.transform(im) 39 | 40 | return im 41 | -------------------------------------------------------------------------------- /src/torchjpeg/dct/_block.py: -------------------------------------------------------------------------------- 1 | from typing import Tuple 2 | 3 | import torch 4 | import torch.nn.functional 5 | from torch import Tensor 6 | 7 | 8 | def blockify(im: Tensor, size: int) -> Tensor: 9 | r""" 10 | Breaks an image into non-overlapping blocks of equal size. 11 | 12 | Parameters 13 | ---------- 14 | im : Tensor 15 | The image to break into blocks, must be in :math:`(N, C, H, W)` format. 16 | size : Tuple[int, int] 17 | The size of the blocks in :math:`(H, W)` format. 18 | 19 | Returns 20 | ------- 21 | A tensor containing the non-overlappng blocks in :math:`(N, C, L, H, W)` format where :math:`L` is the 22 | number of non-overlapping blocks in the image channel indexed by :math:`(N, C)` and :math:`(H, W)` matches 23 | the block size. 24 | 25 | Note 26 | ---- 27 | If the image does not split evenly into blocks of the given size, the result will have some overlap. It 28 | is the callers responsibility to pad the input to a multiple of the block size, no error will be thrown 29 | in this case. 30 | """ 31 | bs = im.shape[0] 32 | ch = im.shape[1] 33 | h = im.shape[2] 34 | w = im.shape[3] 35 | 36 | im = im.reshape(bs * ch, 1, h, w) 37 | im = torch.nn.functional.unfold(im, kernel_size=(size, size), stride=(size, size)) 38 | im = im.transpose(1, 2) 39 | im = im.reshape(bs, ch, -1, size, size) 40 | 41 | return im 42 | 43 | 44 | def deblockify(blocks: Tensor, size: Tuple[int, int]) -> Tensor: 45 | r""" 46 | Reconstructs an image given non-overlapping blocks of equal size. 47 | 48 | Args: 49 | blocks (Tensor): The non-overlapping blocks in :math:`(N, C, L, H, W)` format. 50 | size: (Tuple[int, int]): The dimensions of the original image (e.g. the desired output) 51 | in :math:`(H, W)` format. 52 | 53 | Returns: 54 | The image in :math:`(N, C, H, W)` format. 55 | 56 | Note: 57 | If the blocks have some overlap, or if the output size cannot be constructed from the given number of non-overlapping 58 | blocks, this function will raise an exception unlike :py:func:`blockify`. 59 | 60 | """ 61 | bs = blocks.shape[0] 62 | ch = blocks.shape[1] 63 | block_size = blocks.shape[3] 64 | 65 | blocks = blocks.reshape(bs * ch, -1, int(block_size**2)) 66 | blocks = blocks.transpose(1, 2) 67 | blocks = torch.nn.functional.fold(blocks, output_size=size, kernel_size=(block_size, block_size), stride=(block_size, block_size)) 68 | blocks = blocks.reshape(bs, ch, size[0], size[1]) 69 | 70 | return blocks 71 | -------------------------------------------------------------------------------- /src/torchjpeg/dct/_color.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import Tensor 3 | 4 | 5 | def to_ycbcr(x: Tensor, data_range: float = 255) -> Tensor: 6 | r""" 7 | Converts a Tensor from RGB color space to YCbCr color space 8 | 9 | Parameters 10 | ---------- 11 | x : Tensor 12 | The input Tensor holding an RGB image in :math:`(\ldots, C, H ,W)` format (where :math:`\ldots` indicates an arbitrary number of dimensions). 13 | data_range : float 14 | The range of the input/output data. i.e., 255 indicates pixels in [0, 255], 1.0 indicates pixels in [0, 1]. Only 1.0 and 255 are supported. 15 | 16 | Returns 17 | ------- 18 | Tensor 19 | The YCbCr result of the same shape as the input and with the same data range. 20 | 21 | Note 22 | ----- 23 | This function implements the "full range" conversion used by JPEG, e.g. it does **not** implement the ITU-R BT.601 standard which 24 | many libraries (excluding PIL) use as the default definition of YCbCr. This conversion (for [0, 255]) is given by: 25 | 26 | .. math:: 27 | \begin{aligned} 28 | Y&=&0&+(0.299&\cdot R)&+(0.587&\cdot G)&+(0.114&\cdot B) \\ 29 | C_{B}&=&128&-(0.168736&\cdot R)&-(0.331264&\cdot G)&+(0.5&\cdot B) \\ 30 | C_{R}&=&128&+(0.5&\cdot R)&-(0.418688&\cdot G)&-(0.081312&\cdot B) 31 | \end{aligned} 32 | 33 | """ 34 | assert data_range in [1.0, 255] 35 | 36 | # fmt: off 37 | ycbcr_from_rgb = torch.tensor([ 38 | 0.29900, 0.58700, 0.11400, 39 | -0.168735892, -0.331264108, 0.50000, 40 | 0.50000, -0.418687589, -0.081312411 41 | ], 42 | device=x.device).view(3, 3).transpose(0, 1) 43 | # fmt: on 44 | 45 | if data_range == 255: 46 | b = torch.tensor([0, 128, 128], device=x.device).view(3, 1, 1) 47 | else: 48 | b = torch.tensor([0, 0.5, 0.5], device=x.device).view(3, 1, 1) 49 | 50 | x = torch.einsum("cv,...cxy->...vxy", [ycbcr_from_rgb, x]) 51 | x += b 52 | 53 | return x.contiguous() 54 | 55 | 56 | def to_rgb(x: Tensor, data_range: float = 255) -> Tensor: 57 | r""" 58 | Converts a Tensor from YCbCr color space to RGB color space 59 | 60 | Parameters 61 | ---------- 62 | x : Tensor 63 | The input Tensor holding a YCbCr image in :math:`(\ldots, C, H ,W)` format (where :math:`\ldots` indicates an arbitrary number of dimensions). 64 | data_range : float 65 | The range of the input/output data. i.e., 255 indicates pixels in [0, 255], 1.0 indicates pixels in [0, 1]. Only 1.0 and 255 are supported. 66 | 67 | Returns 68 | ------- 69 | Tensor 70 | The RGB result of the same shape as the input and with the same data range. 71 | 72 | Note 73 | ----- 74 | This function expects the input to be "full range" conversion used by JPEG, e.g. it does **not** implement the ITU-R BT.601 standard which 75 | many libraries (excluding PIL) use as the default definition of YCbCr. If the input came from this library or from PIL it should be fine. 76 | The conversion (for [0, 255]) is given by: 77 | 78 | .. math:: 79 | \begin{aligned} 80 | R&=&Y&&&+1.402&\cdot (C_{R}-128) \\ 81 | G&=&Y&-0.344136&\cdot (C_{B}-128)&-0.714136&\cdot (C_{R}-128 ) \\ 82 | B&=&Y&+1.772&\cdot (C_{B}-128)& 83 | \end{aligned} 84 | 85 | """ 86 | assert data_range in [1.0, 255] 87 | 88 | # fmt: off 89 | rgb_from_ycbcr = torch.tensor([ 90 | 1, 0, 1.40200, 91 | 1, -0.344136286, -0.714136286, 92 | 1, 1.77200, 0 93 | ], 94 | device=x.device).view(3, 3).transpose(0, 1) 95 | # fmt: on 96 | 97 | if data_range == 255: 98 | b = torch.tensor([-179.456, 135.458816, -226.816], device=x.device).view(3, 1, 1) 99 | else: 100 | b = torch.tensor([-0.70374902, 0.531211043, -0.88947451], device=x.device).view(3, 1, 1) 101 | 102 | x = torch.einsum("cv,...cxy->...vxy", [rgb_from_ycbcr, x]) 103 | x += b 104 | 105 | return x.contiguous() 106 | -------------------------------------------------------------------------------- /src/torchjpeg/dct/_stats.py: -------------------------------------------------------------------------------- 1 | import importlib.resources 2 | from pathlib import Path 3 | from typing import Union 4 | 5 | import torch 6 | from torch import Tensor 7 | 8 | 9 | class Stats: 10 | r""" 11 | This class holds pre-computed per-channel and per-frequency DCT coefficient stats. 12 | 13 | The stats are loaded from a file, this can be written using :py:func:`torch.save`. 14 | The file should contain a single dictionary with string keys containing channel names. 15 | The value of each entry should be a dictionary with the keys: "mean, variance, min, and max" 16 | with the corresponding statistics as Tensors. 17 | 18 | Pre-computed stats are available for color or grayscale images (pass "color" and "grayscale" respectively for 19 | the root argument), these stats were computed from the Flickr 2k dataset, a large corpus of high quality images and 20 | are suitable for general use. 21 | 22 | Args: 23 | root (:py:class:`pathlib.Path`, string, or literals "color", "grayscale"): The path to load the statistics from or "color" to use built in color stats or "grayscale" to use built in grayscale stats. 24 | normtype (str): Either "ms" for mean-variance normalization or "01" for zero-one normalization. 25 | """ 26 | 27 | def __init__(self, root: Union[str, Path], normtype: str = "ms") -> None: 28 | self.type = normtype 29 | 30 | if root in ("color", "grayscale"): 31 | reader = importlib.resources.open_binary("torchjpeg.dct.stats", f"{root}.pt") 32 | else: 33 | if isinstance(root, str): 34 | root = Path(root) 35 | 36 | reader = root.open("rb") 37 | 38 | stats = torch.load(reader) 39 | 40 | self.mean = {x: stats[x]["mean"].view(1, 1, 8, 8) for x in stats.keys()} 41 | self.variance = {x: stats[x]["variance"].view(1, 1, 8, 8) for x in stats.keys()} 42 | self.std = {x: torch.sqrt(self.variance[x]) for x in stats.keys()} 43 | 44 | self.min = {x: stats[x]["min"].view(1, 1, 8, 8) for x in stats.keys()} 45 | self.max = {x: stats[x]["max"].view(1, 1, 8, 8) for x in stats.keys()} 46 | 47 | def normalize(self, blocks: Tensor, normtype: str = "y") -> Tensor: 48 | r""" 49 | Normalizes blocks of coefficients. 50 | 51 | Args: 52 | blocks (Tensor): a Tensor containing blocks of DCT coefficients in the format :math:`(N, C, L, H, W)`. 53 | normtype (str): Which channel to normalize, "y" by default. 54 | 55 | Returns: 56 | Tensor: The normalized coefficients. 57 | """ 58 | if self.type == "ms": 59 | return self._mean_variance_f(blocks, normtype) 60 | if self.type == "01": 61 | return self._zero_one_f(blocks, normtype) 62 | 63 | raise NotImplementedError(f"Unknown norm type {normtype}, must be 01 or ms") 64 | 65 | def denormalize(self, blocks: Tensor, normtype: str = "y") -> Tensor: 66 | r""" 67 | Denormalizes blocks of coefficients. 68 | 69 | Args: 70 | blocks (Tensor): a Tensor containing blocks of normalized DCT coefficients in the format :math:`(N, C, L, H, W)`. 71 | normtype (str): Which channel to denormalize, "y" by default. 72 | 73 | Returns: 74 | Tensor: The denormalized coefficients. 75 | """ 76 | if self.type == "ms": 77 | return self._mean_variance_r(blocks, normtype) 78 | if self.type == "01": 79 | return self._zero_one_r(blocks, normtype) 80 | 81 | raise NotImplementedError(f"Unknown norm type {normtype}, must be 01 or ms") 82 | 83 | def _mean_variance_f(self, blocks: Tensor, normtype: str = "y") -> Tensor: 84 | m = self.mean[normtype].to(blocks.device) 85 | s = self.std[normtype].to(blocks.device) 86 | 87 | return (blocks - m) / s 88 | 89 | def _zero_one_f(self, blocks: Tensor, normtype: str = "y") -> Tensor: 90 | m = -self.min[normtype].to(blocks.device) 91 | s = self.max[normtype] - self.min[normtype] 92 | s = s.to(blocks.device) 93 | 94 | return (blocks + m) / s 95 | 96 | def _mean_variance_r(self, blocks: Tensor, normtype: str = "y") -> Tensor: 97 | s = self.std[normtype].to(blocks.device) 98 | m = self.mean[normtype].to(blocks.device) 99 | 100 | return blocks * s + m 101 | 102 | def _zero_one_r(self, blocks: Tensor, normtype: str = "y") -> Tensor: 103 | s = self.max[normtype] - self.min[normtype] 104 | s = s.to(blocks.device) 105 | m = -self.min[normtype].to(blocks.device) 106 | 107 | return blocks * s - m 108 | -------------------------------------------------------------------------------- /src/torchjpeg/dct/stats/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/torchjpeg/dct/stats/__init__.py -------------------------------------------------------------------------------- /src/torchjpeg/dct/stats/color.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/torchjpeg/dct/stats/color.pt -------------------------------------------------------------------------------- /src/torchjpeg/dct/stats/grayscale.pt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/src/torchjpeg/dct/stats/grayscale.pt -------------------------------------------------------------------------------- /src/torchjpeg/metrics/__init__.py: -------------------------------------------------------------------------------- 1 | r""" 2 | The :code:`torchjpeg.metrcs` package provides useful metrics for measuring JPEG quality. All the 3 | metrics in this package take inputs in format :math:`(N, C, H, W)` and produces outputs of format 4 | :math:`(N)` by averaging spatially and over channels. The batch dimension is not averaged. Inputs 5 | should be images in [0, 1]. 6 | """ 7 | from ._psnr import * 8 | from ._psnrb import * 9 | from ._size import * 10 | from ._ssim import * 11 | 12 | __all__ = ["psnr", "psnrb", "blocking_effect_factor", "ssim", "size"] 13 | -------------------------------------------------------------------------------- /src/torchjpeg/metrics/_psnr.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import Tensor 3 | 4 | 5 | def psnr(image: Tensor, target: Tensor) -> Tensor: 6 | r""" 7 | Computes the peak signal-to-noise ratio on a batch of images. 8 | 9 | Args: 10 | image (Tensor): Input images in format :math:`(N, C, H, W)`. 11 | target (Tensor): Target images in format :math:`(N, C, H, W)`. 12 | 13 | Returns: 14 | Tensor: PSNR for each image in the batch, of shape :math:`(N)`. 15 | 16 | Note: 17 | Peak signal-to-noise ratio is an inverse log scale of the mean squared error 18 | measured in decibels. The formula used here is 19 | 20 | .. math:: 21 | 22 | P(x, y) = 10 \log_{10}\left(\frac{1}{\text{MSE}(x, y)}\right) 23 | 24 | """ 25 | mse = torch.nn.functional.mse_loss(image, target, reduction="none") 26 | mse = mse.view(mse.shape[0], -1).mean(1) 27 | return 10 * torch.log10(1 / mse) 28 | -------------------------------------------------------------------------------- /src/torchjpeg/metrics/_psnrb.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | from torch import Tensor 4 | 5 | 6 | def blocking_effect_factor(im: Tensor) -> Tensor: 7 | r""" 8 | Computes the blocking effect factor (BEF) of an image as defined in [1]. 9 | 10 | Blocking effect factor is used as part of :py:func:`psnrb` but can also be used 11 | as an objective measure of "blockiness". 12 | 13 | Args: 14 | im (Tensor): Image of shape :math:`(N, C, H, W)`. 15 | 16 | Returns: 17 | Tensor: The BEF for each image of shape :math:`(N)`. 18 | 19 | Note: 20 | [1] Tadala, Trinadh, and Sri E. Venkata Narayana. "A Novel PSNR-B Approach for Evaluating the Quality of De-blocked Images." (2012). 21 | """ 22 | # This is a fairly complex formula we're implementing, it would be messy with fewer locals 23 | # pylint: disable=too-many-locals 24 | block_size = 8 25 | 26 | block_horizontal_positions = torch.arange(7, im.shape[3] - 1, 8) 27 | block_vertical_positions = torch.arange(7, im.shape[2] - 1, 8) 28 | 29 | horizontal_block_difference = ((im[:, :, :, block_horizontal_positions] - im[:, :, :, block_horizontal_positions + 1]) ** 2).sum(3).sum(2).sum(1) 30 | vertical_block_difference = ((im[:, :, block_vertical_positions, :] - im[:, :, block_vertical_positions + 1, :]) ** 2).sum(3).sum(2).sum(1) 31 | 32 | nonblock_horizontal_positions = np.setdiff1d(torch.arange(0, im.shape[3] - 1), block_horizontal_positions) 33 | nonblock_vertical_positions = np.setdiff1d(torch.arange(0, im.shape[2] - 1), block_vertical_positions) 34 | 35 | horizontal_nonblock_difference = ((im[:, :, :, nonblock_horizontal_positions] - im[:, :, :, nonblock_horizontal_positions + 1]) ** 2).sum(3).sum(2).sum(1) 36 | vertical_nonblock_difference = ((im[:, :, nonblock_vertical_positions, :] - im[:, :, nonblock_vertical_positions + 1, :]) ** 2).sum(3).sum(2).sum(1) 37 | 38 | n_boundary_horiz = im.shape[2] * (im.shape[3] // block_size - 1) 39 | n_boundary_vert = im.shape[3] * (im.shape[2] // block_size - 1) 40 | boundary_difference = (horizontal_block_difference + vertical_block_difference) / (n_boundary_horiz + n_boundary_vert) 41 | 42 | n_nonboundary_horiz = im.shape[2] * (im.shape[3] - 1) - n_boundary_horiz 43 | n_nonboundary_vert = im.shape[3] * (im.shape[2] - 1) - n_boundary_vert 44 | nonboundary_difference = (horizontal_nonblock_difference + vertical_nonblock_difference) / (n_nonboundary_horiz + n_nonboundary_vert) 45 | 46 | scaler = np.log2(block_size) / np.log2(min([im.shape[2], im.shape[3]])) 47 | bef = scaler * (boundary_difference - nonboundary_difference) 48 | 49 | bef[boundary_difference <= nonboundary_difference] = 0 50 | return bef 51 | 52 | 53 | def psnrb(image: Tensor, target: Tensor) -> Tensor: 54 | r""" 55 | Computes the peak signal-to-noise ratio with blocking effect factor from [1]. 56 | 57 | PSNR-B augments the PSNR measure by including the "blockiness" of the degraded image as a way to reduce 58 | the PSNR. For multichannel inputs, the PSNR-B is computed separately for each channel and then averaged. 59 | 60 | Args: 61 | image (Tensor): The input images of shape :math:`(N, C, H, W)`. 62 | target (Tensor): The target images of shape :math:`(N, C, H, W)`. 63 | 64 | Returns: 65 | Tensor: The PSNR-B of each image in the batch of shape :math:`(N)`. 66 | 67 | Warning: 68 | Unlike most metrics this is not symmetric and the order of the arguents is imporant. Blocking effect factor 69 | is only computed for the degraded image, so if the arguments are reversed, there will be very little difference 70 | between this and :py:func:`psnr`. 71 | 72 | Note: 73 | PSNR-B is computed as 74 | 75 | .. math:: 76 | P(x, y) = 10 \log_{10}\left(\frac{1}{\text{MSE}(x, y) + \text{BEF}(x)}\right) 77 | 78 | [1] Tadala, Trinadh, and Sri E. Venkata Narayana. "A Novel PSNR-B Approach for Evaluating the Quality of De-blocked Images." (2012). 79 | """ 80 | 81 | def channel_psnrb(image, target): 82 | mse = torch.nn.functional.mse_loss(image, target, reduction="none") 83 | bef = blocking_effect_factor(image) 84 | 85 | mse = mse.view(mse.shape[0], -1).mean(1) 86 | return 10 * torch.log10(1 / (mse + bef)) 87 | 88 | total = torch.stack([channel_psnrb(image[:, c : c + 1, ...], target[:, c : c + 1, ...]) for c in range(image.shape[1])]).sum(0) 89 | return total / image.shape[1] 90 | -------------------------------------------------------------------------------- /src/torchjpeg/metrics/_size.py: -------------------------------------------------------------------------------- 1 | from io import BytesIO 2 | from typing import Tuple, Union 3 | 4 | import torch 5 | from PIL import Image 6 | from torch import Tensor 7 | from torchvision.transforms.functional import to_pil_image, to_tensor 8 | 9 | 10 | def size(image: Union[Tensor, Image.Image], **kwargs) -> Tuple[Tensor, Tensor]: 11 | r""" 12 | Computes the size in bytes of a JPEG 13 | 14 | Args: 15 | image (Tensor or PIL Image): The image to compress 16 | kwargs: Arguments to pass to the PIL JPEG compressor (like quality or quantization matrices) 17 | 18 | Returns 19 | ------- 20 | Tensor 21 | A single element tensor containing the size in bytes of the image after JPEG compression 22 | Tensor 23 | The compressed image 24 | 25 | Warning: 26 | The output of this function is **not** differentiable. It compresses the image to memory and reads the size of 27 | the resulting buffer. 28 | """ 29 | if isinstance(image, Tensor): 30 | image = to_pil_image(image) 31 | 32 | with BytesIO() as f: 33 | image.save(f, "jpeg", **kwargs) 34 | f.seek(0) 35 | s = f.getbuffer().nbytes 36 | 37 | im = Image.open(f) 38 | im.load() 39 | im = to_tensor(im) 40 | 41 | return torch.tensor([s]), im 42 | -------------------------------------------------------------------------------- /src/torchjpeg/metrics/_ssim.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import Tensor 3 | 4 | 5 | def ssim_single( 6 | image: Tensor, 7 | target: Tensor, 8 | ) -> Tensor: 9 | r""" 10 | Computes SSIM for a single channel 11 | """ 12 | C1 = 0.01**2 13 | C2 = 0.03**2 14 | 15 | avg_filter = torch.ones(1, 1, 8, 8, device=image.device) / 64 16 | 17 | mu_i = torch.nn.functional.conv2d(image, avg_filter) 18 | mu_t = torch.nn.functional.conv2d(target, avg_filter) 19 | 20 | var_i = torch.nn.functional.conv2d(image**2, avg_filter) - mu_i**2 21 | var_t = torch.nn.functional.conv2d(target**2, avg_filter) - mu_t**2 22 | cov_it = torch.nn.functional.conv2d(target * image, avg_filter) - mu_i * mu_t 23 | 24 | ssim_blocks = ((2 * mu_i * mu_t + C1) * (2 * cov_it + C2)) / ((mu_i**2 + mu_t**2 + C1) * (var_i + var_t + C2)) 25 | return ssim_blocks.view(image.shape[0], -1).mean(1) 26 | 27 | 28 | def ssim(image: Tensor, target: Tensor) -> Tensor: 29 | r""" 30 | Computes the structural similarity index of two images as defined in [1]. 31 | 32 | Args: 33 | image (Tensor): The input images of shape :math:`(N, C, H, W)`. 34 | target (Tensor): The target images of shape :math:`(N, C, H, W)`. 35 | 36 | Returns: 37 | Tensor: The SSIM of each image of shape :math:`(N)`. 38 | 39 | Note: 40 | This function uses an :math:`8 \times 8` uniform averaging window used in JPEG evaluation tasks instead of the :math:`11 \times 11` gaussian window 41 | used in the original paper and by default in other SSIM implementations. 42 | 43 | [1] Wang, Zhou, et al. "Image quality assessment: from error visibility to structural similarity." IEEE transactions on image processing 13.4 (2004): 600-612. 44 | """ 45 | total = torch.stack([ssim_single(image[:, c : c + 1, :, :], target[:, c : c + 1, :, :]) for c in range(target.shape[1])]).sum(0) 46 | return total / target.shape[1] 47 | -------------------------------------------------------------------------------- /src/torchjpeg/quantization/__init__.py: -------------------------------------------------------------------------------- 1 | r""" 2 | The :py:mod:`torchjpeg.quantization` package provides functions which quantize DCT coefficients. The IJG (libjpeg) quantization matrices 3 | are included as part of this package as well as code which generates them from a scalar quality factor. Users can also provide their 4 | own quantization matrices. This implementation of the IJG quantization matrices only deals with the "baseline" setting where the 5 | maximum quantization value is 255. Functions in this module operate on single channel images since the channels are often quantized 6 | separately or may not be at the same resolution. 7 | """ 8 | 9 | 10 | from typing import Callable, Optional, Tuple 11 | 12 | import torch 13 | from torch import Tensor 14 | from torch.nn.functional import upsample 15 | 16 | from torchjpeg.dct import blockify, deblockify, double_nn_dct, half_nn_dct 17 | 18 | from . import ijg 19 | from ._quantize import dequantize, quantize 20 | 21 | 22 | def quantize_multichannel(dct: Tensor, mat: Tensor, round_func: Callable[[Tensor], Tensor] = torch.round) -> Tuple[Tensor, Tensor, Tensor]: 23 | r""" 24 | Quantizes a three channel image of DCT coefficients. 25 | 26 | Args: 27 | dct (Tensor): DCT coefficients of shape :math:`(N, 3, H, W)`. 28 | mat (Tensor): Quantization matrix of shape :math:`(1, 2, 8, 8)`. 29 | round: (Callable[[Tensor], Tensor]): Rounding function to use, defaults to :py:func:`torch.round`. 30 | 31 | Returns 32 | ------- 33 | Tensor 34 | Y channel coefficients of shape :math:`(N, 1, H, W)`. 35 | Tensor 36 | Cb channel coefficients of shape :math:`\left(N, 1, \frac{H}{2}, \frac{W}{2}\right)`. 37 | Tensor 38 | Cr channel coefficients of shape :math:`\left(N, 1, \frac{H}{2}, \frac{W}{2}\right)`. 39 | 40 | Note: 41 | This function performs chroma subsampling 42 | """ 43 | y_coefficients = dct[:, 0:1, :, :] 44 | cb_coefficients = dct[:, 1:2, :, :] 45 | cr_coefficients = dct[:, 2:3, :, :] 46 | 47 | cb_coefficients = half_nn_dct(cb_coefficients) 48 | cr_coefficients = half_nn_dct(cr_coefficients) 49 | 50 | y_coefficients = quantize( 51 | y_coefficients, 52 | mat[:, 0:1, :, :], 53 | round_func=round_func, 54 | ) 55 | cb_coefficients = quantize(cb_coefficients, mat[:, 1:2, :, :], round_func=round_func) 56 | cr_coefficients = quantize(cr_coefficients, mat[:, 1:2, :, :], round_func=round_func) 57 | 58 | return y_coefficients, cb_coefficients, cr_coefficients 59 | 60 | 61 | def dequantize_multichannel(y: Tensor, cb: Tensor, cr: Tensor, mat: Tensor) -> Tensor: 62 | r""" 63 | Dequantizes a three channel image. 64 | 65 | Args: 66 | y (Tensor): Quantized Y channel coefficients of shape :math:`(N, 1, H, W)`. 67 | cb (Tensor): Quantized Cb channel coefficients of shape :math:`\left(N, 1, \frac{H}{2}, \frac{W}{2}\right)`. 68 | cr (Tensor): Quantized Cr channel coefficients of shape :math:`\left(N, 1, \frac{H}{2}, \frac{W}{2}\right)`. 69 | 70 | Returns: 71 | Tensor: A three channel image of DCT coefficients. 72 | 73 | Note: 74 | This function assumes chroma subsampling. 75 | """ 76 | y_coefficients = dequantize(y, mat[:, 0:1, :, :]) 77 | cb_coefficients = dequantize(cb, mat[:, 1:2, :, :]) 78 | cr_coefficients = dequantize(cr, mat[:, 1:2, :, :]) 79 | 80 | cb_coefficients = double_nn_dct(cb_coefficients) 81 | cr_coefficients = double_nn_dct(cr_coefficients) 82 | 83 | coefficients = torch.cat([y_coefficients, cb_coefficients, cr_coefficients], dim=1) 84 | return coefficients 85 | 86 | 87 | __all__ = ["quantize", "dequantize", "quantize_multichannel", "dequantize_multichannel"] 88 | -------------------------------------------------------------------------------- /src/torchjpeg/quantization/_quantize.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | 3 | import torch 4 | from torch import Tensor 5 | 6 | from torchjpeg.dct import blockify, deblockify 7 | 8 | 9 | def quantize(dct: Tensor, mat: Tensor, round_func: Callable[[Tensor], Tensor] = torch.round) -> Tensor: 10 | r""" 11 | Quantizes DCT coefficients. 12 | 13 | Args: 14 | dct (Tensor): DCT coefficients of shape :math:`(N, 1, H, W)`. 15 | mat: (Tensor): Quantization matrix of shape :math:`(1, 1, 8, 8)`. 16 | round_func: (Callable[[Tensor], Tensor]): Rounding function to use, defaults to :py:func:`torch.round`. 17 | 18 | Returns: 19 | Tensor: Quantized DCT coefficients. 20 | 21 | Note: 22 | DCT quantization is computed as 23 | 24 | .. math:: 25 | \widetilde{D}_{ij} = \left\lfloor \frac{D_{ij}}{Q_{ij}} \right\rceil 26 | 27 | For DCT coefficients :math:`D` and quantization matrix :math:`Q`. 28 | """ 29 | dct_blocks = blockify(dct, 8) 30 | quantized_blocks = round_func(dct_blocks / mat) 31 | quantized = deblockify(quantized_blocks, (dct.shape[2], dct.shape[3])) 32 | return quantized 33 | 34 | 35 | def dequantize(dct: Tensor, mat: Tensor) -> Tensor: 36 | r""" 37 | Dequantize DCT coefficients. 38 | 39 | Args: 40 | dct (Tensor): Quantized DCT coefficients of shape :math:`(N, 1, H, W)`. 41 | mat: (Tensor): Quantization matrix of shape :math:`(1, 1, 8, 8)`. 42 | 43 | Returns: 44 | Tensor: Quantized DCT coefficients. 45 | 46 | Note: 47 | DCT dequantization is computed as 48 | 49 | .. math:: 50 | D_{ij} = \widetilde{D}_{ij} \cdot Q_{ij} 51 | 52 | For quantized DCT coefficients :math:`\widetilde{D}` and quantization matrix :math:`Q`. 53 | """ 54 | dct_blocks = blockify(dct, 8) 55 | dequantized_blocks = dct_blocks * mat 56 | dequantized = deblockify(dequantized_blocks, (dct.shape[2], dct.shape[3])) 57 | return dequantized 58 | -------------------------------------------------------------------------------- /src/torchjpeg/quantization/ijg.py: -------------------------------------------------------------------------------- 1 | r""" 2 | :py:mod:`torchjpeg.quantization.ijg` provides functions which match the Independent JPEG Group's libjpeg quantization method. 3 | """ 4 | import torch 5 | from torch import Tensor 6 | 7 | from torchjpeg.dct import batch_dct, batch_idct 8 | 9 | from ._quantize import dequantize, quantize 10 | 11 | # Don't mess with matrix formatting 12 | # fmt: off 13 | luma_quant_matrix = torch.tensor([ 14 | 16, 11, 10, 16, 24, 40, 51, 61, 15 | 12, 12, 14, 19, 26, 58, 60, 55, 16 | 14, 13, 16, 24, 40, 57, 69, 56, 17 | 14, 17, 22, 29, 51, 87, 80, 62, 18 | 18, 22, 37, 56, 68, 109, 103, 77, 19 | 24, 35, 55, 64, 81, 104, 113, 92, 20 | 49, 64, 78, 87, 103, 121, 120, 101, 21 | 72, 92, 95, 98, 112, 100, 103, 99 22 | ]) 23 | # fmt: on 24 | 25 | # Don't mess with matrix formatting 26 | # fmt: off 27 | chroma_quant_matrix = torch.tensor([ 28 | 17, 18, 24, 47, 99, 99, 99, 99, 29 | 18, 21, 26, 66, 99, 99, 99, 99, 30 | 24, 26, 56, 99, 99, 99, 99, 99, 31 | 47, 66, 99, 99, 99, 99, 99, 99, 32 | 99, 99, 99, 99, 99, 99, 99, 99, 33 | 99, 99, 99, 99, 99, 99, 99, 99, 34 | 99, 99, 99, 99, 99, 99, 99, 99, 35 | 99, 99, 99, 99, 99, 99, 99, 99 36 | ]) 37 | # fmt: on 38 | 39 | quantization_max = 255.0 40 | 41 | 42 | def qualities_to_scale_factors(qualities: Tensor) -> Tensor: 43 | r""" 44 | Converts a batch of qualities in [0, 100] to a batch of scale factors suitable for scaling one of the IJG reference quantization matrices. 45 | 46 | Args: 47 | qualities (Tensor): A single dimensional batch of qualities. 48 | 49 | Returns: 50 | Tensor: A single dimensional batch of scale factors. 51 | """ 52 | qualities = qualities.clone() 53 | qualities[qualities <= 0] = 1 54 | qualities[qualities > 100] = 100 55 | 56 | indices_0_50 = qualities < 50 57 | indices_50_100 = qualities >= 50 58 | 59 | qualities[indices_0_50] = 5000 // qualities[indices_0_50] 60 | qualities[indices_50_100] = torch.trunc(200 - qualities[indices_50_100] * 2) 61 | 62 | return qualities 63 | 64 | 65 | def scale_quantization_matrices(scale_factor: Tensor, table: str = "luma") -> Tensor: 66 | r""" 67 | Scales one of the IJG reference quantization matrices. 68 | 69 | Args: 70 | scale_factor (Tensor): A batch of :math:`N` scale factors. 71 | table (str): A string indicating the table to use, either "luma" or "chroma" 72 | 73 | Returns: 74 | Tensor: A batch of quantization matrices of shape :math:`(N, 64)`. 75 | """ 76 | if table == "luma": 77 | t = luma_quant_matrix 78 | elif table == "chroma": 79 | t = chroma_quant_matrix 80 | 81 | t = t.to(scale_factor.device) 82 | 83 | t = t.unsqueeze(0) 84 | scale_factor = scale_factor.unsqueeze(1) 85 | 86 | mat = (t * scale_factor + 50) // 100 87 | mat[mat <= 0] = 1 88 | mat[mat > 255] = 255 89 | 90 | return mat 91 | 92 | 93 | def get_coefficients_for_qualities(quality: Tensor, table: str = "luma") -> Tensor: 94 | r""" 95 | Gets IJG quantization matrices for a given batch of qualities. 96 | 97 | Args: 98 | quality (Tensor): A batch of qualities of shape :math:`(N)` 99 | table (str): A string indicating the table to use, either "luma" or "chroma" 100 | 101 | """ 102 | scaler = qualities_to_scale_factors(quality) 103 | mat = scale_quantization_matrices(scaler, table=table) 104 | return mat.view(-1, 1, 8, 8) 105 | 106 | 107 | def quantize_at_quality(dct: Tensor, quality: int, table: str = "luma") -> Tensor: 108 | r""" 109 | Quantizes using a scalar quality instead of a quantization matrix. Uses IJG quantization matrices. 110 | 111 | Args: 112 | dct (Tensor): DCT coefficients of shape :math:`(N, 1, H ,W)`. 113 | quality (int): A scalar in [0, 100] specifying the desired quality. 114 | table (str): One of "luma" or "chroma" to choose the desired set of tables. 115 | 116 | Returns: 117 | Tensor: Quantized DCT coefficients. 118 | """ 119 | mat = get_coefficients_for_qualities(torch.tensor([quality]), table=table) 120 | return quantize(dct, mat) 121 | 122 | 123 | def dequantize_at_quality(dct: Tensor, quality: int, table: str = "luma") -> Tensor: 124 | r""" 125 | Dequantizes using a scalar quality instead of a quantization matrix. uses IJG quantization matrices. 126 | 127 | Args: 128 | dct (Tensor): Quantized DCT coefficients of shape :math:`(N, 1, H, W)`. 129 | quality (int): A scalar in [0, 100] specifying the quality that the coefficients were quantized at. 130 | table (str): One of "luma" or "chroma" to choose the desired set of tables. 131 | """ 132 | mat = get_coefficients_for_qualities(torch.tensor([quality]), table=table) 133 | return dequantize(dct, mat) 134 | 135 | 136 | def compress_coefficients(batch: Tensor, quality: int, table: str = "luma") -> Tensor: 137 | r""" 138 | A high level function that takes a batch of pixels in [0, 1] and returns quantized DCT coefficients. 139 | 140 | Args: 141 | batch (Tensor): A batch of images to quantize of shape `(N, 1, H, W)`. 142 | quality (int): A scalar quality in [0, 100] specifying the desired quality. 143 | table (str): One of "luma" or "chroma" to choose the desired set of tables. 144 | 145 | Returns: 146 | Tensor: A batch of quantized DCT coefficients. 147 | """ 148 | batch = batch * 255 - 128 149 | d = batch_dct(batch) 150 | d = quantize_at_quality(d, quality, table=table) 151 | return d 152 | 153 | 154 | def decompress_coefficients(batch: Tensor, quality: int, table: str = "luma") -> Tensor: 155 | r""" 156 | A high level function that converts quantized DCT coefficients to pixels. 157 | 158 | Args: 159 | batch (Tensor): A batch of quantized DCT coefficients of shape `(N, 1, H, W)`. 160 | quality (int): A scalar quality in [0, 100] specifying the quality the coefficients were quantized at. 161 | table (str): One of "luma" or "chroma" to choose the desired set of tables. 162 | 163 | Returns: 164 | Tensor: A batch of image pixels. 165 | """ 166 | d = dequantize_at_quality(batch, quality, table=table) 167 | d = batch_idct(d) 168 | d = (d + 128) / 255 169 | return d 170 | -------------------------------------------------------------------------------- /tasks.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=missing-function-docstring 2 | from typing import List 3 | 4 | from colorama import Fore, Style 5 | from invoke import Exit, task 6 | 7 | 8 | @task 9 | def lint(c, which="all"): 10 | lint_on: List[str] = [] 11 | if which == "all": 12 | lint_on += ["torchjpeg", "test", "examples", "./*.py"] 13 | else: 14 | lint_on.append(which) 15 | 16 | print(f"{Fore.BLUE}Linting: {Fore.GREEN}{lint_on}{Style.RESET_ALL}") 17 | 18 | for t in lint_on: 19 | r = c.run(f"pylint {t}", warn=True) 20 | if r.exited != 0: 21 | print(f"{Fore.RED}Linting for {Fore.GREEN}{t}{Fore.RED} FAILED{Style.RESET_ALL}") 22 | 23 | 24 | @task 25 | def type_checking(c, which="all"): 26 | tc_on: List[str] = [] 27 | if which == "all": 28 | tc_on += ["src/torchjpeg", "test", "examples", "./*.py"] 29 | else: 30 | tc_on.append(which) 31 | 32 | print(f"{Fore.BLUE}Type Checking: {Fore.GREEN}{tc_on}{Style.RESET_ALL}") 33 | 34 | for t in tc_on: 35 | r = c.run(f"mypy {t}", warn=True) 36 | if r.exited != 0: 37 | print(f"{Fore.RED}Type checking FAILED{Style.RESET_ALL}") 38 | 39 | 40 | @task 41 | def sort_imports(c): 42 | print(f"{Fore.BLUE}Sorting Imports{Style.RESET_ALL}") 43 | c.run("isort .", warn=True) 44 | 45 | 46 | @task 47 | def style(c): 48 | print(f"{Fore.BLUE}Styling Code{Style.RESET_ALL}") 49 | c.run("black .", warn=True) 50 | 51 | 52 | @task 53 | def dco(c): 54 | print(f"{Fore.BLUE}Checking For DCO{Style.RESET_ALL}") 55 | 56 | c.run("git remote add upstream-dco-check https://gitlab.com/torchjpeg/torchjpeg.git", warn=True, hide=True) 57 | c.run("git fetch -n upstream-dco-check", warn=True, hide=True) 58 | r = c.run('git rev-list HEAD ^remotes/upstream-dco-check/master --count --grep "Signed-off-by: .*( <.*@.*>)?$" --invert-grep --extended-regexp', warn=True, hide=True) 59 | c.run("git remote remove upstream-dco-check", warn=True, hide=True) 60 | 61 | cnt = int(r.stdout) 62 | 63 | if cnt > 0: 64 | print(f"{Fore.RED}You have {Fore.GREEN}{cnt}{Fore.RED} commits missing DCO{Style.RESET_ALL}") 65 | print(f"{Fore.RED}DCO check FAILED{Style.RESET_ALL}") 66 | 67 | raise Exit(code=1) 68 | 69 | 70 | @task 71 | def cq(c): 72 | print(f"{Fore.YELLOW}Code Quality{Style.RESET_ALL}") 73 | 74 | try: 75 | dco(c) 76 | finally: 77 | sort_imports(c) 78 | style(c) 79 | type_checking(c) 80 | lint(c) 81 | 82 | 83 | @task 84 | def test(c, which="all"): 85 | test_on: List[str] = [] 86 | if which == "all": 87 | test_on += ["import", "unit", "e2e"] 88 | else: 89 | test_on.append(which) 90 | 91 | print(f"{Fore.BLUE}Testing: {Fore.GREEN}{test_on}{Style.RESET_ALL}") 92 | 93 | for t in test_on: 94 | r = c.run(f"pytest test/{t}", warn=True) 95 | if r.exited != 0: 96 | print(f"{Fore.GREEN}{t}{Fore.RED} tests FAILED{Style.RESET_ALL}") 97 | 98 | 99 | @task 100 | def squashhelp(c, short=False): 101 | c.run("git remote add upstream-squashhelp https://gitlab.com/torchjpeg/torchjpeg.git", warn=True, hide=True) 102 | c.run("git fetch -n upstream-squashhelp", hide=True) 103 | rev = c.run("git merge-base HEAD upstream-squashhelp/master", warn=True, hide=True) 104 | c.run("git remote remove upstream-squashhelp", warn=True, hide=True) 105 | 106 | if not short: 107 | print(f"{Fore.BLUE}The {Fore.YELLOW}merge base{Fore.BLUE} between your branch and {Fore.GREEN}upstream{Fore.BLUE} is commit {Fore.YELLOW}{rev.stdout.strip()}{Fore.BLUE}.{Style.RESET_ALL}") 108 | print(f"{Fore.BLUE}Based on this, the squash command should be {Fore.YELLOW}git rebase -i {rev.stdout.strip()[:8]}{Style.RESET_ALL}") 109 | print(f"{Fore.BLUE}Remember to {Fore.RED}DCO sign-off{Fore.BLUE} your squashed commit and {Fore.GREEN}rebase on upstream{Fore.BLUE} when you're finished.{Style.RESET_ALL}") 110 | else: 111 | print(f"{Fore.YELLOW}git rebase -i {rev.stdout.strip()[:8]}{Style.RESET_ALL}") 112 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/test/__init__.py -------------------------------------------------------------------------------- /test/e2e/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/test/e2e/__init__.py -------------------------------------------------------------------------------- /test/import/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/test/import/__init__.py -------------------------------------------------------------------------------- /test/import/test_import.py: -------------------------------------------------------------------------------- 1 | # The import tests are supposed to test importing only, also these tests don't need docstrings 2 | # pylint: disable=missing-function-docstring,import-outside-toplevel,unused-import 3 | 4 | 5 | def test_import_torchjpeg(): 6 | import torchjpeg 7 | 8 | 9 | def test_import_torchjpeg_codec(): 10 | import torchjpeg.codec 11 | 12 | 13 | def test_import_torchjpeg_dct(): 14 | import torchjpeg.dct 15 | 16 | 17 | def test_import_torchjpeg_quantization(): 18 | import torchjpeg.quantization 19 | 20 | 21 | def test_import_torchjpeg_data(): 22 | import torchjpeg.data 23 | 24 | 25 | def test_import_torchjpeg_transforms(): 26 | import torchjpeg.data.transforms 27 | -------------------------------------------------------------------------------- /test/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Queuecumber/torchjpeg/03e01c498d6a90d83e98bfb5e5575fa91ac0b8e1/test/unit/__init__.py -------------------------------------------------------------------------------- /test/unit/test_dct.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | import torchjpeg.dct 4 | 5 | 6 | def test_zigzag(): 7 | """ 8 | Tests torchjpeg.dct.zigzag by trying to zigzag the integers from [0, 63] in row major order. If it's 9 | working, then it should match the manual zigzag order. 10 | """ 11 | # fmt: off 12 | zigzag_indices = torch.tensor([ 13 | 0, 1, 5, 6, 14, 15, 27, 28, 14 | 2, 4, 7, 13, 16, 26, 29, 42, 15 | 3, 8, 12, 17, 25, 30, 41, 43, 16 | 9, 11, 18, 24, 31, 40, 44, 53, 17 | 10, 19, 23, 32, 39, 45, 52, 54, 18 | 20, 22, 33, 38, 46, 51, 55, 60, 19 | 21, 34, 37, 47, 50, 56, 59, 61, 20 | 35, 36, 48, 49, 57, 58, 62, 63 21 | ]).float() 22 | # fmt: on 23 | 24 | assert torchjpeg.dct.zigzag(torch.arange(64).view(1, 8, 8).float()).squeeze().equal(zigzag_indices) 25 | assert torchjpeg.dct.zigzag(torch.arange(64).view(1, 1, 8, 8).float()).squeeze().equal(zigzag_indices) 26 | -------------------------------------------------------------------------------- /version.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Optional 3 | 4 | from dunamai import Version, bump_version, serialize_pep440 5 | 6 | if "CI_MERGE_REQUEST_IID" in os.environ: 7 | mr_version: Optional[str] = os.environ["CI_MERGE_REQUEST_IID"] 8 | else: 9 | mr_version = None 10 | 11 | build_official = "BUILD_OFFICIAL" in os.environ 12 | 13 | v = Version.from_git(pattern=r"^(?P\d+\.\d+\.\d+)$") 14 | if v.distance == 0: 15 | out = serialize_pep440(v.base, v.stage, v.revision) 16 | else: 17 | if build_official: 18 | out = serialize_pep440(bump_version(v.base), None, None, dev=v.distance) 19 | elif mr_version is not None: 20 | out = serialize_pep440(bump_version(v.base), None, None, dev=v.distance, metadata=[f"mr{mr_version}"]) 21 | else: 22 | out = serialize_pep440(bump_version(v.base), None, None, dev=v.distance, metadata=[f"g{v.commit}"]) 23 | 24 | print(out) 25 | --------------------------------------------------------------------------------