#include #include #include #include #include #define PRINT_IMG_STATS /*Program by Robert R. Pavlis. This program takes a binary ppm file and subtracts a specified value from each pixel in red green and blue, then normalises to maximum intensity This version works with 16 bit colour. This code is endian sensitive*/ int filelength (const char *fileName); int main (int argc, char *argv[]) { unsigned char *ppmimage, *splitit; unsigned short putvalue; char newname[256], filebase[256]; int width, height, count, colours, fstrlen,redcor, greencor, bluecor,newvalue; long int i, j, k, m, lengthppm, ppmheader; double redmult=1.0, greenmult=1.0, bluemult=1.0; FILE *infileppm, *outfileppm; if (argc != 2) { fprintf (stderr, "This program requires a ppm file name\n"); exit (1); } infileppm = fopen (argv[1], "rb"); if (infileppm == NULL) { printf ("ppm Input file not opened\n"); exit (1); } printf("Enter red correction:\n"); scanf("%d", &redcor); printf("Enter green correction:\n"); scanf("%d", &greencor); printf("Enter blue correction:\n"); scanf("%d", &bluecor); printf("Continuing with red %d, blue %d, and green %d\n",redcor, greencor, bluecor); lengthppm = filelength (argv[1]); ppmimage = (char *) malloc (lengthppm); fread (ppmimage, lengthppm, 1, infileppm); /*the file must be in the binary ppm format, whose magic number is 0x50 0x36 */ if ((ppmimage[0] == 0x50) && (ppmimage[1] == 0x33)) /*magic number for text ppm */ { free (ppmimage); fprintf (stderr, "This program must use binary ppm only!\n"); exit (1); } if ((ppmimage[0] != 0x50) || (ppmimage[1] != 0x36)) { free (ppmimage); fprintf (stderr, "Bad Magic Number!\n"); fprintf (stderr, "%s is NOT a ppm file!\n", argv[1]); exit (1); } fclose (infileppm); /*now we have to parse the start of the headers and see if they contain comments, then we must locate the bytes that have width and length specifications. We then need to search for the 0x0A that ends the preliminary specifications. We must read the bit count/colour */ count = 0; ppmheader = 0; for (i = 0; i < 256; i++) { if (count == 1) break; if (ppmimage[i] == 0x0A) if (ppmimage[i + 1] != 0x23) if (count == 0) { width = atoi (ppmimage + i + 1); count = 1; for (j = 1; j < 16; j++) { if (ppmimage[i + j] == 0x20) { height = atoi (ppmimage + i + j + 1); i = i + j; break; } } for (k = 1; k < 16; k++) { if (ppmimage[i + k] == 0x0A) { colours = atoi (ppmimage + i + k + 1); i = i + k; break; } } } } count = 0; for (m = i; m < 256; m++) { if (ppmimage[m] == 0x0A) count++; if (count == 1) { ppmheader = m + 1; break; } } /*at this point the program has parsed the header */ strcpy (filebase, argv[1]); fstrlen = strlen (filebase); /*filebase[fstrlen - 2] = 0x67;*/ strcpy (newname, "cor_"); strcat (newname, filebase); outfileppm = fopen (newname, "wb"); if (outfileppm == NULL) { printf ("New output file not opened\n"); exit (1); } redmult=(double)colours/((double)colours-redcor); greenmult=(double)colours/((double)colours-greencor); bluemult=(double)colours/((double)colours-bluecor); if (colours < 0x100) for (i = ppmheader; i < lengthppm; i += 3) { newvalue=(ppmimage[i]-redcor)*redmult; if(newvalue<0) newvalue=0; if(newvalue>colours) newvalue=colours; ppmimage[i]=newvalue; newvalue=(ppmimage[i+1]-greencor)*greenmult; if(newvalue<0) newvalue=0; if(newvalue>colours) newvalue=colours; ppmimage[i+1]=newvalue; newvalue=(ppmimage[i+2]-bluecor)*bluemult; if(newvalue<0) newvalue=0; if(newvalue>colours) newvalue=colours; ppmimage[i+2]=newvalue; } else { for (i = ppmheader; i < lengthppm; i += 6) { newvalue=0x100*ppmimage[i]+ ppmimage[i+1]; newvalue-=redcor; newvalue*=redmult; if(newvalue<0) newvalue=0; if(newvalue>colours) newvalue=colours; /*newvalue now has the corrected value, needs to be placed bytewise into array*/ putvalue=newvalue; splitit=(unsigned char*)&putvalue; ppmimage[i]=splitit[1]; ppmimage[i+1]=splitit[0]; newvalue=0x100*ppmimage[i+2]+ ppmimage[i+3]; newvalue-=greencor; newvalue*=greenmult; if(newvalue<0) newvalue=0; if(newvalue>colours) newvalue=colours; putvalue=newvalue; splitit=(unsigned char*)&putvalue; ppmimage[i+2]=splitit[1]; ppmimage[i+3]=splitit[0]; newvalue=0x100*ppmimage[i+4]+ ppmimage[i+5]; newvalue-=bluecor; newvalue*=bluemult; if(newvalue<0) newvalue=0; if(newvalue>colours) newvalue=colours; putvalue=newvalue; splitit=(unsigned char*)&putvalue; ppmimage[i+4]=splitit[1]; ppmimage[i+5]=splitit[0]; } } fwrite (ppmimage,1, lengthppm, outfileppm); free (ppmimage); fclose (outfileppm); #ifdef PRINT_IMG_STATS printf ("width=%d, height=%d colours=%d\n", width, height, colours); #endif } int filelength (const char *fileName) { struct stat *st; st = (struct stat *) malloc (sizeof (struct stat)); if (stat (fileName, st) == -1) exit (1); return st->st_size; }