<commit_before>#include <storm/platform/ogl/texture_storage_ogl.h>

#include <algorithm>
#include <map>

#include <storm/platform/ogl/check_result_ogl.h>

namespace storm {

namespace {

// glTexImage*D functions require pixel format and pixel type even when no
// pixel data is specified.

struct PixelDescription {
    GLenum format;
    GLenum type;
};

PixelDescription getCompatiblePixelDescription( GLenum internalFormat ) {
    static const std::map<GLenum, PixelDescription> mapping = {
        {GL_R8, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_R8_SNORM, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_R16, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_R16_SNORM, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_RG8, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_RG8_SNORM, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_RG16, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_RG16_SNORM, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_R3_G3_B2, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB4, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB5, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB8, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB8_SNORM, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB10, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB12, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB16_SNORM, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGBA2, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGBA4, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB5_A1, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_RGBA8, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_RGBA8_SNORM, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_RGB10_A2, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_RGB10_A2UI, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_RGBA12, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_RGBA16, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_SRGB8, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_SRGB8_ALPHA8, {GL_RGBA, GL_UNSIGNED_BYTE}},

        {GL_R16F, {GL_RED, GL_FLOAT}},
        {GL_RG16F, {GL_RG, GL_FLOAT}},
        {GL_RGB16F, {GL_RGB, GL_FLOAT}},
        {GL_RGBA16F, {GL_RGBA, GL_FLOAT}},
        {GL_R32F, {GL_RED, GL_FLOAT}},
        {GL_RG32F, {GL_RG, GL_FLOAT}},
        {GL_RGB32F, {GL_RGB, GL_FLOAT}},
        {GL_RGBA32F, {GL_RGBA, GL_FLOAT}},
        {GL_R11F_G11F_B10F, {GL_RGB, GL_FLOAT}},
        {GL_RGB9_E5, {GL_RGB, GL_FLOAT}},

        {GL_R8I, {GL_RED_INTEGER, GL_INT}},
        {GL_R8UI, {GL_RED_INTEGER, GL_UNSIGNED_INT}},
        {GL_R16I, {GL_RED_INTEGER, GL_INT}},
        {GL_R16UI, {GL_RED_INTEGER, GL_UNSIGNED_INT}},
        {GL_R32I, {GL_RED_INTEGER, GL_INT}},
        {GL_R32UI, {GL_RED_INTEGER, GL_UNSIGNED_INT}},
        {GL_RG8I, {GL_RG_INTEGER, GL_INT}},
        {GL_RG8UI, {GL_RG_INTEGER, GL_UNSIGNED_INT}},
        {GL_RG16I, {GL_RG_INTEGER, GL_INT}},
        {GL_RG16UI, {GL_RG_INTEGER, GL_UNSIGNED_INT}},
        {GL_RG32I, {GL_RG_INTEGER, GL_INT}},
        {GL_RG32UI, {GL_RG_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGB8I, {GL_RGB_INTEGER, GL_INT}},
        {GL_RGB8UI, {GL_RGB_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGB16I, {GL_RGB_INTEGER, GL_INT}},
        {GL_RGB16UI, {GL_RGB_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGB32I, {GL_RGB_INTEGER, GL_INT}},
        {GL_RGB32UI, {GL_RGB_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGBA8I, {GL_RGBA_INTEGER, GL_INT}},
        {GL_RGBA8UI, {GL_RGBA_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGBA16I, {GL_RGBA_INTEGER, GL_INT}},
        {GL_RGBA16UI, {GL_RGBA_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGBA32I, {GL_RGBA_INTEGER, GL_INT}},
        {GL_RGBA32UI, {GL_RGBA_INTEGER, GL_UNSIGNED_INT}},

        {GL_DEPTH_COMPONENT16, {GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}},
        {GL_DEPTH_COMPONENT24, {GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}},
        {GL_DEPTH_COMPONENT32, {GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}},
        {GL_DEPTH_COMPONENT32F, {GL_DEPTH_COMPONENT, GL_FLOAT}},
        {GL_DEPTH24_STENCIL8, {GL_DEPTH_STENCIL, GL_UNSIGNED_INT}},
        {GL_DEPTH32F_STENCIL8, {GL_DEPTH_STENCIL, GL_FLOAT}},
        {GL_STENCIL_INDEX8, {GL_STENCIL_INDEX, GL_UNSIGNED_INT}},

        {GL_COMPRESSED_RED, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_RG, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_RGB, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_RGBA, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_SRGB, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_SRGB_ALPHA, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_RED_RGTC1, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_SIGNED_RED_RGTC1, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_RG_RGTC2, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_SIGNED_RG_RGTC2, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_RGBA_BPTC_UNORM, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, {GL_RGB, GL_FLOAT}},
        {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, {GL_RGB, GL_FLOAT}},
        // {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, {GL_RGB, GL_UNSIGNED_BYTE}},
        // {GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, {GL_RGB, GL_UNSIGNED_BYTE}},
        // {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, {GL_RGBA, GL_UNSIGNED_BYTE}},
        // {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, {GL_RGBA, GL_UNSIGNED_BYTE}},
        // {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, {GL_RGBA, GL_UNSIGNED_BYTE}},
        // {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, {GL_RGBA, GL_UNSIGNED_BYTE}},
        // {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, {GL_RGBA, GL_UNSIGNED_BYTE}},
        // {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, {GL_RGBA, GL_UNSIGNED_BYTE}}
    };
    storm_assert( mapping.count(internalFormat) );
    return mapping.at( internalFormat );
}

}

void APIENTRY glTexStorage1D( GLenum target, GLsizei levels,
    GLenum internalFormat, GLsizei width )
{
    for( GLsizei level = 0; level < levels; ++level ) {
        const PixelDescription pixelDescription =
            getCompatiblePixelDescription( internalFormat );

        ::glTexImage1D( target, level, internalFormat, width, 0,
            pixelDescription.format, pixelDescription.type, nullptr );
        checkResult( "::glTexImage1D" );

        width = std::max( 1, (width / 2) );
    }
}

void APIENTRY glTexStorage2D( GLenum target, GLsizei levels,
    GLenum internalFormat, GLsizei width, GLsizei height )
{
    for( GLsizei level = 0; level < levels; ++level ) {
        const PixelDescription pixelDescription =
            getCompatiblePixelDescription( internalFormat );

        ::glTexImage2D( target, level, internalFormat, width, height, 0,
            pixelDescription.format, pixelDescription.type, nullptr );
        checkResult( "::glTexImage2D" );

        width = std::max( 1, (width / 2) );
        if( target != GL_TEXTURE_1D_ARRAY )
            height = std::max( 1, (height / 2) );
    }
}

void APIENTRY glTexStorage3D( GLenum target, GLsizei levels,
    GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth )
{
    for( GLsizei level = 0; level < levels; ++level ) {
        const PixelDescription pixelDescription =
            getCompatiblePixelDescription( internalFormat );

        ::glTexImage3D( target, level, internalFormat, width, height, depth, 0,
            pixelDescription.format, pixelDescription.type, nullptr );
        checkResult( "::glTexImage3D" );

        width = std::max( 1, (width / 2) );
        height = std::max( 1, (height / 2) );
        if( target != GL_TEXTURE_2D_ARRAY )
            depth = std::max( 1, (depth / 2) );
    }
}

void APIENTRY glTexStorage2DMultisample( GLenum target,
    GLsizei samples,
    GLenum internalFormat,
    GLsizei width,
    GLsizei height,
    GLboolean fixedSampleLocations )
{
    ::glTexImage2DMultisample(
        target, samples, internalFormat, width, height, fixedSampleLocations );
}

void APIENTRY glTexStorage3DMultisample( GLenum target,
    GLsizei samples,
    GLenum internalFormat,
    GLsizei width,
    GLsizei height,
    GLsizei depth,
    GLboolean fixedSampleLocations )
{
    ::glTexStorage3DMultisample( target, samples, internalFormat,
        width, height, depth, fixedSampleLocations );
}

}
<commit_msg>Fixed texture format to pixel format mapping<commit_after>#include <storm/platform/ogl/texture_storage_ogl.h>

#include <algorithm>
#include <map>

#include <storm/platform/ogl/check_result_ogl.h>

namespace storm {

namespace {

// glTexImage*D functions require pixel format and pixel type even when no
// pixel data is specified.

struct PixelDescription {
    GLenum format;
    GLenum type;
};

PixelDescription getCompatiblePixelDescription( GLenum internalFormat ) {
    static const std::map<GLenum, PixelDescription> mapping = {
        {GL_R8, {GL_RED, GL_UNSIGNED_BYTE}},
        {GL_R8_SNORM, {GL_RED, GL_BYTE}},
        {GL_R16, {GL_RED, GL_UNSIGNED_SHORT}},
        {GL_R16_SNORM, {GL_RED, GL_SHORT}},
        {GL_RG8, {GL_RG, GL_UNSIGNED_BYTE}},
        {GL_RG8_SNORM, {GL_RG, GL_BYTE}},
        {GL_RG16, {GL_RG, GL_UNSIGNED_SHORT}},
        {GL_RG16_SNORM, {GL_RG, GL_SHORT}},
        {GL_R3_G3_B2, {GL_RGB, GL_UNSIGNED_BYTE_3_3_2}},
        {GL_RGB4, {GL_RGB, GL_UNSIGNED_SHORT_5_6_5}},
        {GL_RGB5, {GL_RGB, GL_UNSIGNED_SHORT_5_6_5}},
        {GL_RGB8, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_RGB8_SNORM, {GL_RGB, GL_BYTE}},
        {GL_RGB10, {GL_RGB, GL_UNSIGNED_SHORT}},
        {GL_RGB12, {GL_RGB, GL_UNSIGNED_SHORT}},
        {GL_RGB16_SNORM, {GL_RGB, GL_SHORT}},
        {GL_RGBA2, {GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}},
        {GL_RGBA4, {GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}},
        {GL_RGB5_A1, {GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}},
        {GL_RGBA8, {GL_RGBA, GL_UNSIGNED_BYTE}},
        {GL_RGBA8_SNORM, {GL_RGBA, GL_BYTE}},
        {GL_RGB10_A2, {GL_RGBA, GL_UNSIGNED_INT_10_10_10_2}},
        {GL_RGB10_A2UI, {GL_RGBA_INTEGER, GL_UNSIGNED_INT_10_10_10_2}},
        {GL_RGBA12, {GL_RGBA, GL_UNSIGNED_SHORT}},
        {GL_RGBA16, {GL_RGBA, GL_UNSIGNED_SHORT}},
        {GL_SRGB8, {GL_RGB, GL_UNSIGNED_BYTE}},
        {GL_SRGB8_ALPHA8, {GL_RGBA, GL_UNSIGNED_BYTE}},

        {GL_R16F, {GL_RED, GL_HALF_FLOAT}},
        {GL_RG16F, {GL_RG, GL_HALF_FLOAT}},
        {GL_RGB16F, {GL_RGB, GL_HALF_FLOAT}},
        {GL_RGBA16F, {GL_RGBA, GL_HALF_FLOAT}},
        {GL_R32F, {GL_RED, GL_FLOAT}},
        {GL_RG32F, {GL_RG, GL_FLOAT}},
        {GL_RGB32F, {GL_RGB, GL_FLOAT}},
        {GL_RGBA32F, {GL_RGBA, GL_FLOAT}},
        {GL_R11F_G11F_B10F, {GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}},
        {GL_RGB9_E5, {GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}},

        {GL_R8I, {GL_RED_INTEGER, GL_BYTE}},
        {GL_R8UI, {GL_RED_INTEGER, GL_UNSIGNED_BYTE}},
        {GL_R16I, {GL_RED_INTEGER, GL_SHORT}},
        {GL_R16UI, {GL_RED_INTEGER, GL_UNSIGNED_SHORT}},
        {GL_R32I, {GL_RED_INTEGER, GL_INT}},
        {GL_R32UI, {GL_RED_INTEGER, GL_UNSIGNED_INT}},
        {GL_RG8I, {GL_RG_INTEGER, GL_BYTE}},
        {GL_RG8UI, {GL_RG_INTEGER, GL_UNSIGNED_BYTE}},
        {GL_RG16I, {GL_RG_INTEGER, GL_SHORT}},
        {GL_RG16UI, {GL_RG_INTEGER, GL_UNSIGNED_SHORT}},
        {GL_RG32I, {GL_RG_INTEGER, GL_INT}},
        {GL_RG32UI, {GL_RG_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGB8I, {GL_RGB_INTEGER, GL_BYTE}},
        {GL_RGB8UI, {GL_RGB_INTEGER, GL_UNSIGNED_BYTE}},
        {GL_RGB16I, {GL_RGB_INTEGER, GL_SHORT}},
        {GL_RGB16UI, {GL_RGB_INTEGER, GL_UNSIGNED_SHORT}},
        {GL_RGB32I, {GL_RGB_INTEGER, GL_INT}},
        {GL_RGB32UI, {GL_RGB_INTEGER, GL_UNSIGNED_INT}},
        {GL_RGBA8I, {GL_RGBA_INTEGER, GL_BYTE}},
        {GL_RGBA8UI, {GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}},
        {GL_RGBA16I, {GL_RGBA_INTEGER, GL_SHORT}},
        {GL_RGBA16UI, {GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}},
        {GL_RGBA32I, {GL_RGBA_INTEGER, GL_INT}},
        {GL_RGBA32UI, {GL_RGBA_INTEGER, GL_UNSIGNED_INT}},

        {GL_DEPTH_COMPONENT16, {GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}},
        {GL_DEPTH_COMPONENT24, {GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}},
        {GL_DEPTH_COMPONENT32, {GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}},
        {GL_DEPTH_COMPONENT32F, {GL_DEPTH_COMPONENT, GL_FLOAT}},
        {GL_DEPTH24_STENCIL8, {GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}},
        {GL_DEPTH32F_STENCIL8, {GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV}},
        {GL_STENCIL_INDEX8, {GL_STENCIL_INDEX, GL_UNSIGNED_BYTE}}
    };
    storm_assert( mapping.count(internalFormat) );
    return mapping.at( internalFormat );
}

// TODO: support compressed texture formats
// GL_COMPRESSED_RED
// GL_COMPRESSED_RG
// GL_COMPRESSED_RGB
// GL_COMPRESSED_RGBA
// GL_COMPRESSED_SRGB
// GL_COMPRESSED_SRGB_ALPHA
// GL_COMPRESSED_RED_RGTC1
// GL_COMPRESSED_SIGNED_RED_RGTC1
// GL_COMPRESSED_RG_RGTC2
// GL_COMPRESSED_SIGNED_RG_RGTC2
// GL_COMPRESSED_RGBA_BPTC_UNORM
// GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM
// GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT
// GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT
// GL_COMPRESSED_RGB_S3TC_DXT1_EXT
// GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
// GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
// GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
// GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
// GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
// GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT

}

void APIENTRY glTexStorage1D( GLenum target, GLsizei levels,
    GLenum internalFormat, GLsizei width )
{
    for( GLsizei level = 0; level < levels; ++level ) {
        const PixelDescription pixelDescription =
            getCompatiblePixelDescription( internalFormat );

        ::glTexImage1D( target, level, internalFormat, width, 0,
            pixelDescription.format, pixelDescription.type, nullptr );
        checkResult( "::glTexImage1D" );

        width = std::max( 1, (width / 2) );
    }
}

void APIENTRY glTexStorage2D( GLenum target, GLsizei levels,
    GLenum internalFormat, GLsizei width, GLsizei height )
{
    for( GLsizei level = 0; level < levels; ++level ) {
        const PixelDescription pixelDescription =
            getCompatiblePixelDescription( internalFormat );

        ::glTexImage2D( target, level, internalFormat, width, height, 0,
            pixelDescription.format, pixelDescription.type, nullptr );
        checkResult( "::glTexImage2D" );

        width = std::max( 1, (width / 2) );
        if( target != GL_TEXTURE_1D_ARRAY )
            height = std::max( 1, (height / 2) );
    }
}

void APIENTRY glTexStorage3D( GLenum target, GLsizei levels,
    GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth )
{
    for( GLsizei level = 0; level < levels; ++level ) {
        const PixelDescription pixelDescription =
            getCompatiblePixelDescription( internalFormat );

        ::glTexImage3D( target, level, internalFormat, width, height, depth, 0,
            pixelDescription.format, pixelDescription.type, nullptr );
        checkResult( "::glTexImage3D" );

        width = std::max( 1, (width / 2) );
        height = std::max( 1, (height / 2) );
        if( target != GL_TEXTURE_2D_ARRAY )
            depth = std::max( 1, (depth / 2) );
    }
}

void APIENTRY glTexStorage2DMultisample( GLenum target,
    GLsizei samples,
    GLenum internalFormat,
    GLsizei width,
    GLsizei height,
    GLboolean fixedSampleLocations )
{
    ::glTexImage2DMultisample(
        target, samples, internalFormat, width, height, fixedSampleLocations );
}

void APIENTRY glTexStorage3DMultisample( GLenum target,
    GLsizei samples,
    GLenum internalFormat,
    GLsizei width,
    GLsizei height,
    GLsizei depth,
    GLboolean fixedSampleLocations )
{
    ::glTexStorage3DMultisample( target, samples, internalFormat,
        width, height, depth, fixedSampleLocations );
}

}
<|endoftext|>


<commit_before>/**
 * @file pycantera.cpp
 *
 * This is the main file for the Python interface module.
 *
 */

// turn off warnings about long names under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif

#include "cantera/kernel/config.h"

#include "Python.h"

#ifdef HAS_NUMERIC
#include "Numeric/arrayobject.h"
#else
#ifdef HAS_NUMARRAY
#include "numarray/arrayobject.h"
#else
#ifdef HAS_NUMPY
#include "numpy/arrayobject.h"
#else
// Create a compilation error to cause the program to bomb
#include "Numeric/arrayobject.h"
#include "numarray/arrayobject.h"
#include "numpy/libnumarray.h"
#include "numpy/arrayobject.h"
#endif
#endif
#endif

#include "clib/ct.h"
#include "clib/ctxml.h"
#include "clib/ctsurf.h"
#include "clib/ctbdry.h"
#include "clib/ctrpath.h"
#include "clib/ctreactor.h"
#include "clib/ctfunc.h"
#include "clib/ctonedim.h"
#include "clib/ctmultiphase.h"

#include <iostream>
using namespace std;

//  constants defined in the module
static PyObject *ErrorObject;

// local includes
#include "pyutils.h"

#include "ctphase_methods.cpp"
#include "ctthermo_methods.cpp"
#include "ctkinetics_methods.cpp"
#include "cttransport_methods.cpp"
#include "ctxml_methods.cpp"
#include "ctfuncs.cpp"
#include "ctsurf_methods.cpp"
//#include "ctbndry_methods.cpp"
#include "ctrpath_methods.cpp"
#include "ctreactor_methods.cpp"
#include "ctfunc_methods.cpp"
#include "ctonedim_methods.cpp"
#include "ctmultiphase_methods.cpp"

#ifdef INCL_USER_PYTHON
#include "ctuser.h"
#include "ctuser_methods.cpp"
#endif

static PyObject*
pyct_appdelete(PyObject *self, PyObject *args) {
    return Py_BuildValue("i",ct_appdelete());
}

#include "methods.h"
#include "pylogger.h"
//#include "../../src/global.h"
extern "C" {

    /* Initialization function for the module */

    DL_EXPORT(void) init_cantera(void)
    {
        PyObject *m, *d;

        /* Initialize the type of the new type object here; doing it here
         * is required for portability to Windows without requiring C++. */

        /* Create the module and add the functions */
        m = Py_InitModule("_cantera", ct_methods);
        import_array();
        Cantera::Logger* pylog = new Cantera::Py_Logger;
        setLogWriter(pylog);

        /* Add some symbolic constants to the module */
        d = PyModule_GetDict(m);
        ErrorObject = PyErr_NewException((char *)"cantera.error", NULL, NULL);
        PyDict_SetItemString(d, "error", ErrorObject);
#ifdef HAS_NUMERIC
        PyDict_SetItemString(d, "nummod",PyString_FromString("Numeric"));
#else
#ifdef HAS_NUMARRAY
        PyDict_SetItemString(d, "nummod",PyString_FromString("numarray"));
#else
        PyDict_SetItemString(d, "nummod",PyString_FromString("numpy"));
#endif
#endif
    }

}

<commit_msg>Simplified numpy/numarray include to avoid confusing SCons<commit_after>/**
 * @file pycantera.cpp
 *
 * This is the main file for the Python interface module.
 *
 */

// turn off warnings about long names under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif

#include "cantera/kernel/config.h"

#include "Python.h"

#ifdef HAS_NUMERIC
#include "Numeric/arrayobject.h"
#endif

#ifdef HAS_NUMARRAY
#include "numarray/arrayobject.h"
#endif

#ifdef HAS_NUMPY
#include "numpy/arrayobject.h"
#endif

#include "clib/ct.h"
#include "clib/ctxml.h"
#include "clib/ctsurf.h"
#include "clib/ctbdry.h"
#include "clib/ctrpath.h"
#include "clib/ctreactor.h"
#include "clib/ctfunc.h"
#include "clib/ctonedim.h"
#include "clib/ctmultiphase.h"

#include <iostream>
using namespace std;

//  constants defined in the module
static PyObject *ErrorObject;

// local includes
#include "pyutils.h"

#include "ctphase_methods.cpp"
#include "ctthermo_methods.cpp"
#include "ctkinetics_methods.cpp"
#include "cttransport_methods.cpp"
#include "ctxml_methods.cpp"
#include "ctfuncs.cpp"
#include "ctsurf_methods.cpp"
//#include "ctbndry_methods.cpp"
#include "ctrpath_methods.cpp"
#include "ctreactor_methods.cpp"
#include "ctfunc_methods.cpp"
#include "ctonedim_methods.cpp"
#include "ctmultiphase_methods.cpp"

#ifdef INCL_USER_PYTHON
#include "ctuser.h"
#include "ctuser_methods.cpp"
#endif

static PyObject*
pyct_appdelete(PyObject *self, PyObject *args) {
    return Py_BuildValue("i",ct_appdelete());
}

#include "methods.h"
#include "pylogger.h"
//#include "../../src/global.h"
extern "C" {

    /* Initialization function for the module */

    DL_EXPORT(void) init_cantera(void)
    {
        PyObject *m, *d;

        /* Initialize the type of the new type object here; doing it here
         * is required for portability to Windows without requiring C++. */

        /* Create the module and add the functions */
        m = Py_InitModule("_cantera", ct_methods);
        import_array();
        Cantera::Logger* pylog = new Cantera::Py_Logger;
        setLogWriter(pylog);

        /* Add some symbolic constants to the module */
        d = PyModule_GetDict(m);
        ErrorObject = PyErr_NewException((char *)"cantera.error", NULL, NULL);
        PyDict_SetItemString(d, "error", ErrorObject);
#ifdef HAS_NUMERIC
        PyDict_SetItemString(d, "nummod",PyString_FromString("Numeric"));
#else
#ifdef HAS_NUMARRAY
        PyDict_SetItemString(d, "nummod",PyString_FromString("numarray"));
#else
        PyDict_SetItemString(d, "nummod",PyString_FromString("numpy"));
#endif
#endif
    }

}

<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkImageWriter.h"

#include "mitkItkPictureWrite.h"
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageReadAccessor.h"

#include <itkImageIOBase.h>
#include <itkImageIOFactory.h>

mitk::ImageWriter::ImageWriter()
{
  this->SetNumberOfRequiredInputs( 1 );
  m_MimeType = "";
  SetDefaultExtension();
}

mitk::ImageWriter::~ImageWriter()
{
}

void mitk::ImageWriter::SetFileName(const char* fileName)
{
  if ( fileName && ( fileName == this->m_FileName ) )
  {
    return;
  }
  if ( fileName )
  {
    this->m_FileName = fileName;
    this->m_FileNameWithoutExtension = this->m_FileName;
    this->m_Extension.clear();
    std::size_t pos = this->m_FileName.find_last_of("/\\");
    if (pos != std::string::npos)
    {
      std::size_t ppos = this->m_FileName.find_first_of('.', pos);
      if (ppos != std::string::npos)
      {
        this->m_FileNameWithoutExtension = this->m_FileName.substr(0, ppos);
        this->m_Extension = this->m_FileName.substr(ppos);
      }
    }
  }
  else
  {
    this->m_FileName.clear();
    this->m_FileNameWithoutExtension.clear();
    this->m_Extension.clear();
  }
  this->Modified();
}

void mitk::ImageWriter::SetFileName(const std::string & fileName)
{
  this->SetFileName( fileName.c_str() );
}

void mitk::ImageWriter::SetExtension(const char* extension)
{
  if ( extension && ( extension == this->m_Extension ) )
  {
    return;
  }
  if ( extension )
  {
    this->m_Extension = extension;
    this->m_FileName = this->m_FileNameWithoutExtension + this->m_Extension;
  }
  else
  {
    this->m_Extension.clear();
    this->m_FileName = this->m_FileNameWithoutExtension;
  }
  this->Modified();
}

void mitk::ImageWriter::SetExtension(const std::string & extension)
{
  this->SetFileName( extension.c_str() );
}

void mitk::ImageWriter::SetDefaultExtension()
{
  this->m_Extension = ".mhd";
  this->m_FileName = this->m_FileNameWithoutExtension + this->m_Extension;
  this->Modified();
}

#include <vtkConfigure.h>
#include <vtkImageData.h>
#include <vtkXMLImageDataWriter.h>
static void writeVti(const char * filename, mitk::Image* image, int t=0)
{
  vtkXMLImageDataWriter * vtkwriter = vtkXMLImageDataWriter::New();
  vtkwriter->SetFileName( filename );
  vtkwriter->SetInput(image->GetVtkImageData(t));
  vtkwriter->Write();
  vtkwriter->Delete();
}

#include <itkRGBAPixel.h>

void mitk::ImageWriter::WriteByITK(mitk::Image* image, const std::string& fileName)
{
  MITK_INFO << "Writing image: " << fileName << std::endl;
  // Pictures and picture series like .png are written via a different mechanism then volume images.
  // So, they are still multiplexed and thus not support vector images.
  if (fileName.find(".png") != std::string::npos || fileName.find(".tif") != std::string::npos || fileName.find(".jpg") != std::string::npos)
  {
    try
    {
      // switch processing of single/multi-component images
      if( image->GetPixelType(0).GetNumberOfComponents() == 1)
      {
        AccessByItk_1( image, _mitkItkPictureWrite, fileName );
      }
      else
      {
        AccessFixedPixelTypeByItk_1( image, _mitkItkPictureWriteComposite, MITK_ACCESSBYITK_PIXEL_TYPES_SEQ MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES_SEQ , fileName);
      }
    }
    catch(itk::ExceptionObject &e)
    {
      std::cerr << "Caught " << e.what() << std::endl;
    }
    catch(std::exception &e)
    {
      std::cerr << "Caught std::exception " << e.what() << std::endl;
    }

    return;
  }

  // Implementation of writer using itkImageIO directly. This skips the use
  // of templated itkImageFileWriter, which saves the multiplexing on MITK side.

  unsigned int dimension = image->GetDimension();
  unsigned int* dimensions = image->GetDimensions();
  mitk::PixelType pixelType = image->GetPixelType();
  mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
  mitk::Point3D origin = image->GetGeometry()->GetOrigin();

  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( fileName.c_str(),
    itk::ImageIOFactory::WriteMode );

  if(imageIO.IsNull())
  {
    itkExceptionMacro(<< "Error: Could not create itkImageIO via factory for file " << fileName);
  }

  // Set the necessary information for imageIO
  imageIO->SetNumberOfDimensions(dimension);
  imageIO->SetPixelType( pixelType.GetPixelType() );
  imageIO->SetComponentType( pixelType.GetComponentType() < PixelComponentUserType ?
                             static_cast<itk::ImageIOBase::IOComponentType>(pixelType.GetComponentType()) :
                             itk::ImageIOBase::UNKNOWNCOMPONENTTYPE);
  imageIO->SetNumberOfComponents( pixelType.GetNumberOfComponents() );

  itk::ImageIORegion ioRegion( dimension );

  for(unsigned int i=0; i<dimension; i++)
  {
    imageIO->SetDimensions(i,dimensions[i]);
    imageIO->SetSpacing(i,spacing[i]);
    imageIO->SetOrigin(i,origin[i]);

    mitk::Vector3D direction;
    direction.SetVnlVector(image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i));
    vnl_vector< double > axisDirection(dimension);
    for(unsigned int j=0; j<dimension; j++)
    {
      axisDirection[j] = direction[j]/spacing[i];
    }
    imageIO->SetDirection( i, axisDirection );

    ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i) );
    ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i) );
  }

  //use compression if available
  imageIO->UseCompressionOn();

  imageIO->SetIORegion(ioRegion);
  imageIO->SetFileName(fileName);

  ImageReadAccessor imageAccess(image);
  imageIO->Write(imageAccess.GetData());
}

void mitk::ImageWriter::GenerateData()
{
  const std::string& locale = "C";
  const std::string& currLocale = setlocale( LC_ALL, NULL );

  if ( locale.compare(currLocale)!=0 )
  {
    try
    {
      setlocale(LC_ALL, locale.c_str());
    }
    catch(...)
    {
      MITK_INFO << "Could not set locale " << locale;
    }
  }

  if ( m_FileName == "" )
  {
    itkWarningMacro( << "Sorry, filename has not been set!" );
    return ;
  }

  FILE* tempFile = fopen(m_FileName.c_str(),"w");
  if (tempFile==NULL)
  {
    itkExceptionMacro(<<"File location not writeable");
    return;
  }
  fclose(tempFile);
  remove(m_FileName.c_str());

  // Creating clone of input image, since i might change the geometry
  mitk::Image::Pointer input = const_cast<mitk::Image*>(this->GetInput())->Clone();

  // Check if geometry information will be lost
  if (input->GetDimension() == 2)
  {
     if (!input->GetGeometry()->Is2DConvertable())
     {
        MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might consider using Convert2Dto3DImageFilter before saving.";

        // set matrix to identity
        mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New();
        affTrans->SetIdentity();
        mitk::Vector3D spacing = input->GetGeometry()->GetSpacing();
        mitk::Point3D origin = input->GetGeometry()->GetOrigin();
        input->GetGeometry()->SetIndexToWorldTransform(affTrans);
        input->GetGeometry()->SetSpacing(spacing);
        input->GetGeometry()->SetOrigin(origin);
     }
  }

  bool vti = (m_Extension.find(".vti") != std::string::npos);

  // If the extension is NOT .pic and NOT .nrrd and NOT .nii and NOT .nii.gz the following block is entered
  if ( m_Extension.find(".pic") == std::string::npos
       && m_Extension.find(".nrrd") == std::string::npos
       && m_Extension.find(".nii") == std::string::npos
       && m_Extension.find(".nii.gz") == std::string::npos
       )
  {
    if(input->GetDimension() > 3)
    {
      int t, timesteps;

      timesteps = input->GetDimension(3);
      ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
      timeSelector->SetInput(input);
      mitk::Image::Pointer image = timeSelector->GetOutput();
      for(t = 0; t < timesteps; ++t)
      {
        std::ostringstream filename;
        timeSelector->SetTimeNr(t);
        timeSelector->Update();
        if(input->GetTimeSlicedGeometry()->IsValidTime(t))
        {
          const mitk::TimeBounds& timebounds = input->GetTimeSlicedGeometry()->GetGeometry3D(t)->GetTimeBounds();
          filename <<  m_FileNameWithoutExtension << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << m_Extension;
        }
        else
        {
          itkWarningMacro(<<"Error on write: TimeSlicedGeometry invalid of image " << filename << ".");
          filename <<  m_FileNameWithoutExtension << "_T" << t << m_Extension;
        }
        if ( vti )
        {
          writeVti(filename.str().c_str(), input, t);
        }
        else
        {
          WriteByITK(image, filename.str());
        }
      }
    }
    else if ( vti )
    {
      writeVti(m_FileName.c_str(), input);
    }
    else
    {
      WriteByITK(input, m_FileName);
    }
  }
  else
  {
    // use the PicFileWriter for the .pic data type
    if( m_Extension.find(".pic") != std::string::npos )
    {
/*    PicFileWriter::Pointer picWriter = PicFileWriter::New();
    size_t found;
    found = m_FileName.find( m_Extension ); // !!! HAS to be at the very end of the filename (not somewhere in the middle)
    if( m_FileName.length() > 3 && found != m_FileName.length() - 4 )
    {
      //if Extension not in Filename
      std::ostringstream filename;
      filename <<  m_FileName.c_str() << m_Extension;
      picWriter->SetFileName( filename.str().c_str() );
    }
    else
    {
      picWriter->SetFileName( m_FileName.c_str() );
    }
    picWriter->SetInputImage( input );
    picWriter->Write();
*/    }

    // use the ITK .nrrd Image writer
    if( m_Extension.find(".nrrd") != std::string::npos
        || m_Extension.find(".nii") != std::string::npos
        || m_Extension.find(".nii.gz") != std::string::npos
        )
    {
        WriteByITK(input, this->m_FileName);
    }
  }
  m_MimeType = "application/MITK.Pic";

  try
  {
    setlocale(LC_ALL, currLocale.c_str());
  }
  catch(...)
  {
    MITK_INFO << "Could not reset locale " << currLocale;
  }
}

bool mitk::ImageWriter::CanWriteDataType( DataNode* input )
{
  if ( input )
  {
    return this->CanWriteBaseDataType(input->GetData());
  }
  return false;
}

void mitk::ImageWriter::SetInput( DataNode* input )
{
  if( input && CanWriteDataType( input ) )
    this->ProcessObject::SetNthInput( 0, dynamic_cast<mitk::Image*>( input->GetData() ) );
}

std::string mitk::ImageWriter::GetWritenMIMEType()
{
  return m_MimeType;
}

std::vector<std::string> mitk::ImageWriter::GetPossibleFileExtensions()
{
  std::vector<std::string> possibleFileExtensions;
  possibleFileExtensions.push_back(".pic");
  possibleFileExtensions.push_back(".pic.gz");
  possibleFileExtensions.push_back(".bmp");
  possibleFileExtensions.push_back(".dcm");
  possibleFileExtensions.push_back(".DCM");
  possibleFileExtensions.push_back(".dicom");
  possibleFileExtensions.push_back(".DICOM");
  possibleFileExtensions.push_back(".gipl");
  possibleFileExtensions.push_back(".gipl.gz");
  possibleFileExtensions.push_back(".mha");
  possibleFileExtensions.push_back(".nii");
  possibleFileExtensions.push_back(".nii.gz");
  possibleFileExtensions.push_back(".nrrd");
  possibleFileExtensions.push_back(".nhdr");
  possibleFileExtensions.push_back(".png");
  possibleFileExtensions.push_back(".PNG");
  possibleFileExtensions.push_back(".spr");
  possibleFileExtensions.push_back(".mhd");
  possibleFileExtensions.push_back(".vtk");
  possibleFileExtensions.push_back(".vti");
  possibleFileExtensions.push_back(".hdr");
  possibleFileExtensions.push_back(".png");
  possibleFileExtensions.push_back(".tif");
  possibleFileExtensions.push_back(".jpg");
  return possibleFileExtensions;
}

std::string mitk::ImageWriter::GetFileExtension()
{
  return m_Extension;
}

void mitk::ImageWriter::SetInput( mitk::Image* image )
{
  this->ProcessObject::SetNthInput( 0, image );
}

const mitk::Image* mitk::ImageWriter::GetInput()
{
  if ( this->GetNumberOfInputs() < 1 )
  {
    return NULL;
  }
  else
  {
    return static_cast< const mitk::Image * >( this->ProcessObject::GetInput( 0 ) );
  }
}

const char* mitk::ImageWriter::GetDefaultFilename()
{
  return "Image.nrrd";
}

const char* mitk::ImageWriter::GetFileDialogPattern()
{
  return "Image (*.pic, *.pic.gz, *.bmp, *.dcm, *.DCM, *.dicom, *.DICOM, *.gipl, *.gipl.gz, *.mha, "
      "*.nii, *.nii.gz, *.nrrd, *.nhdr, *.png, *.PNG, *.spr, *.mhd, *.vtk, *.vti, *.hdr, *.png, "
      "*.tif, *.jpg)";
}

const char *mitk::ImageWriter::GetDefaultExtension()
{
  return ".nrrd";
}

bool mitk::ImageWriter::CanWriteBaseDataType(BaseData::Pointer data)
{
  return dynamic_cast<mitk::Image*>( data.GetPointer() );
}

void mitk::ImageWriter::DoWrite(BaseData::Pointer data)
{
  if (this->CanWriteBaseDataType(data))
  {
    this->SetInput(dynamic_cast<mitk::Image *>(data.GetPointer()));
    this->Update();
  }
}
<commit_msg>Remove unsupproted image extensions and misleading "," in file dialog pattern.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkImageWriter.h"

#include "mitkItkPictureWrite.h"
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageReadAccessor.h"

#include <itkImageIOBase.h>
#include <itkImageIOFactory.h>

mitk::ImageWriter::ImageWriter()
{
  this->SetNumberOfRequiredInputs( 1 );
  m_MimeType = "";
  SetDefaultExtension();
}

mitk::ImageWriter::~ImageWriter()
{
}

void mitk::ImageWriter::SetFileName(const char* fileName)
{
  if ( fileName && ( fileName == this->m_FileName ) )
  {
    return;
  }
  if ( fileName )
  {
    this->m_FileName = fileName;
    this->m_FileNameWithoutExtension = this->m_FileName;
    this->m_Extension.clear();
    std::size_t pos = this->m_FileName.find_last_of("/\\");
    if (pos != std::string::npos)
    {
      std::size_t ppos = this->m_FileName.find_first_of('.', pos);
      if (ppos != std::string::npos)
      {
        this->m_FileNameWithoutExtension = this->m_FileName.substr(0, ppos);
        this->m_Extension = this->m_FileName.substr(ppos);
      }
    }
  }
  else
  {
    this->m_FileName.clear();
    this->m_FileNameWithoutExtension.clear();
    this->m_Extension.clear();
  }
  this->Modified();
}

void mitk::ImageWriter::SetFileName(const std::string & fileName)
{
  this->SetFileName( fileName.c_str() );
}

void mitk::ImageWriter::SetExtension(const char* extension)
{
  if ( extension && ( extension == this->m_Extension ) )
  {
    return;
  }
  if ( extension )
  {
    this->m_Extension = extension;
    this->m_FileName = this->m_FileNameWithoutExtension + this->m_Extension;
  }
  else
  {
    this->m_Extension.clear();
    this->m_FileName = this->m_FileNameWithoutExtension;
  }
  this->Modified();
}

void mitk::ImageWriter::SetExtension(const std::string & extension)
{
  this->SetFileName( extension.c_str() );
}

void mitk::ImageWriter::SetDefaultExtension()
{
  this->m_Extension = ".mhd";
  this->m_FileName = this->m_FileNameWithoutExtension + this->m_Extension;
  this->Modified();
}

#include <vtkConfigure.h>
#include <vtkImageData.h>
#include <vtkXMLImageDataWriter.h>
static void writeVti(const char * filename, mitk::Image* image, int t=0)
{
  vtkXMLImageDataWriter * vtkwriter = vtkXMLImageDataWriter::New();
  vtkwriter->SetFileName( filename );
  vtkwriter->SetInput(image->GetVtkImageData(t));
  vtkwriter->Write();
  vtkwriter->Delete();
}

#include <itkRGBAPixel.h>

void mitk::ImageWriter::WriteByITK(mitk::Image* image, const std::string& fileName)
{
  MITK_INFO << "Writing image: " << fileName << std::endl;
  // Pictures and picture series like .png are written via a different mechanism then volume images.
  // So, they are still multiplexed and thus not support vector images.
  if (fileName.find(".png") != std::string::npos || fileName.find(".tif") != std::string::npos || fileName.find(".jpg") != std::string::npos)
  {
    try
    {
      // switch processing of single/multi-component images
      if( image->GetPixelType(0).GetNumberOfComponents() == 1)
      {
        AccessByItk_1( image, _mitkItkPictureWrite, fileName );
      }
      else
      {
        AccessFixedPixelTypeByItk_1( image, _mitkItkPictureWriteComposite, MITK_ACCESSBYITK_PIXEL_TYPES_SEQ MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES_SEQ , fileName);
      }
    }
    catch(itk::ExceptionObject &e)
    {
      std::cerr << "Caught " << e.what() << std::endl;
    }
    catch(std::exception &e)
    {
      std::cerr << "Caught std::exception " << e.what() << std::endl;
    }

    return;
  }

  // Implementation of writer using itkImageIO directly. This skips the use
  // of templated itkImageFileWriter, which saves the multiplexing on MITK side.

  unsigned int dimension = image->GetDimension();
  unsigned int* dimensions = image->GetDimensions();
  mitk::PixelType pixelType = image->GetPixelType();
  mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
  mitk::Point3D origin = image->GetGeometry()->GetOrigin();

  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( fileName.c_str(),
    itk::ImageIOFactory::WriteMode );

  if(imageIO.IsNull())
  {
    itkExceptionMacro(<< "Error: Could not create itkImageIO via factory for file " << fileName);
  }

  // Set the necessary information for imageIO
  imageIO->SetNumberOfDimensions(dimension);
  imageIO->SetPixelType( pixelType.GetPixelType() );
  imageIO->SetComponentType( pixelType.GetComponentType() < PixelComponentUserType ?
                             static_cast<itk::ImageIOBase::IOComponentType>(pixelType.GetComponentType()) :
                             itk::ImageIOBase::UNKNOWNCOMPONENTTYPE);
  imageIO->SetNumberOfComponents( pixelType.GetNumberOfComponents() );

  itk::ImageIORegion ioRegion( dimension );

  for(unsigned int i=0; i<dimension; i++)
  {
    imageIO->SetDimensions(i,dimensions[i]);
    imageIO->SetSpacing(i,spacing[i]);
    imageIO->SetOrigin(i,origin[i]);

    mitk::Vector3D direction;
    direction.SetVnlVector(image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i));
    vnl_vector< double > axisDirection(dimension);
    for(unsigned int j=0; j<dimension; j++)
    {
      axisDirection[j] = direction[j]/spacing[i];
    }
    imageIO->SetDirection( i, axisDirection );

    ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i) );
    ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i) );
  }

  //use compression if available
  imageIO->UseCompressionOn();

  imageIO->SetIORegion(ioRegion);
  imageIO->SetFileName(fileName);

  ImageReadAccessor imageAccess(image);
  imageIO->Write(imageAccess.GetData());
}

