2013-12-13 49 views
0

我复制了here的源代码。错误; MPI上的图像处理

努力使基于MPI的图像处理,并得到这些错误:

/tmp/cc0Z7iuC.o: In function `rotate' : 
image.c:(.text+0xd1):undefined reference to `cos' 
image.c:(.text+0xfa):undefined reference to `sin' 
image.c:(.text+0x147):undefined reference to `sin' 
image.c:(.text+0x170):undefined reference to `cos' 
collect2: ld returned 1 exit status 

真的不知道MPI程序是如何工作的,因为我是新来的这一点。

下面的代码:

#include<stdio.h> 
#include<stdlib.h> 
#include<unistd.h> 
#include<stdint.h> 
#include<string.h> 
#include<math.h> 
#include<mpi.h> 
#define BM 0x4D42   // Value of a bitmap type 
#define MAX_FILENAME 256 
#define PI 3.14159265 
#define BLOCK_LOW(id,p,n) ((id)*(n)/(p)) 
#define BLOCK_HIGH(id,p,n) \ 
    (BLOCK_LOW((id)+1,p,n)-1) 
#define BLOCK_SIZE(id,p,n) \ 
    (BLOCK_LOW((id)+1)-BLOCK_LOW(id)) 
#define BLOCK_OWNER(index,p,n) \ 
    (((p)*((index)+1)-1)/(n)) 

// Struct to hold a 2d vector 
#pragma pack(push, 1) 
typedef struct Vector 
{ 
    int x,y; 
} Vector; 
#pragma pack(pop) 
typedef enum { NS, SHIFT, SCALE, ROTATE } operation; 
typedef struct Options 
{ 
    operation op; 
    char * inputfile; 
    char * filename; 
    Vector v; 
    double param; 
    int flag; 
    void (*func)(Vector *v, Vector *r, int p, int row, double sf); 
} Options; 

// BITMAP header 
#pragma pack(push, 1) 
typedef struct 
{ 
    uint16_t type; 
    uint32_t size; 
    uint16_t reserved1, reserved2; 
    uint32_t offset; 
} HEADER; 
#pragma pack(pop) 

// BITMAP information header 
#pragma pack(push, 1) 
typedef struct 
{ 
    uint32_t size; 
    int32_t width, height; 
    uint16_t planes; 
    uint16_t bits; 
    uint32_t compression; 
    uint32_t isize; 
    int32_t xres,yres; 
    uint32_t colors; 
    uint32_t impcolors; 
} IHEADER; 
#pragma pack(pop) 

// Pixel 
#pragma pack(push, 1) 
typedef struct Pixel 
{ 
    uint8_t b,g,r; 
} Pixel; 
#pragma pack(pop) 

// Struct to hold info on a bitmap 
#pragma pack(push, 1) 
typedef struct 
{ 
    HEADER header; 
    IHEADER iheader; 
    Pixel ** array; 
} BMP; 
#pragma pack(pop) 

// Printed if a filename is not supplied 
void usage() 
{ 
//while((c = getopt(argc, argv, "f:o:x:y:r:s:")) != -1) 
    printf("Usage: image_manip: -f <filename> [OPTS]\n\ 
      The program can be run without the following options for a menu.\n\ 
      Otherwise, an output file name is required.\n\ 
      Operations are mutually exclusive.\n\ 
      -o <filename>\tName of output file.\n\ 
      -x <int>\t\tAmount to shift in x direction. Requires -y\n\ 
      -y <int>\t\tAmount to shift in y direction. Requires -x\n\ 
      -r <double>\t\tAmount to rotate image.\n\ 
      -s <double>\t\tAmount to scale image.\n"); 
    exit(1); 
} 
void shift(Vector * v, Vector * r, int p, int row, double sf) 
{ 
    (*r).x = p + (*v).x; 
    (*r).y = row + (*v).y; 
} 
void scale(Vector * v, Vector * r, int p, int row, double sf) 
{ 
    (*r).x = (int)p*sf; 
    (*r).y = (int)row*sf; 
} 
void rotate(Vector * v, Vector *r, int p, int row, double sf) 
{ 
    (*r).x = (int)p*cos(sf*PI/180)+row*sin(sf*PI/180); 
    (*r).y = (int)-1*p*sin(sf*PI/180)+row*cos(sf*PI/180); 
} 


// Performs an image shift 
void do_op(BMP * img, Options * opt) 
{ 
    int rank, size; 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    // Number of bits in a line 
    int linebits = (*img).iheader.width * (*img).iheader.bits; 
    // 4 byte alignment 
    int linebytes = ((linebits + 31)/32)*4; 
    Pixel * current; 
    Vector newvec; 
    // Accounting 
    int row = 0; 
    int p = 0; 
    int count = sizeof(Pixel)*linebytes; 
    MPI_Status status; 
    // Master  
    if(rank == 0) 
    { 
     // Open the new file 
     FILE * nf; 
     nf = fopen((*opt).filename,"w"); 
     // Make sure we are at the beginning 
     fseek(nf,0,SEEK_SET); 

     // Write the headers 
     fwrite(&(*img).header,1,sizeof((*img).header),nf); 
     fwrite(&(*img).iheader,1,sizeof((*img).iheader),nf); 

     // Allocate memory for a new pixel array 
     Pixel ** newimg = malloc(sizeof(Pixel*) * (*img).iheader.height); 

     // For every row 
     for(row = 0; row < (*img).iheader.height; row++) 
     { 
      current = (Pixel *) malloc(sizeof(Pixel)*linebytes); 
      memset(current,0,sizeof(Pixel)*linebytes); 
      MPI_Recv(current, count,MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 
      newimg[status.MPI_TAG] = current; 
     } 
     // Write the new image 
     for(row = (*img).iheader.height-1; row >= 0; row--) 
      fwrite(&newimg[row][0],1,linebytes,nf); 
     fclose(nf); 
     free(newimg); 

    } 
    else 
    { 
     current = (Pixel *) malloc(sizeof(Pixel)*linebytes); 
     // For every row 
     int r = BLOCK_LOW(rank-1,size-1,(*img).iheader.height); 
     Pixel blank; 
     blank.r = blank.g = blank.b = 0; 

     for(row = r; row <= BLOCK_HIGH(rank-1,size-1,(*img).iheader.height); row++) 
     { 
//   fprintf(stderr,"Rank,row [%d][%d]\n",rank,row); 
      // Set the memory to 0 by default (black), this also pads zeroes 
      memset(current,0,sizeof(current)); 

      // For every pixel in the row (3 bytes) 
      for(p = 0; p < linebytes/3; p++) 
      { 
       // Calc x,y 
       (*opt).func(&(*opt).v, &newvec, p, row, (*opt).param); 
       // Make sure they are on the canvas 
       if(newvec.x >= 0 && newvec.x < linebytes/3 && newvec.y < (*img).iheader.height && newvec.y >= 0) 
        current[p] = (*img).array[newvec.y][newvec.x]; 
       else 
        current[p] = blank; 
      } 
      MPI_Send(current, count, MPI_BYTE, 0, row, MPI_COMM_WORLD); 
     } 
    } 
// fprintf(stderr, "Rank %d: %d->%d\n",rank,BLOCK_LOW(rank-1,size-1,(*img).iheader.height),BLOCK_HIGH(rank-1,size-1,(*img).iheader.height)); 
free(current); 
} 



// Program menu 
int do_menu(BMP * img, Options * opts) 
{ 
    int rank,size; 
    int choice; 
    char * name = (char *) malloc(sizeof(char) * MAX_FILENAME); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    //fprintf(stderr,"[%s][%d] %d\n",__FILE__,__LINE__,rank); 
    if(rank == 0) 
    { 
     printf("\ 
       Options\n\ 
       =======\n\ 
       1. Shift\n\ 
       2. Scale\n\ 
       3. Rotate\n\ 
       4. Exit\n\ 
       Enter a selection: "); 
     fflush(stdout); 
     scanf("%d",&choice); 
     if(choice == 1 || choice == 2 || choice == 3) 
     { 
      printf("Enter a filename for the new image: "); 
      fflush(stdout); 
      scanf("%s",name); 
      (*opts).filename = name; 
     } 
    } 
    // \TODO: Merge this 
    if(rank == 0) 
    { 
     switch(choice) 
     { 
      case 1: 
       printf("Enter integer delta x: "); 
      fflush(stdout); 
       scanf("%d",&(*opts).v.x); 
       printf("Enter integer delta y: "); 
      fflush(stdout); 
       scanf("%d",&(*opts).v.y); 
       (*opts).func = shift; 
       break; 
      case 2: 
       printf("Enter a decimal scale factor: "); 
      fflush(stdout); 
       scanf("%lf",&(*opts).param); 
       (*opts).func = scale; 
       break; 
      case 3: 
       printf("Enter decimal degrees to rotate: "); 
      fflush(stdout); 
       scanf("%lf",&(*opts).param); 
       (*opts).func = rotate; 
       break; 
      case 4: 
       return 0; 
       break; 
      default: break; 
     } 
    } 
    MPI_Bcast(opts,sizeof(*opts),MPI_BYTE,0,MPI_COMM_WORLD); 
    do_op(img, opts); 

return 0; 
} 

// Read bitmap header 
int get_bmp_header(FILE * fp, BMP * img) 
{ 
    if(sizeof((*img).header) != fread(&(*img).header,1,sizeof((*img).header),fp)) 
    { 
     perror("Unable to read file"); 
     exit(1); 
    } 
    if(sizeof((*img).iheader) != fread(&(*img).iheader,1,sizeof((*img).iheader),fp)) 
    { 
     perror("Unable to read file"); 
     exit(1); 
    } 
    if((*img).header.type != BM) 
    { 
     printf("Error: Not a valid bitmap file.\n"); 
     exit(1); 
    } 
    return 0; 
} 

// Print attributes 
int print_bmp_attr(BMP * bmp) 
{ 
    printf("File: \n\t\ 
     Type: %X\n\t\ 
     Size: %d\n\t\ 
     Offset: %d\n\t\ 
     Width: %d\n\t\ 
     Height: %d\n\t\ 
     Image Size: %u\n\t\ 
     Bits/Pixel: %u\n\t\ 
     Compression: %u\n\t\ 
     Number of colors: %u\n\t\ 
     Important colors: %u\n", (*bmp).header.type, (*bmp).header.size, (*bmp).header.offset,(*bmp).iheader.width,(*bmp).iheader.height,(*bmp).iheader.isize, (*bmp).iheader.bits, (*bmp).iheader.compression,(*bmp).iheader.colors,(*bmp).iheader.impcolors); 
    return 0; 
} 

void parse_args(int argc, char **argv, Options * opts) 
{ 
// Parse options 
int c = 0; 
while((c = getopt(argc, argv, "f:o:x:y:r:s:")) != -1) 
    { 
     switch(c) 
     { 
     case 'f': 
      (*opts).inputfile = optarg; 
      break; 
     case 'o': 
      (*opts).filename = optarg; 
      break; 
     case 'x': 
      (*opts).flag++; 
      (*opts).op = SHIFT; 
      (*opts).func = shift; 
      (*opts).v.x = atoi(optarg); 
      break; 
     case 'y': 
      (*opts).flag++; 
      (*opts).v.y = atoi(optarg); 
      break; 
     case 'r': 
      (*opts).op = ROTATE; 
      (*opts).func = rotate; 
      (*opts).param = atof(optarg); 
      break; 
     case 's': 
      (*opts).op = SCALE; 
      (*opts).func = scale; 
      (*opts).param = atof(optarg); 
     default: 
      break; 
     } 
    } 

} 
// Main 
int main(int argc, char **argv) 
{ 
    if(MPI_Init(&argc,&argv) != MPI_SUCCESS) 
    { 
     perror("Unable to initialize MPI\n"); 
     exit(1); 
    } 
    FILE * fp = 0; 
    BMP bmp; 
    Options opts; 
    opts.op = NS; 
    opts.filename = 0; 
    opts.flag = 0; 
    parse_args(argc, argv, &opts); 
    if((fp = fopen(opts.inputfile,"rw")) == NULL) 
    { 
     usage(); 
     perror("Unable to open file"); 
     exit(1); 
    } 
    get_bmp_header(fp, &bmp); 
// print_bmp_attr(&bmp); 
    int linebits = bmp.iheader.width * bmp.iheader.bits; 
    int linebytes = ((linebits + 31)/32)*4; 
    Pixel ** img = malloc(sizeof(Pixel*) * bmp.iheader.height); 
    fseek(fp, bmp.header.offset, SEEK_SET); 
    int row = 0; 
    int byte = 0; 
    int column = 0; 
    //int rank, size; 
    Pixel * current; 
    for(row = bmp.iheader.height-1; row >= 0; row--) 
    { 
     current = (Pixel *) malloc(linebytes); 
     column = 0; 
     for(byte = 0; byte < linebytes; byte+=3) 
     { 
      fread(&current[column++],1,sizeof(Pixel),fp); 
     } 
     img[row] = current; 
     fseek(fp, bmp.header.offset + (bmp.iheader.height-1-row) * linebytes, SEEK_SET); 
    } 
    fclose(fp); 
    bmp.array = img; 
    if(opts.op == NS) 
     do_menu(&bmp,&opts); 
    else if(opts.filename == 0) 
     usage(); 
    else 
    { 
     switch(opts.op) 
     { 
      case SCALE: 
       opts.func = scale; 
       break; 
      case SHIFT: 
       if(opts.flag == 2) 
       opts.func = shift; 
       else 
        usage(); 
       break; 
      case ROTATE: 
       opts.func = rotate; 
       break; 
      case NS: 
      default: 
       usage(); 
       break; 
     } 
    do_op(&bmp, &opts); 

    } 
    free(img); 
    MPI_Finalize(); 
    return 0; 
} 

感谢之前

回答

1

您需要用数学库链接:

gcc .... -lm 
+0

是并行工作的呢? – user2913703

+0

它现在正常工作谢谢你^^ – user2913703

+0

@ user2913703,你可以标记答案为接受,如果它解决了你的问题。 – Shahbaz