Reading image from sd card

stella

Member
I have image.pgm on SD card. In this code, I can't print the size of the image after reading, the code inters in loop. The commented lines represent the code in c, and it was work (as a c code) without any problem. I convert some functions the deal with files to can work on Arduino but the problem I can't get the size of image. any help please? to read the image in correct way?

Code:
#include <SD.h>
typedef struct _PGMData {
    int row;
    int col;
    int max_gray;
    int **matrix;
} PGMData;

#define HI(num) (((num) & 0x0000FF00) << 8)
#define LO(num) ((num) & 0x000000FF)


int **allocate_dynamic_matrix(int row, int col)
{
    int **ret_val;
    int i;
 
    ret_val = (int **)malloc(sizeof(int *) * row);
    if (ret_val == NULL) {
        perror("memory allocation failure");
        exit(EXIT_FAILURE);
    }
 
    for (i = 0; i < row; ++i) {
        ret_val[i] = (int *)malloc(sizeof(int) * col);
        if (ret_val[i] == NULL) {
            perror("memory allocation failure");
            exit(EXIT_FAILURE);
        }
    }
 
    return ret_val;
}
 
void deallocate_dynamic_matrix(int **matrix, int row)
{
    int i;
 
    for (i = 0; i < row; ++i) {
        free(matrix[i]);
    }
    free(matrix);
}
void SkipComments(File &fp)
{

    int ch;
    char line[100];
  /*  
    while ((ch = fgetc(fp)) != EOF && isspace(ch)) {
        ;
    }
 
    if (ch == '#') {
        fgets(line, sizeof(line), fp);
        SkipComments(fp);
    } else {
        fseek(fp, -1, SEEK_CUR);
    }
 */

while (fp.available() && isspace(ch) ){
 //  Serial.write(fin.read());
   ch = fp.read();
}
     
if (ch == '#') {
       // fgets(line, sizeof(line), fp);
      
int bar=0;
int in_char;
while((in_char = fp.read()) >= 0){             
    line[bar++] = (char)in_char;
}
        SkipComments(fp);
    } else {
       // fseek(fp, -1, SEEK_CUR);
         fp.seek(fp.position());   
    }


}
//for reading:*

PGMData* readPGM( PGMData *data)
{
    File pgmFile;
    char version[3];
    int i, j;
    int lo, hi;
    if (!SD.begin(BUILTIN_SDCARD)) {
    Serial.println("Failed to mount card read pgm");
  }
   pgmFile = SD.open("/image.pgm", FILE_READ);
  if (!pgmFile) {
    Serial.println("Opening file to read failed read pgm");
  }
   /* if (pgmFile == NULL) {
        perror("cannot open file to read");
        exit(EXIT_FAILURE);
    }*/
  /*  fgets(version, sizeof(version), pgmFile);
    if (strcmp(version, "P5")) {
        fprintf(stderr, "Wrong file type!\n");
        exit(EXIT_FAILURE);
    }
    */

    /*
    SkipComments(pgmFile);
   // fscanf(pgmFile, "%d", &data->col);
    SkipComments(pgmFile);
   // fscanf(pgmFile, "%d", &data->row);
    SkipComments(pgmFile);
   // fscanf(pgmFile, "%d", &data->max_gray);
   */

   while (pgmFile.available()){
 
    SkipComments(pgmFile);
   // fscanf(pgmFile, "%d", &data->col);
   data->col = pgmFile.read();
    SkipComments(pgmFile);
   // fscanf(pgmFile, "%d", &data->row);
   data->row = pgmFile.read();
    SkipComments(pgmFile);
   // fscanf(pgmFile, "%d", &data->max_gray);
   data->max_gray = pgmFile.read();
  
}
   /// fgetc(pgmFile);
    data->matrix = allocate_dynamic_matrix(data->row, data->col);
    if (data->max_gray > 255) {
        for (i = 0; i < data->row; ++i) {
            for (j = 0; j < data->col; ++j) {
                hi = pgmFile.read();    //fgetc(pgmFile);
                lo = pgmFile.read();   //fgetc(pgmFile);
                data->matrix[i][j] = (hi << 8) + lo;
            }
        }
    }
    else {
        for (i = 0; i < data->row; ++i) {
            for (j = 0; j < data->col; ++j) {
                lo = pgmFile.read();   //fgetc(pgmFile);
                data->matrix[i][j] = lo;
            }
        }
    }
 
    pgmFile.close();
    return data;
 
}

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
  while (!Serial){}; 
    PGMData im;
    readPGM( &im);

   Serial.print("The size of image = ");
   Serial.println(im.col);
   Serial.println(im.row);   
}

