/* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. */ /* * pbm.c - interface with PBP/PGM/PPM file formats. * * Author: Raul Rivero * Mathematics Dept. * University of Oviedo * Date: Mon Feb 3 1992 * Copyright (c) 1992, Raul Rivero * */ #include #include extern int LUGverbose; read_pbm_file( name, bitmap ) char *name; bitmap_hdr *bitmap; { FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "rb" ); else handle = stdin; /* Read the bitmap */ read_pbm( handle, bitmap ); rm_compress(); /* Close the file */ Fclose( handle ); } read_pbm(handle, image) FILE *handle; bitmap_hdr *image; { int type; int totalsize; /* Is really a PBM file */ if ( fgetc(handle) != 'P' ) error( 5 ); /* Get its type */ switch( type = fgetc(handle) - '0' ) { case 1: case 4: image->depth = 1; image->cmap = (byte *) Malloc( 6 ); image->cmap[3] = image->cmap[4] = image->cmap[5] = 255; break; case 2: case 5: image->depth = 8; image->cmap = create_bw_pallete(); break; case 3: case 6: image->depth = 24; break; default: fprintf( stderr, "Unknow PBM file type (%d)\n", type ); error( 99 ); } /* Get the sizes and depth */ image->colors = ( 1 << image->depth ); image->magic = LUGUSED; skip_pbm( handle ); fscanf( handle, "%d", &(image->xsize) ); fscanf( handle, "%d", &(image->ysize) ); totalsize = image->xsize * image->ysize; /* Ok, we have it all. Allocate memory */ image->r = (byte *) Malloc( totalsize ); if ( image->depth > 8 ) { image->g = (byte *) Malloc( totalsize ); image->b = (byte *) Malloc( totalsize ); } if ( type < 4 ) { /* An ASCII file */ fprintf( stderr, "The PBM/PGM/PPM ascii file format type is not supported.\n" ); error( 99 ); }else { register int i, j; byte *line, *ptr; byte *rb, *gb, *bb; switch ( type ) { case 4: line = image->r; ptr = line + totalsize; skip_pbm( handle ); /* One byte has 8 pixels, so ... */ while ( line < ptr ) { i = fgetc( handle ); for ( j = 7; j >= 0; j-- ) *line++ = i & ( 1 << j ); } break; case 5: /* Skip the max. value */ fscanf( handle, "%d", &type ); skip_pbm( handle ); /* Read the raw data info */ Fread( image->r, totalsize, 1, handle ); break; case 6: /* Skip the max. value */ fscanf( handle, "%d", &type ); skip_pbm( handle ); /* Set pointers */ line = (byte *) Malloc( 3 * image->xsize ); rb = image->r; gb = image->g; bb = image->b; /* Read each line and split RGB */ for ( i = 0; i < image->ysize; i++ ) { Fread( line, 3, image->xsize, handle ); j = image->xsize, ptr = line; while ( j-- ) { *rb++ = *ptr++; *gb++ = *ptr++; *bb++ = *ptr++; } } /* Free memory */ free( line ); break; } } return 0; } write_pbm_file( name, image ) char *name; bitmap_hdr *image; { FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "wb" ); else handle = stdout; /* Write the bitmap */ write_pbm( handle, image ); /* Close the file */ Fclose( handle ); } write_pbm(handle, image) FILE *handle; bitmap_hdr *image; { int totalsize = image->xsize * image->ysize; bitmap_hdr aux_bitmap; byte *r, *g, *b, *end; register int i, j; if ( image->magic != LUGUSED ) error( 19 ); switch( image->depth ) { case 1: /** B&W images **/ /* * Write the file header: P4 ( b&w / binary format ) * and the image sizes. */ fprintf( handle, "P4\n" ); fprintf( handle, "# PBM image generated by The LUG Library\n"); fprintf( handle, "%d %d\n", image->xsize, image->ysize ); /* Set pointers */ r = image->r; end = r + image->xsize * image->ysize; /* * Now pack all the image. We can build a * single byte from 8 pixels. */ while ( r < end ) { for ( i = 7, j = 0; i >= 0 && r < end; i-- ) if ( *r++ ) j |= ( 1 << i ); fputc( j, handle ); } break; case 32: /** Futures releases **/ case 24: /** True color images **/ /* * Write the file header: P6 ( true color / binary format ), * the image sizes and the max. value. */ fprintf( handle, "P6\n" ); fprintf( handle, "# PBM image generated by The LUG Library\n"); fprintf( handle, "%d %d 255\n", image->xsize, image->ysize ); /* Set pointers */ r = image->r; g = image->g; b = image->b; while ( totalsize-- ) { fputc( *r++, handle ); fputc( *g++, handle ); fputc( *b++, handle ); } break; default: /** Mapped images ( ... ok, only gray mapped ) **/ /* * Write the file header: P5 ( gray map / binary format ), * the image sizes and the max. value. */ fprintf( handle, "P5\n" ); fprintf( handle, "# PGM image generated by The LUG Library\n"); fprintf( handle, "%d %d 255\n", image->xsize, image->ysize ); /* * Now we need a raster level information, so convert * our image ... and write it !. */ to_raw_bw( image, &aux_bitmap ); Fwrite( aux_bitmap.r, totalsize, 1, handle ); /* Free memory */ freebitmap( &aux_bitmap ); break; } return 0; } /* * PBM files suport coments, so if a line begin with * a '#' char then ... */ skip_pbm( handle ) FILE *handle; { int c; while ( !feof( handle ) ) { /* Skip until next line */ while( fgetc( handle ) != '\n' ); /* * If the first char is a '#' then we have * a comment ( so we re-begin ), else return. */ if ( (c = fgetc( handle )) != '#' ) { ungetc( c, handle ); return; } } /* * Hmmm ???, if all the pbm image was comments I suppose * an error, and you ?. */ error( 6 ); }