void mitk::ImageWriter::GenerateData()
{
  const std::string& locale = "C";
  const std::string& currLocale = setlocale( LC_ALL, NULL );

  if ( locale.compare(currLocale)!=0 )
  {
    try
    {
      setlocale(LC_ALL, locale.c_str());
    }
    catch(...)
    {
      MITK_INFO << "Could not set locale " << locale;
    }
  }

  if ( m_FileName == "" )
  {
    itkWarningMacro( << "Sorry, filename has not been set!" );
    return ;
  }

  FILE* tempFile = fopen(m_FileName.c_str(),"w");
  if (tempFile==NULL)
  {
    itkExceptionMacro(<<"File location not writeable");
    return;
  }
  fclose(tempFile);
  remove(m_FileName.c_str());

  // Creating clone of input image, since i might change the geometry
  mitk::Image::Pointer input = const_cast<mitk::Image*>(this->GetInput())->Clone();

  // Check if geometry information will be lost
  if (input->GetDimension() == 2)
  {
     if (!input->GetGeometry()->Is2DConvertable())
     {
        MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might consider using Convert2Dto3DImageFilter before saving.";

        // set matrix to identity
        mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New();
        affTrans->SetIdentity();
        mitk::Vector3D spacing = input->GetGeometry()->GetSpacing();
        mitk::Point3D origin = input->GetGeometry()->GetOrigin();
        input->GetGeometry()->SetIndexToWorldTransform(affTrans);
        input->GetGeometry()->SetSpacing(spacing);
        input->GetGeometry()->SetOrigin(origin);
     }
  }

  bool vti = (m_Extension.find(".vti") != std::string::npos);

  // If the extension is NOT .pic and NOT .nrrd and NOT .nii and NOT .nii.gz the following block is entered
  if ( m_Extension.find(".pic") == std::string::npos
       && m_Extension.find(".nrrd") == std::string::npos
       && m_Extension.find(".nii") == std::string::npos
       && m_Extension.find(".nii.gz") == std::string::npos
       )
  {
    if(input->GetDimension() > 3)
    {
      int t, timesteps;

      timesteps = input->GetDimension(3);
      ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
      timeSelector->SetInput(input);
      mitk::Image::Pointer image = timeSelector->GetOutput();
      for(t = 0; t < timesteps; ++t)
      {
        std::ostringstream filename;
        timeSelector->SetTimeNr(t);
        timeSelector->Update();
        if(input->GetTimeSlicedGeometry()->IsValidTime(t))
        {
          const mitk::TimeBounds& timebounds = input->GetTimeSlicedGeometry()->GetGeometry3D(t)->GetTimeBounds();
          filename <<  m_FileNameWithoutExtension << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << m_Extension;
        }
        else
        {
          itkWarningMacro(<<"Error on write: TimeSlicedGeometry invalid of image " << filename << ".");
          filename <<  m_FileNameWithoutExtension << "_T" << t << m_Extension;
        }
        if ( vti )
        {
          writeVti(filename.str().c_str(), input, t);
        }
        else
        {
          WriteByITK(image, filename.str());
        }
      }
    }
    else if ( vti )
    {
      writeVti(m_FileName.c_str(), input);
    }
    else
    {
      WriteByITK(input, m_FileName);
    }
  }
  else
  {
    // use the PicFileWriter for the .pic data type
    if( m_Extension.find(".pic") != std::string::npos )
    {
/*    PicFileWriter::Pointer picWriter = PicFileWriter::New();
    size_t found;
    found = m_FileName.find( m_Extension ); // !!! HAS to be at the very end of the filename (not somewhere in the middle)
    if( m_FileName.length() > 3 && found != m_FileName.length() - 4 )
    {
      //if Extension not in Filename
      std::ostringstream filename;
      filename <<  m_FileName.c_str() << m_Extension;
      picWriter->SetFileName( filename.str().c_str() );
    }
    else
    {
      picWriter->SetFileName( m_FileName.c_str() );
    }
    picWriter->SetInputImage( input );
    picWriter->Write();
*/    }

    // use the ITK .nrrd Image writer
    if( m_Extension.find(".nrrd") != std::string::npos
        || m_Extension.find(".nii") != std::string::npos
        || m_Extension.find(".nii.gz") != std::string::npos
        )
    {
        WriteByITK(input, this->m_FileName);
    }
  }
  m_MimeType = "application/MITK.Pic";

  try
  {
    setlocale(LC_ALL, currLocale.c_str());
  }
  catch(...)
  {
    MITK_INFO << "Could not reset locale " << currLocale;
  }
}

