Add tifffile.c to the build

This commit is contained in:
Steven Silvester
2014-10-15 20:59:20 -05:00
parent b6f775a7cf
commit 50aff0058a
5 changed files with 994 additions and 0 deletions
+3
View File
@@ -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
+26
View File
@@ -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())
)
+962
View File
@@ -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
}
@@ -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',
+1
View File
@@ -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':