diff --git a/bento.info b/bento.info index 564f1f5a..7518abbc 100644 --- a/bento.info +++ b/bento.info @@ -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 diff --git a/skimage/external/setup.py b/skimage/external/setup.py new file mode 100644 index 00000000..c046cd62 --- /dev/null +++ b/skimage/external/setup.py @@ -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()) + ) diff --git a/skimage/external/tifffile/tifffile.c b/skimage/external/tifffile/tifffile.c new file mode 100644 index 00000000..6aa0eaa1 --- /dev/null +++ b/skimage/external/tifffile/tifffile.c @@ -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 `_ + +: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 +#include +#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 \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 +} + diff --git a/skimage/external/tifffile/_tifffile.py b/skimage/external/tifffile/tiffile_.py similarity index 99% rename from skimage/external/tifffile/_tifffile.py rename to skimage/external/tifffile/tiffile_.py index 83ae4f0e..b2d3303a 100644 --- a/skimage/external/tifffile/_tifffile.py +++ b/skimage/external/tifffile/tiffile_.py @@ -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', diff --git a/skimage/setup.py b/skimage/setup.py index 962adb97..9a8c8ac2 100644 --- a/skimage/setup.py +++ b/skimage/setup.py @@ -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':