bool mitk::ImageWriter::CanWriteDataType( DataNode* input )
{
  if ( input )
  {
    return this->CanWriteBaseDataType(input->GetData());
  }
  return false;
}

void mitk::ImageWriter::SetInput( DataNode* input )
{
  if( input && CanWriteDataType( input ) )
    this->ProcessObject::SetNthInput( 0, dynamic_cast<mitk::Image*>( input->GetData() ) );
}

std::string mitk::ImageWriter::GetWritenMIMEType()
{
  return m_MimeType;
}

std::vector<std::string> mitk::ImageWriter::GetPossibleFileExtensions()
{
  std::vector<std::string> possibleFileExtensions;
  possibleFileExtensions.push_back(".pic");
  possibleFileExtensions.push_back(".pic.gz");
  possibleFileExtensions.push_back(".bmp");
  possibleFileExtensions.push_back(".dcm");
  possibleFileExtensions.push_back(".DCM");
  possibleFileExtensions.push_back(".dicom");
  possibleFileExtensions.push_back(".DICOM");
  possibleFileExtensions.push_back(".gipl");
  possibleFileExtensions.push_back(".gipl.gz");
  possibleFileExtensions.push_back(".mha");
  possibleFileExtensions.push_back(".nii");
  possibleFileExtensions.push_back(".nii.gz");
  possibleFileExtensions.push_back(".nrrd");
  possibleFileExtensions.push_back(".nhdr");
  possibleFileExtensions.push_back(".png");
  possibleFileExtensions.push_back(".PNG");
  possibleFileExtensions.push_back(".spr");
  possibleFileExtensions.push_back(".mhd");
  possibleFileExtensions.push_back(".vtk");
  possibleFileExtensions.push_back(".vti");
  possibleFileExtensions.push_back(".hdr");
  possibleFileExtensions.push_back(".png");
  possibleFileExtensions.push_back(".tif");
  possibleFileExtensions.push_back(".jpg");
  return possibleFileExtensions;
}

