move matio read to new system
This commit is contained in:
parent
70bde4a90d
commit
6864739351
10
TODO
10
TODO
@ -1,6 +1,8 @@
|
||||
- vips2bufpng() is leaky
|
||||
|
||||
- radiance, matlab to go still
|
||||
- test matio load
|
||||
|
||||
- radiance to go still
|
||||
|
||||
- saverawfd should be renamed saveraw_fd, cf. pngsave_buffer
|
||||
|
||||
@ -26,12 +28,6 @@
|
||||
|
||||
|
||||
|
||||
- "header fred.png" does not work, since header uses im_open() which uses
|
||||
VipsForeign
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- make the old format/vips.c into a stub as well?
|
||||
|
||||
|
@ -484,6 +484,12 @@ if test x"$with_matio" != "xno"; then
|
||||
])
|
||||
fi
|
||||
|
||||
if test x"$with_openslide" = x"yes"; then
|
||||
AM_CONDITIONAL(HAVE_MATIO, true)
|
||||
else
|
||||
AM_CONDITIONAL(HAVE_MATIO, false)
|
||||
fi
|
||||
|
||||
# cfitsio
|
||||
AC_ARG_WITH([cfitsio],
|
||||
AS_HELP_STRING([--without-cfitsio], [build without cfitsio (default: test)]))
|
||||
|
@ -20,6 +20,18 @@ libforeign_la_SOURCES = \
|
||||
|
||||
EXTRA_DIST =
|
||||
|
||||
if HAVE_MATIO
|
||||
libforeign_la_SOURCES += \
|
||||
matlab.h \
|
||||
matlab.c \
|
||||
matload.c
|
||||
else
|
||||
EXTRA_DIST += \
|
||||
matlab.h \
|
||||
matlab.c \
|
||||
matload.c
|
||||
endif
|
||||
|
||||
if HAVE_MAGICK
|
||||
libforeign_la_SOURCES += \
|
||||
magick.h \
|
||||
|
@ -1194,6 +1194,7 @@ vips_foreign_write_options( VipsImage *in, const char *filename )
|
||||
void
|
||||
vips_foreign_operation_init( void )
|
||||
{
|
||||
extern GType vips_foreign_load_mat_get_type( void );
|
||||
extern GType vips_foreign_load_ppm_get_type( void );
|
||||
extern GType vips_foreign_save_ppm_get_type( void );
|
||||
extern GType vips_foreign_load_png_get_type( void );
|
||||
@ -1237,6 +1238,10 @@ vips_foreign_operation_init( void )
|
||||
vips_foreign_save_png_buffer_get_type();
|
||||
#endif /*HAVE_PNG*/
|
||||
|
||||
#ifdef HAVE_MATIO
|
||||
vips_foreign_load_mat_get_type();
|
||||
#endif /*HAVE_MATIO*/
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
vips_foreign_load_jpeg_file_get_type();
|
||||
vips_foreign_load_jpeg_buffer_get_type();
|
||||
@ -1870,3 +1875,34 @@ vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_matload:
|
||||
* @filename: file to load
|
||||
* @out: output image
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Read a Matlab save file into a VIPS image.
|
||||
*
|
||||
* This operation searches the save
|
||||
* file for the first array variable with between 1 and 3 dimensions and loads
|
||||
* it as an image. It will not handle complex images. It does not handle
|
||||
* sparse matrices.
|
||||
*
|
||||
* See also: vips_image_new_from_file().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_matload( const char *filename, VipsImage **out, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, out );
|
||||
result = vips_call_split( "matload", ap, filename, out );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
|
305
libvips/foreign/matlab.c
Normal file
305
libvips/foreign/matlab.c
Normal file
@ -0,0 +1,305 @@
|
||||
/* Read matlab save files with libmatio
|
||||
*
|
||||
* 4/8/09
|
||||
* - transpose on load, assemble planes into bands (thanks Mikhail)
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file is part of VIPS.
|
||||
|
||||
VIPS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Remaining issues:
|
||||
|
||||
+ it will not do complex images
|
||||
|
||||
+ it will not handle sparse matricies
|
||||
|
||||
+ it loads the first variable in the file with between 1 and 3 dimensions,
|
||||
is this sensible behaviour?
|
||||
|
||||
+ load only, no save
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
#define DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include <matio.h>
|
||||
|
||||
#include "matlab.h"
|
||||
|
||||
/* What we track during a Mat-file read.
|
||||
*/
|
||||
typedef struct {
|
||||
char *filename;
|
||||
VipsImage *out;
|
||||
|
||||
mat_t *mat;
|
||||
matvar_t *var;
|
||||
} Read;
|
||||
|
||||
static void
|
||||
read_destroy( Read *read )
|
||||
{
|
||||
VIPS_FREE( read->filename );
|
||||
VIPS_FREEF( Mat_VarFree, read->var );
|
||||
VIPS_FREEF( Mat_Close, read->mat );
|
||||
|
||||
vips_free( read );
|
||||
}
|
||||
|
||||
static Read *
|
||||
read_new( const char *filename, VipsImage *out )
|
||||
{
|
||||
Read *read;
|
||||
|
||||
if( !(read = VIPS_NEW( NULL, Read )) )
|
||||
return( NULL );
|
||||
|
||||
read->filename = vips_strdup( NULL, filename );
|
||||
read->out = out;
|
||||
read->mat = NULL;
|
||||
read->var = NULL;
|
||||
|
||||
if( !(read->mat = Mat_Open( filename, MAT_ACC_RDONLY )) ) {
|
||||
vips_error( "mat2vips",
|
||||
_( "unable to open \"%s\"" ), filename );
|
||||
read_destroy( read );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if( !(read->var = Mat_VarReadNextInfo( read->mat )) ) {
|
||||
vips_error( "mat2vips",
|
||||
_( "no matrix variables in \"%s\"" ),
|
||||
filename );
|
||||
read_destroy( read );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "mat2vips: seen:\n" );
|
||||
printf( "var->name == %s\n", read->var->name );
|
||||
printf( "var->class_type == %d\n", read->var->class_type );
|
||||
printf( "var->rank == %d\n", read->var->rank );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
/* Vector to colour image is OK for us.
|
||||
*/
|
||||
if( read->var->rank >= 1 && read->var->rank <= 3 )
|
||||
break;
|
||||
|
||||
VIPS_FREEF( Mat_VarFree, read->var );
|
||||
}
|
||||
|
||||
return( read );
|
||||
}
|
||||
|
||||
/* Matlab classes -> VIPS band formats.
|
||||
*/
|
||||
static int mat2vips_formats[][2] = {
|
||||
{ MAT_C_UINT8, VIPS_FORMAT_UCHAR },
|
||||
{ MAT_C_INT8, VIPS_FORMAT_CHAR },
|
||||
{ MAT_C_UINT16, VIPS_FORMAT_USHORT },
|
||||
{ MAT_C_INT16, VIPS_FORMAT_SHORT },
|
||||
{ MAT_C_UINT32, VIPS_FORMAT_UINT },
|
||||
{ MAT_C_INT32, VIPS_FORMAT_INT },
|
||||
{ MAT_C_SINGLE, VIPS_FORMAT_FLOAT },
|
||||
{ MAT_C_DOUBLE, VIPS_FORMAT_DOUBLE }
|
||||
};
|
||||
|
||||
static int
|
||||
mat2vips_get_header( matvar_t *var, VipsImage *im )
|
||||
{
|
||||
int width, height, bands;
|
||||
VipsBandFormat format;
|
||||
VipsInterpretation interpretation;
|
||||
int i;
|
||||
|
||||
width = 1;
|
||||
height = 1;
|
||||
bands = 1;
|
||||
switch( var->rank ) {
|
||||
case 3:
|
||||
bands = var->dims[2];
|
||||
|
||||
case 2:
|
||||
height = var->dims[1];
|
||||
|
||||
case 1:
|
||||
width = var->dims[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
vips_error( "mat2vips",
|
||||
_( "unsupported rank %d\n" ), var->rank );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( bands > 1 )
|
||||
interpretation = VIPS_INTERPRETATION_MULTIBAND;
|
||||
else
|
||||
interpretation = VIPS_INTERPRETATION_B_W;
|
||||
|
||||
for( i = 0; i < VIPS_NUMBER( mat2vips_formats ); i++ )
|
||||
if( mat2vips_formats[i][0] == var->class_type )
|
||||
break;
|
||||
if( i == VIPS_NUMBER( mat2vips_formats ) ) {
|
||||
vips_error( "mat2vips", _( "unsupported class type %d\n" ),
|
||||
var->class_type );
|
||||
return( -1 );
|
||||
}
|
||||
format = mat2vips_formats[i][1];
|
||||
|
||||
vips_image_init_fields( im,
|
||||
width, height, bands,
|
||||
format,
|
||||
VIPS_CODING_NONE, interpretation, 1.0, 1.0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
vips__mat_header( const char *filename, VipsImage *out )
|
||||
{
|
||||
Read *read;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "mat2vips_header: reading \"%s\"\n", filename );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( !(read = read_new( filename, out )) )
|
||||
return( -1 );
|
||||
if( mat2vips_get_header( read->var, read->out ) ) {
|
||||
read_destroy( read );
|
||||
return( -1 );
|
||||
}
|
||||
read_destroy( read );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
mat2vips_get_data( mat_t *mat, matvar_t *var, VipsImage *im )
|
||||
{
|
||||
int y;
|
||||
PEL *buffer;
|
||||
const int es = VIPS_IMAGE_SIZEOF_ELEMENT( im );
|
||||
|
||||
/* Matlab images are plane-separate, so we have to assemble bands in
|
||||
* image-size chunks.
|
||||
*/
|
||||
const int is = es * im->Xsize * im->Ysize;
|
||||
|
||||
if( Mat_VarReadDataAll( mat, var ) ) {
|
||||
vips_error( "mat2vips", "%s",
|
||||
_( "Mat_VarReadDataAll failed" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Matlab images are in columns, so we have to transpose into
|
||||
* scanlines with this buffer.
|
||||
*/
|
||||
if( !(buffer = VIPS_ARRAY( im, VIPS_IMAGE_SIZEOF_LINE( im ), PEL )) )
|
||||
return( -1 );
|
||||
|
||||
for( y = 0; y < im->Ysize; y++ ) {
|
||||
const PEL *p = var->data + y * es;
|
||||
int x;
|
||||
PEL *q;
|
||||
|
||||
q = buffer;
|
||||
for( x = 0; x < im->Xsize; x++ ) {
|
||||
int b;
|
||||
|
||||
for( b = 0; b < im->Bands; b++ ) {
|
||||
const PEL *p2 = p + b * is;
|
||||
int z;
|
||||
|
||||
for( z = 0; z < es; z++ )
|
||||
q[z] = p2[z];
|
||||
|
||||
q += es;
|
||||
}
|
||||
|
||||
p += es * im->Ysize;
|
||||
}
|
||||
|
||||
if( vips_image_write_line( im, y, buffer ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
vips__mat_load( const char *filename, VipsImage *out )
|
||||
{
|
||||
Read *read;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "mat2vips: reading \"%s\"\n", filename );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( !(read = read_new( filename, out )) )
|
||||
return( -1 );
|
||||
if( mat2vips_get_header( read->var, read->out ) ||
|
||||
mat2vips_get_data( read->mat, read->var, read->out ) ) {
|
||||
read_destroy( read );
|
||||
return( -1 );
|
||||
}
|
||||
read_destroy( read );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
vips__mat_ismat( const char *filename )
|
||||
{
|
||||
mat_t *mat;
|
||||
|
||||
if( !(mat = Mat_Open( filename, MAT_ACC_RDONLY )) )
|
||||
return( 0 );
|
||||
Mat_Close( mat );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
const char *vips__mat_suffs[] = { ".mat", NULL };
|
47
libvips/foreign/matlab.h
Normal file
47
libvips/foreign/matlab.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* common defs for matio read/write
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Copyright (C) 1991-2005 The National Gallery
|
||||
|
||||
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.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifndef VIPS_MAT_H
|
||||
#define VIPS_MAT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
extern const char *vips__mat_suffs[];
|
||||
|
||||
int vips__mat_load( const char *filename, VipsImage *out );
|
||||
int vips__mat_header( const char *filename, VipsImage *out );
|
||||
int vips__mat_ismat( const char *filename );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#endif /*VIPS_MAT_H*/
|
136
libvips/foreign/matload.c
Normal file
136
libvips/foreign/matload.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* load matlab from a file
|
||||
*
|
||||
* 5/12/11
|
||||
* - from tiffload.c
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file is part of VIPS.
|
||||
|
||||
VIPS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
#define DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/buf.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "matlab.h"
|
||||
|
||||
typedef struct _VipsForeignLoadMat {
|
||||
VipsForeignLoad parent_object;
|
||||
|
||||
/* Filename for load.
|
||||
*/
|
||||
char *filename;
|
||||
|
||||
} VipsForeignLoadMat;
|
||||
|
||||
typedef VipsForeignLoadClass VipsForeignLoadMatClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignLoadMat, vips_foreign_load_mat,
|
||||
VIPS_TYPE_FOREIGN_LOAD );
|
||||
|
||||
static VipsForeignFlags
|
||||
vips_foreign_load_mat_get_flags_filename( const char *filename )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static VipsForeignFlags
|
||||
vips_foreign_load_mat_get_flags( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadMat *mat = (VipsForeignLoadMat *) load;
|
||||
|
||||
return( vips_foreign_load_mat_get_flags_filename( mat->filename ) );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_mat_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadMat *mat = (VipsForeignLoadMat *) load;
|
||||
|
||||
if( vips__mat_header( mat->filename, load->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_load_mat_load( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadMat *mat = (VipsForeignLoadMat *) load;
|
||||
|
||||
if( vips__mat_load( mat->filename, load->real ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_mat_class_init( VipsForeignLoadMatClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "matload";
|
||||
object_class->description = _( "load mat from file" );
|
||||
|
||||
foreign_class->suffs = vips__mat_suffs;
|
||||
|
||||
load_class->is_a = vips__mat_ismat;
|
||||
load_class->get_flags_filename =
|
||||
vips_foreign_load_mat_get_flags_filename;
|
||||
load_class->get_flags = vips_foreign_load_mat_get_flags;
|
||||
load_class->header = vips_foreign_load_mat_header;
|
||||
load_class->load = vips_foreign_load_mat_load;
|
||||
|
||||
VIPS_ARG_STRING( class, "filename", 1,
|
||||
_( "Filename" ),
|
||||
_( "Filename to load from" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignLoadMat, filename ),
|
||||
NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_load_mat_init( VipsForeignLoadMat *mat )
|
||||
{
|
||||
}
|
@ -71,6 +71,8 @@
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "ppm.h"
|
||||
|
||||
/* The largest number/field/whatever we can read.
|
||||
*/
|
||||
#define MAX_THING (80)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Read matlab save files with libmatio
|
||||
*
|
||||
* 4/8/09
|
||||
* - transpose on load, assemble planes into bands (thanks Mikhail)
|
||||
* 20/12/11
|
||||
* - just a compat stub
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -30,279 +30,25 @@
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Remaining issues:
|
||||
|
||||
+ it will not do complex images
|
||||
|
||||
+ it will not handle sparse matricies
|
||||
|
||||
+ it loads the first variable in the file with between 1 and 3 dimensions,
|
||||
is this sensible behaviour?
|
||||
|
||||
+ load only, no save
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
#define DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#ifdef HAVE_MATIO
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include <matio.h>
|
||||
|
||||
/* What we track during a Mat-file read.
|
||||
*/
|
||||
typedef struct {
|
||||
char *filename;
|
||||
IMAGE *out;
|
||||
|
||||
mat_t *mat;
|
||||
matvar_t *var;
|
||||
} Read;
|
||||
|
||||
static void
|
||||
read_destroy( Read *read )
|
||||
{
|
||||
IM_FREE( read->filename );
|
||||
IM_FREEF( Mat_VarFree, read->var );
|
||||
IM_FREEF( Mat_Close, read->mat );
|
||||
|
||||
im_free( read );
|
||||
}
|
||||
|
||||
static Read *
|
||||
read_new( const char *filename, IMAGE *out )
|
||||
{
|
||||
Read *read;
|
||||
|
||||
if( !(read = IM_NEW( NULL, Read )) )
|
||||
return( NULL );
|
||||
|
||||
read->filename = im_strdup( NULL, filename );
|
||||
read->out = out;
|
||||
read->mat = NULL;
|
||||
read->var = NULL;
|
||||
|
||||
if( !(read->mat = Mat_Open( filename, MAT_ACC_RDONLY )) ) {
|
||||
im_error( "im_mat2vips",
|
||||
_( "unable to open \"%s\"" ), filename );
|
||||
read_destroy( read );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if( !(read->var = Mat_VarReadNextInfo( read->mat )) ) {
|
||||
im_error( "im_mat2vips",
|
||||
_( "no matrix variables in \"%s\"" ),
|
||||
filename );
|
||||
read_destroy( read );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "im_mat2vips: seen:\n" );
|
||||
printf( "var->name == %s\n", read->var->name );
|
||||
printf( "var->class_type == %d\n", read->var->class_type );
|
||||
printf( "var->rank == %d\n", read->var->rank );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
/* Vector to colour image is OK for us.
|
||||
*/
|
||||
if( read->var->rank >= 1 && read->var->rank <= 3 )
|
||||
break;
|
||||
|
||||
IM_FREEF( Mat_VarFree, read->var );
|
||||
}
|
||||
|
||||
return( read );
|
||||
}
|
||||
|
||||
/* Matlab classes -> VIPS band formats.
|
||||
*/
|
||||
static int mat2vips_formats[][2] = {
|
||||
{ MAT_C_UINT8, IM_BANDFMT_UCHAR },
|
||||
{ MAT_C_INT8, IM_BANDFMT_CHAR },
|
||||
{ MAT_C_UINT16, IM_BANDFMT_USHORT },
|
||||
{ MAT_C_INT16, IM_BANDFMT_SHORT },
|
||||
{ MAT_C_UINT32, IM_BANDFMT_UINT },
|
||||
{ MAT_C_INT32, IM_BANDFMT_INT },
|
||||
{ MAT_C_SINGLE, IM_BANDFMT_FLOAT },
|
||||
{ MAT_C_DOUBLE, IM_BANDFMT_DOUBLE }
|
||||
};
|
||||
|
||||
static int
|
||||
mat2vips_get_header( matvar_t *var, IMAGE *im )
|
||||
{
|
||||
int width, height, bands, format, type;
|
||||
int i;
|
||||
|
||||
width = 1;
|
||||
height = 1;
|
||||
bands = 1;
|
||||
switch( var->rank ) {
|
||||
case 3:
|
||||
bands = var->dims[2];
|
||||
|
||||
case 2:
|
||||
height = var->dims[1];
|
||||
|
||||
case 1:
|
||||
width = var->dims[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
im_error( "im_mat2vips",
|
||||
_( "unsupported rank %d\n" ), var->rank );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( bands > 1 )
|
||||
type = IM_TYPE_MULTIBAND;
|
||||
else
|
||||
type = IM_TYPE_B_W;
|
||||
|
||||
for( i = 0; i < IM_NUMBER( mat2vips_formats ); i++ )
|
||||
if( mat2vips_formats[i][0] == var->class_type )
|
||||
break;
|
||||
if( i == IM_NUMBER( mat2vips_formats ) ) {
|
||||
im_error( "im_mat2vips", _( "unsupported class type %d\n" ),
|
||||
var->class_type );
|
||||
return( -1 );
|
||||
}
|
||||
format = mat2vips_formats[i][1];
|
||||
|
||||
im_initdesc( im,
|
||||
width, height, bands,
|
||||
im_bits_of_fmt( format ), format,
|
||||
IM_CODING_NONE, type, 1.0, 1.0, 0, 0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
mat2vips_header( const char *filename, IMAGE *out )
|
||||
{
|
||||
Read *read;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "mat2vips_header: reading \"%s\"\n", filename );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( !(read = read_new( filename, out )) )
|
||||
return( -1 );
|
||||
if( mat2vips_get_header( read->var, read->out ) ) {
|
||||
read_destroy( read );
|
||||
return( -1 );
|
||||
}
|
||||
read_destroy( read );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
mat2vips_get_data( mat_t *mat, matvar_t *var, IMAGE *im )
|
||||
{
|
||||
int y;
|
||||
PEL *buffer;
|
||||
const int es = IM_IMAGE_SIZEOF_ELEMENT( im );
|
||||
|
||||
/* Matlab images are plane-separate, so we have to assemble bands in
|
||||
* image-size chunks.
|
||||
*/
|
||||
const int is = es * im->Xsize * im->Ysize;
|
||||
|
||||
if( Mat_VarReadDataAll( mat, var ) ) {
|
||||
im_error( "im_mat2vips", "%s",
|
||||
_( "Mat_VarReadDataAll failed" ) );
|
||||
return( -1 );
|
||||
}
|
||||
if( im_outcheck( im ) ||
|
||||
im_setupout( im ) )
|
||||
return( -1 );
|
||||
|
||||
/* Matlab images are in columns, so we have to transpose into
|
||||
* scanlines with this buffer.
|
||||
*/
|
||||
if( !(buffer = IM_ARRAY( im, IM_IMAGE_SIZEOF_LINE( im ), PEL )) )
|
||||
return( -1 );
|
||||
|
||||
for( y = 0; y < im->Ysize; y++ ) {
|
||||
const PEL *p = var->data + y * es;
|
||||
int x;
|
||||
PEL *q;
|
||||
|
||||
q = buffer;
|
||||
for( x = 0; x < im->Xsize; x++ ) {
|
||||
int b;
|
||||
|
||||
for( b = 0; b < im->Bands; b++ ) {
|
||||
const PEL *p2 = p + b * is;
|
||||
int z;
|
||||
|
||||
for( z = 0; z < es; z++ )
|
||||
q[z] = p2[z];
|
||||
|
||||
q += es;
|
||||
}
|
||||
|
||||
p += es * im->Ysize;
|
||||
}
|
||||
|
||||
if( im_writeline( y, im, buffer ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_mat2vips:
|
||||
* @filename: file to load
|
||||
* @out: image to write to
|
||||
*
|
||||
* Read a Matlab save file into a VIPS image.
|
||||
*
|
||||
* This operation searches the save
|
||||
* file for the first array variable with between 1 and 3 dimensions and loads
|
||||
* it as an image. It will not handle complex images. It does not handle
|
||||
* sparse matrices.
|
||||
*
|
||||
* See also: #VipsFormat.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
im_mat2vips( const char *filename, IMAGE *out )
|
||||
{
|
||||
Read *read;
|
||||
VipsImage *t;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "mat2vips: reading \"%s\"\n", filename );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if( !(read = read_new( filename, out )) )
|
||||
if( vips_ppmload( filename, &t, NULL ) )
|
||||
return( -1 );
|
||||
if( mat2vips_get_header( read->var, read->out ) ||
|
||||
mat2vips_get_data( read->mat, read->var, read->out ) ) {
|
||||
read_destroy( read );
|
||||
if( vips_image_write( t, out ) ) {
|
||||
g_object_unref( t );
|
||||
return( -1 );
|
||||
}
|
||||
read_destroy( read );
|
||||
g_object_unref( t );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -310,19 +56,11 @@ im_mat2vips( const char *filename, IMAGE *out )
|
||||
static int
|
||||
ismat( const char *filename )
|
||||
{
|
||||
mat_t *mat;
|
||||
|
||||
if( !(mat = Mat_Open( filename, MAT_ACC_RDONLY )) )
|
||||
return( 0 );
|
||||
Mat_Close( mat );
|
||||
|
||||
return( 1 );
|
||||
return( vips_foreign_is_a( "matload", filename ) );
|
||||
}
|
||||
|
||||
static const char *mat_suffs[] = { ".mat", NULL };
|
||||
|
||||
/* mat format adds no new members.
|
||||
*/
|
||||
typedef VipsFormat VipsFormatMat;
|
||||
typedef VipsFormatClass VipsFormatMatClass;
|
||||
|
||||
@ -336,7 +74,6 @@ vips_format_mat_class_init( VipsFormatMatClass *class )
|
||||
object_class->description = _( "Matlab" );
|
||||
|
||||
format_class->is_a = ismat;
|
||||
format_class->header = mat2vips_header;
|
||||
format_class->load = im_mat2vips;
|
||||
format_class->save = NULL;
|
||||
format_class->suffs = mat_suffs;
|
||||
@ -349,4 +86,3 @@ vips_format_mat_init( VipsFormatMat *object )
|
||||
|
||||
G_DEFINE_TYPE( VipsFormatMat, vips_format_mat, VIPS_TYPE_FORMAT );
|
||||
|
||||
#endif /*HAVE_MATIO*/
|
||||
|
@ -361,6 +361,9 @@ int vips_ppmload( const char *filename, VipsImage **out, ... )
|
||||
int vips_ppmsave( VipsImage *in, const char *filename, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_matload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
Loading…
Reference in New Issue
Block a user