You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
6.8 KiB

/***************************************************************************
ksmatrixmat.cpp
-------------------
begin : 01-January-2000
copyright : (C) 2000 by Kamil Dobkowski
email : kamildobk@poczta.onet.pl
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include"ksmatrixmat.h"
#include<memory>
//-------------------------------------------------------------------------//
KSMatrixMAT::KSMatrixMAT()
{
}
//-------------------------------------------------------------------------//
KSMatrixMAT::~KSMatrixMAT()
{
}
//-------------------------------------------------------------------------//
bool KSMatrixMAT::check( QDataStream &is )
// Filename isn't interesing but should be "*.mat"
// Check the first header in a stream
{
KSMatrix *h = read_header(is);
if ( !h ) return false;
delete h;
return true;
}
//-----------------------------------------------------------------------//
KSHeadersList *KSMatrixMAT::headers( QDataStream& is )
{
KSHeadersList *result = new KSHeadersList();
while ( !is.atEnd() ) {
int data_size;
// read header
KSMatrix *hdr = read_header( is, NULL, NULL, &data_size );
// end of header list
if ( !hdr ) break;
// add it to the list
result->push_back( hdr );
// skip next header.size bytes
is.device()->at( is.device()->at()+data_size );
}
return result;
}
//-------------------------------------------------------------------------//
KSMatrix *KSMatrixMAT::load( QDataStream& is, const QString& matrixname )
{
auto_ptr<KSMatrix> m;
bool swap;
int esize;
int dsize;
while ( !is.atEnd() ) {
// read header
auto_ptr<KSMatrix> h(read_header( is, &swap, &esize, &dsize ));
// Check whether we found matrix, we have been looking for.
if ( h->name() == matrixname ) { m = h; break; }
// skip bytes to the next header
is.device()->at( is.device()->at()+dsize );
// this is not the header we are looking for, delete it
}
if ( is.atEnd() ) return NULL;
int enumb = m->cols()*m->rows();
int estep = enumb / 20 + 1;
int ecurr = 0;
// alloc data, that will be managed by this object
// remember that header has data set to NULL while rows and cols are sot to non-zero
int rows = m->rows();
int cols = m->cols();
m->resize( 0, 0 );
m->resize( rows, cols );
for( int i=0; i<m->cols(); i++ )
for( int j=0; j<m->rows(); j++ ) {
// calculate a pointer to memory
void *ptr = (char*)m->ptr() + j*m->lo() + i*m->po(); // + part*esize;
// read esize bytes in binary format, directly to memory
if ( is.readRawBytes((char*)ptr,esize).device()->status() != IO_Ok ) return NULL;
// if endian ordering is different - swap bytes
if ( swap ) swap_bytes( ptr, esize );
}
return m.release();
}
//-------------------------------------------------------------------------//
KSMatrix *KSMatrixMAT::read_header( QDataStream& is, bool *swap_ptr, int *esize_ptr, int *data_size_ptr )
{
Header header;
Flags flags;
bool swap = false;
is.readRawBytes((char*)&header.type, 4);
is.readRawBytes((char*)&header.mrows, 4);
is.readRawBytes((char*)&header.ncols, 4);
is.readRawBytes((char*)&header.imagf, 4);
is.readRawBytes((char*)&header.namlen, 4);
if ( is.device()->status() != IO_Ok ) return NULL;
// If 'type' is nonzero and the byte order is swapped, 'type' will be
// bigger than we expect, so we swap bytes.
//
// If 'type' is zero, it means the file was written on a little endian
// machine, and we only need to swap if we are running on a big endian
// machine.
//
int type = header.type;
#if defined WORDS_BIGENDIAN
if ( type == 0 ) swap = true;
#endif
if ( type < 0 || type > 9999 ) swap = true;
if ( swap ) {
swap_bytes( &header.type, 4 );
swap_bytes( &header.mrows, 4 );
swap_bytes( &header.ncols, 4 );
swap_bytes( &header.imagf, 4 );
swap_bytes( &header.namlen, 4 );
}
if ( header.type < 0 ||
header.type > 4052 ||
header.imagf > 1 ||
header.imagf < 0 ) return NULL;
type = header.type;
flags.T = TypeT(type % 10); type /= 10;
flags.P = TypeP(type % 10); type /= 10;
flags.O = TypeO(type % 10); type /= 10;
flags.M = TypeM(type % 10);
if ( flags.M == VAX_D_FLOAT ||
flags.M == VAX_G_FLOAT ||
flags.M == CRAY ||
flags.T == TEXT ||
flags.T == SPARSE) return NULL;
// Create output matrix
EType etype;
switch( flags.P ) {
case E_DOUBLE: etype = EDouble; break;
case E_FLOAT: etype = EFloat; break;
case E_INTEGER: etype = ELong; break;
case E_SHORT: etype = EShort; break;
case E_USHORT: etype = EUShort; break;
case E_UCHAR: etype = EUChar; break;
default: return NULL;
}
auto_ptr<KSMatrix> result( KSMatrix::create(etype) );
QCString name( header.namlen );
is.readRawBytes( name.data(), header.namlen );
result->setName( name );
int esize = result->elementSize();
int elementOffset = esize * (header.imagf?2:1);
int lineOffset = elementOffset * header.ncols;
int dataSize = lineOffset * header.mrows;
result->setRawData( NULL, header.mrows, header.ncols, false );
if ( esize_ptr ) *esize_ptr = esize;
if ( swap_ptr ) *swap_ptr = swap;
if ( data_size_ptr ) *data_size_ptr = dataSize;
return result.release();
}
//-------------------------------------------------------------------------//
void KSMatrixMAT::swap_bytes( void *adr, unsigned int len )
// But, but What is it ?!
// Swap 'len' bytes at the pointer 'adr'
{
unsigned int i; char *ptr;
for( ptr=static_cast<char *>(adr), i=0; i < len>>1; i++ ) {
char temp = ptr[i]; ptr[i] = ptr[len-i-1]; ptr[len-i-1] = temp;
}
}
//-------------------------------------------------------------------------//