std::string mitk::ImageWriter::GetFileExtension()
{
  return m_Extension;
}

void mitk::ImageWriter::SetInput( mitk::Image* image )
{
  this->ProcessObject::SetNthInput( 0, image );
}

const mitk::Image* mitk::ImageWriter::GetInput()
{
  if ( this->GetNumberOfInputs() < 1 )
  {
    return NULL;
  }
  else
  {
    return static_cast< const mitk::Image * >( this->ProcessObject::GetInput( 0 ) );
  }
}

const char* mitk::ImageWriter::GetDefaultFilename()
{
  return "Image.nrrd";
}

const char* mitk::ImageWriter::GetFileDialogPattern()
{
  return "Image (*.bmp *.dcm *.DCM *.dicom *.DICOM *.gipl *.gipl.gz *.mha "
      "*.nii *.nii.gz *.nrrd *.nhdr *.png *.PNG *.spr *.mhd *.vtk *.vti *.hdr *.png "
      "*.tif *.jpg)";
}

const char *mitk::ImageWriter::GetDefaultExtension()
{
  return ".nrrd";
}

bool mitk::ImageWriter::CanWriteBaseDataType(BaseData::Pointer data)
{
  return dynamic_cast<mitk::Image*>( data.GetPointer() );
}

void mitk::ImageWriter::DoWrite(BaseData::Pointer data)
{
  if (this->CanWriteBaseDataType(data))
  {
    this->SetInput(dynamic_cast<mitk::Image *>(data.GetPointer()));
    this->Update();
  }
}
<|endoftext|>