void loop() {
  // put your main code here, to run repeatedly:

}
 
I've massaged your code so that it can read a PGM header file. I could only test with an example PGM that was way too big to fit in a teensy, so I can't guarantee that it'll read the image itself correctly.

Code:
// Read a PBM image from Teensy 4.1 built-in SDcard

#include <SD.h>
typedef struct _PGMData {
  int row;
  int col;
  int max_gray;
  int **matrix;
} PGMData;

int **allocate_dynamic_matrix(int row, int col)
{
  int **ret_val;
  int i;
  
  ret_val = (int **)malloc(sizeof(int *) * row);
  if (ret_val == NULL) {
    perror("memory allocation failure A");
    exit(EXIT_FAILURE);
  }

  for (i = 0; i < row; ++i) {
    ret_val[i] = (int *)malloc(sizeof(int) * col);
    if (ret_val[i] == NULL) {
      perror("memory allocation failure B");
      exit(EXIT_FAILURE);
    }
  }

  return ret_val;
}

void deallocate_dynamic_matrix(int **matrix, int row)
{
  int i;

  for (i = 0; i < row; ++i) {
    free(matrix[i]);
  }
  free(matrix);
}

void SkipComments(File pgmFile/*File &fp*/)
{

  int ch;

  while ((ch = pgmFile.read()) != EOF && isspace(ch)) {
    ;
  }
  // If this is a comment, read and ignore
  // all of it up to a newline
  if (ch == '#') {
    while((ch = pgmFile.read()) >= 0) {
      if(ch == '\n' || ch == '\r')break;
    }
    // end of file?
    if(ch < 0)return;
    SkipComments(pgmFile);
  } else {
    // back up one character if this isn't a comment
    // so that we re-read the previous character
    pgmFile.seek(pgmFile.position()-1);
  }
}

// Read one line from the file into istr
char istr[100];
void readln_istr(File pgmFile)
{
  uint32_t i;
  char ch;
  
  for(i = 0; i < sizeof(istr); i++) {
    ch = pgmFile.read();
    istr[i] = ch;
    if(ch == '\r' || ch == '\n') return;
  }
  // The line is too long. Force termination with '\r'
  istr[i - 1] = '\r';
}

PGMData* readPGM( PGMData *data)
{
  File pgmFile;
  char version[3];
  char *p;
  int i, j;
  int lo, hi;

  if (!SD.begin(BUILTIN_SDCARD)) {
    Serial.println("Failed to mount card read pgm");
  }
  pgmFile = SD.open("/image.pgm", FILE_READ);
  if (!pgmFile) {
    Serial.println("Opening file to read failed read pgm");
    // No point continuing
    while(1);
  }

  // Read the version string
  version[0] = pgmFile.read();
  version[1] = pgmFile.read();
  version[2] = 0;
  // Ignore the whites[ace that follows the P5 */
  SkipComments(pgmFile);
  if (strcmp(version, "P5")) {
    Serial.printf("Wrong file type!\n");
    while(1);
  }
  // read the line containing the dimensions
  // of the image
  readln_istr(pgmFile);
  // parse the line
  // get the number of columns
  data->col = atoi(istr);
  for(p = istr; *p != ' ' && *p; p++);
  p++;
  // and the number of rows
  data->row = atoi(p);

  // Read the line containing the max_gray value
  readln_istr(pgmFile);
  data->max_gray = atoi(istr);

Serial.printf("file dimensions %d x %d : Max_gray = %d\n",data->col,data->row,data->max_gray);

  data->matrix = allocate_dynamic_matrix(data->row, data->col);
  if (data->max_gray > 255) {
    for (i = 0; i < data->row; ++i) {
      for (j = 0; j < data->col; ++j) {
        hi = pgmFile.read();    //fgetc(pgmFile);
        lo = pgmFile.read();   //fgetc(pgmFile);
        data->matrix[i][j] = (hi << 8) + lo;
      }
    }
  } else {
    for (i = 0; i < data->row; ++i) {
      for (j = 0; j < data->col; ++j) {
        lo = pgmFile.read();   //fgetc(pgmFile);
        data->matrix[i][j] = lo;
      }
    }
  }

  pgmFile.close();
  return data;

}

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial) {};
  PGMData im;
  readPGM( &im);

  Serial.print("The size of image = ");
  Serial.println(im.col);
  Serial.println(im.row);
}

void loop()
{
  // put your main code here, to run repeatedly:

}

Pete
 
Back
Top