<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef __itkByteSwapper_hxx
#define __itkByteSwapper_hxx
#include "itkByteSwapper.h"
#include <memory>
#include <cstring>

namespace itk
{
// The following are the public methods --------------------------------
//
// Machine definitions
#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
bool ByteSwapper< T >::SystemIsBigEndian() { return true; }
template< typename T >
bool ByteSwapper< T >::SystemIsLittleEndian() { return false; }
#else
template< typename T >
bool ByteSwapper< T >::SystemIsBigEndian() { return false; }
template< typename T >
bool ByteSwapper< T >::SystemIsLittleEndian() { return true; }
#endif

//------Big Endian methods----------------------------------------------

// Use different swap methods based on type
#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToBigEndian(T *){}
#else
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToBigEndian(T *p)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2( (void *)p );
      return;
    case 4:
      ByteSwapper< T >::Swap4( (void *)p );
      return;
    case 8:
      ByteSwapper< T >::Swap8( (void *)p );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToBigEndian(T *, BufferSizeType)
{
  // nothing needs to be done here...
}

#else

#ifdef __INTEL_COMPILER
#pragma warning disable 280 //remark #280: selector expression is constant
#endif
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToBigEndian(T *p, BufferSizeType num)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2Range( (void *)p, num );
      return;
    case 4:
      ByteSwapper< T >::Swap4Range( (void *)p, num );
      return;
    case 8:
      ByteSwapper< T >::Swap8Range( (void *)p, num );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
      return;
    }
}