<commit_before>#include "mitkParRecFileReader.h"
#include <itkImageFileReader.h>

#ifdef __GNUC__
#define stricmp strcasecmp
#endif

void mitk::ParRecFileReader::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();

  if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
    return;

  itkDebugMacro(<<"Reading PAR file for GenerateOutputInformation()" << m_FileName);

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" && m_FilePrefix == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  m_RecFileName = "";
  if( m_FileName != "")
  {
    int extPos=m_FileName.find_last_of(".");
    if(extPos>=-1)
    {
      const char *ext=m_FileName.c_str()+extPos+1;
      if(stricmp(ext,"par")==0)
        m_RecFileName = m_FileName.substr(0,extPos);
      else
        m_RecFileName = m_FileName;
    }
    else
        m_RecFileName = m_FileName;

    m_RecFileName.append(".rec");

    bool headerRead = false;

    mitk::PixelType type;
    unsigned int dimension=0;
    unsigned int dimensions[4]={0,0,1,1};
    float sliceThickness=0.0;
    float sliceGap=0.0;
    float sliceSpacing=0.0;
    mitk::Vector3D thickness(1.0,1.0,1.0);
    mitk::Vector3D gap(0.0,0.0,0.0);
    mitk::Vector3D spacing;

    FILE *f;
    f=fopen(m_FileName.c_str(), "r");
    if(f!=NULL)
    {
      while(!feof(f))
      {
        char s[300], *p;
        fgets(s,200,f);
        if(strstr(s,"Max. number of cardiac phases"))
        {
          p=strchr(s,':')+1;
          dimensions[3]=atoi(p);
          if(dimensions[3]>1)
            dimension=4;
        }
        else
        if(strstr(s,"Max. number of slices/locations"))
        {
          p=strchr(s,':')+1;
          dimensions[2]=atoi(p);
          if(dimension==0)
          {
            if(dimensions[2]>1)
              dimension=3;
            else
              dimension=2;
          }
        }
        else
        if(strstr(s,"Image pixel size"))
        {
          p=strchr(s,':')+1;
          int bpe=atoi(p);
          if(bpe==8)
            type=typeid(ipUInt1_t);
          else
            type=typeid(ipUInt2_t);
        }
        else
        if(strstr(s,"Recon resolution"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%u %u", dimensions, dimensions+1);
        }
        else
        if(strstr(s,"FOV (ap,fh,rl) [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f %f %f", &thickness.x, &thickness.y, &thickness.z);
        }
        else
        if(strstr(s,"Slice thickness [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f", &sliceThickness);
        }
        else
        if(strstr(s,"Slice gap [mm]"))
        {
          p=s+strcspn(s,"-0123456789");
          sscanf(p,"%f", &sliceGap);
        }
      }
      fclose(f);

//C:\home\ivo\data\coronaries\ucsf-wholeheart-2.par
      sliceSpacing = sliceThickness+sliceGap;
      if(fabs(thickness.x/dimensions[2]-sliceSpacing)<0.0001)
        thickness.x=thickness.y;
      else
      if(fabs(thickness.y/dimensions[2]-sliceSpacing)<0.0001)
        thickness.y=thickness.x;
      thickness.z=sliceSpacing;

      thickness.x/=dimensions[0];
      thickness.y/=dimensions[1];
      spacing=thickness+gap;

      if((dimension>0) && (dimensions[0]>0) && (dimensions[1]>0))
        headerRead = true;
    }

    if( headerRead == false)
    {
      itk::ImageFileReaderException e(__FILE__, __LINE__);
      itk::OStringStream msg;
      msg << " Could not read file "
        << m_FileName.c_str();
      e.SetDescription(msg.str().c_str());
      throw e;
      return;
    }

    output->Initialize(type, dimension, dimensions);
    output->GetSlicedGeometry()->SetSpacing(spacing);

    output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
    output->GetSlicedGeometry()->SetEvenlySpaced();
  }

  m_ReadHeaderTime.Modified();
}

void mitk::ParRecFileReader::GenerateData()
{
  mitk::Image::Pointer output = this->GetOutput();

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_RecFileName == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "FileName for rec-file empty");
  }

  if( m_RecFileName != "")
  {
    FILE *f = fopen(m_RecFileName.c_str(), "r");
    if(f==NULL)
    {
      throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not open rec-file.");
    }

    int zstart, zmax;
    int tstart, tmax;

    zstart=output->GetRequestedRegion().GetIndex(2);
    tstart=output->GetRequestedRegion().GetIndex(3);

    zmax=zstart+output->GetRequestedRegion().GetSize(2);
    tmax=tstart+output->GetRequestedRegion().GetSize(3);

    bool ignore4Dtopogram=false;
    {
      int slicePlusTimeSize=output->GetDimension(0)*output->GetDimension(1)*output->GetDimension(3)*output->GetPixelType().GetBpe()/8;
    if(output->GetDimension(3)>1)
      ignore4Dtopogram=true;

      int z,t;
      for(t=tstart;t<tmax;++t)
        for(z=zstart;z<zmax;++z)
        {
			    if(ignore4Dtopogram)
            fseek(f,slicePlusTimeSize*z+(sliceSize+1)*t,SEEK_SET);
          else
            fseek(f,slicePlusTimeSize*z+sliceSize*t,SEEK_SET);
      	  fread(data, sliceSize, 1, f);
          output->SetSlice(data,z,t,0);
        }
    }
    //else
    //{
    //  for(;z<zmax;++z)
    //  {
    //    fseek(f,sliceSize*z,SEEK_SET);
    //  	fread(data, sliceSize, 1, f);
    //    output->SetSlice(data,z,0,0);
    //  }
    //}
    free(data);
  }
}

mitk::ParRecFileReader::ParRecFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}

mitk::ParRecFileReader::~ParRecFileReader()
{
}
<commit_msg>fixed the fix<commit_after>#include "mitkParRecFileReader.h"
#include <itkImageFileReader.h>

#ifdef __GNUC__
#define stricmp strcasecmp
#endif

void mitk::ParRecFileReader::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();

  if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
    return;

  itkDebugMacro(<<"Reading PAR file for GenerateOutputInformation()" << m_FileName);

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_FileName == "" && m_FilePrefix == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
  }

  m_RecFileName = "";
  if( m_FileName != "")
  {
    int extPos=m_FileName.find_last_of(".");
    if(extPos>=-1)
    {
      const char *ext=m_FileName.c_str()+extPos+1;
      if(stricmp(ext,"par")==0)
        m_RecFileName = m_FileName.substr(0,extPos);
      else
        m_RecFileName = m_FileName;
    }
    else
        m_RecFileName = m_FileName;

    m_RecFileName.append(".rec");

    bool headerRead = false;

    mitk::PixelType type;
    unsigned int dimension=0;
    unsigned int dimensions[4]={0,0,1,1};
    float sliceThickness=0.0;
    float sliceGap=0.0;
    float sliceSpacing=0.0;
    mitk::Vector3D thickness(1.0,1.0,1.0);
    mitk::Vector3D gap(0.0,0.0,0.0);
    mitk::Vector3D spacing;

    FILE *f;
    f=fopen(m_FileName.c_str(), "r");
    if(f!=NULL)
    {
      while(!feof(f))
      {
        char s[300], *p;
        fgets(s,200,f);
        if(strstr(s,"Max. number of cardiac phases"))
        {
          p=strchr(s,':')+1;
          dimensions[3]=atoi(p);
          if(dimensions[3]>1)
            dimension=4;
        }
        else
        if(strstr(s,"Max. number of slices/locations"))
        {
          p=strchr(s,':')+1;
          dimensions[2]=atoi(p);
          if(dimension==0)
          {
            if(dimensions[2]>1)
              dimension=3;
            else
              dimension=2;
          }
        }
        else
        if(strstr(s,"Image pixel size"))
        {
          p=strchr(s,':')+1;
          int bpe=atoi(p);
          if(bpe==8)
            type=typeid(ipUInt1_t);
          else
            type=typeid(ipUInt2_t);
        }
        else
        if(strstr(s,"Recon resolution"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%u %u", dimensions, dimensions+1);
        }
        else
        if(strstr(s,"FOV (ap,fh,rl) [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f %f %f", &thickness.x, &thickness.y, &thickness.z);
        }
        else
        if(strstr(s,"Slice thickness [mm]"))
        {
          p=s+strcspn(s,"0123456789");
          sscanf(p,"%f", &sliceThickness);
        }
        else
        if(strstr(s,"Slice gap [mm]"))
        {
          p=s+strcspn(s,"-0123456789");
          sscanf(p,"%f", &sliceGap);
        }
      }
      fclose(f);

//C:\home\ivo\data\coronaries\ucsf-wholeheart-2.par
      sliceSpacing = sliceThickness+sliceGap;
      if(fabs(thickness.x/dimensions[2]-sliceSpacing)<0.0001)
        thickness.x=thickness.y;
      else
      if(fabs(thickness.y/dimensions[2]-sliceSpacing)<0.0001)
        thickness.y=thickness.x;
      thickness.z=sliceSpacing;

      thickness.x/=dimensions[0];
      thickness.y/=dimensions[1];
      spacing=thickness+gap;

      if((dimension>0) && (dimensions[0]>0) && (dimensions[1]>0))
        headerRead = true;
    }

    if( headerRead == false)
    {
      itk::ImageFileReaderException e(__FILE__, __LINE__);
      itk::OStringStream msg;
      msg << " Could not read file "
        << m_FileName.c_str();
      e.SetDescription(msg.str().c_str());
      throw e;
      return;
    }

    output->Initialize(type, dimension, dimensions);
    output->GetSlicedGeometry()->SetSpacing(spacing);

    output->GetSlicedGeometry()->SetGeometry2D(mitk::Image::BuildStandardPlaneGeometry2D(output->GetSlicedGeometry(), dimensions).GetPointer(), 0);
    output->GetSlicedGeometry()->SetEvenlySpaced();
  }

  m_ReadHeaderTime.Modified();
}

