mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-27 19:48:43 +08:00
Add tifffile.c to the build
This commit is contained in:
@@ -157,6 +157,9 @@ Library:
|
||||
Extension: skimage.graph._ncut_cy
|
||||
Sources:
|
||||
skimage/graph/_ncut_cy.pyx
|
||||
Extension: skimage.external.tifffile._tifffile
|
||||
Sources:
|
||||
skimage/external/tifffile/_tifffile.c
|
||||
|
||||
Executable: skivi
|
||||
Module: skimage.scripts.skivi
|
||||
|
||||
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os.path
|
||||
|
||||
base_path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def configuration(parent_package='', top_path=None):
|
||||
from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs
|
||||
|
||||
config = Configuration('external', parent_package, top_path)
|
||||
|
||||
config.add_extension('tifffile._tifffile',
|
||||
sources=['tifffile/_tifffile.c'],
|
||||
include_dirs=[get_numpy_include_dirs()])
|
||||
return config
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(maintainer='scikit-image Developers',
|
||||
maintainer_email='scikit-image@googlegroups.com',
|
||||
description='External Libaries',
|
||||
url='https://github.com/scikit-image/scikit-image',
|
||||
license='Modified BSD',
|
||||
**(configuration(top_path='').todict())
|
||||
)
|
||||
Vendored
+962
@@ -0,0 +1,962 @@
|
||||
|
||||
|
||||
/* tifffile.c
|
||||
|
||||
A Python C extension module for decoding PackBits and LZW encoded TIFF data.
|
||||
|
||||
Refer to the tifffile.py module for documentation and tests.
|
||||
|
||||
:Author:
|
||||
`Christoph Gohlke <http://www.lfd.uci.edu/~gohlke/>`_
|
||||
|
||||
:Organization:
|
||||
Laboratory for Fluorescence Dynamics, University of California, Irvine
|
||||
|
||||
:Version: 2013.11.05
|
||||
|
||||
Install
|
||||
-------
|
||||
Use this Python distutils setup script to build the extension module::
|
||||
|
||||
# setup.py
|
||||
# Usage: ``python setup.py build_ext --inplace``
|
||||
from distutils.core import setup, Extension
|
||||
import numpy
|
||||
setup(name='_tifffile',
|
||||
ext_modules=[Extension('_tifffile', ['tifffile.c'],
|
||||
include_dirs=[numpy.get_include()])])
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright (c) 2008-2014, Christoph Gohlke
|
||||
Copyright (c) 2008-2014, The Regents of the University of California
|
||||
Produced at the Laboratory for Fluorescence Dynamics
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the names of any
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define _VERSION_ "2013.11.05"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
||||
|
||||
#include "Python.h"
|
||||
#include "string.h"
|
||||
#include "numpy/arrayobject.h"
|
||||
|
||||
/* little endian by default */
|
||||
#ifndef MSB
|
||||
#define MSB 1
|
||||
#endif
|
||||
|
||||
#if MSB
|
||||
#define LSB 0
|
||||
#define BOC '<'
|
||||
#else
|
||||
#define LSB 1
|
||||
#define BOC '>'
|
||||
#endif
|
||||
|
||||
#define NO_ERROR 0
|
||||
#define VALUE_ERROR -1
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#ifdef _WIN64
|
||||
typedef __int64 ssize_t;
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#define SSIZE_MAX (9223372036854775808)
|
||||
#else
|
||||
typedef int ssize_t;
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#define SSIZE_MAX (2147483648)
|
||||
#endif
|
||||
#else
|
||||
/* non MS compilers */
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#define SWAP2BYTES(x) \
|
||||
((((x) >> 8) & 0x00FF) | (((x) & 0x00FF) << 8))
|
||||
|
||||
#define SWAP4BYTES(x) \
|
||||
((((x) >> 24) & 0x00FF) | (((x)&0x00FF) << 24) | \
|
||||
(((x) >> 8 ) & 0xFF00) | (((x)&0xFF00) << 8))
|
||||
|
||||
#define SWAP8BYTES(x) \
|
||||
((((x) >> 56) & 0x00000000000000FF) | (((x) >> 40) & 0x000000000000FF00) | \
|
||||
(((x) >> 24) & 0x0000000000FF0000) | (((x) >> 8) & 0x00000000FF000000) | \
|
||||
(((x) << 8) & 0x000000FF00000000) | (((x) << 24) & 0x0000FF0000000000) | \
|
||||
(((x) << 40) & 0x00FF000000000000) | (((x) << 56) & 0xFF00000000000000))
|
||||
|
||||
struct BYTE_STRING {
|
||||
unsigned int ref; /* reference count */
|
||||
unsigned int len; /* length of string */
|
||||
char *str; /* pointer to bytes */
|
||||
};
|
||||
|
||||
typedef union {
|
||||
uint8_t b[2];
|
||||
uint16_t i;
|
||||
} u_uint16;
|
||||
|
||||
typedef union {
|
||||
uint8_t b[4];
|
||||
uint32_t i;
|
||||
} u_uint32;
|
||||
|
||||
typedef union {
|
||||
uint8_t b[8];
|
||||
uint64_t i;
|
||||
} u_uint64;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* C functions */
|
||||
|
||||
/* Return mask for itemsize bits */
|
||||
unsigned char bitmask(const int itemsize) {
|
||||
unsigned char result = 0;
|
||||
unsigned char power = 1;
|
||||
int i;
|
||||
for (i = 0; i < itemsize; i++) {
|
||||
result += power;
|
||||
power *= 2;
|
||||
}
|
||||
return result << (8 - itemsize);
|
||||
}
|
||||
|
||||
/** Unpack sequence of tigthly packed 1-32 bit integers.
|
||||
|
||||
Native byte order will be returned.
|
||||
|
||||
Input data array should be padded to the next 16, 32 or 64-bit boundary
|
||||
if itemsize not in (1, 2, 4, 8, 16, 24, 32, 64).
|
||||
|
||||
*/
|
||||
int unpackbits(
|
||||
unsigned char *data,
|
||||
const ssize_t size, /** size of data in bytes */
|
||||
const int itemsize, /** number of bits in integer */
|
||||
ssize_t numitems, /** number of items to unpack */
|
||||
unsigned char *result /** buffer to store unpacked items */
|
||||
)
|
||||
{
|
||||
ssize_t i, j, k, storagesize;
|
||||
unsigned char value;
|
||||
/* Input validation is done in wrapper function */
|
||||
storagesize = (ssize_t)(ceil(itemsize / 8.0));
|
||||
storagesize = storagesize < 3 ? storagesize : storagesize > 4 ? 8 : 4;
|
||||
switch (itemsize) {
|
||||
case 8:
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
memcpy(result, data, numitems*storagesize);
|
||||
return NO_ERROR;
|
||||
case 1:
|
||||
for (i = 0, j = 0; i < numitems/8; i++) {
|
||||
value = data[i];
|
||||
result[j++] = (value & (unsigned char)(128)) >> 7;
|
||||
result[j++] = (value & (unsigned char)(64)) >> 6;
|
||||
result[j++] = (value & (unsigned char)(32)) >> 5;
|
||||
result[j++] = (value & (unsigned char)(16)) >> 4;
|
||||
result[j++] = (value & (unsigned char)(8)) >> 3;
|
||||
result[j++] = (value & (unsigned char)(4)) >> 2;
|
||||
result[j++] = (value & (unsigned char)(2)) >> 1;
|
||||
result[j++] = (value & (unsigned char)(1));
|
||||
}
|
||||
if (numitems % 8) {
|
||||
value = data[i];
|
||||
switch (numitems % 8) {
|
||||
case 7: result[j+6] = (value & (unsigned char)(2)) >> 1;
|
||||
case 6: result[j+5] = (value & (unsigned char)(4)) >> 2;
|
||||
case 5: result[j+4] = (value & (unsigned char)(8)) >> 3;
|
||||
case 4: result[j+3] = (value & (unsigned char)(16)) >> 4;
|
||||
case 3: result[j+2] = (value & (unsigned char)(32)) >> 5;
|
||||
case 2: result[j+1] = (value & (unsigned char)(64)) >> 6;
|
||||
case 1: result[j] = (value & (unsigned char)(128)) >> 7;
|
||||
}
|
||||
}
|
||||
return NO_ERROR;
|
||||
case 2:
|
||||
for (i = 0, j = 0; i < numitems/4; i++) {
|
||||
value = data[i];
|
||||
result[j++] = (value & (unsigned char)(192)) >> 6;
|
||||
result[j++] = (value & (unsigned char)(48)) >> 4;
|
||||
result[j++] = (value & (unsigned char)(12)) >> 2;
|
||||
result[j++] = (value & (unsigned char)(3));
|
||||
}
|
||||
if (numitems % 4) {
|
||||
value = data[i];
|
||||
switch (numitems % 4) {
|
||||
case 3: result[j+2] = (value & (unsigned char)(12)) >> 2;
|
||||
case 2: result[j+1] = (value & (unsigned char)(48)) >> 4;
|
||||
case 1: result[j] = (value & (unsigned char)(192)) >> 6;
|
||||
}
|
||||
}
|
||||
return NO_ERROR;
|
||||
case 4:
|
||||
for (i = 0, j = 0; i < numitems/2; i++) {
|
||||
value = data[i];
|
||||
result[j++] = (value & (unsigned char)(240)) >> 4;
|
||||
result[j++] = (value & (unsigned char)(15));
|
||||
}
|
||||
if (numitems % 2) {
|
||||
value = data[i];
|
||||
result[j] = (value & (unsigned char)(240)) >> 4;
|
||||
}
|
||||
return NO_ERROR;
|
||||
case 24:
|
||||
j = k = 0;
|
||||
for (i = 0; i < numitems; i++) {
|
||||
result[j++] = 0;
|
||||
result[j++] = data[k++];
|
||||
result[j++] = data[k++];
|
||||
result[j++] = data[k++];
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
/* 3, 5, 6, 7 */
|
||||
if (itemsize < 8) {
|
||||
int shr = 16;
|
||||
u_uint16 value, mask, tmp;
|
||||
j = k = 0;
|
||||
value.b[MSB] = data[j++];
|
||||
value.b[LSB] = data[j++];
|
||||
mask.b[MSB] = bitmask(itemsize);
|
||||
mask.b[LSB] = 0;
|
||||
for (i = 0; i < numitems; i++) {
|
||||
shr -= itemsize;
|
||||
tmp.i = (value.i & mask.i) >> shr;
|
||||
result[k++] = tmp.b[LSB];
|
||||
if (shr < itemsize) {
|
||||
value.b[MSB] = value.b[LSB];
|
||||
value.b[LSB] = data[j++];
|
||||
mask.i <<= 8 - itemsize;
|
||||
shr += 8;
|
||||
} else {
|
||||
mask.i >>= itemsize;
|
||||
}
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
/* 9, 10, 11, 12, 13, 14, 15 */
|
||||
if (itemsize < 16) {
|
||||
int shr = 32;
|
||||
u_uint32 value, mask, tmp;
|
||||
mask.i = 0;
|
||||
j = k = 0;
|
||||
#if MSB
|
||||
for (i = 3; i >= 0; i--) {
|
||||
value.b[i] = data[j++];
|
||||
}
|
||||
mask.b[3] = 0xFF;
|
||||
mask.b[2] = bitmask(itemsize-8);
|
||||
for (i = 0; i < numitems; i++) {
|
||||
shr -= itemsize;
|
||||
tmp.i = (value.i & mask.i) >> shr;
|
||||
result[k++] = tmp.b[0]; /* swap bytes */
|
||||
result[k++] = tmp.b[1];
|
||||
if (shr < itemsize) {
|
||||
value.b[3] = value.b[1];
|
||||
value.b[2] = value.b[0];
|
||||
value.b[1] = data[j++];
|
||||
value.b[0] = data[j++];
|
||||
mask.i <<= 16 - itemsize;
|
||||
shr += 16;
|
||||
} else {
|
||||
mask.i >>= itemsize;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* not implemented */
|
||||
#endif
|
||||
return NO_ERROR;
|
||||
}
|
||||
/* 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31 */
|
||||
if (itemsize < 32) {
|
||||
int shr = 64;
|
||||
u_uint64 value, mask, tmp;
|
||||
mask.i = 0;
|
||||
j = k = 0;
|
||||
#if MSB
|
||||
for (i = 7; i >= 0; i--) {
|
||||
value.b[i] = data[j++];
|
||||
}
|
||||
mask.b[7] = 0xFF;
|
||||
mask.b[6] = 0xFF;
|
||||
mask.b[5] = itemsize > 23 ? 0xFF : bitmask(itemsize-16);
|
||||
mask.b[4] = itemsize < 24 ? 0x00 : bitmask(itemsize-24);
|
||||
for (i = 0; i < numitems; i++) {
|
||||
shr -= itemsize;
|
||||
tmp.i = (value.i & mask.i) >> shr;
|
||||
result[k++] = tmp.b[0]; /* swap bytes */
|
||||
result[k++] = tmp.b[1];
|
||||
result[k++] = tmp.b[2];
|
||||
result[k++] = tmp.b[3];
|
||||
if (shr < itemsize) {
|
||||
value.b[7] = value.b[3];
|
||||
value.b[6] = value.b[2];
|
||||
value.b[5] = value.b[1];
|
||||
value.b[4] = value.b[0];
|
||||
value.b[3] = data[j++];
|
||||
value.b[2] = data[j++];
|
||||
value.b[1] = data[j++];
|
||||
value.b[0] = data[j++];
|
||||
mask.i <<= 32 - itemsize;
|
||||
shr += 32;
|
||||
} else {
|
||||
mask.i >>= itemsize;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Not implemented */
|
||||
#endif
|
||||
return NO_ERROR;
|
||||
}
|
||||
return VALUE_ERROR;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Python functions */
|
||||
|
||||
/** Unpack tightly packed integers. */
|
||||
char py_unpackints_doc[] = "Unpack groups of bits into numpy array.";
|
||||
|
||||
static PyObject*
|
||||
py_unpackints(PyObject *obj, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *byteobj = NULL;
|
||||
PyArrayObject *result = NULL;
|
||||
PyArray_Descr *dtype = NULL;
|
||||
char *encoded = NULL;
|
||||
char *decoded = NULL;
|
||||
Py_ssize_t encoded_len = 0;
|
||||
Py_ssize_t decoded_len = 0;
|
||||
Py_ssize_t runlen = 0;
|
||||
Py_ssize_t i;
|
||||
int storagesize, bytesize;
|
||||
int itemsize = 0;
|
||||
int skipbits = 0;
|
||||
static char *kwlist[] = {"data", "dtype", "itemsize", "runlen", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&i|i", kwlist,
|
||||
&byteobj, PyArray_DescrConverter, &dtype, &itemsize, &runlen))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(byteobj);
|
||||
|
||||
if (((itemsize < 1) || (itemsize > 32)) && (itemsize != 64)) {
|
||||
PyErr_Format(PyExc_ValueError, "itemsize out of range");
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if (!PyBytes_Check(byteobj)) {
|
||||
PyErr_Format(PyExc_TypeError, "expected byte string as input");
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
encoded = PyBytes_AS_STRING(byteobj);
|
||||
encoded_len = PyBytes_GET_SIZE(byteobj);
|
||||
bytesize = (int)ceil(itemsize / 8.0);
|
||||
storagesize = bytesize < 3 ? bytesize : bytesize > 4 ? 8 : 4;
|
||||
if ((encoded_len < bytesize) || (encoded_len > SSIZE_MAX / storagesize)) {
|
||||
PyErr_Format(PyExc_ValueError, "data size out of range");
|
||||
goto _fail;
|
||||
}
|
||||
if (dtype->elsize != storagesize) {
|
||||
PyErr_Format(PyExc_TypeError, "dtype.elsize doesn't fit itemsize");
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if (runlen == 0) {
|
||||
runlen = (Py_ssize_t)(((uint64_t)encoded_len*8) / (uint64_t)itemsize);
|
||||
}
|
||||
skipbits = (Py_ssize_t)(((uint64_t)runlen * (uint64_t)itemsize) % 8);
|
||||
if (skipbits > 0) {
|
||||
skipbits = 8 - skipbits;
|
||||
}
|
||||
decoded_len = (Py_ssize_t)((uint64_t)runlen * (((uint64_t)encoded_len*8) /
|
||||
((uint64_t)runlen*(uint64_t)itemsize + (uint64_t)skipbits)));
|
||||
|
||||
result = (PyArrayObject *)PyArray_SimpleNew(1, &decoded_len,
|
||||
dtype->type_num);
|
||||
if (result == NULL) {
|
||||
PyErr_Format(PyExc_MemoryError, "unable to allocate output array");
|
||||
goto _fail;
|
||||
}
|
||||
decoded = (char *)PyArray_DATA(result);
|
||||
|
||||
for (i = 0; i < decoded_len; i+=runlen) {
|
||||
if (NO_ERROR !=
|
||||
unpackbits((unsigned char *) encoded,
|
||||
(ssize_t) encoded_len,
|
||||
(int) itemsize,
|
||||
(ssize_t) runlen,
|
||||
(unsigned char *) decoded)) {
|
||||
PyErr_Format(PyExc_ValueError, "unpackbits() failed");
|
||||
goto _fail;
|
||||
}
|
||||
encoded += (Py_ssize_t)(((uint64_t)runlen * (uint64_t)itemsize +
|
||||
(uint64_t)skipbits) / 8);
|
||||
decoded += runlen * storagesize;
|
||||
}
|
||||
|
||||
if ((dtype->byteorder != BOC) && (itemsize % 8 == 0)) {
|
||||
switch (dtype->elsize) {
|
||||
case 2: {
|
||||
uint16_t *d = (uint16_t *)PyArray_DATA(result);
|
||||
for (i = 0; i < PyArray_SIZE(result); i++) {
|
||||
*d = SWAP2BYTES(*d); d++;
|
||||
}
|
||||
break; }
|
||||
case 4: {
|
||||
uint32_t *d = (uint32_t *)PyArray_DATA(result);
|
||||
for (i = 0; i < PyArray_SIZE(result); i++) {
|
||||
*d = SWAP4BYTES(*d); d++;
|
||||
}
|
||||
break; }
|
||||
case 8: {
|
||||
uint64_t *d = (uint64_t *)PyArray_DATA(result);
|
||||
for (i = 0; i < PyArray_SIZE(result); i++) {
|
||||
*d = SWAP8BYTES(*d); d++;
|
||||
}
|
||||
break; }
|
||||
}
|
||||
}
|
||||
Py_DECREF(byteobj);
|
||||
Py_DECREF(dtype);
|
||||
return PyArray_Return(result);
|
||||
|
||||
_fail:
|
||||
Py_XDECREF(byteobj);
|
||||
Py_XDECREF(result);
|
||||
Py_XDECREF(dtype);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Decode TIFF PackBits encoded string. */
|
||||
char py_decodepackbits_doc[] = "Return TIFF PackBits decoded string.";
|
||||
|
||||
static PyObject *
|
||||
py_decodepackbits(PyObject *obj, PyObject *args)
|
||||
{
|
||||
int n;
|
||||
char e;
|
||||
char *decoded = NULL;
|
||||
char *encoded = NULL;
|
||||
char *encoded_end = NULL;
|
||||
char *encoded_pos = NULL;
|
||||
unsigned int encoded_len;
|
||||
unsigned int decoded_len;
|
||||
PyObject *byteobj = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &byteobj))
|
||||
return NULL;
|
||||
|
||||
if (!PyBytes_Check(byteobj)) {
|
||||
PyErr_Format(PyExc_TypeError, "expected byte string as input");
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
Py_INCREF(byteobj);
|
||||
encoded = PyBytes_AS_STRING(byteobj);
|
||||
encoded_len = (unsigned int)PyBytes_GET_SIZE(byteobj);
|
||||
|
||||
/* release GIL: byte/string objects are immutable */
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
/* determine size of decoded string */
|
||||
encoded_pos = encoded;
|
||||
encoded_end = encoded + encoded_len;
|
||||
decoded_len = 0;
|
||||
while (encoded_pos < encoded_end) {
|
||||
n = (int)*encoded_pos++;
|
||||
if (n >= 0) {
|
||||
n++;
|
||||
if (encoded_pos+n > encoded_end)
|
||||
n = (int)(encoded_end - encoded_pos);
|
||||
encoded_pos += n;
|
||||
decoded_len += n;
|
||||
} else if (n > -128) {
|
||||
encoded_pos++;
|
||||
decoded_len += 1-n;
|
||||
}
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
result = PyBytes_FromStringAndSize(0, decoded_len);
|
||||
if (result == NULL) {
|
||||
PyErr_Format(PyExc_MemoryError, "failed to allocate decoded string");
|
||||
goto _fail;
|
||||
}
|
||||
decoded = PyBytes_AS_STRING(result);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
/* decode string */
|
||||
encoded_end = encoded + encoded_len;
|
||||
while (encoded < encoded_end) {
|
||||
n = (int)*encoded++;
|
||||
if (n >= 0) {
|
||||
n++;
|
||||
if (encoded+n > encoded_end)
|
||||
n = (int)(encoded_end - encoded);
|
||||
/* memmove(decoded, encoded, n); decoded += n; encoded += n; */
|
||||
while (n--)
|
||||
*decoded++ = *encoded++;
|
||||
} else if (n > -128) {
|
||||
n = 1 - n;
|
||||
e = *encoded++;
|
||||
/* memset(decoded, e, n); decoded += n; */
|
||||
while (n--)
|
||||
*decoded++ = e;
|
||||
}
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
Py_DECREF(byteobj);
|
||||
return result;
|
||||
|
||||
_fail:
|
||||
Py_XDECREF(byteobj);
|
||||
Py_XDECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Decode TIFF LZW encoded string. */
|
||||
char py_decodelzw_doc[] = "Return TIFF LZW decoded string.";
|
||||
|
||||
static PyObject *
|
||||
py_decodelzw(PyObject *obj, PyObject *args)
|
||||
{
|
||||
PyThreadState *_save = NULL;
|
||||
PyObject *byteobj = NULL;
|
||||
PyObject *result = NULL;
|
||||
int i, j;
|
||||
unsigned int encoded_len = 0;
|
||||
unsigned int decoded_len = 0;
|
||||
unsigned int result_len = 0;
|
||||
unsigned int table_len = 0;
|
||||
unsigned int len;
|
||||
unsigned int code, c, oldcode, mask, shr;
|
||||
uint64_t bitcount, bitw;
|
||||
char *encoded = NULL;
|
||||
char *result_ptr = NULL;
|
||||
char *table2 = NULL;
|
||||
char *cptr;
|
||||
struct BYTE_STRING *decoded = NULL;
|
||||
struct BYTE_STRING *decoded_ptr = NULL;
|
||||
struct BYTE_STRING *table[4096];
|
||||
struct BYTE_STRING *newentry, *newresult, *t;
|
||||
int little_endian = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &byteobj))
|
||||
return NULL;
|
||||
|
||||
if (!PyBytes_Check(byteobj)) {
|
||||
PyErr_Format(PyExc_TypeError, "expected byte string as input");
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
Py_INCREF(byteobj);
|
||||
encoded = PyBytes_AS_STRING(byteobj);
|
||||
encoded_len = (unsigned int)PyBytes_GET_SIZE(byteobj);
|
||||
/*
|
||||
if (encoded_len >= 512 * 1024 * 1024) {
|
||||
PyErr_Format(PyExc_ValueError, "encoded data > 512 MB not supported");
|
||||
goto _fail;
|
||||
}
|
||||
*/
|
||||
/* release GIL: byte/string objects are immutable */
|
||||
_save = PyEval_SaveThread();
|
||||
|
||||
if ((*encoded != -128) || ((*(encoded+1) & 128))) {
|
||||
PyEval_RestoreThread(_save);
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"strip must begin with CLEAR code");
|
||||
goto _fail;
|
||||
}
|
||||
little_endian = (*(unsigned short *)encoded) & 128;
|
||||
|
||||
/* allocate buffer for codes and pointers */
|
||||
decoded_len = 0;
|
||||
len = (encoded_len + encoded_len/9) * sizeof(decoded);
|
||||
decoded = PyMem_Malloc(len * sizeof(void *));
|
||||
if (decoded == NULL) {
|
||||
PyEval_RestoreThread(_save);
|
||||
PyErr_Format(PyExc_MemoryError, "failed to allocate decoded");
|
||||
goto _fail;
|
||||
}
|
||||
memset((void *)decoded, 0, len * sizeof(void *));
|
||||
decoded_ptr = decoded;
|
||||
|
||||
/* cache strings of length 2 */
|
||||
cptr = table2 = PyMem_Malloc(256*256*2 * sizeof(char));
|
||||
if (table2 == NULL) {
|
||||
PyEval_RestoreThread(_save);
|
||||
PyErr_Format(PyExc_MemoryError, "failed to allocate table2");
|
||||
goto _fail;
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
for (j = 0; j < 256; j++) {
|
||||
*cptr++ = (char)i;
|
||||
*cptr++ = (char)j;
|
||||
}
|
||||
}
|
||||
|
||||
memset(table, 0, sizeof(table));
|
||||
table_len = 258;
|
||||
bitw = 9;
|
||||
shr = 23;
|
||||
mask = 4286578688;
|
||||
bitcount = 0;
|
||||
result_len = 0;
|
||||
code = 0;
|
||||
oldcode = 0;
|
||||
|
||||
while ((unsigned int)((bitcount + bitw) / 8) <= encoded_len) {
|
||||
/* read next code */
|
||||
code = *((unsigned int *)((void *)(encoded + (bitcount / 8))));
|
||||
if (little_endian)
|
||||
code = SWAP4BYTES(code);
|
||||
code <<= (unsigned int)(bitcount % 8);
|
||||
code &= mask;
|
||||
code >>= shr;
|
||||
bitcount += bitw;
|
||||
|
||||
if (code == 257) /* end of information */
|
||||
break;
|
||||
|
||||
if (code == 256) { /* clearcode */
|
||||
/* initialize table and switch to 9 bit */
|
||||
while (table_len > 258) {
|
||||
t = table[--table_len];
|
||||
t->ref--;
|
||||
if (t->ref == 0) {
|
||||
if (t->len > 2)
|
||||
PyMem_Free(t->str);
|
||||
PyMem_Free(t);
|
||||
}
|
||||
}
|
||||
bitw = 9;
|
||||
shr = 23;
|
||||
mask = 4286578688;
|
||||
|
||||
/* read next code */
|
||||
code = *((unsigned int *)((void *)(encoded + (bitcount / 8))));
|
||||
if (little_endian)
|
||||
code = SWAP4BYTES(code);
|
||||
code <<= bitcount % 8;
|
||||
code &= mask;
|
||||
code >>= shr;
|
||||
bitcount += bitw;
|
||||
|
||||
if (code == 257) /* end of information */
|
||||
break;
|
||||
|
||||
/* decoded.append(table[code]) */
|
||||
if (code < 256) {
|
||||
result_len++;
|
||||
*((int *)decoded_ptr++) = code;
|
||||
} else {
|
||||
newresult = table[code];
|
||||
newresult->ref++;
|
||||
result_len += newresult->len;
|
||||
*(struct BYTE_STRING **)decoded_ptr++ = newresult;
|
||||
}
|
||||
} else {
|
||||
if (code < table_len) {
|
||||
/* code is in table */
|
||||
/* newresult = table[code]; */
|
||||
/* newentry = table[oldcode] + table[code][0] */
|
||||
/* decoded.append(newresult); table.append(newentry) */
|
||||
if (code < 256) {
|
||||
c = code;
|
||||
*((unsigned int *)decoded_ptr++) = code;
|
||||
result_len++;
|
||||
} else {
|
||||
newresult = table[code];
|
||||
newresult->ref++;
|
||||
c = (unsigned int) *newresult->str;
|
||||
*(struct BYTE_STRING **)decoded_ptr++ = newresult;
|
||||
result_len += newresult->len;
|
||||
}
|
||||
newentry = PyMem_Malloc(sizeof(struct BYTE_STRING));
|
||||
newentry->ref = 1;
|
||||
if (oldcode < 256) {
|
||||
newentry->len = 2;
|
||||
newentry->str = table2 + (oldcode << 9) +
|
||||
((unsigned char)c << 1);
|
||||
} else {
|
||||
len = table[oldcode]->len;
|
||||
newentry->len = len + 1;
|
||||
newentry->str = PyMem_Malloc(newentry->len);
|
||||
if (newentry->str == NULL)
|
||||
break;
|
||||
memmove(newentry->str, table[oldcode]->str, len);
|
||||
newentry->str[len] = c;
|
||||
}
|
||||
table[table_len++] = newentry;
|
||||
} else {
|
||||
/* code is not in table */
|
||||
/* newentry = newresult = table[oldcode] + table[oldcode][0] */
|
||||
/* decoded.append(newresult); table.append(newentry) */
|
||||
newresult = PyMem_Malloc(sizeof(struct BYTE_STRING));
|
||||
newentry = newresult;
|
||||
newentry->ref = 2;
|
||||
if (oldcode < 256) {
|
||||
newentry->len = 2;
|
||||
newentry->str = table2 + 514*oldcode;
|
||||
} else {
|
||||
len = table[oldcode]->len;
|
||||
newentry->len = len + 1;
|
||||
newentry->str = PyMem_Malloc(newentry->len);
|
||||
if (newentry->str == NULL)
|
||||
break;
|
||||
memmove(newentry->str, table[oldcode]->str, len);
|
||||
newentry->str[len] = *table[oldcode]->str;
|
||||
}
|
||||
table[table_len++] = newentry;
|
||||
*(struct BYTE_STRING **)decoded_ptr++ = newresult;
|
||||
result_len += newresult->len;
|
||||
}
|
||||
}
|
||||
oldcode = code;
|
||||
/* increase bit-width if necessary */
|
||||
switch (table_len) {
|
||||
case 511:
|
||||
bitw = 10;
|
||||
shr = 22;
|
||||
mask = 4290772992;
|
||||
break;
|
||||
case 1023:
|
||||
bitw = 11;
|
||||
shr = 21;
|
||||
mask = 4292870144;
|
||||
break;
|
||||
case 2047:
|
||||
bitw = 12;
|
||||
shr = 20;
|
||||
mask = 4293918720;
|
||||
}
|
||||
}
|
||||
|
||||
PyEval_RestoreThread(_save);
|
||||
|
||||
if (code != 257) {
|
||||
PyErr_WarnEx(NULL,
|
||||
"py_decodelzw encountered unexpected end of stream", 1);
|
||||
}
|
||||
|
||||
/* result = ''.join(decoded) */
|
||||
decoded_len = (unsigned int)(decoded_ptr - decoded);
|
||||
decoded_ptr = decoded;
|
||||
result = PyBytes_FromStringAndSize(0, result_len);
|
||||
if (result == NULL) {
|
||||
PyErr_Format(PyExc_MemoryError, "failed to allocate decoded string");
|
||||
goto _fail;
|
||||
}
|
||||
result_ptr = PyBytes_AS_STRING(result);
|
||||
|
||||
_save = PyEval_SaveThread();
|
||||
|
||||
while (decoded_len--) {
|
||||
code = *((unsigned int *)decoded_ptr);
|
||||
if (code < 256) {
|
||||
*result_ptr++ = (char)code;
|
||||
} else {
|
||||
t = *((struct BYTE_STRING **)decoded_ptr);
|
||||
memmove(result_ptr, t->str, t->len);
|
||||
result_ptr += t->len;
|
||||
if (--t->ref == 0) {
|
||||
if (t->len > 2)
|
||||
PyMem_Free(t->str);
|
||||
PyMem_Free(t);
|
||||
}
|
||||
}
|
||||
decoded_ptr++;
|
||||
}
|
||||
PyMem_Free(decoded);
|
||||
|
||||
while (table_len-- > 258) {
|
||||
t = table[table_len];
|
||||
if (t->len > 2)
|
||||
PyMem_Free(t->str);
|
||||
PyMem_Free(t);
|
||||
}
|
||||
PyMem_Free(table2);
|
||||
|
||||
PyEval_RestoreThread(_save);
|
||||
|
||||
Py_DECREF(byteobj);
|
||||
return result;
|
||||
|
||||
_fail:
|
||||
if (table2 != NULL)
|
||||
PyMem_Free(table2);
|
||||
if (decoded != NULL) {
|
||||
/* Bug? are decoded_ptr and decoded_len correct? */
|
||||
while (decoded_len--) {
|
||||
code = *((unsigned int *) decoded_ptr);
|
||||
if (code > 258) {
|
||||
t = *((struct BYTE_STRING **) decoded_ptr);
|
||||
if (--t->ref == 0) {
|
||||
if (t->len > 2)
|
||||
PyMem_Free(t->str);
|
||||
PyMem_Free(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
PyMem_Free(decoded);
|
||||
}
|
||||
while (table_len-- > 258) {
|
||||
t = table[table_len];
|
||||
if (t->len > 2)
|
||||
PyMem_Free(t->str);
|
||||
PyMem_Free(t);
|
||||
}
|
||||
|
||||
Py_XDECREF(byteobj);
|
||||
Py_XDECREF(result);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Create Python module */
|
||||
|
||||
char module_doc[] =
|
||||
"A Python C extension module for decoding PackBits and LZW encoded "
|
||||
"TIFF data.\n\n"
|
||||
"Refer to the tifffile.py module for documentation and tests.\n\n"
|
||||
"Authors:\n Christoph Gohlke <http://www.lfd.uci.edu/~gohlke/>\n"
|
||||
" Laboratory for Fluorescence Dynamics, University of California, Irvine."
|
||||
"\n\nVersion: %s\n";
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
#if MSB
|
||||
{"unpackints", (PyCFunction)py_unpackints, METH_VARARGS|METH_KEYWORDS,
|
||||
py_unpackints_doc},
|
||||
#endif
|
||||
{"decodelzw", (PyCFunction)py_decodelzw, METH_VARARGS,
|
||||
py_decodelzw_doc},
|
||||
{"decodepackbits", (PyCFunction)py_decodepackbits, METH_VARARGS,
|
||||
py_decodepackbits_doc},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
||||
struct module_state {
|
||||
PyObject *error;
|
||||
};
|
||||
|
||||
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
|
||||
|
||||
static int module_traverse(PyObject *m, visitproc visit, void *arg) {
|
||||
Py_VISIT(GETSTATE(m)->error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int module_clear(PyObject *m) {
|
||||
Py_CLEAR(GETSTATE(m)->error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_tifffile",
|
||||
NULL,
|
||||
sizeof(struct module_state),
|
||||
module_methods,
|
||||
NULL,
|
||||
module_traverse,
|
||||
module_clear,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define INITERROR return NULL
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit__tifffile(void)
|
||||
|
||||
#else
|
||||
|
||||
#define INITERROR return
|
||||
|
||||
PyMODINIT_FUNC
|
||||
init_tifffile(void)
|
||||
|
||||
#endif
|
||||
{
|
||||
PyObject *module;
|
||||
|
||||
char *doc = (char *)PyMem_Malloc(sizeof(module_doc) + sizeof(_VERSION_));
|
||||
PyOS_snprintf(doc, sizeof(doc), module_doc, _VERSION_);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
moduledef.m_doc = doc;
|
||||
module = PyModule_Create(&moduledef);
|
||||
#else
|
||||
module = Py_InitModule3("_tifffile", module_methods, doc);
|
||||
#endif
|
||||
|
||||
PyMem_Free(doc);
|
||||
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
|
||||
if (_import_array() < 0) {
|
||||
Py_DECREF(module);
|
||||
INITERROR;
|
||||
}
|
||||
|
||||
{
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
PyObject *s = PyString_FromString(_VERSION_);
|
||||
#else
|
||||
PyObject *s = PyUnicode_FromString(_VERSION_);
|
||||
#endif
|
||||
PyObject *dict = PyModule_GetDict(module);
|
||||
PyDict_SetItemString(dict, "__version__", s);
|
||||
Py_DECREF(s);
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
#endif
|
||||
}
|
||||
|
||||
+2
@@ -151,6 +151,8 @@ from xml.etree import cElementTree as etree
|
||||
|
||||
import numpy
|
||||
|
||||
from . import _tifffile
|
||||
|
||||
__version__ = '0.3.1'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
__all__ = ('imsave', 'imread', 'imshow', 'TiffFile', 'TiffWriter',
|
||||
@@ -21,6 +21,7 @@ def configuration(parent_package='', top_path=None):
|
||||
config.add_subpackage('transform')
|
||||
config.add_subpackage('util')
|
||||
config.add_subpackage('segmentation')
|
||||
config.add_subpackage('external')
|
||||
|
||||
def add_test_directories(arg, dirname, fnames):
|
||||
if dirname.split(os.path.sep)[-1] == 'tests':
|
||||
|
||||
Reference in New Issue
Block a user