#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToBigEndian(T *p, int num, OStreamType *fp)
{
  num *= sizeof( T );
  fp->write( (char *)p, num );
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToBigEndian(T *p, int num, OStreamType *fp)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::SwapWrite2Range( (void *)p, num, fp );
      return;
    case 4:
      ByteSwapper< T >::SwapWrite4Range( (void *)p, num, fp );
      return;
    case 8:
      ByteSwapper< T >::SwapWrite8Range( (void *)p, num, fp );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#endif

//------Little Endian methods----------------------------------------------

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToLittleEndian(T *p)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2( (void *)p );
      return;
    case 4:
      ByteSwapper< T >::Swap4( (void *)p );
      return;
    case 8:
      ByteSwapper< T >::Swap8( (void *)p );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToLittleEndian(T *){}
#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToLittleEndian(T *p, BufferSizeType num)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2Range( (void *)p, num );
      return;
    case 4:
      ByteSwapper< T >::Swap4Range( (void *)p, num );
      return;
    case 8:
      ByteSwapper< T >::Swap8Range( (void *)p, num );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToLittleEndian(T *, BufferSizeType) {}
#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToLittleEndian(T *p, int num, OStreamType *fp)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::SwapWrite2Range( (void *)p, num, fp );
      return;
    case 4:
      ByteSwapper< T >::SwapWrite4Range( (void *)p, num, fp );
      return;
    case 8:
      ByteSwapper< T >::SwapWrite8Range( (void *)p, num, fp );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToLittleEndian(T *p, int num, OStreamType *fp)
{
  num *= sizeof( T );
  fp->write( (char *)p, num );
}

#endif

// The following are the protected methods -------------------------
//

//------2-byte methods----------------------------------------------

// Swap 2 byte word.
template< typename T >
void
ByteSwapper< T >
::Swap2(void *pin)
{
  unsigned short *      p = reinterpret_cast< unsigned short * >( pin );
  const unsigned short h1 = (*p) << static_cast<short unsigned int>(8);
  const unsigned short h2 = (*p) >> static_cast<short unsigned int>(8);
  *p = h1 | h2;
}

// Swap bunch of bytes. Num is the number of two byte words to swap.
template< typename T >
void
ByteSwapper< T >
::Swap2Range(void *ptr, BufferSizeType num)
{
  char * pos = reinterpret_cast< char * >( ptr );
  for ( BufferSizeType i = 0; i < num; i++ )
    {
    const char one_byte = pos[0];
    pos[0] = pos[1];
    pos[1] = one_byte;
    pos = pos + 2;
    }
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::SwapWrite2Range(void *ptr, BufferSizeType num, OStreamType *fp)
{
  BufferSizeType chunkSize = 1000000;
  if ( num < chunkSize )
    {
    chunkSize = num;
    }
  char * cpy = new char[chunkSize * 2];
  while ( num )
    {
    memcpy(cpy, ptr, chunkSize * 2);

    char * pos = cpy;
    for ( BufferSizeType i = 0; i < chunkSize; i++ )
      {
      const char one_byte = pos[0];
      pos[0] = pos[1];
      pos[1] = one_byte;
      pos = pos + 2;
      }
    fp->write( (char *)cpy, static_cast<std::streamsize>(2 * chunkSize) );
    ptr = (char *)ptr + chunkSize * 2;
    num -= chunkSize;
    if ( num < chunkSize )
      {
      chunkSize = num;
      }
    }
  delete[] cpy;
}

//------4-byte methods----------------------------------------------

// Swap four byte word.
template< typename T >
void
ByteSwapper< T >
::Swap4(void *ptr)
{
  char  one_byte;
  char *p = reinterpret_cast< char * >( ptr );

  one_byte    = p[0];
  p[0] = p[3];
  p[3] = one_byte;

  one_byte    = p[1];
  p[1] = p[2];
  p[2] = one_byte;
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::Swap4Range(void *ptr, BufferSizeType num)
{
  char           one_byte;
  char *         pos = reinterpret_cast< char * >( ptr );
  BufferSizeType i;

  for ( i = 0; i < num; i++ )
    {
    one_byte = pos[0];
    pos[0] = pos[3];
    pos[3] = one_byte;

    one_byte = pos[1];
    pos[1] = pos[2];
    pos[2] = one_byte;
    pos = pos + 4;
    }
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::SwapWrite4Range(void *ptr, BufferSizeType num, OStreamType *fp)
{
  BufferSizeType chunkSize = 1000000;

  if ( num < chunkSize )
    {
    chunkSize = num;
    }
  char * cpy = new char[chunkSize * 4];

  while ( num )
    {
    memcpy(cpy, ptr, chunkSize * 4);

    char * pos = cpy;
    for ( BufferSizeType i = 0; i < chunkSize; i++ )
      {
      char one_byte = pos[0];
      pos[0] = pos[3];
      pos[3] = one_byte;

      one_byte = pos[1];
      pos[1] = pos[2];
      pos[2] = one_byte;
      pos = pos + 4;
      }
    fp->write( (char *)cpy, static_cast<std::streamsize>(4 * chunkSize) );
    ptr  = (char *)ptr + chunkSize * 4;
    num -= chunkSize;
    if ( num < chunkSize )
      {
      chunkSize = num;
      }
    }
  delete[] cpy;
}

//------8-byte methods----------------------------------------------

// Swap 8 byte double precision
template< typename T >
void
ByteSwapper< T >
::Swap8(void *ptr)
{
  char  one_byte;
  char *p = reinterpret_cast< char * >( ptr );

  one_byte    = p[0];
  p[0] = p[7];
  p[7] = one_byte;

  one_byte    = p[1];
  p[1] = p[6];
  p[6] = one_byte;

  one_byte    = p[2];
  p[2] = p[5];
  p[5] = one_byte;

  one_byte    = p[3];
  p[3] = p[4];
  p[4] = one_byte;
}

// Swap bunch of bytes. Num is the number of eight byte words to swap.
template< typename T >
void
ByteSwapper< T >
::Swap8Range(void *ptr, BufferSizeType num)
{
  char           one_byte;
  char *         pos = reinterpret_cast< char * >( ptr );
  BufferSizeType i;

  for ( i = 0; i < num; i++ )
    {
    one_byte    = pos[0];
    pos[0] = pos[7];
    pos[7] = one_byte;

    one_byte    = pos[1];
    pos[1] = pos[6];
    pos[6] = one_byte;

    one_byte    = pos[2];
    pos[2] = pos[5];
    pos[5] = one_byte;

    one_byte    = pos[3];
    pos[3] = pos[4];
    pos[4] = one_byte;
    pos = pos + 8;
    }
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::SwapWrite8Range(void *ptr, BufferSizeType num, OStreamType *fp)
{
  BufferSizeType chunkSize = 1000000;
  if ( num < chunkSize )
    {
    chunkSize = num;
    }
  char * cpy = new char[chunkSize * 8];

  while ( num )
    {
    memcpy(cpy, ptr, chunkSize * 8);

    ByteSwapper< T >::Swap8Range( (void *)cpy, chunkSize );

    fp->write( (char *)cpy, static_cast<std::streamsize>(8 * chunkSize) );
    ptr  = (char *)ptr + chunkSize * 8;
    num -= chunkSize;
    if ( num < chunkSize )
      {
      chunkSize = num;
      }
    }
  delete[] cpy;
}
} // end namespace itk

#endif
<commit_msg>STYLE: fix cppcheck style warning<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef __itkByteSwapper_hxx
#define __itkByteSwapper_hxx
#include "itkByteSwapper.h"
#include <memory>
#include <cstring>

namespace itk
{
// The following are the public methods --------------------------------
//
// Machine definitions
#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
bool ByteSwapper< T >::SystemIsBigEndian() { return true; }
template< typename T >
bool ByteSwapper< T >::SystemIsLittleEndian() { return false; }
#else
template< typename T >
bool ByteSwapper< T >::SystemIsBigEndian() { return false; }
template< typename T >
bool ByteSwapper< T >::SystemIsLittleEndian() { return true; }
#endif

//------Big Endian methods----------------------------------------------

// Use different swap methods based on type
#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToBigEndian(T *){}
#else
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToBigEndian(T *p)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2( (void *)p );
      return;
    case 4:
      ByteSwapper< T >::Swap4( (void *)p );
      return;
    case 8:
      ByteSwapper< T >::Swap8( (void *)p );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToBigEndian(T *, BufferSizeType)
{
  // nothing needs to be done here...
}

#else

#ifdef __INTEL_COMPILER
#pragma warning disable 280 //remark #280: selector expression is constant
#endif
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToBigEndian(T *p, BufferSizeType num)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2Range( (void *)p, num );
      return;
    case 4:
      ByteSwapper< T >::Swap4Range( (void *)p, num );
      return;
    case 8:
      ByteSwapper< T >::Swap8Range( (void *)p, num );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
      return;
    }
}

#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToBigEndian(T *p, int num, OStreamType *fp)
{
  num *= sizeof( T );
  fp->write( (char *)p, num );
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToBigEndian(T *p, int num, OStreamType *fp)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::SwapWrite2Range( (void *)p, num, fp );
      return;
    case 4:
      ByteSwapper< T >::SwapWrite4Range( (void *)p, num, fp );
      return;
    case 8:
      ByteSwapper< T >::SwapWrite8Range( (void *)p, num, fp );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#endif

//------Little Endian methods----------------------------------------------

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToLittleEndian(T *p)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2( (void *)p );
      return;
    case 4:
      ByteSwapper< T >::Swap4( (void *)p );
      return;
    case 8:
      ByteSwapper< T >::Swap8( (void *)p );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapFromSystemToLittleEndian(T *){}
#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToLittleEndian(T *p, BufferSizeType num)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::Swap2Range( (void *)p, num );
      return;
    case 4:
      ByteSwapper< T >::Swap4Range( (void *)p, num );
      return;
    case 8:
      ByteSwapper< T >::Swap8Range( (void *)p, num );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapRangeFromSystemToLittleEndian(T *, BufferSizeType) {}
#endif

#ifdef CMAKE_WORDS_BIGENDIAN
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToLittleEndian(T *p, int num, OStreamType *fp)
{
  switch ( sizeof( T ) )
    {
    case 1:
      return;
    case 2:
      ByteSwapper< T >::SwapWrite2Range( (void *)p, num, fp );
      return;
    case 4:
      ByteSwapper< T >::SwapWrite4Range( (void *)p, num, fp );
      return;
    case 8:
      ByteSwapper< T >::SwapWrite8Range( (void *)p, num, fp );
      return;
    default:
      itkGenericExceptionMacro (<< "Cannot swap number of bytes requested");
    }
}

#else
template< typename T >
void
ByteSwapper< T >
::SwapWriteRangeFromSystemToLittleEndian(T *p, int num, OStreamType *fp)
{
  num *= sizeof( T );
  fp->write( (char *)p, num );
}

#endif

// The following are the protected methods -------------------------
//

//------2-byte methods----------------------------------------------

// Swap 2 byte word.
template< typename T >
void
ByteSwapper< T >
::Swap2(void *pin)
{
  unsigned short *      p = reinterpret_cast< unsigned short * >( pin );
  const unsigned short h1 = (*p) << static_cast<short unsigned int>(8);
  const unsigned short h2 = (*p) >> static_cast<short unsigned int>(8);
  *p = h1 | h2;
}

// Swap bunch of bytes. Num is the number of two byte words to swap.
template< typename T >
void
ByteSwapper< T >
::Swap2Range(void *ptr, BufferSizeType num)
{
  char * pos = reinterpret_cast< char * >( ptr );
  for ( BufferSizeType i = 0; i < num; i++ )
    {
    const char one_byte = pos[0];
    pos[0] = pos[1];
    pos[1] = one_byte;
    pos = pos + 2;
    }
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::SwapWrite2Range(void *ptr, BufferSizeType num, OStreamType *fp)
{
  BufferSizeType chunkSize = 1000000;
  if ( num < chunkSize )
    {
    chunkSize = num;
    }
  char * cpy = new char[chunkSize * 2];
  while ( num )
    {
    memcpy(cpy, ptr, chunkSize * 2);

    char * pos = cpy;
    for ( BufferSizeType i = 0; i < chunkSize; i++ )
      {
      const char one_byte = pos[0];
      pos[0] = pos[1];
      pos[1] = one_byte;
      pos = pos + 2;
      }
    fp->write( (char *)cpy, static_cast<std::streamsize>(2 * chunkSize) );
    ptr = (char *)ptr + chunkSize * 2;
    num -= chunkSize;
    if ( num < chunkSize )
      {
      chunkSize = num;
      }
    }
  delete[] cpy;
}

//------4-byte methods----------------------------------------------

// Swap four byte word.
template< typename T >
void
ByteSwapper< T >
::Swap4(void *ptr)
{
  char  one_byte;
  char *p = reinterpret_cast< char * >( ptr );

  one_byte    = p[0];
  p[0] = p[3];
  p[3] = one_byte;

  one_byte    = p[1];
  p[1] = p[2];
  p[2] = one_byte;
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::Swap4Range(void *ptr, BufferSizeType num)
{
  char *         pos = reinterpret_cast< char * >( ptr );

  for ( BufferSizeType i = 0; i < num; i++ )
    {
    char one_byte = pos[0];
    pos[0] = pos[3];
    pos[3] = one_byte;

    one_byte = pos[1];
    pos[1] = pos[2];
    pos[2] = one_byte;
    pos = pos + 4;
    }
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::SwapWrite4Range(void *ptr, BufferSizeType num, OStreamType *fp)
{
  BufferSizeType chunkSize = 1000000;

  if ( num < chunkSize )
    {
    chunkSize = num;
    }
  char * cpy = new char[chunkSize * 4];

  while ( num )
    {
    memcpy(cpy, ptr, chunkSize * 4);

    char * pos = cpy;
    for ( BufferSizeType i = 0; i < chunkSize; i++ )
      {
      char one_byte = pos[0];
      pos[0] = pos[3];
      pos[3] = one_byte;

      one_byte = pos[1];
      pos[1] = pos[2];
      pos[2] = one_byte;
      pos = pos + 4;
      }
    fp->write( (char *)cpy, static_cast<std::streamsize>(4 * chunkSize) );
    ptr  = (char *)ptr + chunkSize * 4;
    num -= chunkSize;
    if ( num < chunkSize )
      {
      chunkSize = num;
      }
    }
  delete[] cpy;
}

//------8-byte methods----------------------------------------------

// Swap 8 byte double precision
template< typename T >
void
ByteSwapper< T >
::Swap8(void *ptr)
{
  char  one_byte;
  char *p = reinterpret_cast< char * >( ptr );

  one_byte    = p[0];
  p[0] = p[7];
  p[7] = one_byte;

  one_byte    = p[1];
  p[1] = p[6];
  p[6] = one_byte;

  one_byte    = p[2];
  p[2] = p[5];
  p[5] = one_byte;

  one_byte    = p[3];
  p[3] = p[4];
  p[4] = one_byte;
}

// Swap bunch of bytes. Num is the number of eight byte words to swap.
template< typename T >
void
ByteSwapper< T >
::Swap8Range(void *ptr, BufferSizeType num)
{
  char *         pos = reinterpret_cast< char * >( ptr );

  for ( BufferSizeType i = 0; i < num; i++ )
    {
    char one_byte    = pos[0];
    pos[0] = pos[7];
    pos[7] = one_byte;

    one_byte    = pos[1];
    pos[1] = pos[6];
    pos[6] = one_byte;

    one_byte    = pos[2];
    pos[2] = pos[5];
    pos[5] = one_byte;

    one_byte    = pos[3];
    pos[3] = pos[4];
    pos[4] = one_byte;
    pos = pos + 8;
    }
}

// Swap bunch of bytes. Num is the number of four byte words to swap.
template< typename T >
void
ByteSwapper< T >
::SwapWrite8Range(void *ptr, BufferSizeType num, OStreamType *fp)
{
  BufferSizeType chunkSize = 1000000;
  if ( num < chunkSize )
    {
    chunkSize = num;
    }
  char * cpy = new char[chunkSize * 8];

  while ( num )
    {
    memcpy(cpy, ptr, chunkSize * 8);

    ByteSwapper< T >::Swap8Range( (void *)cpy, chunkSize );

    fp->write( (char *)cpy, static_cast<std::streamsize>(8 * chunkSize) );
    ptr  = (char *)ptr + chunkSize * 8;
    num -= chunkSize;
    if ( num < chunkSize )
      {
      chunkSize = num;
      }
    }
  delete[] cpy;
}
} // end namespace itk

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 Muhammad Tayyab Akram
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern "C" {
#include <Headers/SBBase.h>
#include <Headers/SBConfig.h>
#include <Source/SBGeneralCategoryLookup.h>
}

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iostream>

#include <Parser/UnicodeData.h>

#include "Utilities/Convert.h"
#include "Utilities/Unicode.h"

#include "Configuration.h"
#include "GeneralCategoryLookupTester.h"

using namespace std;
using namespace SheenBidi::Parser;
using namespace SheenBidi::Tester;
using namespace SheenBidi::Tester::Utilities;

static const string DEFAULT_GENERAL_CATEGORY = "Cn";

GeneralCategoryLookupTester::GeneralCategoryLookupTester(const UnicodeData &unicodeData) :
    m_unicodeData(unicodeData)
{
}

void GeneralCategoryLookupTester::test()
{
#ifdef SB_CONFIG_UNITY
    cout << "Cannot run general category lookup tester in unity mode." << endl;
#else
    cout << "Running general category lookup tester." << endl;

    size_t failCounter = 0;
    string uniGeneralCategory;

    for (uint32_t codePoint = 0; codePoint < Unicode::MAX_CODE_POINT; codePoint++) {
        m_unicodeData.getGeneralCategory(codePoint, uniGeneralCategory);
        const string &expGeneralCategory = (uniGeneralCategory.length() ? uniGeneralCategory : DEFAULT_GENERAL_CATEGORY);

        SBGeneralCategory valGeneralCategory = SBGeneralCategoryDetermine(codePoint);
        const string &genGeneralCategory = Convert::generalCategoryToString(valGeneralCategory);

        if (genGeneralCategory != expGeneralCategory) {
            if (Configuration::DISPLAY_ERROR_DETAILS) {
                cout << "Invalid general category found: " << endl
                     << "  Code Point: " << codePoint << endl
                     << "  Expected General Category: " << expGeneralCategory << endl
                     << "  Generated General Category: " << genGeneralCategory << endl;
            }

            failCounter++;
        }
    }

    cout << failCounter << " error/s." << endl;
    cout << endl;
#endif
}
<commit_msg>[test] Included last code point in general category lookup tester...<commit_after>/*
 * Copyright (C) 2018 Muhammad Tayyab Akram
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern "C" {
#include <Headers/SBBase.h>
#include <Headers/SBConfig.h>
#include <Source/SBGeneralCategoryLookup.h>
}

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iostream>

#include <Parser/UnicodeData.h>

#include "Utilities/Convert.h"
#include "Utilities/Unicode.h"

#include "Configuration.h"
#include "GeneralCategoryLookupTester.h"

using namespace std;
using namespace SheenBidi::Parser;
using namespace SheenBidi::Tester;
using namespace SheenBidi::Tester::Utilities;

static const string DEFAULT_GENERAL_CATEGORY = "Cn";

GeneralCategoryLookupTester::GeneralCategoryLookupTester(const UnicodeData &unicodeData) :
    m_unicodeData(unicodeData)
{
}

void GeneralCategoryLookupTester::test()
{
#ifdef SB_CONFIG_UNITY
    cout << "Cannot run general category lookup tester in unity mode." << endl;
#else
    cout << "Running general category lookup tester." << endl;

    size_t failCounter = 0;
    string uniGeneralCategory;

    for (uint32_t codePoint = 0; codePoint <= Unicode::MAX_CODE_POINT; codePoint++) {
        m_unicodeData.getGeneralCategory(codePoint, uniGeneralCategory);
        const string &expGeneralCategory = (uniGeneralCategory.length() ? uniGeneralCategory : DEFAULT_GENERAL_CATEGORY);

        SBGeneralCategory valGeneralCategory = SBGeneralCategoryDetermine(codePoint);
        const string &genGeneralCategory = Convert::generalCategoryToString(valGeneralCategory);

        if (genGeneralCategory != expGeneralCategory) {
            if (Configuration::DISPLAY_ERROR_DETAILS) {
                cout << "Invalid general category found: " << endl
                     << "  Code Point: " << codePoint << endl
                     << "  Expected General Category: " << expGeneralCategory << endl
                     << "  Generated General Category: " << genGeneralCategory << endl;
            }

            failCounter++;
        }
    }

    cout << failCounter << " error/s." << endl;
    cout << endl;
#endif
}
<|endoftext|>


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

  Program:   gdcm
  Module:    gdcmPixelWriteConvert.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
  l'Image). All rights reserved. See Doc/License.txt or
  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

#include "gdcmDebug.h"
#include "gdcmPixelWriteConvert.h"
#include "gdcmFile.h"
#include "gdcmUtil.h"

#include <vector>

#define WITHOFFSETTABLE 1

namespace gdcm
{
//-----------------------------------------------------------------------------
// Constructor / Destructor
/**
 * \brief Constructor
 */
PixelWriteConvert::PixelWriteConvert()
{
   ReadData     = 0;
   ReadDataSize = 0;

   UserData     = 0;
   UserDataSize = 0;
   Compressed   = false;
}

/**
 * \brief Destructor
 */
PixelWriteConvert::~PixelWriteConvert()
{
   if( Compressed )
     {
     delete[] UserData;
     }
}

//-----------------------------------------------------------------------------
// Public
/**
 * \brief   sets Read Data (and size)
 * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
 *                     just cast the pointer for calling the method)
 * @param   size data size, in bytes
 */
void PixelWriteConvert::SetReadData(uint8_t *data, size_t size)
{
   ReadData = data;
   ReadDataSize = size;
}

/**
 * \brief   Sets the internal pointer to the caller's inData
 *          image representation, BUT WITHOUT COPYING THE DATA.
 *          - 'image' Pixels are presented as C-like 2D arrays : line per line.
 *          - 'volume'Pixels are presented as C-like 3D arrays : plane per plane
 * \warning Since the pixels are not copied, it is the caller's responsability
 *          not to deallocate its data before gdcm uses them (e.g. with
 *          the Write() method )
 * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
 *                     just cast the pointer for calling the method)
 * @param   size size, in bytes.
 */
void PixelWriteConvert::SetUserData(uint8_t *data, size_t size)
{
   UserData = data;
   UserDataSize = size;
}

/**
 * \brief   Get Data (UserData or ReadData)
 * @return  data (uint8_t is for prototyping. if your data is
 *                    *not* uint8_t, just cast the returned pointer)
 */
uint8_t *PixelWriteConvert::GetData()
{
   if ( UserData )
   {
      return UserData;
   }
   else
   {
      return ReadData;
   }
}

/**
 * \brief   Get Data Size (UserData or ReadData)
 * @return  size, in bytes.
 */
size_t PixelWriteConvert::GetDataSize()
{
   if ( UserData )
   {
      return UserDataSize;
   }
   else
   {
      return ReadDataSize;
   }
}

typedef std::pair<size_t, uint32_t> JpegPair; //offset, jpeg size
typedef std::vector<JpegPair> JpegVector;

bool gdcm_write_JPEG2000_file (std::ostream *of, char *inputdata, size_t inputlength,
  int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated,
  int sign, int quality);

void WriteDICOMItems(std::ostream *fp, JpegVector &v)
{
  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t dummy = 0x12345678;
  size_t offset = fp->tellp();
  JpegPair jp;
  jp.first = offset;
  v.push_back(jp);
  gdcm::binary_write(*fp, dummy);
}

// PS 3.5, page 66
void EncodeWithoutBasicOffsetTable(std::ostream *fp, int numFrag)// JpegVector& v) //, uint32_t length)
{
  assert( numFrag == 1);

  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t item_length = 0x0000;
  gdcm::binary_write(*fp, item_length);

}

// PS 3.5, page 67
void EncodeWithBasicOffsetTable(std::ostream *fp, int numFrag, size_t &start)
{
  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t item_length = numFrag*4; // sizeof(uint32_t)
  gdcm::binary_write(*fp, item_length);

  // Just prepare the space
  start = fp->tellp(); //to be able to rewind
  for(int i=0; i<numFrag;++i)
    {
    uint32_t dummy = 0x0000;
    gdcm::binary_write(*fp, dummy);
    }
}

void UpdateBasicOffsetTable(std::ostream *fp, JpegVector const &v, size_t pos)
{
  JpegVector::const_iterator i;
  fp->seekp( pos );
  const JpegPair &first = v[0];
  for(i=v.begin(); i!=v.end(); ++i)
    {
    const JpegPair &jp = *i;
    if(i == v.begin() ){ assert( jp.first - first.first == 0); }
    gdcm::binary_write(*fp, jp.first - first.first);
    //std::cerr << "Updating Table:" << jp.first - first.first << std::endl;
    }
}

void UpdateJpegFragmentSize(std::ostream *fp, JpegVector const &v)
{
  JpegVector::const_iterator i;
  for(i= v.begin(); i!=v.end(); ++i)
    {
    const JpegPair &jp = *i;
    fp->seekp( jp.first );
    gdcm::binary_write(*fp, jp.second );
    //std::cerr << "Updating:" << jp.first << "," << jp.second << std::endl;
    }
}

void CloseJpeg(std::ostream *fp, JpegVector &v)
{
  // sequence terminator
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe0dd;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);

  uint32_t length = 0x0;
  gdcm::binary_write(*fp, length);

  // Jpeg is done, now update the frag length
  UpdateJpegFragmentSize(fp, v);
}

// I need to pass the File*. I do not understand how PixelWriteConvert is supposed
// to access this information otherwise
// size can now be computer from File attributes (what an API...)
void PixelWriteConvert::SetCompressJPEG2000UserData(uint8_t *data, size_t size, File *image)
{
  Compressed = true;
  //char * userData = reinterpret_cast<char*>(UserData);

   itksys_ios::ostringstream *of = new itksys_ios::ostringstream();
    int xsize = image->GetXSize();
   int ysize = image->GetYSize();
  int zsize =  image->GetZSize();
    int samplesPerPixel = image->GetSamplesPerPixel();
   //std::cout << "X: " << xsize << std::endl;
   //std::cout << "Y: " << ysize << std::endl;
   //std::cout << "Sample: " << samplesPerPixel << std::endl;
    int bitsallocated = image->GetBitsAllocated();
    int sign = image->IsSignedPixelData();
   unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
    assert( fragment_size*zsize == size );

   JpegVector JpegFragmentSize;
#if WITHOFFSETTABLE
   size_t bots; //basic offset table start
   EncodeWithBasicOffsetTable(of, zsize, bots);
#else
   EncodeWithoutBasicOffsetTable(of, 1);
#endif
   uint8_t *pImageData = data;
   for(int i=0; i<zsize;i++)
     {
     WriteDICOMItems(of, JpegFragmentSize);
     size_t beg = of->tellp();
     gdcm_write_JPEG2000_file(of, (char*)pImageData,size,
       image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
       image->GetBitsAllocated(), sign, 100);
     //userData, UserDataSize);
     //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize,
     //       samplesPerPixel, quality, JpegFragmentSize);
     //assert( !(fragment_size % 2) );
     // Update the JpegVector with offset
     size_t end = of->tellp();
     //static int i = 0;
     JpegPair &jp = JpegFragmentSize[i];
     jp.second = end-beg;
     if( ((end-beg) % 2) )
       {
       of->put( '\0' );
       jp.second += 1;
       }
     assert( !(jp.second % 2) );
     //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
     //++i;
     pImageData += fragment_size;
     }
   CloseJpeg(of, JpegFragmentSize);
#if WITHOFFSETTABLE
   UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
#endif

   size_t of_size = of->str().size();
   UserData = new uint8_t[of_size];
   memcpy(UserData, of->str().c_str(), of_size);
   UserDataSize = of_size;

}

bool gdcm_write_JPEG_file8 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);
bool gdcm_write_JPEG_file12 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);
bool gdcm_write_JPEG_file16 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);

void PixelWriteConvert::SetCompressJPEGUserData(uint8_t *data, size_t size, File *image)
{
  (void)data;
  (void)size;
  (void)image;
  Compressed = true;
  //char * userData = reinterpret_cast<char*>(UserData);

   itksys_ios::ostringstream *of = new itksys_ios::ostringstream();
    int xsize = image->GetXSize();
   int ysize = image->GetYSize();
  int zsize =  image->GetZSize();
    int samplesPerPixel = image->GetSamplesPerPixel();
   //std::cout << "X: " << xsize << std::endl;
   //std::cout << "Y: " << ysize << std::endl;
   //std::cout << "Sample: " << samplesPerPixel << std::endl;
    int bitsallocated = image->GetBitsAllocated();
   unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
    assert( fragment_size*zsize == size );

   JpegVector JpegFragmentSize;
#if WITHOFFSETTABLE
   size_t bots; //basic offset table start
   EncodeWithBasicOffsetTable(of, zsize, bots);
#else
   EncodeWithoutBasicOffsetTable(of, 1);
#endif
   uint8_t *pImageData = data;
   for(int i=0; i<zsize;i++)
     {
     WriteDICOMItems(of, JpegFragmentSize);
  size_t beg = of->tellp();
     if( bitsallocated == 8 )
       {
       gdcm_write_JPEG_file8(of, (char*)pImageData,size,
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100 );
       }
     else if (bitsallocated <= 12)
       {
       assert( bitsallocated >= 8 );
       gdcm_write_JPEG_file12(of, (char*)pImageData,size,
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100);
       }
     else if (bitsallocated <= 16)
       {
       assert( bitsallocated >= 12 );
       gdcm_write_JPEG_file16(of, (char*)pImageData,size,
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100);
       }
     else
       {
       abort();
       }
    size_t end = of->tellp();
    //static int i = 0;
    JpegPair &jp = JpegFragmentSize[i];
      jp.second = end-beg;
    if( ((end-beg) % 2) )
      {
      of->put( '\0' );
      jp.second += 1;
      }
    assert( !(jp.second % 2) );
    //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
    //++i;

  //JpegPair &jp = v[0];
  //jp.second = 15328;

     //userData, UserDataSize);
     //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize,
     //       samplesPerPixel, quality, JpegFragmentSize);
     //assert( !(fragment_size % 2) );
     pImageData += fragment_size;
     }
   CloseJpeg(of, JpegFragmentSize);
#if WITHOFFSETTABLE
   UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
#endif

   size_t of_size = of->str().size();
   UserData = new uint8_t[of_size];
   memcpy(UserData, of->str().c_str(), of_size);
   UserDataSize = of_size;

}

//-----------------------------------------------------------------------------
// Protected
//bool PixelWriteConvert::CompressJPEG2000(uint8_t *data, size_t size)
//{
//}

//-----------------------------------------------------------------------------
// Private

//-----------------------------------------------------------------------------
// Print

//-----------------------------------------------------------------------------
} // end namespace gdcm
<commit_msg>COMP: Fix compilation on some plateform that require explicit cast<commit_after>/*=========================================================================

  Program:   gdcm
  Module:    gdcmPixelWriteConvert.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
  l'Image). All rights reserved. See Doc/License.txt or
  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

#include "gdcmDebug.h"
#include "gdcmPixelWriteConvert.h"
#include "gdcmFile.h"
#include "gdcmUtil.h"

#include <vector>

#define WITHOFFSETTABLE 1

namespace gdcm
{
//-----------------------------------------------------------------------------
// Constructor / Destructor
/**
 * \brief Constructor
 */
PixelWriteConvert::PixelWriteConvert()
{
   ReadData     = 0;
   ReadDataSize = 0;

   UserData     = 0;
   UserDataSize = 0;
   Compressed   = false;
}

/**
 * \brief Destructor
 */
PixelWriteConvert::~PixelWriteConvert()
{
   if( Compressed )
     {
     delete[] UserData;
     }
}

//-----------------------------------------------------------------------------
// Public
/**
 * \brief   sets Read Data (and size)
 * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
 *                     just cast the pointer for calling the method)
 * @param   size data size, in bytes
 */
void PixelWriteConvert::SetReadData(uint8_t *data, size_t size)
{
   ReadData = data;
   ReadDataSize = size;
}

/**
 * \brief   Sets the internal pointer to the caller's inData
 *          image representation, BUT WITHOUT COPYING THE DATA.
 *          - 'image' Pixels are presented as C-like 2D arrays : line per line.
 *          - 'volume'Pixels are presented as C-like 3D arrays : plane per plane
 * \warning Since the pixels are not copied, it is the caller's responsability
 *          not to deallocate its data before gdcm uses them (e.g. with
 *          the Write() method )
 * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
 *                     just cast the pointer for calling the method)
 * @param   size size, in bytes.
 */
void PixelWriteConvert::SetUserData(uint8_t *data, size_t size)
{
   UserData = data;
   UserDataSize = size;
}

/**
 * \brief   Get Data (UserData or ReadData)
 * @return  data (uint8_t is for prototyping. if your data is
 *                    *not* uint8_t, just cast the returned pointer)
 */
uint8_t *PixelWriteConvert::GetData()
{
   if ( UserData )
   {
      return UserData;
   }
   else
   {
      return ReadData;
   }
}

/**
 * \brief   Get Data Size (UserData or ReadData)
 * @return  size, in bytes.
 */
size_t PixelWriteConvert::GetDataSize()
{
   if ( UserData )
   {
      return UserDataSize;
   }
   else
   {
      return ReadDataSize;
   }
}

typedef std::pair<size_t, uint32_t> JpegPair; //offset, jpeg size
typedef std::vector<JpegPair> JpegVector;

bool gdcm_write_JPEG2000_file (std::ostream *of, char *inputdata, size_t inputlength,
  int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated,
  int sign, int quality);

void WriteDICOMItems(std::ostream *fp, JpegVector &v)
{
  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t dummy = 0x12345678;
  size_t offset = fp->tellp();
  JpegPair jp;
  jp.first = offset;
  v.push_back(jp);
  gdcm::binary_write(*fp, dummy);
}

// PS 3.5, page 66
void EncodeWithoutBasicOffsetTable(std::ostream *fp, int numFrag)// JpegVector& v) //, uint32_t length)
{
  assert( numFrag == 1);

  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t item_length = 0x0000;
  gdcm::binary_write(*fp, item_length);

}

// PS 3.5, page 67
void EncodeWithBasicOffsetTable(std::ostream *fp, int numFrag, size_t &start)
{
  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t item_length = numFrag*4; // sizeof(uint32_t)
  gdcm::binary_write(*fp, item_length);

  // Just prepare the space
  start = fp->tellp(); //to be able to rewind
  for(int i=0; i<numFrag;++i)
    {
    uint32_t dummy = 0x0000;
    gdcm::binary_write(*fp, dummy);
    }
}

void UpdateBasicOffsetTable(std::ostream *fp, JpegVector const &v, size_t pos)
{
  JpegVector::const_iterator i;
  fp->seekp( pos );
  const JpegPair &first = v[0];
  for(i=v.begin(); i!=v.end(); ++i)
    {
    const JpegPair &jp = *i;
    if(i == v.begin() ){ assert( jp.first - first.first == 0); }
    uint32_t offset = jp.first - first.first;
    gdcm::binary_write(*fp, offset);
    //std::cerr << "Updating Table:" << jp.first - first.first << std::endl;
    }
}

void UpdateJpegFragmentSize(std::ostream *fp, JpegVector const &v)
{
  JpegVector::const_iterator i;
  for(i= v.begin(); i!=v.end(); ++i)
    {
    const JpegPair &jp = *i;
    fp->seekp( jp.first );
    uint32_t length = jp.second;
    gdcm::binary_write(*fp, length);
    //std::cerr << "Updating:" << jp.first << "," << jp.second << std::endl;
    }
}

void CloseJpeg(std::ostream *fp, JpegVector &v)
{
  // sequence terminator
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe0dd;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);

  uint32_t length = 0x0;
  gdcm::binary_write(*fp, length);

  // Jpeg is done, now update the frag length
  UpdateJpegFragmentSize(fp, v);
}