void mitk::ParRecFileReader::GenerateData()
{
  mitk::Image::Pointer output = this->GetOutput();

  // Check to see if we can read the file given the name or prefix
  //
  if ( m_RecFileName == "" )
  {
    throw itk::ImageFileReaderException(__FILE__, __LINE__, "FileName for rec-file empty");
  }

  if( m_RecFileName != "")
  {
    FILE *f = fopen(m_RecFileName.c_str(), "r");
    if(f==NULL)
    {
      throw itk::ImageFileReaderException(__FILE__, __LINE__, "Could not open rec-file.");
    }

    int zstart, zmax;
    int tstart, tmax;

    zstart=output->GetRequestedRegion().GetIndex(2);
    tstart=output->GetRequestedRegion().GetIndex(3);

    zmax=zstart+output->GetRequestedRegion().GetSize(2);
    tmax=tstart+output->GetRequestedRegion().GetSize(3);

    int sliceSize=output->GetDimension(0)*output->GetDimension(1)*output->GetPixelType().GetBpe()/8;
    void *data = malloc(sliceSize);

    bool ignore4Dtopogram=false;
    {
      int slicePlusTimeSize=output->GetDimension(0)*output->GetDimension(1)*output->GetDimension(3)*output->GetPixelType().GetBpe()/8;
    if(output->GetDimension(3)>1)
      ignore4Dtopogram=true;

      int z,t;
      for(t=tstart;t<tmax;++t)
        for(z=zstart;z<zmax;++z)
        {
			    if(ignore4Dtopogram)
            fseek(f,slicePlusTimeSize*z+(sliceSize+1)*t,SEEK_SET);
          else
            fseek(f,slicePlusTimeSize*z+sliceSize*t,SEEK_SET);
      	  fread(data, sliceSize, 1, f);
          output->SetSlice(data,z,t,0);
        }
    }
    //else
    //{
    //  for(;z<zmax;++z)
    //  {
    //    fseek(f,sliceSize*z,SEEK_SET);
    //  	fread(data, sliceSize, 1, f);
    //    output->SetSlice(data,z,0,0);
    //  }
    //}
    free(data);
  }
}

mitk::ParRecFileReader::ParRecFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}

mitk::ParRecFileReader::~ParRecFileReader()
{
}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Image.h"

#include "../base/Logger.h"
#include "../base/Exception.h"
#include "../base/ObjectCounter.h"

#include "../graphics/Filterfliprgb.h"

#include "SDLDisplayEngine.h"
#include "OGLSurface.h"

#include <Magick++.h>

#include <iostream>
#include <sstream>

using namespace std;

