├── MANIFEST.in
├── .travis.yml
├── tifffile
├── __init__.py
└── _tifffile.c
├── .gitignore
├── HISTORY.rst
├── Makefile
├── LICENSE
├── test_tifffile.py
├── setup.py
└── README.rst
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include HISTORY.rst
2 | include LICENSE
3 | include README.rst
4 | include tifffile/_tifffile.c
5 |
6 |
7 | recursive-exclude * __pycache__
8 | recursive-exclude * *.py[co]
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # vim ft=yaml
2 |
3 | # After changing this file, check it on:
4 | # http://yaml-online-parser.appspot.com/
5 |
6 | language: python
7 | sudo: false
8 |
9 | python:
10 | - 2.7
11 | - 3.5
12 |
13 | before_install:
14 | - pip install -U pip
15 | - pip install numpy
16 | - pip install -e .
17 |
18 | script:
19 | - make test
20 |
--------------------------------------------------------------------------------
/tifffile/__init__.py:
--------------------------------------------------------------------------------
1 | from .tifffile import imsave, imread, imshow, TiffFile, TiffWriter, TiffSequence, FileHandle, lazyattr, natural_sorted, decode_lzw, stripnull, memmap, stripnull, format_size, squeeze_axes, create_output, repeat_nd, product
2 |
3 | __version__ = '0.15.1'
4 | __all__ = (
5 | 'imsave', 'imread', 'imshow', 'TiffFile', 'TiffWriter', 'TiffSequence',
6 | # utility functions used in oiffile and czifile
7 | 'FileHandle', 'lazyattr', 'natural_sorted', 'decode_lzw', 'stripnull',
8 | 'memmap', 'stripnull', 'format_size', 'squeeze_axes', 'create_output', 'repeat_nd', 'product'
9 | )
10 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache
2 |
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 |
8 | # Packages
9 | *.egg
10 | *.egg-info
11 | dist
12 | build
13 | eggs
14 | parts
15 | bin
16 | var
17 | sdist
18 | develop-eggs
19 | .installed.cfg
20 | lib
21 | lib64
22 |
23 | # Installer logs
24 | pip-log.txt
25 |
26 | # Unit test / coverage reports
27 | .coverage
28 | .tox
29 | nosetests.xml
30 | htmlcov
31 |
32 | # Translations
33 | *.mo
34 |
35 | # Mr Developer
36 | .mr.developer.cfg
37 | .project
38 | .pydevproject
39 |
40 | # Complexity
41 | output/*.html
42 | output/*/index.html
43 |
44 | # Sphinx
45 | docs/_build
46 |
47 | MANIFEST
48 |
49 | *.tif
50 |
51 | .DS_Store
52 |
--------------------------------------------------------------------------------
/HISTORY.rst:
--------------------------------------------------------------------------------
1 | .. :changelog:
2 |
3 | History
4 | -------
5 |
6 |
7 | 0.6.0 (2015-06-14)
8 | ---------------------
9 | * Make tifffile a package, fix handling of _tifffile.c files
10 |
11 |
12 | 0.4.0 (2014-12-13)
13 | ---------------------
14 | * Do not require importlib to use tifffile.c
15 | * Fix SSIZE_MAX bug for mingw
16 |
17 |
18 | 0.3.0 (2014-10-12)
19 | ---------------------
20 | * Install as a top-level python and compiled file.
21 |
22 |
23 | 0.2.0 (2014-10-12)
24 | ---------------------
25 | * Add __version__ attribute and update PyPI classifiers.
26 |
27 |
28 | 0.1.0 (2014-10-11)
29 | ---------------------
30 |
31 | * First release on PyPI.
32 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Note: This is meant for tifffile developer use only
2 | .PHONY: all clean test release update
3 |
4 | export TEST_ARGS=--exe -v
5 | export NAME=tifffile
6 | export VERSION=`python -c "import $(NAME); print($(NAME).__version__)"`
7 | export SITE=http://www.lfd.uci.edu/~gohlke/code/
8 |
9 | all: clean
10 | python setup.py build_ext -i
11 | python setup.py install
12 |
13 | clean:
14 | rm -rf build
15 | rm -rf dist
16 | find . -name "*.so" -o -name "*.pyc" | xargs rm -f
17 |
18 | test: clean
19 | python setup.py build_ext -i
20 | export PYTHONWARNINGS="all"; nosetests $(TEST_ARGS)
21 | make clean
22 |
23 | release: test
24 | pip install twine
25 | git tag v$(VERSION); true
26 | git commit -a -m "Release $(VERSION)"; true
27 | git push origin --all; true
28 | git push origin --tags; true
29 | rm -rf dist
30 | python setup.py register
31 | python setup.py sdist
32 | twine upload dist/*
33 | printf '\nUpgrade tifffile-feedstock with release and sha256 sum:'
34 | shasum -a 256 dist/*.tar.gz
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008-2014, Christoph Gohlke
2 | Copyright (c) 2008-2014, The Regents of the University of California
3 | Produced at the Laboratory for Fluorescence Dynamics
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright
10 | notice, this list of conditions and the following disclaimer.
11 | * Redistributions in binary form must reproduce the above copyright
12 | notice, this list of conditions and the following disclaimer in the
13 | documentation and/or other materials provided with the distribution.
14 | * Neither the name of the copyright holders nor the names of any
15 | contributors may be used to endorse or promote products derived
16 | from this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | POSSIBILITY OF SUCH DAMAGE.
29 |
--------------------------------------------------------------------------------
/test_tifffile.py:
--------------------------------------------------------------------------------
1 | import os
2 | import numpy as np
3 | import sys
4 |
5 | try:
6 | import skimage as si
7 | except Exception:
8 | si = None
9 |
10 | from numpy.testing import (
11 | assert_array_equal, assert_array_almost_equal, run_module_suite)
12 | from numpy.testing.decorators import skipif
13 |
14 | from tempfile import NamedTemporaryFile
15 | from tifffile import imread, imsave
16 |
17 |
18 | np.random.seed(0)
19 |
20 |
21 | @skipif(si is None)
22 | def test_imread_uint16():
23 | expected = np.load(os.path.join(si.data_dir, 'chessboard_GRAY_U8.npy'))
24 | img = imread(os.path.join(si.data_dir, 'chessboard_GRAY_U16.tif'))
25 | assert img.dtype == np.uint16
26 | assert_array_almost_equal(img, expected)
27 |
28 |
29 | @skipif(si is None)
30 | def test_imread_uint16_big_endian():
31 | expected = np.load(os.path.join(si.data_dir, 'chessboard_GRAY_U8.npy'))
32 | img = imread(os.path.join(si.data_dir, 'chessboard_GRAY_U16B.tif'))
33 | assert img.dtype == np.uint16
34 | assert_array_almost_equal(img, expected)
35 |
36 |
37 | @skipif(sys.version.startswith('2.6') or sys.version.startswith('3.2'))
38 | def test_extension():
39 | from tifffile.tifffile import decode_lzw
40 | import types
41 | assert isinstance(decode_lzw, types.BuiltinFunctionType), type(decode_lzw)
42 |
43 |
44 | class TestSave:
45 |
46 | def roundtrip(self, dtype, x):
47 | f = NamedTemporaryFile(suffix='.tif')
48 | fname = f.name
49 | f.close()
50 | imsave(fname, x)
51 | y = imread(fname)
52 | assert_array_equal(x, y)
53 |
54 | def test_imsave_roundtrip(self):
55 | for shape in [(10, 10), (10, 10, 3), (10, 10, 4)]:
56 | for dtype in (np.uint8, np.uint16, np.float32, np.int16,
57 | np.float64):
58 | x = np.random.rand(*shape)
59 |
60 | if not np.issubdtype(dtype, float):
61 | x = (x * np.iinfo(dtype).max).astype(dtype)
62 | else:
63 | x = x.astype(dtype)
64 | yield self.roundtrip, dtype, x
65 |
66 |
67 | if __name__ == "__main__":
68 | run_module_suite()
69 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import re
5 |
6 | from setuptools import find_packages, setup
7 | from setuptools.command.build_ext import build_ext as _build_ext
8 | from setuptools.extension import Extension
9 |
10 | with open('README.rst') as f:
11 | readme = f.read()
12 |
13 | with open('tifffile/__init__.py') as f:
14 | text = f.read()
15 |
16 | version = re.search("__version__ = '(.*?)'", text).groups()[0]
17 |
18 |
19 | # See https://stackoverflow.com/a/21621689/3622042
20 | class build_ext(_build_ext):
21 | def finalize_options(self):
22 | _build_ext.finalize_options(self)
23 |
24 | # Prevent numpy from thinking it is still in its setup process:
25 | __builtins__.__NUMPY_SETUP__ = False
26 |
27 | import numpy
28 | self.include_dirs.append(numpy.get_include())
29 |
30 |
31 | ext_modules = [Extension('tifffile._tifffile', ['tifffile/_tifffile.c'])]
32 |
33 |
34 | setup(
35 | name='tifffile',
36 | version=version,
37 | description='Read and write image data from and to TIFF files.',
38 | long_description=readme,
39 | author='Steven Silvester',
40 | author_email='steven.silvester@ieee.org',
41 | url='https://github.com/blink1073/tifffile',
42 | include_package_data=True,
43 | setup_requires=[
44 | 'numpy>=1.8.2'
45 | ],
46 | install_requires=[
47 | 'numpy>=1.8.2',
48 | 'pathlib;python_version<"3.0"',
49 | 'enum34;python_version<"3.0"',
50 | 'futures; python_version == "2.7"'
51 | ],
52 | license="BSD",
53 | zip_safe=False,
54 | packages=find_packages(),
55 | cmdclass={
56 | 'build_ext': build_ext
57 | },
58 | ext_modules=ext_modules,
59 | keywords='tifffile',
60 | classifiers=[
61 | 'Development Status :: 4 - Beta',
62 | 'Intended Audience :: Developers',
63 | 'License :: OSI Approved :: BSD License',
64 | 'Operating System :: OS Independent',
65 | "Programming Language :: C",
66 | "Programming Language :: Python :: 2",
67 | 'Programming Language :: Python :: 2.7',
68 | 'Programming Language :: Python :: 3',
69 | 'Programming Language :: Python :: 3.4',
70 | ],
71 | )
72 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | =============================================================================================
2 | This repository is deprecated and not directly tied to the released package on PyPI.
3 | =============================================================================================
4 |
5 | ===============================
6 | Tifffile
7 | ===============================
8 |
9 | .. image:: https://badge.fury.io/py/tifffile.png
10 | :target: http://badge.fury.io/py/tifffile
11 |
12 | .. image:: https://pypip.in/d/tifffile/badge.png
13 | :target: https://pypi.python.org/pypi/tifffile
14 |
15 |
16 | Read and write image data from and to TIFF files.
17 |
18 | Image and metadata can be read from TIFF, BigTIFF, OME-TIFF, STK, LSM, NIH,
19 | SGI, ImageJ, MicroManager, FluoView, SEQ and GEL files.
20 | Only a subset of the TIFF specification is supported, mainly uncompressed
21 | and losslessly compressed 2**(0 to 6) bit integer, 16, 32 and 64-bit float,
22 | grayscale and RGB(A) images, which are commonly used in bio-scientific imaging.
23 | Specifically, reading JPEG and CCITT compressed image data or EXIF, IPTC, GPS,
24 | and XMP metadata is not implemented.
25 | Only primary info records are read for STK, FluoView, MicroManager, and
26 | NIH image formats.
27 |
28 | TIFF, the Tagged Image File Format, is under the control of Adobe Systems.
29 | BigTIFF allows for files greater than 4 GB. STK, LSM, FluoView, SGI, SEQ, GEL,
30 | and OME-TIFF, are custom extensions defined by Molecular Devices (Universal
31 | Imaging Corporation), Carl Zeiss MicroImaging, Olympus, Silicon Graphics
32 | International, Media Cybernetics, Molecular Dynamics, and the Open Microscopy
33 | Environment consortium respectively.
34 |
35 | For command line usage run ``python tifffile.py --help``
36 |
37 | :Author:
38 | `Christoph Gohlke `_
39 |
40 | :Organization:
41 | Laboratory for Fluorescence Dynamics, University of California, Irvine
42 |
43 | :Version: 2017.01.12
44 |
45 | Requirements
46 | ------------
47 | * `CPython 2.7 or 3.4 `_
48 | * `Numpy 1.11 `_
49 | * `Matplotlib 1.5 `_ (optional for plotting)
50 |
51 | Installation
52 | ------------
53 | * If using conda, `conda install tifffile -c conda-forge`.
54 | * Otherwise, `pip install tifffile`.
55 |
56 | Notes
57 | -----
58 | This is a mirror of the code at http://www.lfd.uci.edu/~gohlke/code/tifffile.py.html. For any development concerns, please email Christoph Gohlke at
59 | ``cgohlke at uci.edu``.
60 |
61 | The API is not stable yet and might change between revisions.
62 |
63 | Tested on little-endian platforms only.
64 |
65 | Other Python packages and modules for reading bio-scientific TIFF files:
66 |
67 | * `Imread `_
68 | * `PyLibTiff `_
69 | * `SimpleITK `_
70 | * `PyLSM `_
71 | * `PyMca.TiffIO.py `_ (same as fabio.TiffIO)
72 | * `BioImageXD.Readers `_
73 | * `Cellcognition.io `_
74 | * `CellProfiler.bioformats
75 | `_
76 |
77 | Acknowledgements
78 | ----------------
79 | * Egor Zindy, University of Manchester, for cz_lsm_scan_info specifics.
80 | * Wim Lewis for a bug fix and some read_cz_lsm functions.
81 | * Hadrien Mary for help on reading MicroManager files.
82 |
83 | References
84 | ----------
85 | (1) TIFF 6.0 Specification and Supplements. Adobe Systems Incorporated.
86 | http://partners.adobe.com/public/developer/tiff/
87 | (2) TIFF File Format FAQ. http://www.awaresystems.be/imaging/tiff/faq.html
88 | (3) MetaMorph Stack (STK) Image File Format.
89 | http://support.meta.moleculardevices.com/docs/t10243.pdf
90 | (4) Image File Format Description LSM 5/7 Release 6.0 (ZEN 2010).
91 | Carl Zeiss MicroImaging GmbH. BioSciences. May 10, 2011
92 | (5) File Format Description - LSM 5xx Release 2.0.
93 | http://ibb.gsf.de/homepage/karsten.rodenacker/IDL/Lsmfile.doc
94 | (6) The OME-TIFF format.
95 | http://www.openmicroscopy.org/site/support/file-formats/ome-tiff
96 | (7) UltraQuant(r) Version 6.0 for Windows Start-Up Guide.
97 | http://www.ultralum.com/images%20ultralum/pdf/UQStart%20Up%20Guide.pdf
98 | (8) Micro-Manager File Formats.
99 | http://www.micro-manager.org/wiki/Micro-Manager_File_Formats
100 | (9) Tags for TIFF and Related Specifications. Digital Preservation.
101 | http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml
102 |
103 | Examples
104 | --------
105 |
106 | >>> data = numpy.random.rand(5, 301, 219)
107 | >>> imsave('temp.tif', data)
108 |
109 | >>> image = imread('temp.tif')
110 | >>> numpy.testing.assert_array_equal(image, data)
111 |
112 | >>> with TiffFile('temp.tif') as tif:
113 | ... images = tif.asarray()
114 | ... for page in tif:
115 | ... for tag in page.tags.values():
116 | ... t = tag.name, tag.value
117 | ... image = page.asarray()
118 |
119 |
120 | Known build errors
121 | ------------------
122 | On Windows, the error `Error:unable to find vcvarsall.bat` means that distutils is not correctly configured to use the C compiler. Modify (or create, if not existing) the configuration file `distutils.cfg` (located for example at `C:\\Python27\\Lib\\distutils\\distutils.cfg`) to contain::
123 |
124 | [build]
125 | compiler=mingw32
126 |
127 |
--------------------------------------------------------------------------------
/tifffile/_tifffile.c:
--------------------------------------------------------------------------------
1 |
2 |
3 | /* tifffile.c
4 |
5 | A Python C extension module for decoding PackBits and LZW encoded TIFF data.
6 |
7 | Refer to the tifffile.py module for documentation and tests.
8 |
9 | :Author:
10 | `Christoph Gohlke `_
11 |
12 | :Organization:
13 | Laboratory for Fluorescence Dynamics, University of California, Irvine
14 |
15 | :Version: 2018.02.10
16 |
17 | Requirements
18 | ------------
19 | * `CPython 2.7 or 3.6 `_
20 | * `Numpy 1.13 `_
21 | * A Python distutils compatible C compiler (build)
22 | * `stdint.h `_ for msvc9 compiler
23 |
24 | Install
25 | -------
26 | Use this Python distutils setup script to build the extension module::
27 |
28 | # setup.py
29 | # Usage: ``python setup.py build_ext --inplace``
30 | from distutils.core import setup, Extension
31 | import numpy
32 | setup(name='_tifffile',
33 | ext_modules=[Extension('_tifffile', ['tifffile.c'],
34 | include_dirs=[numpy.get_include()])])
35 |
36 | License
37 | -------
38 | Copyright (c) 2008-2018, Christoph Gohlke
39 | Copyright (c) 2008-2018, The Regents of the University of California
40 | Produced at the Laboratory for Fluorescence Dynamics
41 | All rights reserved.
42 |
43 | Redistribution and use in source and binary forms, with or without
44 | modification, are permitted provided that the following conditions are met:
45 |
46 | * Redistributions of source code must retain the above copyright
47 | notice, this list of conditions and the following disclaimer.
48 | * Redistributions in binary form must reproduce the above copyright
49 | notice, this list of conditions and the following disclaimer in the
50 | documentation and/or other materials provided with the distribution.
51 | * Neither the name of the copyright holders nor the names of any
52 | contributors may be used to endorse or promote products derived
53 | from this software without specific prior written permission.
54 |
55 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
56 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
59 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 | POSSIBILITY OF SUCH DAMAGE.
66 | */
67 |
68 | #define _VERSION_ "2018.02.10"
69 |
70 | #define WIN32_LEAN_AND_MEAN
71 | #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
72 |
73 | #include "Python.h"
74 | #include "string.h"
75 | #include "numpy/arrayobject.h"
76 |
77 | #include
78 |
79 | /* little endian by default */
80 | #ifndef MSB
81 | #define MSB 1
82 | #endif
83 |
84 | #if MSB
85 | #define LSB 0
86 | #define BOC '<'
87 | #else
88 | #define LSB 1
89 | #define BOC '>'
90 | #endif
91 |
92 | #define NO_ERROR 0
93 | #define VALUE_ERROR -1
94 |
95 | #ifndef SSIZE_MAX
96 | #define SSIZE_MAX INTPTR_MAX
97 | #endif
98 |
99 | #define SWAP2BYTES(x) \
100 | ((((x) >> 8) & 0x00FF) | (((x) & 0x00FF) << 8))
101 |
102 | #define SWAP4BYTES(x) \
103 | ((((x) >> 24) & 0x00FF) | (((x)&0x00FF) << 24) | \
104 | (((x) >> 8 ) & 0xFF00) | (((x)&0xFF00) << 8))
105 |
106 | #define SWAP8BYTES(x) \
107 | ((((x) >> 56) & 0x00000000000000FF) | (((x) >> 40) & 0x000000000000FF00) | \
108 | (((x) >> 24) & 0x0000000000FF0000) | (((x) >> 8) & 0x00000000FF000000) | \
109 | (((x) << 8) & 0x000000FF00000000) | (((x) << 24) & 0x0000FF0000000000) | \
110 | (((x) << 40) & 0x00FF000000000000) | (((x) << 56) & 0xFF00000000000000))
111 |
112 | typedef union {
113 | uint8_t b[2];
114 | uint16_t i;
115 | } u_uint16;
116 |
117 | typedef union {
118 | uint8_t b[4];
119 | uint32_t i;
120 | } u_uint32;
121 |
122 | typedef union {
123 | uint8_t b[8];
124 | uint64_t i;
125 | } u_uint64;
126 |
127 | typedef struct {
128 | ssize_t len;
129 | char* str;
130 | } string_t;
131 |
132 | /*****************************************************************************/
133 | /* C functions */
134 |
135 | /* Return mask for itemsize bits */
136 | unsigned char bitmask(const int itemsize) {
137 | unsigned char result = 0;
138 | unsigned char power = 1;
139 | int i;
140 | for (i = 0; i < itemsize; i++) {
141 | result += power;
142 | power *= 2;
143 | }
144 | return result << (8 - itemsize);
145 | }
146 |
147 | /** Unpack sequence of tigthly packed 1-32 bit integers.
148 |
149 | Native byte order will be returned.
150 |
151 | Input data array should be padded to the next 16, 32 or 64-bit boundary
152 | if itemsize not in (1, 2, 4, 8, 16, 24, 32, 64).
153 |
154 | */
155 | int unpackbits(
156 | unsigned char* data,
157 | const ssize_t size, /** size of data in bytes */
158 | const int itemsize, /** number of bits in integer */
159 | ssize_t numitems, /** number of items to unpack */
160 | unsigned char* result /** buffer to store unpacked items */
161 | )
162 | {
163 | ssize_t i, j, k, storagesize;
164 | unsigned char value;
165 | /* Input validation is done in wrapper function */
166 | storagesize = (ssize_t)(ceil(itemsize / 8.0));
167 | storagesize = storagesize < 3 ? storagesize : storagesize > 4 ? 8 : 4;
168 | switch (itemsize) {
169 | case 8:
170 | case 16:
171 | case 32:
172 | case 64:
173 | memcpy(result, data, numitems*storagesize);
174 | return NO_ERROR;
175 | case 1:
176 | for (i = 0, j = 0; i < numitems/8; i++) {
177 | value = data[i];
178 | result[j++] = (value & (unsigned char)(128)) >> 7;
179 | result[j++] = (value & (unsigned char)(64)) >> 6;
180 | result[j++] = (value & (unsigned char)(32)) >> 5;
181 | result[j++] = (value & (unsigned char)(16)) >> 4;
182 | result[j++] = (value & (unsigned char)(8)) >> 3;
183 | result[j++] = (value & (unsigned char)(4)) >> 2;
184 | result[j++] = (value & (unsigned char)(2)) >> 1;
185 | result[j++] = (value & (unsigned char)(1));
186 | }
187 | if (numitems % 8) {
188 | value = data[i];
189 | switch (numitems % 8) {
190 | case 7: result[j+6] = (value & (unsigned char)(2)) >> 1;
191 | case 6: result[j+5] = (value & (unsigned char)(4)) >> 2;
192 | case 5: result[j+4] = (value & (unsigned char)(8)) >> 3;
193 | case 4: result[j+3] = (value & (unsigned char)(16)) >> 4;
194 | case 3: result[j+2] = (value & (unsigned char)(32)) >> 5;
195 | case 2: result[j+1] = (value & (unsigned char)(64)) >> 6;
196 | case 1: result[j] = (value & (unsigned char)(128)) >> 7;
197 | }
198 | }
199 | return NO_ERROR;
200 | case 2:
201 | for (i = 0, j = 0; i < numitems/4; i++) {
202 | value = data[i];
203 | result[j++] = (value & (unsigned char)(192)) >> 6;
204 | result[j++] = (value & (unsigned char)(48)) >> 4;
205 | result[j++] = (value & (unsigned char)(12)) >> 2;
206 | result[j++] = (value & (unsigned char)(3));
207 | }
208 | if (numitems % 4) {
209 | value = data[i];
210 | switch (numitems % 4) {
211 | case 3: result[j+2] = (value & (unsigned char)(12)) >> 2;
212 | case 2: result[j+1] = (value & (unsigned char)(48)) >> 4;
213 | case 1: result[j] = (value & (unsigned char)(192)) >> 6;
214 | }
215 | }
216 | return NO_ERROR;
217 | case 4:
218 | for (i = 0, j = 0; i < numitems/2; i++) {
219 | value = data[i];
220 | result[j++] = (value & (unsigned char)(240)) >> 4;
221 | result[j++] = (value & (unsigned char)(15));
222 | }
223 | if (numitems % 2) {
224 | value = data[i];
225 | result[j] = (value & (unsigned char)(240)) >> 4;
226 | }
227 | return NO_ERROR;
228 | case 24:
229 | j = k = 0;
230 | for (i = 0; i < numitems; i++) {
231 | result[j++] = 0;
232 | result[j++] = data[k++];
233 | result[j++] = data[k++];
234 | result[j++] = data[k++];
235 | }
236 | return NO_ERROR;
237 | }
238 | /* 3, 5, 6, 7 */
239 | if (itemsize < 8) {
240 | int shr = 16;
241 | u_uint16 value, mask, tmp;
242 | j = k = 0;
243 | value.b[MSB] = data[j++];
244 | value.b[LSB] = data[j++];
245 | mask.b[MSB] = bitmask(itemsize);
246 | mask.b[LSB] = 0;
247 | for (i = 0; i < numitems; i++) {
248 | shr -= itemsize;
249 | tmp.i = (value.i & mask.i) >> shr;
250 | result[k++] = tmp.b[LSB];
251 | if (shr < itemsize) {
252 | value.b[MSB] = value.b[LSB];
253 | value.b[LSB] = data[j++];
254 | mask.i <<= 8 - itemsize;
255 | shr += 8;
256 | } else {
257 | mask.i >>= itemsize;
258 | }
259 | }
260 | return NO_ERROR;
261 | }
262 | /* 9, 10, 11, 12, 13, 14, 15 */
263 | if (itemsize < 16) {
264 | int shr = 32;
265 | u_uint32 value, mask, tmp;
266 | mask.i = 0;
267 | j = k = 0;
268 | #if MSB
269 | for (i = 3; i >= 0; i--) {
270 | value.b[i] = data[j++];
271 | }
272 | mask.b[3] = 0xFF;
273 | mask.b[2] = bitmask(itemsize-8);
274 | for (i = 0; i < numitems; i++) {
275 | shr -= itemsize;
276 | tmp.i = (value.i & mask.i) >> shr;
277 | result[k++] = tmp.b[0]; /* swap bytes */
278 | result[k++] = tmp.b[1];
279 | if (shr < itemsize) {
280 | value.b[3] = value.b[1];
281 | value.b[2] = value.b[0];
282 | value.b[1] = j < size ? data[j++] : 0;
283 | value.b[0] = j < size ? data[j++] : 0;
284 | mask.i <<= 16 - itemsize;
285 | shr += 16;
286 | } else {
287 | mask.i >>= itemsize;
288 | }
289 | }
290 | #else
291 | /* not implemented */
292 | #endif
293 | return NO_ERROR;
294 | }
295 | /* 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31 */
296 | if (itemsize < 32) {
297 | int shr = 64;
298 | u_uint64 value, mask, tmp;
299 | mask.i = 0;
300 | j = k = 0;
301 | #if MSB
302 | for (i = 7; i >= 0; i--) {
303 | value.b[i] = data[j++];
304 | }
305 | mask.b[7] = 0xFF;
306 | mask.b[6] = 0xFF;
307 | mask.b[5] = itemsize > 23 ? 0xFF : bitmask(itemsize-16);
308 | mask.b[4] = itemsize < 24 ? 0x00 : bitmask(itemsize-24);
309 | for (i = 0; i < numitems; i++) {
310 | shr -= itemsize;
311 | tmp.i = (value.i & mask.i) >> shr;
312 | result[k++] = tmp.b[0]; /* swap bytes */
313 | result[k++] = tmp.b[1];
314 | result[k++] = tmp.b[2];
315 | result[k++] = tmp.b[3];
316 | if (shr < itemsize) {
317 | value.b[7] = value.b[3];
318 | value.b[6] = value.b[2];
319 | value.b[5] = value.b[1];
320 | value.b[4] = value.b[0];
321 | value.b[3] = j < size ? data[j++] : 0;
322 | value.b[2] = j < size ? data[j++] : 0;
323 | value.b[1] = j < size ? data[j++] : 0;
324 | value.b[0] = j < size ? data[j++] : 0;
325 | mask.i <<= 32 - itemsize;
326 | shr += 32;
327 | } else {
328 | mask.i >>= itemsize;
329 | }
330 | }
331 | #else
332 | /* Not implemented */
333 | #endif
334 | return NO_ERROR;
335 | }
336 | return VALUE_ERROR;
337 | }
338 |
339 | /*****************************************************************************/
340 | /* Python functions */
341 |
342 |
343 | /** Reverse bits in bytes of byte string or ndarray. */
344 | char py_reverse_bitorder_doc[] =
345 | "Reverse bits in each byte of byte string or numpy array.";
346 |
347 | static PyObject*
348 | py_reverse_bitorder(PyObject* obj, PyObject* args)
349 | {
350 | PyObject* dataobj = NULL;
351 | PyObject* result = NULL;
352 | PyArray_Descr* dtype = NULL;
353 | PyArrayIterObject* iter = NULL;
354 | unsigned char* dataptr = NULL;
355 | unsigned char* resultptr = NULL;
356 | Py_ssize_t size, stride;
357 | Py_ssize_t i, j;
358 | int axis = -1;
359 |
360 | if (!PyArg_ParseTuple(args, "O", &dataobj))
361 | return NULL;
362 |
363 | Py_INCREF(dataobj);
364 |
365 | if (PyBytes_Check(dataobj)) {
366 | dataptr = (unsigned char*)PyBytes_AS_STRING(dataobj);
367 | size = PyBytes_GET_SIZE(dataobj);
368 |
369 | result = PyBytes_FromStringAndSize(NULL, size);
370 | if (result == NULL) {
371 | PyErr_Format(PyExc_MemoryError, "unable to allocate result");
372 | goto _fail;
373 | }
374 | resultptr = (unsigned char*)PyBytes_AS_STRING(result);
375 |
376 | Py_BEGIN_ALLOW_THREADS
377 | for (i = 0; i < size; i++) {
378 | /* http://graphics.stanford.edu/~seander/bithacks.html
379 | #ReverseByteWith64Bits */
380 | *resultptr++ = (unsigned char)(((*dataptr++ * 0x80200802ULL) &
381 | 0x0884422110ULL) * 0x0101010101ULL >> 32);
382 | }
383 | Py_END_ALLOW_THREADS
384 |
385 | Py_DECREF(dataobj);
386 | return result;
387 | }
388 | else if (PyArray_Check(dataobj)) {
389 | dtype = PyArray_DTYPE((PyArrayObject*) dataobj);
390 | if (dtype->elsize == 0) {
391 | PyErr_Format(PyExc_ValueError, "can not handle dtype");
392 | goto _fail;
393 | }
394 | iter = (PyArrayIterObject*)PyArray_IterAllButAxis(dataobj, &axis);
395 | size = PyArray_DIM((PyArrayObject*)dataobj, axis);
396 | stride = PyArray_STRIDE((PyArrayObject*)dataobj, axis);
397 | stride -= dtype->elsize;
398 |
399 | Py_BEGIN_ALLOW_THREADS
400 | while (iter->index < iter->size) {
401 | dataptr = (unsigned char*)iter->dataptr;
402 | for(i = 0; i < size; i++) {
403 | for(j = 0; j < dtype->elsize; j++) {
404 | *dataptr = (unsigned char)(((*dataptr * 0x80200802ULL) &
405 | 0x0884422110ULL) * 0x0101010101ULL >> 32);
406 | dataptr++;
407 | }
408 | dataptr += stride;
409 | }
410 | PyArray_ITER_NEXT(iter);
411 | }
412 | Py_END_ALLOW_THREADS
413 |
414 | Py_DECREF(iter);
415 | Py_DECREF(dataobj);
416 | Py_RETURN_NONE;
417 | } else {
418 | PyErr_Format(PyExc_TypeError, "not a byte string or ndarray");
419 | goto _fail;
420 | }
421 |
422 | _fail:
423 | Py_XDECREF(dataobj);
424 | Py_XDECREF(result);
425 | Py_XDECREF(iter);
426 | return NULL;
427 | }
428 |
429 |
430 | /** Unpack tightly packed integers. */
431 | char py_unpackints_doc[] = "Unpack groups of bits into numpy array.";
432 |
433 | static PyObject*
434 | py_unpackints(PyObject* obj, PyObject* args, PyObject* kwds)
435 | {
436 | PyObject* byteobj = NULL;
437 | PyArrayObject* result = NULL;
438 | PyArray_Descr* dtype = NULL;
439 | char* encoded = NULL;
440 | char* decoded = NULL;
441 | Py_ssize_t encoded_len = 0;
442 | Py_ssize_t decoded_len = 0;
443 | Py_ssize_t runlen = 0;
444 | Py_ssize_t i;
445 | int storagesize, bytesize;
446 | int itemsize = 0;
447 | int skipbits = 0;
448 | static char* kwlist[] = {"data", "dtype", "itemsize", "runlen", NULL};
449 |
450 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&i|i", kwlist,
451 | &byteobj, PyArray_DescrConverter, &dtype, &itemsize, &runlen))
452 | return NULL;
453 |
454 | Py_INCREF(byteobj);
455 |
456 | if (((itemsize < 1) || (itemsize > 32)) && (itemsize != 64)) {
457 | PyErr_Format(PyExc_ValueError, "itemsize out of range");
458 | goto _fail;
459 | }
460 |
461 | if (!PyBytes_Check(byteobj)) {
462 | PyErr_Format(PyExc_TypeError, "expected byte string as input");
463 | goto _fail;
464 | }
465 |
466 | encoded = PyBytes_AS_STRING(byteobj);
467 | encoded_len = PyBytes_GET_SIZE(byteobj);
468 | bytesize = (int)ceil(itemsize / 8.0);
469 | storagesize = bytesize < 3 ? bytesize : bytesize > 4 ? 8 : 4;
470 | if ((encoded_len < bytesize) || (encoded_len > SSIZE_MAX / storagesize)) {
471 | PyErr_Format(PyExc_ValueError, "data size out of range");
472 | goto _fail;
473 | }
474 | if (dtype->elsize != storagesize) {
475 | PyErr_Format(PyExc_TypeError, "dtype.elsize does not fit itemsize");
476 | goto _fail;
477 | }
478 |
479 | if (runlen == 0) {
480 | runlen = (Py_ssize_t)(((uint64_t)encoded_len*8) / (uint64_t)itemsize);
481 | }
482 | skipbits = (Py_ssize_t)(((uint64_t)runlen * (uint64_t)itemsize) % 8);
483 | if (skipbits > 0) {
484 | skipbits = 8 - skipbits;
485 | }
486 | decoded_len = (Py_ssize_t)((uint64_t)runlen * (((uint64_t)encoded_len*8) /
487 | ((uint64_t)runlen*(uint64_t)itemsize + (uint64_t)skipbits)));
488 |
489 | result = (PyArrayObject*)PyArray_SimpleNew(1, &decoded_len,
490 | dtype->type_num);
491 | if (result == NULL) {
492 | PyErr_Format(PyExc_MemoryError, "unable to allocate output array");
493 | goto _fail;
494 | }
495 | decoded = (char*)PyArray_DATA(result);
496 |
497 | encoded_len = (ssize_t)(((uint64_t)runlen * (uint64_t)itemsize +
498 | (uint64_t)skipbits) / 8);
499 |
500 | for (i = 0; i < decoded_len; i+=runlen) {
501 | if (NO_ERROR != unpackbits((unsigned char*) encoded,
502 | (ssize_t) encoded_len,
503 | (int) itemsize,
504 | (ssize_t) runlen,
505 | (unsigned char*) decoded)) {
506 | PyErr_Format(PyExc_ValueError, "unpackbits() failed");
507 | goto _fail;
508 | }
509 | encoded += encoded_len;
510 | decoded += runlen * storagesize;
511 | }
512 |
513 | if ((dtype->byteorder != BOC) && (itemsize % 8 == 0)) {
514 | switch (dtype->elsize) {
515 | case 2: {
516 | uint16_t* d = (uint16_t*)PyArray_DATA(result);
517 | for (i = 0; i < PyArray_SIZE(result); i++) {
518 | *d = SWAP2BYTES(*d);
519 | d++;
520 | }
521 | break; }
522 | case 4: {
523 | uint32_t* d = (uint32_t*)PyArray_DATA(result);
524 | for (i = 0; i < PyArray_SIZE(result); i++) {
525 | *d = SWAP4BYTES(*d);
526 | d++;
527 | }
528 | break; }
529 | case 8: {
530 | uint64_t* d = (uint64_t*)PyArray_DATA(result);
531 | for (i = 0; i < PyArray_SIZE(result); i++) {
532 | *d = SWAP8BYTES(*d);
533 | d++;
534 | }
535 | break; }
536 | }
537 | }
538 | Py_DECREF(byteobj);
539 | Py_DECREF(dtype);
540 | return PyArray_Return(result);
541 |
542 | _fail:
543 | Py_XDECREF(byteobj);
544 | Py_XDECREF(result);
545 | Py_XDECREF(dtype);
546 | return NULL;
547 | }
548 |
549 |
550 | /** Decode TIFF PackBits encoded string. */
551 | char py_decodepackbits_doc[] = "Return TIFF PackBits decoded string.";
552 |
553 | static PyObject*
554 | py_decodepackbits(PyObject* obj, PyObject* args)
555 | {
556 | int n;
557 | char e;
558 | char* decoded = NULL;
559 | char* encoded = NULL;
560 | char* encoded_end = NULL;
561 | char* encoded_pos = NULL;
562 | unsigned int encoded_len;
563 | unsigned int decoded_len;
564 | PyObject* byteobj = NULL;
565 | PyObject* result = NULL;
566 |
567 | if (!PyArg_ParseTuple(args, "O", &byteobj))
568 | return NULL;
569 |
570 | if (!PyBytes_Check(byteobj)) {
571 | PyErr_Format(PyExc_TypeError, "expected byte string as input");
572 | goto _fail;
573 | }
574 |
575 | Py_INCREF(byteobj);
576 | encoded = PyBytes_AS_STRING(byteobj);
577 | encoded_len = (unsigned int)PyBytes_GET_SIZE(byteobj);
578 |
579 | /* release GIL: byte/string objects are immutable */
580 | Py_BEGIN_ALLOW_THREADS
581 |
582 | /* determine size of decoded string */
583 | encoded_pos = encoded;
584 | encoded_end = encoded + encoded_len;
585 | decoded_len = 0;
586 | while (encoded_pos < encoded_end) {
587 | n = (int)*encoded_pos++;
588 | if (n >= 0) {
589 | n++;
590 | if (encoded_pos+n > encoded_end)
591 | n = (int)(encoded_end - encoded_pos);
592 | encoded_pos += n;
593 | decoded_len += n;
594 | } else if (n > -128) {
595 | encoded_pos++;
596 | decoded_len += 1-n;
597 | }
598 | }
599 | Py_END_ALLOW_THREADS
600 |
601 | result = PyBytes_FromStringAndSize(NULL, decoded_len);
602 | if (result == NULL) {
603 | PyErr_Format(PyExc_MemoryError, "failed to allocate decoded string");
604 | goto _fail;
605 | }
606 | decoded = PyBytes_AS_STRING(result);
607 |
608 | Py_BEGIN_ALLOW_THREADS
609 |
610 | /* decode string */
611 | encoded_end = encoded + encoded_len;
612 | while (encoded < encoded_end) {
613 | n = (int)*encoded++;
614 | if (n >= 0) {
615 | n++;
616 | if (encoded+n > encoded_end)
617 | n = (int)(encoded_end - encoded);
618 | /* memmove(decoded, encoded, n); decoded += n; encoded += n; */
619 | while (n--)
620 | *decoded++ = *encoded++;
621 | } else if (n > -128) {
622 | n = 1 - n;
623 | e = *encoded++;
624 | /* memset(decoded, e, n); decoded += n; */
625 | while (n--)
626 | *decoded++ = e;
627 | }
628 | }
629 | Py_END_ALLOW_THREADS
630 |
631 | Py_DECREF(byteobj);
632 | return result;
633 |
634 | _fail:
635 | Py_XDECREF(byteobj);
636 | Py_XDECREF(result);
637 | return NULL;
638 | }
639 |
640 |
641 | /** Decode TIFF LZW encoded string. */
642 | char py_decodelzw_doc[] = "Return TIFF LZW decoded string.";
643 |
644 | #define GET_NEXT_CODE \
645 | { \
646 | const uint8_t* bytes = (uint8_t*)((void*)(encoded + (bitcount>>3))); \
647 | code = (uint32_t) bytes[0]; \
648 | code <<= 8; \
649 | code |= (uint32_t) bytes[1]; \
650 | code <<= 8; \
651 | if ((bitcount + 24) <= encoded_size) \
652 | code |= (uint32_t) bytes[2]; \
653 | code <<= 8; \
654 | code <<= (uint32_t)(bitcount % 8); \
655 | code &= mask; \
656 | code >>= shr; \
657 | bitcount += bitw; \
658 | }
659 |
660 |
661 | static PyObject*
662 | py_decodelzw(PyObject* obj, PyObject* args)
663 | {
664 | PyObject* byteobj = NULL;
665 | PyObject* decoded = NULL;
666 | string_t* table = NULL;
667 | char* encoded = NULL;
668 | char* buffer = NULL;
669 | char* pbuffer = NULL;
670 | char* pdecoded = NULL;
671 | char* pstr = NULL;
672 | int little_endian;
673 | uint32_t code, oldcode, mask, shr, table_size;
674 | ssize_t i, decoded_size, buffersize, buffer_size;
675 | uint64_t bitcount, bitw, encoded_size;
676 |
677 | if (!PyArg_ParseTuple(args, "O", &byteobj))
678 | return NULL;
679 |
680 | if (!PyBytes_Check(byteobj)) {
681 | PyErr_Format(PyExc_TypeError, "expected byte string as input");
682 | goto _fail;
683 | }
684 |
685 | Py_INCREF(byteobj);
686 | encoded = PyBytes_AS_STRING(byteobj);
687 | encoded_size = (uint64_t)PyBytes_GET_SIZE(byteobj);
688 | /*
689 | if (encoded_size >= 512 * 1024 * 1024) {
690 | PyErr_Format(PyExc_ValueError, "encoded data > 512 MB not supported");
691 | goto _fail;
692 | }
693 | */
694 | encoded_size *= 8; /* bits */
695 |
696 | if (*encoded == 0) {
697 | /* TODO: old style LZW codes are written in reversed bit order */
698 | PyErr_Format(PyExc_ValueError, "can not decode old-style LZW");
699 | goto _fail;
700 | }
701 |
702 | if ((*encoded != -128) || ((*(encoded+1) & 128))) {
703 | PyErr_Format(PyExc_ValueError, "strip must begin with CLEAR code");
704 | goto _fail;
705 | }
706 | little_endian = (*(uint16_t*)encoded) & 128;
707 |
708 | table = PyMem_Malloc(4096 * sizeof(string_t));
709 | if (table == NULL) {
710 | PyErr_Format(PyExc_MemoryError, "failed to allocate table");
711 | goto _fail;
712 | }
713 | for (i = 0; i < 4096; i++) {
714 | table[i].len = 1;
715 | }
716 |
717 | /* determine length of output and string buffer */
718 | table_size = 258;
719 | bitw = 9;
720 | shr = 23;
721 | mask = 4286578688u;
722 | bitcount = 0;
723 | decoded_size = 0;
724 | buffer_size = 0;
725 | buffersize = 0;
726 | code = 0;
727 | oldcode = 0;
728 |
729 | Py_BEGIN_ALLOW_THREADS
730 | while ((bitcount + bitw) <= encoded_size) {
731 | /* read next code */
732 | GET_NEXT_CODE
733 |
734 | if (code == 257) break; /* end of information */
735 |
736 | if (code == 256) { /* clearcode */
737 | /* initialize table and switch to 9-bit */
738 | table_size = 258;
739 | bitw = 9;
740 | shr = 23;
741 | mask = 4286578688u;
742 | if (buffersize > buffer_size)
743 | buffer_size = buffersize;
744 | buffersize = 0;
745 |
746 | /* read next code, skip clearcodes */
747 | do { GET_NEXT_CODE } while (code == 256);
748 |
749 | if (code == 257) break; /* end of information */
750 |
751 | decoded_size++;
752 | } else {
753 | if (code < table_size) {
754 | /* code is in table */
755 | decoded_size += table[code].len;
756 | buffersize += table[oldcode].len + 1;
757 | } else {
758 | /* code is not in table */
759 | decoded_size += table[oldcode].len + 1;
760 | }
761 | table[table_size++].len = table[oldcode].len + 1;
762 |
763 | /* increase bit-width if necessary */
764 | switch (table_size) {
765 | case 511:
766 | bitw = 10; shr = 22; mask = 4290772992u;
767 | break;
768 | case 1023:
769 | bitw = 11; shr = 21; mask = 4292870144u;
770 | break;
771 | case 2047:
772 | bitw = 12; shr = 20; mask = 4293918720u;
773 | }
774 | }
775 | oldcode = code;
776 | }
777 | Py_END_ALLOW_THREADS
778 |
779 | if (buffersize > buffer_size)
780 | buffer_size = buffersize;
781 |
782 | if (code != 257) {
783 | /*
784 | PyErr_WarnEx(
785 | NULL, "py_decodelzw encountered unexpected end of stream", 1);
786 | */
787 | }
788 |
789 | /* allocate output and buffer string */
790 | decoded = PyBytes_FromStringAndSize(0, decoded_size);
791 | if (decoded == NULL) {
792 | PyErr_Format(PyExc_MemoryError, "failed to allocate decoded string");
793 | goto _fail;
794 | }
795 | pdecoded = PyBytes_AS_STRING(decoded);
796 |
797 | buffer = PyMem_Malloc(buffer_size);
798 | if (buffer == NULL) {
799 | PyErr_Format(PyExc_MemoryError, "failed to allocate string buffer");
800 | goto _fail;
801 | }
802 |
803 | /* decode input to output string */
804 | table_size = 258;
805 | bitw = 9;
806 | shr = 23;
807 | mask = 4286578688u;
808 | bitcount = 0;
809 | pbuffer = buffer;
810 |
811 | Py_BEGIN_ALLOW_THREADS
812 | while ((bitcount + bitw) <= encoded_size) {
813 | /* read next code */
814 | GET_NEXT_CODE
815 |
816 | if (code == 257) break; /* end of information */
817 |
818 | if (code == 256) { /* clearcode */
819 | /* initialize table and switch to 9-bit */
820 | table_size = 258;
821 | bitw = 9;
822 | shr = 23;
823 | mask = 4286578688u;
824 | pbuffer = buffer;
825 |
826 | /* read next code, skip clearcodes */
827 | do { GET_NEXT_CODE } while (code == 256);
828 |
829 | if (code == 257) break; /* end of information */
830 |
831 | *pdecoded++ = code;
832 | } else {
833 | if (code < table_size) {
834 | /* code is in table */
835 | /* decoded.append(table[code]) */
836 | if (code < 256) {
837 | *pdecoded++ = code;
838 | } else {
839 | pstr = table[code].str;
840 | for (i = 0; i < table[code].len; i++) {
841 | *pdecoded++ = *pstr++;
842 | }
843 | }
844 | /* table.append(table[oldcode] + table[code][0]) */
845 | table[table_size].str = pbuffer;
846 | if (oldcode < 256) {
847 | *pbuffer++ = oldcode;
848 | } else {
849 | pstr = table[oldcode].str;
850 | for (i = 0; i < table[oldcode].len; i++) {
851 | *pbuffer++ = *pstr++;
852 | }
853 | }
854 | if (code < 256) {
855 | *pbuffer++ = code;
856 | } else {
857 | *pbuffer++ = table[code].str[0];
858 | }
859 | } else {
860 | /* code is not in table */
861 | /* outstring = table[oldcode] + table[oldcode][0] */
862 | /* decoded.append(outstring) */
863 | /* table.append(outstring) */
864 | table[table_size].str = pdecoded;
865 | if (oldcode < 256) {
866 | *pdecoded++ = oldcode;
867 | *pdecoded++ = oldcode;
868 | } else {
869 | pstr = table[oldcode].str;
870 | for (i = 0; i < table[oldcode].len; i++) {
871 | *pdecoded++ = *pstr++;
872 | }
873 | *pdecoded++ = table[oldcode].str[0];
874 | }
875 | }
876 | table[table_size++].len = table[oldcode].len + 1;
877 |
878 | /* increase bit-width if necessary */
879 | switch (table_size) {
880 | case 511:
881 | bitw = 10; shr = 22; mask = 4290772992u;
882 | break;
883 | case 1023:
884 | bitw = 11; shr = 21; mask = 4292870144u;
885 | break;
886 | case 2047:
887 | bitw = 12; shr = 20; mask = 4293918720u;
888 | }
889 | }
890 | oldcode = code;
891 | }
892 | Py_END_ALLOW_THREADS
893 |
894 | PyMem_Free(buffer);
895 | PyMem_Free(table);
896 | Py_DECREF(byteobj);
897 | return decoded;
898 |
899 | _fail:
900 |
901 | if (table)
902 | PyMem_Free(table);
903 | if (buffer)
904 | PyMem_Free(buffer);
905 |
906 | Py_XDECREF(byteobj);
907 | Py_XDECREF(decoded);
908 |
909 | return NULL;
910 | }
911 |
912 | /*****************************************************************************/
913 | /* Create Python module */
914 |
915 | char module_doc[] =
916 | "A Python C extension module for decoding PackBits and LZW encoded "
917 | "TIFF data.\n\n"
918 | "Refer to the tifffile.py module for documentation and tests.\n\n"
919 | "Authors:\n Christoph Gohlke \n"
920 | " Laboratory for Fluorescence Dynamics, University of California, Irvine."
921 | "\n\nVersion: %s\n";
922 |
923 | static PyMethodDef module_methods[] = {
924 | #if MSB
925 | {"unpack_ints", (PyCFunction)py_unpackints, METH_VARARGS|METH_KEYWORDS,
926 | py_unpackints_doc},
927 | #endif
928 | {"decode_lzw", (PyCFunction)py_decodelzw, METH_VARARGS,
929 | py_decodelzw_doc},
930 | {"decode_packbits", (PyCFunction)py_decodepackbits, METH_VARARGS,
931 | py_decodepackbits_doc},
932 | {"reverse_bitorder", (PyCFunction)py_reverse_bitorder, METH_VARARGS,
933 | py_reverse_bitorder_doc},
934 | {NULL, NULL, 0, NULL} /* Sentinel */
935 | };
936 |
937 | #if PY_MAJOR_VERSION >= 3
938 |
939 | struct module_state {
940 | PyObject* error;
941 | };
942 |
943 | #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
944 |
945 | static int module_traverse(PyObject* m, visitproc visit, void *arg) {
946 | Py_VISIT(GETSTATE(m)->error);
947 | return 0;
948 | }
949 |
950 | static int module_clear(PyObject* m) {
951 | Py_CLEAR(GETSTATE(m)->error);
952 | return 0;
953 | }
954 |
955 | static struct PyModuleDef moduledef = {
956 | PyModuleDef_HEAD_INIT,
957 | "_tifffile",
958 | NULL,
959 | sizeof(struct module_state),
960 | module_methods,
961 | NULL,
962 | module_traverse,
963 | module_clear,
964 | NULL
965 | };
966 |
967 | #define INITERROR return NULL
968 |
969 | PyMODINIT_FUNC
970 | PyInit__tifffile(void)
971 |
972 | #else
973 |
974 | #define INITERROR return
975 |
976 | PyMODINIT_FUNC
977 | init_tifffile(void)
978 |
979 | #endif
980 | {
981 | PyObject* module;
982 |
983 | char* doc = (char*)PyMem_Malloc(sizeof(module_doc) + sizeof(_VERSION_));
984 | PyOS_snprintf(doc, sizeof(module_doc) + sizeof(_VERSION_),
985 | module_doc, _VERSION_);
986 |
987 | #if PY_MAJOR_VERSION >= 3
988 | moduledef.m_doc = doc;
989 | module = PyModule_Create(&moduledef);
990 | #else
991 | module = Py_InitModule3("_tifffile", module_methods, doc);
992 | #endif
993 |
994 | PyMem_Free(doc);
995 |
996 | if (module == NULL)
997 | INITERROR;
998 |
999 | if (_import_array() < 0) {
1000 | Py_DECREF(module);
1001 | INITERROR;
1002 | }
1003 |
1004 | {
1005 | #if PY_MAJOR_VERSION < 3
1006 | PyObject* s = PyString_FromString(_VERSION_);
1007 | #else
1008 | PyObject* s = PyUnicode_FromString(_VERSION_);
1009 | #endif
1010 | PyObject* dict = PyModule_GetDict(module);
1011 | PyDict_SetItemString(dict, "__version__", s);
1012 | Py_DECREF(s);
1013 | }
1014 |
1015 | #if PY_MAJOR_VERSION >= 3
1016 | return module;
1017 | #endif
1018 | }
1019 |
1020 |
--------------------------------------------------------------------------------