// I need to pass the File*. I do not understand how PixelWriteConvert is supposed
// to access this information otherwise
// size can now be computer from File attributes (what an API...)
void PixelWriteConvert::SetCompressJPEG2000UserData(uint8_t *data, size_t size, File *image)
{
  Compressed = true;
  //char * userData = reinterpret_cast<char*>(UserData);

   itksys_ios::ostringstream *of = new itksys_ios::ostringstream();
    int xsize = image->GetXSize();
   int ysize = image->GetYSize();
  int zsize =  image->GetZSize();
    int samplesPerPixel = image->GetSamplesPerPixel();
   //std::cout << "X: " << xsize << std::endl;
   //std::cout << "Y: " << ysize << std::endl;
   //std::cout << "Sample: " << samplesPerPixel << std::endl;
    int bitsallocated = image->GetBitsAllocated();
    int sign = image->IsSignedPixelData();
   unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
    assert( fragment_size*zsize == size );

   JpegVector JpegFragmentSize;
#if WITHOFFSETTABLE
   size_t bots; //basic offset table start
   EncodeWithBasicOffsetTable(of, zsize, bots);
#else
   EncodeWithoutBasicOffsetTable(of, 1);
#endif
   uint8_t *pImageData = data;
   for(int i=0; i<zsize;i++)
     {
     WriteDICOMItems(of, JpegFragmentSize);
     size_t beg = of->tellp();
     gdcm_write_JPEG2000_file(of, (char*)pImageData,size,
       image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
       image->GetBitsAllocated(), sign, 100);
     //userData, UserDataSize);
     //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize,
     //       samplesPerPixel, quality, JpegFragmentSize);
     //assert( !(fragment_size % 2) );
     // Update the JpegVector with offset
     size_t end = of->tellp();
     //static int i = 0;
     JpegPair &jp = JpegFragmentSize[i];
     jp.second = end-beg;
     if( ((end-beg) % 2) )
       {
       of->put( '\0' );
       jp.second += 1;
       }
     assert( !(jp.second % 2) );
     //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
     //++i;
     pImageData += fragment_size;
     }
   CloseJpeg(of, JpegFragmentSize);
#if WITHOFFSETTABLE
   UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
#endif

   size_t of_size = of->str().size();
   UserData = new uint8_t[of_size];
   memcpy(UserData, of->str().c_str(), of_size);
   UserDataSize = of_size;

}