namespace avg {

Image::Image(OGLSurface * pSurface, const string& sFilename)
    : m_sFilename(sFilename),
      m_pBmp(createDefaultBitmap()),
      m_pSurface(pSurface),
      m_pEngine(0),
      m_State(NOT_AVAILABLE)
{
    ObjectCounter::get()->incRef(&typeid(*this));
    load();
}

Image::~Image()
{
    if (m_State == GPU) {
        m_pSurface->destroy();
    }
    ObjectCounter::get()->decRef(&typeid(*this));
}

void Image::setBitmap(const Bitmap * pBmp)
{
    if(!pBmp) {
        throw Exception(AVG_ERR_UNSUPPORTED, "setBitmap(): bitmap must not be None!");
    }
    PixelFormat pf = calcSurfacePF(*pBmp);
    if (m_pEngine) {
        if (m_State == NOT_AVAILABLE || m_pSurface->getSize() != pBmp->getSize() ||
                m_pSurface->getPixelFormat() != pf)
        {
            m_pSurface->create(pBmp->getSize(), pf);
        }
        BitmapPtr pSurfaceBmp = m_pSurface->lockBmp();
        pSurfaceBmp->copyPixels(*pBmp);
        m_pSurface->unlockBmps();
        m_pBmp=BitmapPtr(createDefaultBitmap());
        m_State = GPU;
    } else {
        m_pBmp = BitmapPtr(new Bitmap(pBmp->getSize(), pf, ""));
        m_pBmp->copyPixels(*pBmp);
        m_State = CPU;
    }
    m_sFilename = "";

}

void Image::moveToGPU(SDLDisplayEngine* pEngine)
{
    m_pEngine = pEngine;
    if (m_pScene) {
        m_pSurface->create(m_pScene->getSize(), B8G8R8X8);
        m_pSurface->setTexID(m_pScene->getTexID());
        m_State = GPU;
    } else {
        if (m_State == CPU) {
            m_State = GPU;
            setupSurface();
        }
    }
}

void Image::moveToCPU()
{
    if (m_State != GPU) {
        return;
    }

    if (!m_pScene) {
        m_pBmp = m_pSurface->readbackBmp();
    }
    discardOnCPU();
}

void Image::discardOnCPU()
{
    if (m_State != GPU) {
        return;
    }

    m_pEngine = 0;
    m_pSurface->destroy();
    if (!m_pScene) {
        m_sFilename = "";
        m_pBmp = BitmapPtr(createDefaultBitmap());
        m_State = CPU;
    }
}

void Image::setFilename(const std::string& sFilename)
{
    if (m_State == GPU) {
        m_pSurface->destroy();
    }
    m_pScene = OffscreenScenePtr();
    m_State = NOT_AVAILABLE;
    m_pBmp = BitmapPtr(createDefaultBitmap());
    m_sFilename = sFilename;
    load();
    if (m_pEngine) {
        moveToGPU(m_pEngine);
    }
}

void Image::setScene(OffscreenScenePtr pScene)
{
    if (pScene == m_pScene) {
        return;
    }
    if (!pScene) {
        m_sFilename = "";
        switch(m_State) {
            case CPU:
                m_pBmp = BitmapPtr(createDefaultBitmap());
                break;
            case GPU:
                m_pSurface->destroy();
                break;
            default:
                break;
        }
    }
    m_pScene = pScene;
    m_State = CPU;
    if (m_pEngine) {
        m_pSurface->create(m_pScene->getSize(), B8G8R8X8);
        m_pSurface->setTexID(m_pScene->getTexID());
        moveToGPU(m_pEngine);
    }
}

OffscreenScenePtr Image::getScene() const
{
    return m_pScene;
}

const string& Image::getFilename() const
{
    return m_sFilename;
}

BitmapPtr Image::getBitmap()
{
    if (m_State == GPU) {
        return m_pSurface->readbackBmp();
    } else {
        if (m_pScene) {
            return BitmapPtr();
        } else {
            return BitmapPtr(new Bitmap(*m_pBmp));
        }
    }
}

IntPoint Image::getSize()
{
    if (m_State == GPU) {
        return m_pSurface->getSize();
    } else {
        if (m_pScene) {
            return m_pScene->getSize();
        } else {
            return m_pBmp->getSize();
        }
    }
}

PixelFormat Image::getPixelFormat()
{
    if (m_State == GPU) {
        return m_pSurface->getPixelFormat();
    } else {
        if (m_pScene) {
            return B8G8R8X8;
        } else {
            return m_pBmp->getPixelFormat();
        }
    }
}

OGLSurface* Image::getSurface()
{
    AVG_ASSERT(m_State != CPU);
    return m_pSurface;
}

Image::State Image::getState()
{
    return m_State;
}

SDLDisplayEngine* Image::getEngine()
{
    return m_pEngine;
}

void Image::load()
{
    if (m_sFilename == "") {
        return;
    }
    AVG_TRACE(Logger::MEMORY, "Loading " << m_sFilename);
    m_pBmp = BitmapPtr(new Bitmap(m_sFilename));
    m_State = CPU;
}

void Image::setupSurface()
{
    PixelFormat pf = calcSurfacePF(*m_pBmp);
    m_pSurface->create(m_pBmp->getSize(), pf);
    BitmapPtr pSurfaceBmp = m_pSurface->lockBmp();
    pSurfaceBmp->copyPixels(*m_pBmp);
    m_pSurface->unlockBmps();
    m_pBmp=BitmapPtr(createDefaultBitmap());
}

PixelFormat Image::calcSurfacePF(const Bitmap& bmp)
{
    PixelFormat pf;
    pf = B8G8R8X8;
    if (bmp.hasAlpha()) {
        pf = B8G8R8A8;
    }
    if (bmp.getPixelFormat() == I8) {
        pf = I8;
    }
    return pf;
}

Bitmap* Image::createDefaultBitmap() const
{
    return new Bitmap(IntPoint(1,1), B8G8R8X8);
}

}
<commit_msg>Fixed discarding of images on unlink(false) (Bug #127).<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Image.h"

#include "../base/Logger.h"
#include "../base/Exception.h"
#include "../base/ObjectCounter.h"

#include "../graphics/Filterfliprgb.h"

#include "SDLDisplayEngine.h"
#include "OGLSurface.h"

#include <Magick++.h>

#include <iostream>
#include <sstream>

using namespace std;

namespace avg {

Image::Image(OGLSurface * pSurface, const string& sFilename)
    : m_sFilename(sFilename),
      m_pBmp(createDefaultBitmap()),
      m_pSurface(pSurface),
      m_pEngine(0),
      m_State(NOT_AVAILABLE)
{
    ObjectCounter::get()->incRef(&typeid(*this));
    load();
}

Image::~Image()
{
    if (m_State == GPU) {
        m_pSurface->destroy();
    }
    ObjectCounter::get()->decRef(&typeid(*this));
}

void Image::setBitmap(const Bitmap * pBmp)
{
    if(!pBmp) {
        throw Exception(AVG_ERR_UNSUPPORTED, "setBitmap(): bitmap must not be None!");
    }
    PixelFormat pf = calcSurfacePF(*pBmp);
    if (m_pEngine) {
        if (m_State == NOT_AVAILABLE || m_pSurface->getSize() != pBmp->getSize() ||
                m_pSurface->getPixelFormat() != pf)
        {
            m_pSurface->create(pBmp->getSize(), pf);
        }
        BitmapPtr pSurfaceBmp = m_pSurface->lockBmp();
        pSurfaceBmp->copyPixels(*pBmp);
        m_pSurface->unlockBmps();
        m_pBmp=BitmapPtr(createDefaultBitmap());
        m_State = GPU;
    } else {
        m_pBmp = BitmapPtr(new Bitmap(pBmp->getSize(), pf, ""));
        m_pBmp->copyPixels(*pBmp);
        m_State = CPU;
    }
    m_sFilename = "";

}

void Image::moveToGPU(SDLDisplayEngine* pEngine)
{
    m_pEngine = pEngine;
    if (m_pScene) {
        m_pSurface->create(m_pScene->getSize(), B8G8R8X8);
        m_pSurface->setTexID(m_pScene->getTexID());
        m_State = GPU;
    } else {
        if (m_State == CPU) {
            m_State = GPU;
            setupSurface();
        }
    }
}

void Image::moveToCPU()
{
    if (m_State != GPU) {
        return;
    }

    if (!m_pScene) {
        m_pBmp = m_pSurface->readbackBmp();
        m_State = CPU;
    }
    m_pEngine = 0;
    m_pSurface->destroy();
}

void Image::discardOnCPU()
{
    if (m_State != GPU) {
        return;
    }

    m_pEngine = 0;
    m_pSurface->destroy();
    if (!m_pScene) {
        m_sFilename = "";
        m_pBmp = BitmapPtr(createDefaultBitmap());
        m_State = CPU;
    }
}

void Image::setFilename(const std::string& sFilename)
{
    if (m_State == GPU) {
        m_pSurface->destroy();
    }
    m_pScene = OffscreenScenePtr();
    m_State = NOT_AVAILABLE;
    m_pBmp = BitmapPtr(createDefaultBitmap());
    m_sFilename = sFilename;
    load();
    if (m_pEngine) {
        moveToGPU(m_pEngine);
    }
}

void Image::setScene(OffscreenScenePtr pScene)
{
    if (pScene == m_pScene) {
        return;
    }
    if (!pScene) {
        m_sFilename = "";
        switch(m_State) {
            case CPU:
                m_pBmp = BitmapPtr(createDefaultBitmap());
                break;
            case GPU:
                m_pSurface->destroy();
                break;
            default:
                break;
        }
    }
    m_pScene = pScene;
    m_State = CPU;
    if (m_pEngine) {
        m_pSurface->create(m_pScene->getSize(), B8G8R8X8);
        m_pSurface->setTexID(m_pScene->getTexID());
        moveToGPU(m_pEngine);
    }
}

OffscreenScenePtr Image::getScene() const
{
    return m_pScene;
}

const string& Image::getFilename() const
{
    return m_sFilename;
}

BitmapPtr Image::getBitmap()
{
    if (m_State == GPU) {
        return m_pSurface->readbackBmp();
    } else {
        if (m_pScene) {
            return BitmapPtr();
        } else {
            return BitmapPtr(new Bitmap(*m_pBmp));
        }
    }
}

IntPoint Image::getSize()
{
    if (m_State == GPU) {
        return m_pSurface->getSize();
    } else {
        if (m_pScene) {
            return m_pScene->getSize();
        } else {
            return m_pBmp->getSize();
        }
    }
}

PixelFormat Image::getPixelFormat()
{
    if (m_State == GPU) {
        return m_pSurface->getPixelFormat();
    } else {
        if (m_pScene) {
            return B8G8R8X8;
        } else {
            return m_pBmp->getPixelFormat();
        }
    }
}

OGLSurface* Image::getSurface()
{
    AVG_ASSERT(m_State != CPU);
    return m_pSurface;
}

Image::State Image::getState()
{
    return m_State;
}

SDLDisplayEngine* Image::getEngine()
{
    return m_pEngine;
}

void Image::load()
{
    if (m_sFilename == "") {
        return;
    }
    AVG_TRACE(Logger::MEMORY, "Loading " << m_sFilename);
    m_pBmp = BitmapPtr(new Bitmap(m_sFilename));
    m_State = CPU;
}

void Image::setupSurface()
{
    PixelFormat pf = calcSurfacePF(*m_pBmp);
    m_pSurface->create(m_pBmp->getSize(), pf);
    BitmapPtr pSurfaceBmp = m_pSurface->lockBmp();
    pSurfaceBmp->copyPixels(*m_pBmp);
    m_pSurface->unlockBmps();
    m_pBmp=BitmapPtr(createDefaultBitmap());
}

PixelFormat Image::calcSurfacePF(const Bitmap& bmp)
{
    PixelFormat pf;
    pf = B8G8R8X8;
    if (bmp.hasAlpha()) {
        pf = B8G8R8A8;
    }
    if (bmp.getPixelFormat() == I8) {
        pf = I8;
    }
    return pf;
}

Bitmap* Image::createDefaultBitmap() const
{
    return new Bitmap(IntPoint(1,1), B8G8R8X8);
}

}
<|endoftext|>


<commit_before>
#include "openmc/progress_bar.h"

#include <sstream>
#include <iostream>
#include <iomanip>

#define BAR_WIDTH 72

ProgressBar::ProgressBar() {
  //  bar = "???% |                                                                |";

  set_value(0.0);
}

void
ProgressBar::set_value(double val) {
  // set the bar percentage
  if (val >= 100.0) {
    bar.append("100");
  } else if (val <= 0.0) {
    bar.append("  0");
  } else {
    std::stringstream ss;
    ss << std::setfill(' ') << std::setw(3) << (int)val;
    bar.append(ss.str());
  }

  bar.append("% |");

  // remaining width of the bar
  int remain = BAR_WIDTH - bar.size() - 1;

  // set the bar width
  if (val >= 100.0) {
    bar.append(remain, '=');
  } else {
    int width = (int)(65*val/100);
    std::cout << "Setting width: " << width;
    bar.append(width, '=');
    bar.append(1, '>');
    bar.append(remain-width-1, ' ');
  }

  bar.append("|");

  // write the bar
  std::cout << '\r' << bar << std::flush;

  // reset the bar value
  bar = ""; //???% |                                                                |";
}
<commit_msg>Removing unused code and print.<commit_after>
#include "openmc/progress_bar.h"

#include <sstream>
#include <iostream>
#include <iomanip>

#define BAR_WIDTH 72

ProgressBar::ProgressBar() {
  bar = "";
  set_value(0.0);
}

void
ProgressBar::set_value(double val) {
  // set the bar percentage
  if (val >= 100.0) {
    bar.append("100");
  } else if (val <= 0.0) {
    bar.append("  0");
  } else {
    std::stringstream ss;
    ss << std::setfill(' ') << std::setw(3) << (int)val;
    bar.append(ss.str());
  }

  bar.append("% |");

  // remaining width of the bar
  int remain = BAR_WIDTH - bar.size() - 1;

  // set the bar width
  if (val >= 100.0) {
    bar.append(remain, '=');
  } else {
    int width = (int)(65*val/100);
    bar.append(width, '=');
    bar.append(1, '>');
    bar.append(remain-width-1, ' ');
  }

  bar.append("|");

  // write the bar
  std::cout << '\r' << bar << std::flush;

  // reset the bar value
  bar = "";
}
<|endoftext|>


<commit_before>/*
 +----------------------------------------------------------------------+
 | Swoole                                                               |
 +----------------------------------------------------------------------+
 | Copyright (c) 2012-2017 The Swoole Group                             |
 +----------------------------------------------------------------------+
 | This source file is subject to version 2.0 of the Apache license,    |
 | that is bundled with this package in the file LICENSE, and is        |
 | available through the world-wide-web at the following url:           |
 | http://www.apache.org/licenses/LICENSE-2.0.html                      |
 | If you did not receive a copy of the Apache2.0 license and are unable|
 | to obtain it through the world-wide-web, please send a note to       |
 | license@swoole.com so we can mail you a copy immediately.            |
 +----------------------------------------------------------------------+
 | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
 +----------------------------------------------------------------------+
 */

#include "swoole.h"
#include "swoole_string.h"
#include "swoole_socket.h"
#include "swoole_protocol.h"
#include "swoole_log.h"

namespace swoole {
/**
 * return the package total length
 */
ssize_t Protocol::default_length_func(Protocol *protocol, network::Socket *socket, const char *data, uint32_t size) {
    uint16_t length_offset = protocol->package_length_offset;
    uint8_t package_length_size =
        protocol->get_package_length_size ? protocol->get_package_length_size(socket) : protocol->package_length_size;
    int32_t body_length;

    if (package_length_size == 0) {
        // protocol error
        return SW_ERR;
    }
    /**
     * no have length field, wait more data
     */
    if (size < length_offset + package_length_size) {
        protocol->real_header_length = length_offset + package_length_size;
        return 0;
    }
    body_length = swoole_unpack(protocol->package_length_type, data + length_offset);
    // Length error
    // Protocol length is not legitimate, out of bounds or exceed the allocated length
    if (body_length < 0) {
        swWarn("invalid package (size=%d) from socket#%u<%s:%d>",
               size,
               socket->fd,
               socket->info.get_ip(),
               socket->info.get_port());
        return SW_ERR;
    }
    swDebug("length=%d", protocol->package_body_offset + body_length);

    // total package length
    return protocol->package_body_offset + body_length;
}

int Protocol::recv_split_by_eof(network::Socket *socket, String *buffer) {
    if (buffer->length < package_eof_len) {
        return SW_CONTINUE;
    }

    int retval;

    size_t n = buffer->split(package_eof, package_eof_len, [&](const char *data, size_t length) -> int {
        if (onPackage(this, socket, data, length) < 0) {
            retval = SW_CLOSE;
            return false;
        }
        if (socket->removed) {
            return false;
        }
        return true;
    });

    if (socket->removed) {
        return SW_CLOSE;
    }

    if (n < 0) {
        return retval;
    } else if (n == 0) {
        return SW_CONTINUE;
    } else if (n < buffer->length) {
        off_t offset;
        buffer->reduce(n);
        offset = buffer->length - package_eof_len;
        buffer->offset = offset > 0 ? offset : 0;
    } else {
        swString_clear(buffer);
    }

#ifdef SW_USE_OPENSSL
    if (socket->ssl) {
        return SW_CONTINUE;
    }
#endif

    return SW_OK;
}

/**
 * @return SW_ERR: close the connection
 * @return SW_OK: continue
 */
int Protocol::recv_with_length_protocol(network::Socket *socket, String *buffer) {
    ssize_t package_length;
    uint8_t _package_length_size = get_package_length_size ? get_package_length_size(socket) : package_length_size;
    uint32_t recv_size;
    ssize_t recv_n = 0;

    if (_package_length_size == 0) {
        // protocol error
        return SW_ERR;
    }

    if (socket->skip_recv) {
        socket->skip_recv = 0;
        goto _do_get_length;
    }

_do_recv:
    if (socket->removed) {
        return SW_OK;
    }
    if (buffer->offset > 0) {
        recv_size = buffer->offset - buffer->length;
    } else {
        recv_size = package_length_offset + _package_length_size;
    }

    recv_n = socket->recv(buffer->str + buffer->length, recv_size, 0);
    if (recv_n < 0) {
        switch (socket->catch_error(errno)) {
        case SW_ERROR:
            swSysWarn("recv(%d, %d) failed", socket->fd, recv_size);
            return SW_OK;
        case SW_CLOSE:
            return SW_ERR;
        default:
            return SW_OK;
        }
    } else if (recv_n == 0) {
        return SW_ERR;
    } else {
        buffer->length += recv_n;

        if (socket->recv_wait) {
            if (buffer->length >= (size_t) buffer->offset) {
            _do_dispatch:
                if (onPackage(this, socket, buffer->str, buffer->offset) < 0) {
                    return SW_ERR;
                }
                if (socket->removed) {
                    return SW_OK;
                }
                socket->recv_wait = 0;

                if (buffer->length > (size_t) buffer->offset) {
                    buffer->reduce(buffer->offset);
                    goto _do_get_length;
                } else {
                    swString_clear(buffer);
                }
            }
#ifdef SW_USE_OPENSSL
            if (socket->ssl) {
                goto _do_recv;
            }
#endif
            return SW_OK;
        } else {
        _do_get_length:
            package_length = get_package_length(this, socket, buffer->str, buffer->length);
            // invalid package, close connection.
            if (package_length < 0) {
                return SW_ERR;
            }
            // no length
            else if (package_length == 0) {
                if (buffer->length == package_length_offset + package_length_size) {
                    swoole_error_log(SW_LOG_WARNING,
                                     SW_ERROR_PACKAGE_LENGTH_NOT_FOUND,
                                     "bad request, No length found in %ld bytes",
                                     buffer->length);
                    return SW_ERR;
                } else {
                    return SW_OK;
                }
            } else if (package_length > package_max_length) {
                swoole_error_log(SW_LOG_WARNING,
                                 SW_ERROR_PACKAGE_LENGTH_TOO_LARGE,
                                 "package is too big, remote_addr=%s:%d, length=%zu",
                                 socket->info.get_ip(),
                                 socket->info.get_port(),
                                 package_length);
                return SW_ERR;
            }
            // get length success
            else {
                if (buffer->size < (size_t) package_length) {
                    if (swString_extend(buffer, package_length) < 0) {
                        return SW_ERR;
                    }
                }
                socket->recv_wait = 1;
                buffer->offset = package_length;

                if (buffer->length >= (size_t) package_length) {
                    goto _do_dispatch;
                } else {
                    goto _do_recv;
                }
            }
        }
    }
    return SW_OK;
}

/**
 * @return SW_ERR: close the connection
 * @return SW_OK: continue
 */
int Protocol::recv_with_eof_protocol(network::Socket *socket, String *buffer) {
    bool recv_again = false;
    int buf_size;

_recv_data:
    buf_size = buffer->size - buffer->length;
    char *buf_ptr = buffer->str + buffer->length;

    if (buf_size > SW_BUFFER_SIZE_STD) {
        buf_size = SW_BUFFER_SIZE_STD;
    }

    int n = socket->recv(buf_ptr, buf_size, 0);
    if (n < 0) {
        switch (socket->catch_error(errno)) {
        case SW_ERROR:
            swSysWarn("recv from socket#%d failed", socket->fd);
            return SW_OK;
        case SW_CLOSE:
            return SW_ERR;
        default:
            return SW_OK;
        }
    } else if (n == 0) {
        return SW_ERR;
    } else {
        buffer->length += n;

        if (buffer->length < package_eof_len) {
            return SW_OK;
        }

        if (split_by_eof) {
            int retval = recv_split_by_eof(socket, buffer);
            if (retval == SW_CONTINUE) {
                recv_again = true;
            } else if (retval == SW_CLOSE) {
                return SW_ERR;
            } else {
                return SW_OK;
            }
        } else if (memcmp(buffer->str + buffer->length - package_eof_len,
                          package_eof,
                          package_eof_len) == 0) {
            buffer->offset = buffer->length;
            if (onPackage(this, socket, buffer->str, buffer->length) < 0) {
                return SW_ERR;
            }
            if (socket->removed) {
                return SW_OK;
            }
            swString_clear(buffer);
#ifdef SW_USE_OPENSSL
            if (socket->ssl && SSL_pending(socket->ssl) > 0) {
                goto _recv_data;
            }
#endif
            return SW_OK;
        }

        // over max length, will discard
        if (buffer->length == package_max_length) {
            swWarn("Package is too big. package_length=%d", (int) buffer->length);
            return SW_ERR;
        }

        // buffer is full, may have not read data
        if (buffer->length == buffer->size) {
            recv_again = true;
            if (buffer->size < package_max_length) {
                uint32_t extend_size = swoole_size_align(buffer->size * 2, SwooleG.pagesize);
                if (extend_size > package_max_length) {
                    extend_size = package_max_length;
                }
                if (swString_extend(buffer, extend_size) < 0) {
                    return SW_ERR;
                }
            }
        }
        // no eof
        if (recv_again) {
            goto _recv_data;
        }
    }
    return SW_OK;
}

}
<commit_msg>Fixed: fix type-limits error (#3560)<commit_after>/*
 +----------------------------------------------------------------------+
 | Swoole                                                               |
 +----------------------------------------------------------------------+
 | Copyright (c) 2012-2017 The Swoole Group                             |
 +----------------------------------------------------------------------+
 | This source file is subject to version 2.0 of the Apache license,    |
 | that is bundled with this package in the file LICENSE, and is        |
 | available through the world-wide-web at the following url:           |
 | http://www.apache.org/licenses/LICENSE-2.0.html                      |
 | If you did not receive a copy of the Apache2.0 license and are unable|
 | to obtain it through the world-wide-web, please send a note to       |
 | license@swoole.com so we can mail you a copy immediately.            |
 +----------------------------------------------------------------------+
 | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
 +----------------------------------------------------------------------+
 */

#include "swoole.h"
#include "swoole_string.h"
#include "swoole_socket.h"
#include "swoole_protocol.h"
#include "swoole_log.h"

namespace swoole {
/**
 * return the package total length
 */
ssize_t Protocol::default_length_func(Protocol *protocol, network::Socket *socket, const char *data, uint32_t size) {
    uint16_t length_offset = protocol->package_length_offset;
    uint8_t package_length_size =
        protocol->get_package_length_size ? protocol->get_package_length_size(socket) : protocol->package_length_size;
    int32_t body_length;

    if (package_length_size == 0) {
        // protocol error
        return SW_ERR;
    }
    /**
     * no have length field, wait more data
     */
    if (size < length_offset + package_length_size) {
        protocol->real_header_length = length_offset + package_length_size;
        return 0;
    }
    body_length = swoole_unpack(protocol->package_length_type, data + length_offset);
    // Length error
    // Protocol length is not legitimate, out of bounds or exceed the allocated length
    if (body_length < 0) {
        swWarn("invalid package (size=%d) from socket#%u<%s:%d>",
               size,
               socket->fd,
               socket->info.get_ip(),
               socket->info.get_port());
        return SW_ERR;
    }
    swDebug("length=%d", protocol->package_body_offset + body_length);

    // total package length
    return protocol->package_body_offset + body_length;
}

int Protocol::recv_split_by_eof(network::Socket *socket, String *buffer) {
    if (buffer->length < package_eof_len) {
        return SW_CONTINUE;
    }

    int retval;

    ssize_t n = buffer->split(package_eof, package_eof_len, [&](const char *data, size_t length) -> int {
        if (onPackage(this, socket, data, length) < 0) {
            retval = SW_CLOSE;
            return false;
        }
        if (socket->removed) {
            return false;
        }
        return true;
    });

    if (socket->removed) {
        return SW_CLOSE;
    }

    if (n < 0) {
        return retval;
    } else if (n == 0) {
        return SW_CONTINUE;
    } else if (n < buffer->length) {
        off_t offset;
        buffer->reduce(n);
        offset = buffer->length - package_eof_len;
        buffer->offset = offset > 0 ? offset : 0;
    } else {
        swString_clear(buffer);
    }

#ifdef SW_USE_OPENSSL
    if (socket->ssl) {
        return SW_CONTINUE;
    }
#endif

    return SW_OK;
}

/**
 * @return SW_ERR: close the connection
 * @return SW_OK: continue
 */
int Protocol::recv_with_length_protocol(network::Socket *socket, String *buffer) {
    ssize_t package_length;
    uint8_t _package_length_size = get_package_length_size ? get_package_length_size(socket) : package_length_size;
    uint32_t recv_size;
    ssize_t recv_n = 0;

    if (_package_length_size == 0) {
        // protocol error
        return SW_ERR;
    }

    if (socket->skip_recv) {
        socket->skip_recv = 0;
        goto _do_get_length;
    }

_do_recv:
    if (socket->removed) {
        return SW_OK;
    }
    if (buffer->offset > 0) {
        recv_size = buffer->offset - buffer->length;
    } else {
        recv_size = package_length_offset + _package_length_size;
    }

    recv_n = socket->recv(buffer->str + buffer->length, recv_size, 0);
    if (recv_n < 0) {
        switch (socket->catch_error(errno)) {
        case SW_ERROR:
            swSysWarn("recv(%d, %d) failed", socket->fd, recv_size);
            return SW_OK;
        case SW_CLOSE:
            return SW_ERR;
        default:
            return SW_OK;
        }
    } else if (recv_n == 0) {
        return SW_ERR;
    } else {
        buffer->length += recv_n;

        if (socket->recv_wait) {
            if (buffer->length >= (size_t) buffer->offset) {
            _do_dispatch:
                if (onPackage(this, socket, buffer->str, buffer->offset) < 0) {
                    return SW_ERR;
                }
                if (socket->removed) {
                    return SW_OK;
                }
                socket->recv_wait = 0;

                if (buffer->length > (size_t) buffer->offset) {
                    buffer->reduce(buffer->offset);
                    goto _do_get_length;
                } else {
                    swString_clear(buffer);
                }
            }
#ifdef SW_USE_OPENSSL
            if (socket->ssl) {
                goto _do_recv;
            }
#endif
            return SW_OK;
        } else {
        _do_get_length:
            package_length = get_package_length(this, socket, buffer->str, buffer->length);
            // invalid package, close connection.
            if (package_length < 0) {
                return SW_ERR;
            }
            // no length
            else if (package_length == 0) {
                if (buffer->length == package_length_offset + package_length_size) {
                    swoole_error_log(SW_LOG_WARNING,
                                     SW_ERROR_PACKAGE_LENGTH_NOT_FOUND,
                                     "bad request, No length found in %ld bytes",
                                     buffer->length);
                    return SW_ERR;
                } else {
                    return SW_OK;
                }
            } else if (package_length > package_max_length) {
                swoole_error_log(SW_LOG_WARNING,
                                 SW_ERROR_PACKAGE_LENGTH_TOO_LARGE,
                                 "package is too big, remote_addr=%s:%d, length=%zu",
                                 socket->info.get_ip(),
                                 socket->info.get_port(),
                                 package_length);
                return SW_ERR;
            }
            // get length success
            else {
                if (buffer->size < (size_t) package_length) {
                    if (swString_extend(buffer, package_length) < 0) {
                        return SW_ERR;
                    }
                }
                socket->recv_wait = 1;
                buffer->offset = package_length;

                if (buffer->length >= (size_t) package_length) {
                    goto _do_dispatch;
                } else {
                    goto _do_recv;
                }
            }
        }
    }
    return SW_OK;
}

/**
 * @return SW_ERR: close the connection
 * @return SW_OK: continue
 */
int Protocol::recv_with_eof_protocol(network::Socket *socket, String *buffer) {
    bool recv_again = false;
    int buf_size;

_recv_data:
    buf_size = buffer->size - buffer->length;
    char *buf_ptr = buffer->str + buffer->length;

    if (buf_size > SW_BUFFER_SIZE_STD) {
        buf_size = SW_BUFFER_SIZE_STD;
    }

    int n = socket->recv(buf_ptr, buf_size, 0);
    if (n < 0) {
        switch (socket->catch_error(errno)) {
        case SW_ERROR:
            swSysWarn("recv from socket#%d failed", socket->fd);
            return SW_OK;
        case SW_CLOSE:
            return SW_ERR;
        default:
            return SW_OK;
        }
    } else if (n == 0) {
        return SW_ERR;
    } else {
        buffer->length += n;

        if (buffer->length < package_eof_len) {
            return SW_OK;
        }

        if (split_by_eof) {
            int retval = recv_split_by_eof(socket, buffer);
            if (retval == SW_CONTINUE) {
                recv_again = true;
            } else if (retval == SW_CLOSE) {
                return SW_ERR;
            } else {
                return SW_OK;
            }
        } else if (memcmp(buffer->str + buffer->length - package_eof_len,
                          package_eof,
                          package_eof_len) == 0) {
            buffer->offset = buffer->length;
            if (onPackage(this, socket, buffer->str, buffer->length) < 0) {
                return SW_ERR;
            }
            if (socket->removed) {
                return SW_OK;
            }
            swString_clear(buffer);
#ifdef SW_USE_OPENSSL
            if (socket->ssl && SSL_pending(socket->ssl) > 0) {
                goto _recv_data;
            }
#endif
            return SW_OK;
        }

        // over max length, will discard
        if (buffer->length == package_max_length) {
            swWarn("Package is too big. package_length=%d", (int) buffer->length);
            return SW_ERR;
        }

        // buffer is full, may have not read data
        if (buffer->length == buffer->size) {
            recv_again = true;
            if (buffer->size < package_max_length) {
                uint32_t extend_size = swoole_size_align(buffer->size * 2, SwooleG.pagesize);
                if (extend_size > package_max_length) {
                    extend_size = package_max_length;
                }
                if (swString_extend(buffer, extend_size) < 0) {
                    return SW_ERR;
                }
            }
        }
        // no eof
        if (recv_again) {
            goto _recv_data;
        }
    }
    return SW_OK;
}

}
<|endoftext|>