/*************************************************************************** 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 //-------------------------------------------------------------------------// 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 m; bool swap; int esize; int dsize; while ( !is.atEnd() ) { // read header auto_ptr 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; icols(); i++ ) for( int j=0; jrows(); 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 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(adr), i=0; i < len>>1; i++ ) { char temp = ptr[i]; ptr[i] = ptr[len-i-1]; ptr[len-i-1] = temp; } } //-------------------------------------------------------------------------//