bool gdcm_write_JPEG_file8 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);
bool gdcm_write_JPEG_file12 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);
bool gdcm_write_JPEG_file16 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);

void PixelWriteConvert::SetCompressJPEGUserData(uint8_t *data, size_t size, File *image)
{
  (void)data;
  (void)size;
  (void)image;
  Compressed = true;
  //char * userData = reinterpret_cast<char*>(UserData);

   itksys_ios::ostringstream *of = new itksys_ios::ostringstream();
    int xsize = image->GetXSize();
   int ysize = image->GetYSize();
  int zsize =  image->GetZSize();
    int samplesPerPixel = image->GetSamplesPerPixel();
   //std::cout << "X: " << xsize << std::endl;
   //std::cout << "Y: " << ysize << std::endl;
   //std::cout << "Sample: " << samplesPerPixel << std::endl;
    int bitsallocated = image->GetBitsAllocated();
   unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
    assert( fragment_size*zsize == size );

   JpegVector JpegFragmentSize;
#if WITHOFFSETTABLE
   size_t bots; //basic offset table start
   EncodeWithBasicOffsetTable(of, zsize, bots);
#else
   EncodeWithoutBasicOffsetTable(of, 1);
#endif
   uint8_t *pImageData = data;
   for(int i=0; i<zsize;i++)
     {
     WriteDICOMItems(of, JpegFragmentSize);
  size_t beg = of->tellp();
     if( bitsallocated == 8 )
       {
       gdcm_write_JPEG_file8(of, (char*)pImageData,size,
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100 );
       }
     else if (bitsallocated <= 12)
       {
       assert( bitsallocated >= 8 );
       gdcm_write_JPEG_file12(of, (char*)pImageData,size,
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100);
       }
     else if (bitsallocated <= 16)
       {
       assert( bitsallocated >= 12 );
       gdcm_write_JPEG_file16(of, (char*)pImageData,size,
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100);
       }
     else
       {
       abort();
       }
    size_t end = of->tellp();
    //static int i = 0;
    JpegPair &jp = JpegFragmentSize[i];
      jp.second = end-beg;
    if( ((end-beg) % 2) )
      {
      of->put( '\0' );
      jp.second += 1;
      }
    assert( !(jp.second % 2) );
    //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
    //++i;

  //JpegPair &jp = v[0];
  //jp.second = 15328;

     //userData, UserDataSize);
     //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize,
     //       samplesPerPixel, quality, JpegFragmentSize);
     //assert( !(fragment_size % 2) );
     pImageData += fragment_size;
     }
   CloseJpeg(of, JpegFragmentSize);
#if WITHOFFSETTABLE
   UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
#endif

   size_t of_size = of->str().size();
   UserData = new uint8_t[of_size];
   memcpy(UserData, of->str().c_str(), of_size);
   UserDataSize = of_size;

}

