Source code for version 0.1, under the GNU LGPL.
This is a parallel interface to the PGM and PPM "raw" file formats,
using the MPI-2 I/O API as its lower-level I/O layer. This allows for
potentially higher performance in parallel than the standard POSIX
open()/read()/write() I/O
interface.
This API is built around the image_t object, which
contains an image's overall dimensions as well as subsetting
information for parallel access. The image_t object also
contains a void pointer called pixel which can point to
an arbitrary pixel buffer. The pixel buffer may be allocated in terms
of the following types:
gray8_t (8-bit grayscale -- 1 byte/pixel)
gray16_t (16-bit grayscale -- 2 bytes/pixel)
rgb8_t (8-bit RGB -- 3 bytes/pixel)
rgb16_t (16-bit RGB -- 6 bytes/pixel)
Because of the way the PNM file formats are structured, the image header and the raster data are handled separately. An image's header MUST be read or written before its raster data may be read or written.
PBM_TYPE (type value for PBM files, not currently supported)
PGM_TYPE (type value for PGM files)
PPM_TYPE (type value for PPM files)
PNM_MAXVAL_8BIT (maximum value for 8-bit samples)
PNM_MAXVAL_16BIT (maximum value for 16-bit samples)
p2nm_dup_image()
P2NM_BUFFER_SHARE (new image shares old image's pixel buffer)
P2NM_BUFFER_DUP (new image gets a copy of old
images pixel buffer)
All routines marked collective must be called by all MPI processes in the specified communicator.
/* Register MPI datatypes associated with P2NM */ void p2nm_register_types(void); /* Create a new image */ int p2nm_new_image(image_t *image, int type, int width, int height, int maxval); /* Allocate an image's pixel buffer */ int p2nm_allocate_pixbuf(image_t *image); /* Free an image's pixel buffer */ int p2nm_deallocate_pixbuf(image_t *image); /* Set the filename of an image */ int p2nm_name_image(image_t *image, const char *name); /* Create a duplicate of an image */ int p2nm_dup_image(image_t image, image_t *newimage, int flag); /* Create a duplicate of an image which points at only a subset of the image */ int p2nm_create_subimage(image_t image, int xstart, int ystart, int width, int height, image_t *newimage); /* Read an image header -- COLLECTIVE */ int p2nm_read_header(image_t *image, MPI_Comm comm); /* Write an image header -- COLLECTIVE */ int p2nm_write_header(image_t *image, MPI_Comm comm, MPI_Info info); /* Open an image's raster data -- COLLECTIVE */ int p2nm_open_image(image_t *image, MPI_Comm comm, int amode, MPI_Info info, MPI_File *fd); /* Read an image's raster data */ int p2nm_read_image(image_t *image, MPI_File fd, MPI_Status *status); /* Write an image's raster data */ int p2nm_write_image(image_t *image, MPI_File fd, MPI_Status *status); /* Read an image's raster data in parallel -- COLLECTIVE */ int p2nm_read_image_all(image_t *image, MPI_File fd, MPI_Status *status); /* Write an image's raster data in parallel -- COLLECTIVE */ int p2nm_write_image_all(image_t *image, MPI_File fd, MPI_Status *status);
To read an existing PNM file serially:
image_t image; MPI_File fd; MPI_Status status; ... MPI_Init(&argc,&argv); p2nm_register_types(); ... p2nm_name_image(&image,"foo.ppm"); p2nm_read_header(&image,MPI_COMM_SELF); p2nm_allocate_pixbuf(&image); p2nm_open_image(&image,MPI_COMM_SELF,MPI_MODE_RDONLY,MPI_INFO_NULL,&fd); p2nm_read_image(&image,fd,&status); MPI_File_close(&fd);
To write out an image to a file serially:
image_t image; MPI_File fd; MPI_Status status; ... MPI_Init(&argc,&argv); p2nm_register_types(); ... p2nm_create_image(&image,PPM_TYPE,width,height,maxval); /* or dup another image object */ p2nm_name_image(&image,"foo.ppm"); /* code to fill in image's pixel buffer */ p2nm_write_header(&image,MPI_COMM_SELF); p2nm_open_image(&image,MPI_COMM_SELF,MPI_MODE_WRONLY,MPI_INFO_NULL,&fd); p2nm_write_image(&image,fd,&status); MPI_File_close(&fd);
To read segments of an existing PNM file in parallel:
int xstart,ystart,subwidth,subheight; image_t image,parimage; MPI_File fd; MPI_Status status; ... MPI_Init(&argc,&argv); p2nm_register_types(); ... p2nm_name_image(&image,"foo.ppm"); p2nm_read_header(&image,MPI_COMM_WORLD); /* code to compute my values for xstart,ystart,subwidth,subheight */ p2nm_create_subimage(image,xstart,ystart,subwidth,subheight,&parimage); p2nm_allocate_pixbuf(&parimage); p2nm_open_image(&parimage,MPI_COMM_WORLD,MPI_MODE_RDONLY,MPI_INFO_NULL,&fd); p2nm_read_image_all(&parimage,fd,&status); MPI_File_close(&fd);
To write segments of an image to a PNM file in parallel:
int xstart,ystart,subwidth,subheight; image_t image,parimage; MPI_File fd; MPI_Status status; ... MPI_Init(&argc,&argv); p2nm_register_types(); ... p2nm_create_image(&image,PPM_TYPE,width,height,maxval); /* or dup another image object */ p2nm_name_image(&image,"foo.ppm"); p2nm_write_header(&image,MPI_COMM_WORLD); /* code to compute my values for xstart,ystart,subwidth,subheight */ /* NOTE -- MUST NOT OVERLAP!!!!! */ p2nm_create_subimage(image,xstart,ystart,subwidth,subheight,&parimage); p2nm_allocate_pixbuf(&parimage); p2nm_open_image(&parimage,MPI_COMM_WORLD,MPI_MODE_WRONLY,MPI_INFO_NULL,&fd); p2nm_write_image_all(&parimage,fd,&status); MPI_File_close(&fd);
p2nm does not currently handle PNM files with comments in the header.