/************************************************************************** * pilchard_int.c * * Pilchard Interface Code * * Brad Stinson (sbj@y12.doe.gov) UTK ECE 552 Spring 2003 * * Feel free to use this code, but please leave this header intact. * * * * Code to open a 24-bit color bitmap/bif file, load it to memory, and * * handle comm between the FPGA to send the original image, and receive * * the modified image. * * * * This codes loads data to locations 0 - 7, then loads another address * * that specifies what action the FPGA should take (see the code). It * * then polls locations 255 looking for a value of 0x1 which indicates * * that the FPGA is done, memory is then read from locations 0 - 7, and * * adddress 255 is set back to zero. * * * * BMP and BIF file inputs must have widths and heights divisible by 8 * * The code could be modified to buffer images that are not divisible by * * 8. If you do this, remember that BMP files insert buffers (usually * * null bits to make each row (width) evenly divisible by 4. This means * * you will need to remove (or ignore) these null bits before processing * * and you'll need to add them back (or insert them) if building a BMP as * * the output file. I have written code to do this, but I left it out * * because I felt it overly complicated things, and it was somewhat of a * * bottleneck. Contact me if you'd like to see this code. * * * * BIF format is Bouldin Image Format, created by Mike McCollum. * * Java software is available to convert from popular image formats to * * BIF. Contact Mike at jmccoll2@utk.edu for more info * * * * compiled with : gcc -o pilchard_int pilchard_int.c iflib.c * **************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "iflib.h" typedef unsigned char byte; typedef unsigned short word; typedef unsigned long dword; typedef struct tagBITMAP //The structure for a bitmap or bif { word width; word height; byte *data; } BITMAP; /************************************************************************** * fskip * * Skips bytes in a file when reading. * **************************************************************************/ void fskip(FILE *fp, int num_bytes) { int i; for (i=0; i \n\nInput can be either a .bmp or .bif file. Output is new_image.bmp/bif\nin the directory where the program is located.\n\nExample Usage: pilchard_int C:\\test.bmp bmp brighten 50\n\n"); } /************************************************************************** * load_bmp_bif * * Loads a bitmap or bif file into memory. * * file = name of file, b is BITMAP struct mem location, * * type = 1 for bitmap, 0 for bif * **************************************************************************/ void load_bmp_bif(char *file,BITMAP *b,short type) { FILE *fp; long index; int x; if ((fp = fopen(file,"rb")) == NULL) { printf("Error opening file %s.\n",file); exit(1); } if (type) { // check to see if it is a valid bitmap file // bitmap color order is B G R if (fgetc(fp)!='B' || fgetc(fp)!='M') { fclose(fp); printf("%s is not a bitmap file.\n",file); exit(1); } // read in the width and height of the image for a bitmap fskip(fp,16); fread(&b->width, sizeof(word), 1, fp); fskip(fp,2); fread(&b->height,sizeof(word), 1, fp); fskip(fp,30); } else { // read in the width and height of the image for a bif // BIF color order is R G B fread(&b->width, sizeof(word), 1, fp); fread(&b->height,sizeof(word), 1, fp); } //we're going to be working with 24-bit files (8 bits red, 8 green, 8 blue) //memory allocation is width * height * 3 if ((b->data = (byte *) malloc((long)(b->width*b->height*3))) == NULL) { fclose(fp); printf("Error allocating memory for file %s.\n",file); exit(1); } for (index=0;index<=((b->height-1)*b->width*3);index+=(b->width*3)) { for (x=0;x<(b->width*3);x++) //each element in row { b->data[(long)index+x]=(byte)fgetc(fp); } } fclose(fp); } int main(int argc, char *argv[]) { byte opcode, *bmp_file_data, *new_image_pre, *new_image_post_hflip; int color,fd,filetype,i,x,y,j,k,m,n,p,index; long offset,q, dataindex; short params; dword filesize, compression, datasize, hres, wres, headersize, bmpoffset; word planes, bitsperpixel; double temp_float, fraction, integer, elapsed_time; int64 datalong; char *memp; FILE *fp; BITMAP bmp; //check the command line params if (argc < 4) { printf("\nNot Enough Arguments!\n"); helpdisplay(); exit(1); } if ((strcmp(argv[1], "/?") == 0) || (strcmp(argv[1], "/h") == 0)) { helpdisplay(); exit(1); } if (!((strcmp(argv[2], "bif") == 0) || (strcmp(argv[2], "bmp") == 0))) { helpdisplay(); exit(1); } if (strstr(argv[1], "bif") != NULL) { printf("\nLoading BIF file...\n"); filetype = 0; load_bmp_bif(argv[1],&bmp, 0); } else { filetype = 1; printf("\nLoading BMP file...\n"); load_bmp_bif(argv[1],&bmp, 1); } //setup the opcodes based on input commands argv[2] and argv[3] if (strcmp(argv[3],"brighten")== 0){ if (argc < 5) { printf("\nNot Enough Arguments!\n"); helpdisplay(); exit(1); } opcode = 0; printf("Setting up brighten operation...\n"); params = atoi(argv[4]); printf("Setting up lighten operation [%s]...\n", argv[4]); } else if (strcmp(argv[3],"darken") == 0){ if (argc < 5) { printf("\nNot Enough Arguments!\n"); helpdisplay(); exit(1); } opcode = 1; params = atoi(argv[4]); printf("Setting up darken operation [%s]...\n", argv[4]); } else if (strcmp(argv[3],"blur") == 0){ opcode = 2; printf("Setting up blur operation...\n"); } else if (strcmp(argv[3],"negative") == 0){ opcode = 3; printf("Setting up negative operation...\n"); } else if (strcmp(argv[3],"dct") == 0){ opcode = 4; printf("Setting up discrete cosine transform operation...\n"); } else{ printf("Instruction not understood. Please try again.\n"); helpdisplay(); exit(1); } //>>>Address 8: Brighten (w[0] = brightness factor) 0 //>>>Address 9: Darken (w[0] = darkness factor) 1 //>>>Address 10: Blur (no parameters) 2 //>>>Address 11: Negative (no parameters) 3 //>>>Address 12: Discrete Cosine Transform 4 //open dual port ram on pilchard printf("Opening DPRAM on the Pilchard...\n"); fd = open(DEVICE, O_RDWR); memp = (char *)mmap(NULL, MTRRZ, PROT_READ, MAP_PRIVATE, fd, 0); if (memp == MAP_FAILED) { perror(DEVICE); exit(1); } if ((new_image_pre = (byte *) malloc((long)(bmp.width*bmp.height*3*sizeof(byte)))) == NULL) { printf("Error allocating new_image_pre memory"); exit(1); } printf("Segmenting image data and beginning Pilchard load...\n"); elapsed_time = 0; p=0; for (color=0;color<3;color++) { offset = k = (long)color; for(i=0;i<(bmp.width*bmp.height);i+=64) //(width * height)/64 times { printf("Transferring data to the pilchard ( Load [%d] )\n",p++); for (j=0;j<8;j++) { datalong.w[0] = (unsigned long)bmp.data[offset]; offset+=3; datalong.w[0] |= (unsigned long)bmp.data[offset] << 8; offset+=3; datalong.w[0] |= (unsigned long)bmp.data[offset] << 16; offset+=3; datalong.w[0] |= (unsigned long)bmp.data[offset] << 24; offset+=3; datalong.w[1] = (unsigned long)bmp.data[offset]; offset+=3; datalong.w[1] |= (unsigned long)bmp.data[offset] << 8; offset+=3; datalong.w[1] |= (unsigned long)bmp.data[offset] << 16; offset+=3; datalong.w[1] |= (unsigned long)bmp.data[offset] << 24; offset+=3; //write data and wait for response write64(datalong, memp+(j<<3)); //debug data out to pilchard //printf("color = %d, i = %d, offset = %d, datalong0 = %u, datalong1 = %u\n",color,i,offset-3,datalong.w[0],datalong.w[1]); } //getchar(); switch (opcode) { case 0: //brighten write brighten params to address 8 datalong.w[1] = 0x0; datalong.w[0] = params; write64(datalong, memp+(8<<3)); break; case 1: //darken datalong.w[1] = 0x0; datalong.w[0] = params; write64(datalong, memp+(9<<3)); break; case 2: //blur datalong.w[1] = 0x0; datalong.w[0] = 0x1; write64(datalong, memp+(10<<3)); break; case 3: //negative datalong.w[1] = 0x0; datalong.w[0] = 0x1; write64(datalong, memp+(11<<3)); break; case 4: //dct datalong.w[1] = 0x0; datalong.w[0] = 0x1; write64(datalong, memp+(12<<3)); break; } //wait for response, and start building output data //decomment once the VHDL code is complete, get rid of for loop delay //do { // read64(&datalong, memp+(0xFF << 3)); //address 255 looking for it to be set to 0x1; //} while (datalong.w[0] != 0x1); for(j=0;j<10;j++) {} //kill some time <= temporary! printf("Data received...\n"); //now write 255 back to 0 datalong.w[1] = 0x0; datalong.w[0] = 0x0; write64(datalong, memp+(0xFF << 3)); //read in the data from addresses 0 - 7 for (j=0;j<8;j++) { read64(&datalong, memp+(j << 3)); //put received data into a buffer new_image_pre[k]=(datalong.w[0] & 0xff); k += 3; new_image_pre[k]=(datalong.w[0] & 0xff00) >> 8; k += 3; new_image_pre[k]=(datalong.w[0] & 0xff0000) >> 16; k += 3; new_image_pre[k]=(datalong.w[0] & 0xff000000) >> 24; k += 3; new_image_pre[k]=(datalong.w[1] & 0xff); k += 3; new_image_pre[k]=(datalong.w[1] & 0xff00) >> 8; k += 3; new_image_pre[k]=(datalong.w[1] & 0xff0000) >> 16; k += 3; new_image_pre[k]=(datalong.w[1] & 0xff000000) >> 24; k += 3; //debug data coming in from pilchard //printf("color = %d, i = %d, offset = %d, datalong0 = %u, datalong1 = %u\n",color,i,k-3,datalong.w[0],datalong.w[1]); } //getchar(); } } munmap(memp, MTRRZ); close(fd); printf("Assembling and writing output %s file...\n", argv[2]); if ((new_image_post_hflip = (byte *) malloc((long)(bmp.width*bmp.height*3))) == NULL) { printf("Error allocating new_image_post_hflip memory"); exit(1); } if ((bmp_file_data = (byte *) malloc((long)((bmp.width*bmp.height*3)+(3*bmp.height)))) == NULL) //extra 3*bmp.height for buffering the bmp file (not used in this version) { printf("Error allocating new_image_post memory"); exit(1); } x=0; if (strcmp(argv[2],"bif") == 0){ //bif file write if ((fp = fopen("new_image.bif","wb")) == NULL) { printf("Error opening new_image file \n"); exit(1); } fwrite(&bmp.width, sizeof(word), 1, fp); fwrite(&bmp.height, sizeof(word), 1, fp); for (index=0;index<(bmp.width*bmp.height*3);index++) { fputc((byte)new_image_pre[index], fp); } printf("\nFile new_image.bif successfully written.\nProgram Complete!\n"); } //bitmap file write else { if ((fp = fopen("new_image.bmp","wb")) == NULL) { printf("Error opening new_image file \n"); exit(1); } //if it was a bif before, we need to do a horizontal flip if (!filetype){ n=m=0; for (k=0;k0;index--) { fputc((byte)bmp_file_data[index], fp); } } else { for (index=0;index<(filesize - 0x36);index++) { fputc((byte)bmp_file_data[index], fp); } } printf("\nFile new_image.bmp successfully written.\nProgram Complete!\n"); } free(bmp.data); free(new_image_pre); free(new_image_post_hflip); free(bmp_file_data); return 1; }