//-----------------------------------------------------------------------------
// Protected
//bool PixelWriteConvert::CompressJPEG2000(uint8_t *data, size_t size)
//{
//}

//-----------------------------------------------------------------------------
// Private

//-----------------------------------------------------------------------------
// Print

//-----------------------------------------------------------------------------
} // end namespace gdcm
<|endoftext|>


<commit_before>/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gluonobject.h"
#include "gluonobjectprivate.h"
#include "gameproject.h"

#include <QtCore/QVariant>
#include <QtCore/QPointF>
#include <QtGui/QColor>
#include <Eigen/Geometry>
#include <QtCore/QDebug>
#include <QMetaClassInfo>

using namespace Gluon;

REGISTER_OBJECTTYPE(GluonObject)

GluonObject::GluonObject(QObject * parent)
{
    d = new GluonObjectPrivate();
}

GluonObject::~GluonObject()
{
}

GluonObject *
GluonObject::instantiate()
{
    if(QString(this->metaObject()->className()) != QString("Gluon::GluonObject"))
        qDebug() << "Missing instantiate() implementation in" << this->metaObject()->className();
    return new GluonObject(this);
}

void
GluonObject::sanitize()
{
    GluonObject * theChild = 0;
    foreach(QObject * child, this->children())
    {
        if(child->inherits("GluonObject"))
        {
            theChild = qobject_cast<GluonObject*>(child);
            theChild->sanitize();
        }
    }

    // Make sure the GameProject is set... Iterate upwards until you either reach
    // the first GameProject instance, or you run into a parent which is null
    QObject * currentParent = this->parent();
    while(currentParent)
    {
        if(qobject_cast<GameProject*>(currentParent))
        {
            setGameProject(qobject_cast<GameProject*>(currentParent));
            break;
        }
        currentParent = currentParent->parent();
    }

    // Run through all properties, check whether they are set to the correct
    // value. If they should be pointing to something, make them!
    // (e.g. GameObject(Projectname.Something))
    // This step is only possible if a gameProject is available. Otherwise
    // you will be unable to find the other objects!
    if(gameProject())
    {
        QStringList objectTypeNames = GluonObjectFactory::instance()->objectTypeNames();

        qDebug() << "Sanitizing properties in" << this->name();
        const QMetaObject *metaobject = this->metaObject();
        if(metaobject == NULL)
            return;
        int count = metaobject->propertyCount();
        for(int i = 0; i < count; ++i)
        {
            QMetaProperty metaproperty = metaobject->property(i);

            // This is really only relevant if the property value is a string.
            // If it is not, what happens below is irrelevant
            if(metaproperty.type() != QVariant::String)
                continue;

            const QString theName(metaproperty.name());
            if(theName == "objectName" || theName == "name")
                continue;

            QString theValue(metaproperty.read(this).toString());
            // Yes, i know this is O(n*m) but it does not happen during gameplay
            foreach(const QString &name, objectTypeNames)
            {
                // Reset the value of this property to be a reference to GluonObjct
                // instance by that name, found in the project
                if(theValue.startsWith(name + '(') && theValue.endsWith(')'))
                {
                    QString theReferencedName = theValue.mid(name.length() + 2, theValue.length() - (name.length() + 3));
                    QVariant theReferencedObject;
                    theReferencedObject.setValue<GluonObject*>(gameProject()->findItemByName(theReferencedName));
                    this->setProperty(metaproperty.name(), theReferencedObject);
                    break;
                }
            }
        }

        // Then get all the dynamic ones (in case any such exist)
        QList<QByteArray> propertyNames = dynamicPropertyNames();
        foreach(QByteArray propName, propertyNames)
        {
            const QString theName(propName);
            if(theName == "objectName" || theName == "name")
                continue;

            // This is really only relevant if the property value is a string.
            // If it is not, what happens below is irrelevant
            if(property(propName).type() != QVariant::String)
                continue;

            QString theValue(property(propName).toString());
            // Yes, i know this is O(n*m) but it does not happen during gameplay
            foreach(const QString &name, objectTypeNames)
            {
                // Reset the value of this property to be a reference to GluonObjct
                // instance by that name, found in the project
                if(theValue.startsWith(name + '(') && theValue.endsWith(')'))
                {
                    QString theReferencedName = theValue.mid(name.length() + 2, theValue.length() - (name.length() + 3));
                    QVariant theReferencedObject;
                    theReferencedObject.setValue<GluonObject*>(gameProject()->findItemByName(theReferencedName));
                    this->setProperty(propName, theReferencedObject);
                    break;
                }
            }
        }
    }
}

