There are a few different ways to send this. There are a few answers on SO that explain some of them, here, here.
If you want to continue on along the lines that you are doing, I'd create a contiguous type for a 1D array and then expand that with another contiguous type to a 2D array.
A BIG BIG WARNING I do not check for errors, you REALLY REALLY SHOULD.
I've changed you code around a bit, as I don't like using typedef's of structs. I also put the creation of the basic MPI pixel datatype into a function and added some test sending routines (of course you could extend them to pass in the pixel(s) you want to send:
/*
* Create a MPI datatype of a pixel.
*/
int
mpi_pixel_init(MPI_Datatype *mpi_pixel)
{
struct pixel_s pixel; /* instance of structure */
int i = 0; /* temporary loop indexer */
int count = 3; /* number of blocks in the struct */
int blocks[3] = {1, 1, 1}; /* set up 3 blocks */
MPI_Datatype types[3] = { /* pixel internal types */
MPI_UNSIGNED_CHAR,
MPI_UNSIGNED_CHAR,
MPI_UNSIGNED_CHAR
};
MPI_Aint dis[3] = { /* internal displacements */
offsetof(struct pixel_s, r),
offsetof(struct pixel_s, g),
offsetof(struct pixel_s, b)
};
MPI_Type_create_struct(count, blocks, dis, types, mpi_pixel);
MPI_Type_commit(mpi_pixel);
return(EXIT_SUCCESS);
}
Test sending a single pixel:
/* Send a single pixel */
int
send_pixel(int src, int dst, MPI_Datatype mpixel)
{
int rank = 0;
struct pixel_s x = {0};
MPI_Status stat;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == src) {
x.r = 255;
x.g = 128;
x.b = 128;
MPI_Send(&x, 1, mpixel, 1, 1, MPI_COMM_WORLD);
} else if (rank == dst) {
MPI_Recv(&x, 1, mpixel, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
printf("Single pixel\n");
printf("%d:\tr: %d\tg: %d\tb: %d\n", rank, x.r, x.g, x.b);
printf("----\n");
}
return(EXIT_SUCCESS);
}
Test sending a row of pixels:
/* Send a row/1D of pixels */
int
send_1d_pixels(int src, int dst, MPI_Datatype cpixel)
{
int i = 0;
int rank = 0;
struct pixel_s x[ROWS] = {0};
MPI_Status stat;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
/* Test sending a row of pixels */
if (rank == src) {
for (i = 0; i < ROWS; ++i) {
x[i].r = i;
x[i].g = i + 128;
x[i].b = 255 - i;
}
MPI_Send(&x, 1, cpixel, 1, TAG, MPI_COMM_WORLD);
} else if (rank == dst) {
MPI_Recv(&x, 1, cpixel, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
printf("Row of pixels\n");
for (i = 0; i < ROWS; ++i) {
printf("%d:\tr: %d\tg: %d\tb: %d\n", i,
x[i].r, x[i].g, x[i].b);
}
printf("----\n");
}
return(EXIT_SUCCESS);
}
Test sending a 2D array of pixels:
/* Send an 2D array of pixels */
int
send_2d_pixels(int src, int dst, MPI_Datatype apixel)
{
int i = 0;
int j = 0;
int rank = 0;
struct pixel_s x[ROWS][COLS] = {0};
MPI_Status stat;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
/* Test sending one pixel */
if (rank == src) {
for (i = 0; i < ROWS; ++i) {
for (j = 0; j < COLS; ++j) {
x[i][j].r = i;
x[i][j].g = j;
x[i][j].b = i*COLS + j;
}
}
MPI_Send(&x, 1, apixel, 1, TAG, MPI_COMM_WORLD);
} else if (rank == dst) {
MPI_Recv(&x, 1, apixel, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
printf("Array of pixels\n");
for (i = 0; i < ROWS; ++i) {
for (j = 0; j < COLS; ++j) {
printf("(%d,%d):\tr: %d\tg: %d\tb: %d\n", i, j,
x[i][j].r, x[i][j].g, x[i][j].b);
}
}
printf("----\n");
}
return(EXIT_SUCCESS);
}
Then later on you can use it as:
/*
* Create a 2D array of MPI pixels.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <mpi.h>
#define TAG 1
#define COLS 10
#define ROWS 10
struct pixel_s {
unsigned char r;
unsigned char g;
unsigned char b;
};
int mpi_pixel_init(MPI_Datatype *);
int send_pixel(int, int, MPI_Datatype);
int send_1d_pixels(int, int, MPI_Datatype);
int send_2d_pixels(int, int, MPI_Datatype);
int
main(int argc, char **argv)
{
MPI_Datatype mpixel; /* single pixel */
MPI_Datatype cmpixel; /* row/contiguous pixels */
MPI_Datatype ampixel; /* 2D array of pixels */
MPI_Init(&argc, &argv);
/* Create an MPI pixel datatype */
mpi_pixel_init(&mpixel);
/* Create a 1D array (contiguous) pixels */
MPI_Type_contiguous(ROWS, mpixel, &cmpixel);
MPI_Type_commit(&cmpixel);
/* Create a 2D array from a 1D array of pixels */
MPI_Type_contiguous(COLS, cmpixel, &ixel);
MPI_Type_commit(&ixel);
/* Test sending one pixel */
send_pixel(0, 1, mpixel);
/* Test sending a row of pixels */
send_1d_pixels(0, 1, cmpixel);
/* Test sending a 2D array of pixels */
send_2d_pixels(0, 1, ampixel);
/* Free up the types and finalize MPI */
MPI_Type_free(&ixel);
MPI_Type_free(&cmpixel);
MPI_Type_free(&mpixel);
MPI_Finalize();
return(EXIT_SUCCESS);
}