Commit 399d19ab authored by André Anjos's avatar André Anjos 💬
Browse files

All compiles file; All tests passing

parent 38baf284
......@@ -17,7 +17,6 @@ before_install:
- sudo add-apt-repository -y ppa:biometrics/bob.preview
- sudo apt-get update -qq
- sudo apt-get install -qq --force-yes bob-dev libjpeg8-dev libnetpbm10-dev libpng12-dev libtiff4-dev libgif-dev
- sudo apt-get install -qq python-imaging
- if [ -n "${NUMPYSPEC}" ]; then sudo apt-get install -qq libatlas-dev libatlas-base-dev liblapack-dev gfortran; fi
- if [ -n "${NUMPYSPEC}" ]; then pip install --upgrade pip setuptools; fi
- if [ -n "${NUMPYSPEC}" ]; then pip install --find-links http://wheels.astropy.org/ --find-links http://wheels2.astropy.org/ --use-wheel numpy$NUMPYSPEC sphinx nose; fi
......@@ -26,8 +25,8 @@ install:
- "python bootstrap.py"
- "CFLAGS=-coverage ./bin/buildout"
script:
- "./bin/python -c 'from xbob.io.base import get_config; print(get_config())'"
- "./bin/coverage run --source=xbob.io.base ./bin/nosetests -sv"
- "./bin/python -c 'from xbob.io.image import get_config; print(get_config())'"
- "./bin/coverage run --source=xbob.io.image ./bin/nosetests -sv"
- "./bin/sphinx-build -b doctest doc sphinx"
- "./bin/sphinx-build -b html doc sphinx"
after_success:
......
......@@ -4,7 +4,7 @@
[buildout]
parts = scripts
eggs = xbob.io.matlab
eggs = xbob.io.image
extensions = xbob.buildout
mr.developer
auto-checkout = *
......
......@@ -5,22 +5,286 @@
from setuptools import setup, find_packages, dist
dist.Distribution(dict(setup_requires=['xbob.blitz', 'xbob.io.base']))
from xbob.extension.utils import egrep, find_header, find_library
from xbob.blitz.extension import Extension
import xbob.io.base
include_dirs = [xbob.io.base.get_include()]
packages = ['bob-io >= 2.0.0a2']
packages = ['bob-io >= 2.0.0a2', 'libtiff-4', 'libpng']
version = '2.0.0a0'
# Check if python-imaging means pil or pillow
pil_or_pillow = []
try:
import pkg_resources
pkg_resources.require('PIL')
pil_or_pillow.append('pil')
except pkg_resources.DistributionNotFound as e:
pil_or_pillow.append('pillow')
def libjpeg_version(header):
version = egrep(header, r"#\s*define\s+JPEG_LIB_VERSION_(MINOR|MAJOR)\s+(\d+)")
if not len(version): return None
# we have a match, produce a string version of the version number
major = int(version[0].group(2))
minor = int(version[1].group(2))
return '%d.%d' % (major, minor)
class jpeg:
def __init__ (self, requirement='', only_static=False):
"""
Searches for libjpeg in stock locations. Allows user to override.
If the user sets the environment variable XBOB_PREFIX_PATH, that prefixes
the standard path locations.
Parameters:
requirement, str
A string, indicating a version requirement for this library. For example,
``'>= 8.2'``.
only_static, boolean
A flag, that indicates if we intend to link against the static library
only. This will trigger our library search to disconsider shared
libraries when searching.
"""
self.name = 'libjpeg'
header = 'jpeglib.h'
candidates = find_header(header)
if not candidates:
raise RuntimeError("could not find %s's `%s' - have you installed %s on this machine?", name, header, name)
found = False
if not requirement:
self.include_directory = os.path.dirname(candidates[0])
self.version = libjpeg_version(candidates[0])
found = True
else:
# requirement is 'operator' 'version'
operator, required = [k.strip() for k in requirement.split(' ', 1)]
# now check for user requirements
for candidate in candidates:
version = libjpeg_version(candidate)
available = LooseVersion(version)
if (operator == '<' and available < required) or \
(operator == '<=' and available <= required) or \
(operator == '>' and available > required) or \
(operator == '>=' and available >= required) or \
(operator == '==' and available == required):
self.include_directory = os.path.dirname(candidate)
self.version = version
found = True
break
if not found:
raise RuntimeError("could not find the required (%s) version of %s on the file system (looked at: %s)" % (requirement, name, ', '.join(candidates)))
# normalize
self.include_directory = os.path.normpath(self.include_directory)
# find library
prefix = os.path.dirname(os.path.dirname(self.include_directory))
module = 'jpeg'
candidates = find_library(module, version=self.version, prefixes=[prefix], only_static=only_static)
if not candidates:
raise RuntimeError("cannot find required %s binary module `%s' - make sure libsvm is installed on `%s'" % (name, module, prefix))
# libraries
self.libraries = []
name, ext = os.path.splitext(os.path.basename(candidates[0]))
if ext in ['.so', '.a', '.dylib', '.dll']:
self.libraries.append(name[3:]) #strip 'lib' from the name
else: #link against the whole thing
self.libraries.append(':' + os.path.basename(candidates[0]))
# library path
self.library_directory = os.path.dirname(candidates[0])
def macros(self):
return [
('HAVE_%s' % self.name.upper(), '1'),
('%s_VERSION' % self.name.upper(), '"%s"' % self.version),
]
def libgif_version(header):
version = egrep(header, r"#\s*define\s+GIFLIB_(RELEASE|MINOR|MAJOR)\s+(\d+)")
if not len(version): return None
# we have a match, produce a string version of the version number
major = int(version[0].group(2))
minor = int(version[1].group(2))
release = int(version[2].group(2))
return '%d.%d.%d' % (major, minor, release)
class gif:
def __init__ (self, requirement='', only_static=False):
"""
Searches for libgif in stock locations. Allows user to override.
If the user sets the environment variable XBOB_PREFIX_PATH, that prefixes
the standard path locations.
Parameters:
requirement, str
A string, indicating a version requirement for this library. For example,
``'>= 8.2'``.
only_static, boolean
A flag, that indicates if we intend to link against the static library
only. This will trigger our library search to disconsider shared
libraries when searching.
"""
self.name = 'giflib'
header = 'gif_lib.h'
candidates = find_header(header)
if not candidates:
raise RuntimeError("could not find %s's `%s' - have you installed %s on this machine?", name, header, name)
found = False
if not requirement:
self.include_directory = os.path.dirname(candidates[0])
self.version = libgif_version(candidates[0])
found = True
else:
# requirement is 'operator' 'version'
operator, required = [k.strip() for k in requirement.split(' ', 1)]
# now check for user requirements
for candidate in candidates:
version = libgif_version(candidate)
available = LooseVersion(version)
if (operator == '<' and available < required) or \
(operator == '<=' and available <= required) or \
(operator == '>' and available > required) or \
(operator == '>=' and available >= required) or \
(operator == '==' and available == required):
self.include_directory = os.path.dirname(candidate)
self.version = version
found = True
break
if not found:
raise RuntimeError("could not find the required (%s) version of %s on the file system (looked at: %s)" % (requirement, name, ', '.join(candidates)))
# normalize
self.include_directory = os.path.normpath(self.include_directory)
# find library
prefix = os.path.dirname(os.path.dirname(self.include_directory))
module = 'gif'
candidates = find_library(module, version=self.version, prefixes=[prefix], only_static=only_static)
if not candidates:
raise RuntimeError("cannot find required %s binary module `%s' - make sure libsvm is installed on `%s'" % (name, module, prefix))
# libraries
self.libraries = []
name, ext = os.path.splitext(os.path.basename(candidates[0]))
if ext in ['.so', '.a', '.dylib', '.dll']:
self.libraries.append(name[3:]) #strip 'lib' from the name
else: #link against the whole thing
self.libraries.append(':' + os.path.basename(candidates[0]))
# library path
self.library_directory = os.path.dirname(candidates[0])
def macros(self):
return [
('HAVE_%s' % self.name.upper(), '1'),
('%s_VERSION' % self.name.upper(), '"%s"' % self.version),
]
class netpbm:
def __init__ (self, only_static=False):
"""
Searches for netpbm in stock locations. Allows user to override.
If the user sets the environment variable XBOB_PREFIX_PATH, that prefixes
the standard path locations.
Parameters:
only_static, boolean
A flag, that indicates if we intend to link against the static library
only. This will trigger our library search to disconsider shared
libraries when searching.
"""
self.name = 'netpbm'
header = 'pam.h'
candidates = find_header(header, subpaths=[self.name])
if not candidates:
raise RuntimeError("could not find %s's `%s' - have you installed %s on this machine?", name, header, name)
self.include_directory = os.path.dirname(candidates[0])
found = True
# normalize
self.include_directory = os.path.normpath(self.include_directory)
# find library
prefix = os.path.dirname(os.path.dirname(self.include_directory))
module = 'netpbm'
candidates = find_library(module, prefixes=[prefix], only_static=only_static)
if not candidates:
raise RuntimeError("cannot find required %s binary module `%s' - make sure libsvm is installed on `%s'" % (name, module, prefix))
# libraries
self.libraries = []
name, ext = os.path.splitext(os.path.basename(candidates[0]))
if ext in ['.so', '.a', '.dylib', '.dll']:
self.libraries.append(name[3:]) #strip 'lib' from the name
else: #link against the whole thing
self.libraries.append(':' + os.path.basename(candidates[0]))
# library path
self.library_directory = os.path.dirname(candidates[0])
def macros(self):
return [ ('HAVE_%s' % self.name.upper(), '1'), ]
jpeg_pkg = jpeg()
gif_pkg = gif()
netpbm_pkg = netpbm()
extra_compile_args = [
'-isystem', jpeg_pkg.include_directory,
'-isystem', gif_pkg.include_directory,
'-isystem', netpbm_pkg.include_directory,
]
library_dirs = [
jpeg_pkg.library_directory,
gif_pkg.library_directory,
netpbm_pkg.library_directory,
]
libraries = \
jpeg_pkg.libraries + \
gif_pkg.libraries + \
netpbm_pkg.libraries
define_macros = \
jpeg_pkg.macros() + \
gif_pkg.macros() + \
netpbm_pkg.macros()
setup(
......@@ -41,7 +305,7 @@ setup(
'setuptools',
'xbob.blitz',
'xbob.io.base',
] + pil_or_pillow,
],
namespace_packages=[
"xbob",
......@@ -56,6 +320,10 @@ setup(
packages = packages,
include_dirs = include_dirs,
version = version,
extra_compile_args = extra_compile_args,
library_dirs = library_dirs,
libraries = libraries,
define_macros = define_macros,
),
Extension("xbob.io.image._library",
[
......@@ -65,12 +333,15 @@ setup(
"xbob/io/image/jpeg.cpp",
"xbob/io/image/bmp.cpp",
"xbob/io/image/netpbm.cpp",
"xbob/io/image/file.cpp",
"xbob/io/image/main.cpp",
],
packages = packages,
include_dirs = include_dirs,
version = version,
extra_compile_args = extra_compile_args,
library_dirs = library_dirs,
libraries = libraries,
define_macros = define_macros,
),
],
......
......@@ -17,8 +17,7 @@
#include <boost/algorithm/string.hpp>
#include <string>
#include <bob/io/CodecRegistry.h>
#include <bob/core/logging.h>
#include <bob/io/File.h>
// The following documentation is mostly coming from wikipedia:
// http://en.wikipedia.org/wiki/BMP_file_format
......
......@@ -7,8 +7,8 @@
* Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
*/
#ifndef BOB_IO_MATLAB_FILE_H
#define BOB_IO_MATLAB_FILE_H
#ifndef BOB_IO_IMAGE_FILE_H
#define BOB_IO_IMAGE_FILE_H
#include <boost/shared_ptr.hpp>
#include <bob/io/File.h>
......@@ -38,4 +38,4 @@ boost::shared_ptr<bob::io::File> make_netpbm_file (const char* path, char mode);
boost::shared_ptr<bob::io::File> make_png_file (const char* path, char mode);
boost::shared_ptr<bob::io::File> make_bmp_file (const char* path, char mode);
#endif /* BOB_IO_MATLAB_FILE_H */
#endif /* BOB_IO_IMAGE_FILE_H */
......@@ -17,6 +17,8 @@
#include <boost/algorithm/string.hpp>
#include <string>
#include <bob/io/File.h>
extern "C" {
#include <gif_lib.h>
}
......@@ -646,6 +648,6 @@ class ImageGifFile: public bob::io::File {
std::string ImageGifFile::s_codecname = "bob.image_gif";
boost::shared_ptr<bob::io::File> make_giff_file (const char* path, char mode) {
boost::shared_ptr<bob::io::File> make_gif_file (const char* path, char mode) {
return boost::make_shared<ImageGifFile>(path, mode);
}
......@@ -18,6 +18,8 @@
#include <boost/algorithm/string.hpp>
#include <string>
#include <bob/io/File.h>
#include <jpeglib.h>
// Default JPEG quality
......
......@@ -81,8 +81,7 @@ static PyObject* create_module (void) {
}
}
else {
PyErr_Format(PyExc_RuntimeError, "LibJPEG compiled with " << BITS_IN_JSAMPLE <<
" bits depth (instead of 8). JPEG images are hence not supported.");
PyErr_Format(PyExc_RuntimeError, "libjpeg compiled with `%d' bits depth (instead of 8). JPEG images are hence not supported.", BITS_IN_JSAMPLE);
PyErr_Print();
}
......
......@@ -17,6 +17,8 @@
#include <boost/algorithm/string.hpp>
#include <string>
#include <bob/io/File.h>
extern "C" {
// This header must come last, as it brings a lot of global stuff that messes up other headers...
#include <pam.h>
......@@ -315,7 +317,7 @@ class ImageNetpbmFile: public bob::io::File {
public: //api
ImageNetpbmFile(const std::string& path, char mode):
ImageNetpbmFile(const char* path, char mode):
m_filename(path),
m_newfile(true) {
......@@ -341,8 +343,8 @@ class ImageNetpbmFile: public bob::io::File {
virtual ~ImageNetpbmFile() { }
virtual const std::string& filename() const {
return m_filename;
virtual const char* filename() const {
return m_filename.c_str();
}
virtual const bob::core::array::typeinfo& type_all() const {
......@@ -357,8 +359,8 @@ class ImageNetpbmFile: public bob::io::File {
return m_length;
}
virtual const std::string& name() const {
return s_codecname;
virtual const char* name() const {
return s_codecname.c_str();
}
virtual void read_all(bob::core::array::interface& buffer) {
......@@ -415,7 +417,7 @@ std::string ImageNetpbmFile::s_codecname = "bob.image_netpbm";
static bool netpbm_initialized = false;
boost::shared_ptr<bob::io::File> make_netpbm_file (const std::string& path, char mode) {
boost::shared_ptr<bob::io::File> make_netpbm_file (const char* path, char mode) {
if (!netpbm_initialized) {
pm_init("bob",0);
netpbm_initialized = true;
......
......@@ -17,7 +17,7 @@
#include <boost/algorithm/string.hpp>
#include <string>
#include <bob/io/CodecRegistry.h>
#include <bob/io/File.h>
extern "C" {
#include <png.h>
......
......@@ -8,7 +8,9 @@
"""Runs some image tests
"""
from . import load, test_utils
import os
import numpy
from xbob.io.base import load, write, test_utils
# These are some global parameters for the test.
PNG_INDEXED_COLOR = test_utils.datafile('img_indexed_color.png', __name__)
......@@ -20,3 +22,29 @@ def test_png_indexed_color():
assert img.shape == (3,22,32)
assert img[0,0,0] == 255
assert img[0,17,17] == 117
def transcode(filename):
tmpname = test_utils.temporary_filename(suffix=os.path.splitext(filename)[1])
try:
# complete transcoding test
image = load(filename)
# save with the same extension
write(image, tmpname)
# reload the image from the file
image2 = load(tmpname)
assert numpy.array_equal(image, image2)
finally:
if os.path.exists(tmpname): os.unlink(tmpname)
def test_netpbm():
transcode(test_utils.datafile('test.pgm', __name__)) #indexed, works fine
transcode(test_utils.datafile('test.pbm', __name__)) #indexed, works fine
transcode(test_utils.datafile('test.ppm', __name__)) #indexed, works fine
#transcode(test_utils.datafile('test.jpg', __name__)) #does not work because of re-compression
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# Andre Anjos <andre.anjos@idiap.ch>
# Wed Nov 16 13:27:15 2011 +0100
#
# Copyright (C) 2011-2013 Idiap Research Institute, Martigny, Switzerland
"""A combined test for all built-in types of Array/interaction in
python.
"""
import os
import sys
import numpy
import nose.tools
from . import load, write, peek, peek_all, File, test_utils
def test_peek():
f = test_utils.datafile('test1.hdf5', __name__)
assert peek(f) == (numpy.uint16, (3,), (1,))
assert peek_all(f) == (numpy.uint16, (3,3), (3,1))
def test_iteration():
fname = test_utils.datafile('matlab_2d.hdf5', __name__)
f = File(fname, 'r')
nose.tools.eq_(len(f), 512)
objs = load(fname)
for l, i in zip(objs, f):
assert numpy.allclose(l, i)
def test_indexing():
fname = test_utils.datafile('matlab_2d.hdf5', __name__)
f = File(fname, 'r')
nose.tools.eq_(len(f), 512)
objs = load(fname)
nose.tools.eq_(len(f), len(objs))
# simple indexing
assert numpy.allclose(f[0], objs[0])
assert numpy.allclose(f[1], objs[1])
assert numpy.allclose(f[-1], objs[-1])
assert numpy.allclose(f[-2], objs[-2])
def test_slicing_empty():
fname = test_utils.datafile('matlab_2d.hdf5', __name__)
f = File(fname, 'r')
objs = f[1:1]
assert objs.shape == tuple()
def test_slicing_0():
fname = test_utils.datafile('matlab_2d.hdf5', __name__)
f = File(fname, 'r')
objs = f[:]
for i, k in enumerate(load(fname)):
assert numpy.allclose(k, objs[i])
def test_slicing_1():
fname = test_utils.datafile('matlab_2d.hdf5', __name__)
f = File(fname, 'r')
# get slice
s1 = f[3:10:2]
nose.tools.eq_(len(s1), 4)
assert numpy.allclose(s1[0], f[3])
assert numpy.allclose(s1[1], f[5])
assert numpy.allclose(s1[2], f[7])
assert numpy.allclose(s1[3], f[9])
def test_slicing_2():
fname = test_utils.datafile('matlab_2d.hdf5', __name__)
f = File(fname, 'r')
# get negative slicing
s = f[-10:-2:3]
nose.tools.eq_(len(s), 3)
assert numpy.allclose(s[0], f[len(f)-10])
assert numpy.allclose(s[1], f[len(f)-7])
assert numpy.allclose(s[2], f[len(f)-4])
def test_slicing_3():
fname = test_utils.datafile('matlab_2d.hdf5', __name__)
f = File(fname, 'r')