GameProject *
GluonObject::gameProject() const
{
    return d->gameProject;
}

void
GluonObject::setGameProject(GameProject * newGameProject)
{
    d->gameProject = newGameProject;
}

QString
GluonObject::name() const
{
    return d->name;
}

void
GluonObject::setName(const QString &newName)
{
    d->name = newName;
}

QString
GluonObject::toGDL(int indentLevel) const
{
    QString serializedObject;
    qDebug() << "Serializing object named" << this->name();

    QString indentChars(indentLevel * 4, ' ');

    // Only jump to net line in case we are inside another object
    if(indentLevel > 0)
        serializedObject += '\n';

    QString minimalClassName(this->metaObject()->className());
    if(QString(this->metaObject()->className()).startsWith(QString("Gluon::")))
        minimalClassName = minimalClassName.right(minimalClassName.length() - 7);
    serializedObject += QString("%1{ %2(%3)").arg(indentChars).arg(minimalClassName).arg(this->name());

    serializedObject += propertiesToGDL(indentLevel + 1);

    // Run through all the children to get them as well
    foreach(QObject* child, children())
    {
        GluonObject* theChild = qobject_cast<GluonObject*>(child);
        if(theChild)
            serializedObject += theChild->toGDL(indentLevel + 1);
    }

    return QString("%1\n%2}").arg(serializedObject).arg(indentChars);
}

QString
GluonObject::propertiesToGDL(int indentLevel) const
{
    QString serializedObject;

    QString indentChars(indentLevel * 4, ' ');

    // Get all the normally defined properties
    const QMetaObject *metaobject = this->metaObject();
    int count = metaobject->propertyCount();
    for(int i = 0; i < count; ++i)
    {
        QMetaProperty metaproperty = metaobject->property(i);
        const QString theName(metaproperty.name());
        if(theName == "objectName" || theName == "name")
            continue;
        serializedObject += this->getStringFromProperty(theName, indentChars);
    }

    // Then get all the dynamic ones (in case any such exist)
    QList<QByteArray> propertyNames = dynamicPropertyNames();
    foreach(QByteArray propName, propertyNames)
    {
        const QString theName(propName);
        serializedObject += this->getStringFromProperty(theName, indentChars);
    }

    return serializedObject;
}

void
GluonObject::setPropertyFromString(const QString &propertyName, const QString &propertyValue)
{
    QVariant value;

    // propertyValue format is type(value)
    QRegExp rx("(\\w+)\\((.+)\\)");
    int pos = rx.indexIn(propertyValue);

    QString theTypeName = rx.cap(1);
    QString theValue = rx.cap(2);
    qDebug() << "  Setting property" << propertyName << "of type" << theTypeName << "to value" << theValue;

    if(theTypeName == "string") {
        value = theValue;
    } else if(theTypeName == "bool") {
        value = theValue.toFloat();
    } else if(theTypeName == "float") {
        value = theValue.toFloat();
    } else if(theTypeName == "int") {
        value = theValue.toInt();
    } else if(theTypeName == "vector2d") {
        float x = 0.0f, y = 0.0f;
        //, z = 0.0f;
        QStringList splitValues = theValue.split(";");
        if(splitValues.length() > 0)
        {
            x = splitValues.at(0).toFloat();
            y = splitValues.at(1).toFloat();
            //z = splitValues.at(2).toFloat();
        }
        value = QPointF(x, y);
    } else if(theTypeName == "rgba") {
        int r = 0, g = 0, b = 0, a = 0;
        QStringList splitValues = theValue.split(";");
        if(splitValues.length() > 0)
            r = splitValues[0].toInt();
        if(splitValues.length() > 1)
            g = splitValues[1].toInt();
        if(splitValues.length() > 2)
            b = splitValues[2].toInt();
        if(splitValues.length() > 3)
            a = splitValues[3].toInt();
        value = QColor(r, g, b, a);
    } else {
        // If all else fails, pass the value through verbatim
        value = propertyValue;
    }

    this->setProperty(propertyName.toUtf8(), value);
}

QString
GluonObject::getStringFromProperty(const QString &propertyName, const QString &indentChars) const
{
    QString value;

    QVariant theValue = this->property(propertyName.toUtf8());

    QColor theColor;
    switch(theValue.type())
    {
        case QVariant::String:
            value = "string(" + theValue.toString() + ')';
            break;
        case QVariant::Bool:
            value = QString("bool(%1)").arg(theValue.toBool());
            break;
        case QVariant::Double:
            value = QString("float(%1)").arg(theValue.toDouble());
            break;
        case QVariant::Int:
            value = QString("int(%1)").arg(theValue.toInt());
            break;
        case QVariant::PointF:
            value = QString("vector2d(%1;%2)").arg(theValue.toPointF().x()).arg(theValue.toPointF().y());
            break;
        case QVariant::Color:
            theColor = theValue.value<QColor>();
            value = QString("rgba(%1;%2;%3;%4)").arg(theColor.red()).arg(theColor.green()).arg(theColor.blue()).arg(theColor.alpha());
            break;
        default:
            value = theValue.toString();
            break;
    }

    if(value.isEmpty())
        return QString();

    return QString("\n%1%2 %3").arg(indentChars).arg(propertyName).arg(value);
}

#include "gluonobject.moc"
<commit_msg>Debug++<commit_after>/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gluonobject.h"
#include "gluonobjectprivate.h"
#include "gameproject.h"

#include <QtCore/QVariant>
#include <QtCore/QPointF>
#include <QtGui/QColor>
#include <Eigen/Geometry>
#include <QtCore/QDebug>
#include <QMetaClassInfo>

using namespace Gluon;

REGISTER_OBJECTTYPE(GluonObject)

GluonObject::GluonObject(QObject * parent)
{
    d = new GluonObjectPrivate();
}

GluonObject::~GluonObject()
{
}

GluonObject *
GluonObject::instantiate()
{
    if(QString(this->metaObject()->className()) != QString("Gluon::GluonObject"))
        qDebug() << "Missing instantiate() implementation in" << this->metaObject()->className();
    return new GluonObject(this);
}

