#include #include #include typedef struct { unsigned int width; unsigned int height; unsigned char* data; } Image; static int readPGM( Image* pgm, FILE* fp ) { int headerNumbersRead = 0; int inNumber = 0; int number = 0; int inHeader = 1; int ch; if ( fp == 0 ) { return __LINE__; } if ( ( ch = fgetc( fp ) ) != 'P' || ( ch = fgetc( fp ) ) != '5' ) { fprintf( stderr, "Not a valid raw pgm file\n" ); return __LINE__; } while ( inHeader && ( ch = fgetc( fp ) ) != EOF ) { if ( isdigit( ch ) ) { if ( !inNumber ) { number = 0; inNumber = 1; } number *= 10; number += ( ch - '0' ); } else { if ( inNumber ) { switch ( ++headerNumbersRead ) { case 1: pgm->width = number; break; case 2: pgm->height = number; break; case 3: inHeader = 0; break; } inNumber = 0; } if ( ch == '#' ) { while ( ( ch = fgetc( fp ) ) != EOF && ch != '\n' ) { /* do nothing */; } } else if ( !isspace( ch ) ) { fprintf( stderr, "Illegal header character <%c>\n", ch ); } } } if ( ch != '\n' ) { while ( ( ch = fgetc( fp ) ) != EOF && ch != '\n' ) { /* do nothing */; } } if ( pgm->width == 0 || pgm->height == 0 ) { fprintf( stderr, "Invalid width or height\n" ); fclose( fp ); return __LINE__; } pgm->data = (unsigned char*)malloc( pgm->width * pgm->height ); if ( pgm->data == 0 ) { fprintf( stderr, "Out of memory\n" ); fclose( fp ); return __LINE__; } fread( pgm->data, 1, pgm->width * pgm->height, fp ); return 0; } static void offsetImage( Image* image, unsigned int offset ) { if ( offset != 0 ) { unsigned char* buf = (unsigned char*)malloc( image->width * image->height ); if ( buf != 0 ) { unsigned int preSize = offset * image->width; unsigned int postSize = ( image->height - offset ) * image->width; memcpy( buf, &image->data[ preSize ], postSize ); memcpy( &buf[ postSize ], image->data, preSize ); free( image->data ); image->data = buf; } } } int main( int argc, const char* argv[] ) { unsigned int help = 0; const char* fileName = 0; FILE* fp = stdin; unsigned int reps = 0; unsigned int offset = 0; unsigned int ii; Image pgm; for ( ii=1; ii < argc; ++ii ) { if ( !strcmp( argv[ ii ], "-file" ) ) { fileName = argv[ ++ii ]; } else if ( !strcmp( argv[ ii ], "-reps" ) ) { reps = strtol( argv[ ++ii ], 0, 0 ); } else if ( !strcmp( argv[ ii ], "-offset" ) ) { offset = strtol( argv[ ++ii ], 0, 0 ); } else { help = 1; } } if ( help ) { fprintf( stderr, "Usage: %s\n", argv[0] ); fprintf( stderr, "\t[-file fileName]\n" ); fprintf( stderr, "\t[-reps repetitions]\n" ); fprintf( stderr, "\t[-offset starting line number]\n" ); return __LINE__; } if ( fileName != 0 ) { fp = fopen( fileName, "rb" ); } if ( readPGM( &pgm, fp ) != 0 ) { fprintf( stderr, "Couldn't read pgm: %s\n", fileName ); if ( fp != 0 ) { fclose( fp ); } return __LINE__; } if ( fp != 0 ) { fclose( fp ); } offsetImage( &pgm, offset % pgm.height ); fprintf( stdout, "%d # %s\n", pgm.width, argv[0] ); for ( ii=0; ( reps == 0 ) || ii < reps; ++ii ) { if ( fwrite( pgm.data, 1, pgm.width * pgm.height, stdout ) != pgm.width * pgm.height ) { fprintf( stderr, "Didn't write a full chunk\n" ); return __LINE__; } } return 0; }