void
GluonObject::sanitize()
{
    GluonObject * theChild = 0;
    foreach(QObject * child, this->children())
    {
        if(child->inherits("GluonObject"))
        {
            theChild = qobject_cast<GluonObject*>(child);
            theChild->sanitize();
        }
    }

    // Make sure the GameProject is set... Iterate upwards until you either reach
    // the first GameProject instance, or you run into a parent which is null
    QObject * currentParent = this->parent();
    while(currentParent)
    {
        if(qobject_cast<GameProject*>(currentParent))
        {
            setGameProject(qobject_cast<GameProject*>(currentParent));
            break;
        }
        currentParent = currentParent->parent();
    }

    // Run through all properties, check whether they are set to the correct
    // value. If they should be pointing to something, make them!
    // (e.g. GameObject(Projectname.Something))
    // This step is only possible if a gameProject is available. Otherwise
    // you will be unable to find the other objects!
    if(gameProject())
    {
        QStringList objectTypeNames = GluonObjectFactory::instance()->objectTypeNames();

        qDebug() << "Sanitizing properties in" << this->name();
        const QMetaObject *metaobject = this->metaObject();
        if(metaobject == NULL)
            return;
        int count = metaobject->propertyCount();
        for(int i = 0; i < count; ++i)
        {
            QMetaProperty metaproperty = metaobject->property(i);

            // This is really only relevant if the property value is a string.
            // If it is not, what happens below is irrelevant
            if(metaproperty.type() != QVariant::String)
                continue;

            const QString theName(metaproperty.name());
            if(theName == "objectName" || theName == "name")
                continue;

            QString theValue(metaproperty.read(this).toString());
            // Yes, i know this is O(n*m) but it does not happen during gameplay
            foreach(const QString &name, objectTypeNames)
            {
                // Reset the value of this property to be a reference to GluonObjct
                // instance by that name, found in the project
                if(theValue.startsWith(name + '(') && theValue.endsWith(')'))
                {
                    QString theReferencedName = theValue.mid(name.length() + 2, theValue.length() - (name.length() + 3));
                    QVariant theReferencedObject;
                    theReferencedObject.setValue<GluonObject*>(gameProject()->findItemByName(theReferencedName));
                    this->setProperty(metaproperty.name(), theReferencedObject);
                    qDebug() << "Set the property" << metaproperty.name() << "to reference the object" << theReferencedName << "of type" << name;
                    break;
                }
            }
        }

        // Then get all the dynamic ones (in case any such exist)
        QList<QByteArray> propertyNames = dynamicPropertyNames();
        foreach(QByteArray propName, propertyNames)
        {
            const QString theName(propName);
            if(theName == "objectName" || theName == "name")
                continue;

            // This is really only relevant if the property value is a string.
            // If it is not, what happens below is irrelevant
            if(property(propName).type() != QVariant::String)
                continue;

            QString theValue(property(propName).toString());
            // Yes, i know this is O(n*m) but it does not happen during gameplay
            foreach(const QString &name, objectTypeNames)
            {
                // Reset the value of this property to be a reference to GluonObjct
                // instance by that name, found in the project
                if(theValue.startsWith(name + '(') && theValue.endsWith(')'))
                {
                    QString theReferencedName = theValue.mid(name.length() + 2, theValue.length() - (name.length() + 3));
                    QVariant theReferencedObject;
                    theReferencedObject.setValue<GluonObject*>(gameProject()->findItemByName(theReferencedName));
                    this->setProperty(propName, theReferencedObject);
                    break;
                }
            }
        }
    }
}

GameProject *
GluonObject::gameProject() const
{
    return d->gameProject;
}

void
GluonObject::setGameProject(GameProject * newGameProject)
{
    d->gameProject = newGameProject;
}

QString
GluonObject::name() const
{
    return d->name;
}

void
GluonObject::setName(const QString &newName)
{
    d->name = newName;
}

QString
GluonObject::toGDL(int indentLevel) const
{
    QString serializedObject;
    qDebug() << "Serializing object named" << this->name();

    QString indentChars(indentLevel * 4, ' ');

    // Only jump to net line in case we are inside another object
    if(indentLevel > 0)
        serializedObject += '\n';

    QString minimalClassName(this->metaObject()->className());
    if(QString(this->metaObject()->className()).startsWith(QString("Gluon::")))
        minimalClassName = minimalClassName.right(minimalClassName.length() - 7);
    serializedObject += QString("%1{ %2(%3)").arg(indentChars).arg(minimalClassName).arg(this->name());

    serializedObject += propertiesToGDL(indentLevel + 1);

    // Run through all the children to get them as well
    foreach(QObject* child, children())
    {
        GluonObject* theChild = qobject_cast<GluonObject*>(child);
        if(theChild)
            serializedObject += theChild->toGDL(indentLevel + 1);
    }

    return QString("%1\n%2}").arg(serializedObject).arg(indentChars);
}

QString
GluonObject::propertiesToGDL(int indentLevel) const
{
    QString serializedObject;

    QString indentChars(indentLevel * 4, ' ');

    // Get all the normally defined properties
    const QMetaObject *metaobject = this->metaObject();
    int count = metaobject->propertyCount();
    for(int i = 0; i < count; ++i)
    {
        QMetaProperty metaproperty = metaobject->property(i);
        const QString theName(metaproperty.name());
        if(theName == "objectName" || theName == "name")
            continue;
        serializedObject += this->getStringFromProperty(theName, indentChars);
    }

    // Then get all the dynamic ones (in case any such exist)
    QList<QByteArray> propertyNames = dynamicPropertyNames();
    foreach(QByteArray propName, propertyNames)
    {
        const QString theName(propName);
        serializedObject += this->getStringFromProperty(theName, indentChars);
    }

    return serializedObject;
}

void
GluonObject::setPropertyFromString(const QString &propertyName, const QString &propertyValue)
{
    QVariant value;

    // propertyValue format is type(value)
    QRegExp rx("(\\w+)\\((.+)\\)");
    int pos = rx.indexIn(propertyValue);

    QString theTypeName = rx.cap(1);
    QString theValue = rx.cap(2);
    qDebug() << "  Setting property" << propertyName << "of type" << theTypeName << "to value" << theValue;

    if(theTypeName == "string") {
        value = theValue;
    } else if(theTypeName == "bool") {
        value = theValue.toFloat();
    } else if(theTypeName == "float") {
        value = theValue.toFloat();
    } else if(theTypeName == "int") {
        value = theValue.toInt();
    } else if(theTypeName == "vector2d") {
        float x = 0.0f, y = 0.0f;
        //, z = 0.0f;
        QStringList splitValues = theValue.split(";");
        if(splitValues.length() > 0)
        {
            x = splitValues.at(0).toFloat();
            y = splitValues.at(1).toFloat();
            //z = splitValues.at(2).toFloat();
        }
        value = QPointF(x, y);
    } else if(theTypeName == "rgba") {
        int r = 0, g = 0, b = 0, a = 0;
        QStringList splitValues = theValue.split(";");
        if(splitValues.length() > 0)
            r = splitValues[0].toInt();
        if(splitValues.length() > 1)
            g = splitValues[1].toInt();
        if(splitValues.length() > 2)
            b = splitValues[2].toInt();
        if(splitValues.length() > 3)
            a = splitValues[3].toInt();
        value = QColor(r, g, b, a);
    } else {
        // If all else fails, pass the value through verbatim
        value = propertyValue;
    }

    this->setProperty(propertyName.toUtf8(), value);
}

QString
GluonObject::getStringFromProperty(const QString &propertyName, const QString &indentChars) const
{
    QString value;

    QVariant theValue = this->property(propertyName.toUtf8());

    QColor theColor;
    switch(theValue.type())
    {
        case QVariant::String:
            value = "string(" + theValue.toString() + ')';
            break;
        case QVariant::Bool:
            value = QString("bool(%1)").arg(theValue.toBool());
            break;
        case QVariant::Double:
            value = QString("float(%1)").arg(theValue.toDouble());
            break;
        case QVariant::Int:
            value = QString("int(%1)").arg(theValue.toInt());
            break;
        case QVariant::PointF:
            value = QString("vector2d(%1;%2)").arg(theValue.toPointF().x()).arg(theValue.toPointF().y());
            break;
        case QVariant::Color:
            theColor = theValue.value<QColor>();
            value = QString("rgba(%1;%2;%3;%4)").arg(theColor.red()).arg(theColor.green()).arg(theColor.blue()).arg(theColor.alpha());
            break;
        default:
            value = theValue.toString();
            break;
    }

    if(value.isEmpty())
        return QString();

    return QString("\n%1%2 %3").arg(indentChars).arg(propertyName).arg(value);
}

#include "gluonobject.moc"
<|endoftext|>


<commit_before>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 unsigned long long times[100];
 int f = 0;
 for (int i=0; i<100; i++)
  times[i] = 0;

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];
 unsigned long long timenow = getMilliseconds();

 while (keepGoing) {
  image = cvQueryFrame(capture);
  times[0] += getMilliseconds() - timenow;
  timenow = getMilliseconds();
// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));
  times[1] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask filters out areas with too many edges
// removed for now; it didn't generalize well
/*
  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 200, 1, THRESH_BINARY);
  blur(canny*255, canny, Size(width/10, height/10));
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny mask", gray.mul(canny));
*/

// this mask filters out areas which have not changed much
// background needs to be updated when person is not in frame
// use OVR SDK to do this later
  Mat flow;
  absdiff(blurred_img, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  morphFast(flow);
  threshold(flow, flow, 60, 1, THRESH_BINARY);
  imshow("flow mask", gray.mul(flow));
  times[2] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets anything kind of dark (DK2) and dilates
  Mat kindofdark;
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
  imshow("dark mask", gray.mul(kindofdark));
  times[3] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets rid of anything far away from red stuff
// did not work well and was slow
/*
  Mat notlips;
  Mat channels[3];
  split(image, channels);
  channels[2].convertTo(notlips, CV_32FC1);
  divide(notlips, gray, notlips, 1, CV_32FC1);
  //equalistHist is horrible for a red background
  //equalizeHist(notlips, notlips);
  threshold(notlips, notlips, tracker3/30.0, 1, THRESH_BINARY);
  notlips.convertTo(notlips, CV_8UC1);
  imshow("lip mask", notlips*255);
  Mat otherMorph = notlips.clone();
  int tx = tracker1+1-(tracker1%2);
  if (tx<3) tx=1;
  if (tx>90) tx=91;
  morphFast(notlips, 100, tx, 0, 0);
  int ty = tracker2+1-(tracker2%2);
  if (ty<3) ty=1;
  if (ty>90) ty=91;
  morphFast(notlips, 100, ty, 0, 1);
  imshow("lips2", notlips.mul(gray));
  morphFast(otherMorph, 100, tx, 0, 1);
  morphFast(otherMorph, 100, tx, 0, 0);
  imshow("lips3", otherMorph.mul(gray));
  waitKey(1);
*/

  Mat mask = flow.mul(kindofdark);
// open the mask
  Mat smallMask0, smallMask1;
  resize(mask, smallMask0, Size(width/5,height/5));
  Mat erodeKernel = ellipticKernel(79,79);
  erode(smallMask0, smallMask1, erodeKernel);
  Mat dilateKernel = ellipticKernel(69,69);
//69,79
  dilate(smallMask1, smallMask1, dilateKernel);
  bitwise_and(smallMask0, smallMask1, smallMask1);
  resize(smallMask1, mask, Size(width, height));
  imshow("morph mask", gray.mul(mask));
  times[4] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// update background with new morph mask
// average what we know is background with prior background
// erode it first since we really want to be sure it's bg

  Mat erodedMask;
  erode(smallMask1, erodedMask, erodeKernel);
  resize(erodedMask, erodedMask, Size(width, height));
  imshow("erosion", erodedMask.mul(gray));
  Mat mask_;
  subtract(1,erodedMask,mask_);
  Mat mask3, mask3_;
  channel[0] = erodedMask;
  channel[1] = erodedMask;
  channel[2] = erodedMask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_)/2 + blurred_img.mul(mask3_)/2);
  times[5] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

  imshow("background", background);

/*
  Moments lol = moments(gray, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);
*/

/*
  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  int scale = 3;
  Mat classifyThis;
  equalizeHist(gray, gray);//ew; watch out not to use this later
  resize(gray.mul(mask), classifyThis, Size(width/scale,height/scale));
//  bilateralFilter(gray, classifyThis, 15, 10, 1);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  for (size_t i=0; i<mouths.size(); i++) {
   Rect scaled(mouths[i].x*scale, mouths[i].y*scale, mouths[i].width*scale,mouths[i].height*scale);
   rectangle(image, scaled, Scalar(255,0,0));
  }
  imshow("MOUTH", image);
*/

  for (int i=0; i<6; i++) {
   printf("%llu , ", times[i]);
   times[i] = 0;
  }

  printf("\n");

  keepGoing = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

void morphFast(Mat inout, int smallsize = 100, int factor = 25, int eq = 1, int diler = 0) {
 int width, height;
 width = inout.size().width;
 height = inout.size().height;
 Mat downsample;
 resize(inout, downsample, Size(smallsize,smallsize));
 Mat kernel = ellipticKernel(factor);
 if (diler) {
  erode(downsample, downsample, kernel);
 } else {
  dilate(downsample, downsample, kernel);
 }
 if (eq) {
  equalizeHist(downsample, downsample);
 }
 resize(downsample, inout, Size(width, height));
}

int main (int argc, char** argv) {

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 unsigned long long times[100];
 int f = 0;
 for (int i=0; i<100; i++)
  times[i] = 0;

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

 Mat background = cvQueryFrame(capture);
 background = background.clone();
 blur(background, background, Size(50,50));

 Mat image;
 Mat channel[3];
 unsigned long long timenow = getMilliseconds();

 while (keepGoing) {
  image = cvQueryFrame(capture);
  times[0] += getMilliseconds() - timenow;
  timenow = getMilliseconds();
// preprocess by rotating according to OVR roll
//  imshow("webcam", image);

// let's make multiple masks where 0=not mouth, 1=uncertain

// then multiply them together and multiply that with image
// and run haar classifier on image

  Mat gray, blurred_img;
  cvtColor(image, gray, CV_RGB2GRAY);
  blur(image, blurred_img, Size(50,50));
  times[1] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask filters out areas with too many edges
// removed for now; it didn't generalize well
/*
  Mat canny;
  Canny(gray, canny, 50, 50, 3);
  blur(canny, canny, Size(width/20,height/20));
  bitwise_not(canny, canny);
  threshold(canny, canny, 200, 1, THRESH_BINARY);
  blur(canny*255, canny, Size(width/10, height/10));
  threshold(canny, canny, 220, 1, THRESH_BINARY);
  imshow("canny mask", gray.mul(canny));
*/

// this mask filters out areas which have not changed much
// background needs to be updated when person is not in frame
// use OVR SDK to do this later
  Mat flow;
  absdiff(blurred_img, background, flow);
  cvtColor(flow, flow, CV_RGB2GRAY);
  morphFast(flow);
  threshold(flow, flow, 60, 1, THRESH_BINARY);
  imshow("flow mask", gray.mul(flow));
  times[2] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets anything kind of dark (DK2) and dilates
  Mat kindofdark;
  equalizeHist(gray, kindofdark);
  threshold(kindofdark, kindofdark, 100, 1, THRESH_BINARY_INV);
  morphFast(kindofdark, 100, 17, 0);
  imshow("dark mask", gray.mul(kindofdark));
  times[3] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// this mask gets rid of anything far away from red stuff
// did not work well and was slow
/*
  Mat notlips;
  Mat channels[3];
  split(image, channels);
  channels[2].convertTo(notlips, CV_32FC1);
  divide(notlips, gray, notlips, 1, CV_32FC1);
  //equalistHist is horrible for a red background
  //equalizeHist(notlips, notlips);
  threshold(notlips, notlips, tracker3/30.0, 1, THRESH_BINARY);
  notlips.convertTo(notlips, CV_8UC1);
  imshow("lip mask", notlips*255);
  Mat otherMorph = notlips.clone();
  int tx = tracker1+1-(tracker1%2);
  if (tx<3) tx=1;
  if (tx>90) tx=91;
  morphFast(notlips, 100, tx, 0, 0);
  int ty = tracker2+1-(tracker2%2);
  if (ty<3) ty=1;
  if (ty>90) ty=91;
  morphFast(notlips, 100, ty, 0, 1);
  imshow("lips2", notlips.mul(gray));
  morphFast(otherMorph, 100, tx, 0, 1);
  morphFast(otherMorph, 100, tx, 0, 0);
  imshow("lips3", otherMorph.mul(gray));
  waitKey(1);
*/

  Mat mask = flow.mul(kindofdark);
// open the mask
  Mat smallMask0, smallMask1;
  resize(mask, smallMask0, Size(width/5,height/5));
  Mat erodeKernel = ellipticKernel(79,79);
  erode(smallMask0, smallMask1, erodeKernel);
  Mat dilateKernel = ellipticKernel(69,69);
//69,79
  dilate(smallMask1, smallMask1, dilateKernel);
  bitwise_and(smallMask0, smallMask1, smallMask1);
  resize(smallMask1, mask, Size(width, height));
  imshow("morph mask", gray.mul(mask));
  times[4] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

// update background with new morph mask
// average what we know is background with prior background
// erode it first since we really want to be sure it's bg

  Mat erodedMask;
  dilate(smallMask1, erodedMask, erodeKernel);
  resize(erodedMask, erodedMask, Size(width, height));
  imshow("erosion", erodedMask.mul(gray));
  Mat mask_;
  subtract(1,erodedMask,mask_);
  Mat mask3, mask3_;
  channel[0] = erodedMask;
  channel[1] = erodedMask;
  channel[2] = erodedMask;
  merge(channel, 3, mask3);
  channel[0] = mask_;
  channel[1] = mask_;
  channel[2] = mask_;
  merge(channel, 3, mask3_);

  background = background.mul(mask3) +
   (background.mul(mask3_)/2 + blurred_img.mul(mask3_)/2);
  times[5] += getMilliseconds() - timenow;
  timenow = getMilliseconds();

  imshow("background", background);

/*
  Moments lol = moments(gray, 1);
  circle(image, Point(lol.m10/lol.m00,lol.m01/lol.m00),20,Scalar(128),30);
  imshow("leimage", image);
*/

/*
  CascadeClassifier mouth_cascade;
  mouth_cascade.load("Mouth.xml");
  vector<Rect> mouths;
  int scale = 3;
  Mat classifyThis;
  equalizeHist(gray, gray);//ew; watch out not to use this later
  resize(gray.mul(mask), classifyThis, Size(width/scale,height/scale));
//  bilateralFilter(gray, classifyThis, 15, 10, 1);
  mouth_cascade.detectMultiScale(classifyThis, mouths, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  for (size_t i=0; i<mouths.size(); i++) {
   Rect scaled(mouths[i].x*scale, mouths[i].y*scale, mouths[i].width*scale,mouths[i].height*scale);
   rectangle(image, scaled, Scalar(255,0,0));
  }
  imshow("MOUTH", image);
*/

  for (int i=0; i<6; i++) {
   printf("%llu , ", times[i]);
   times[i] = 0;
  }

  printf("\n");

  keepGoing = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>