/***************************************************** * * file d:\cips\delas.c * * Functions: This file contains * main * display_image_portion * read_string * read_image * my_read * get_image_name * get_parameters * show_parameters * read_header * color_transform * display_menu * * Purpose: This program displays images on the EGA * monitor. * It can display either a 300x500 section of a * single * channel of an image, or three channels of a * 100x500 * section of an image. This can use either a straight * mapping of 256 gray levels to 16 colors or a modified * mapping that brings out selected objects in the image. * * Modifications: * 17 June 1987 - created * 8 August 1987 - added the ability to draw a * grid over the image and label areas with * a C or an L. * 30 August 1987 - major changes made so that this is * the only display routine needed. * 9 April 1988 - moved to Borland's Turbo C 1.5. * This has a library of graphics routines that * are more reliable and execute faster. * 13 September 1990 - put in function * blank_out_display to help reduce * the contrast when taking photos. * 15 September 1990 - put the x_offset and * y_offset parameters in to center the * image display. * ********************************************************/ #include "d:\lsu\vision3.h" short image[ROWS][COLS]; main() { char channels[80], color_transform[80], file_name[80], response[80]; int a, b, c, channel, double_display, horizontal, ie, il, key, le, ll, not_finished, r, vertical, x_offset, y_offset; unsigned int block, color, i, j, x, y; unsigned long histogram[256]; _setvideomode(_TEXTC80); /* MSC 6.0 statements */ _setbkcolor(1); _settextcolor(7); _clearscreen(_GCLEARSCREEN); strcpy(file_name, "d:/images/nbrite.dat"); strcpy(channels, "Single channel"); strcpy(color_transform, "Modified transform"); channel = 1; il = 1; ll = 100; ie = 1; le = 100; horizontal = 5; vertical = 4; double_display = 0; printf("\nThis is the display program."); printf("\nThis program can either display a 300x500 section of"); printf("\nan image or three channels of a 100x500 section of an"); printf("\nimage. The parameters entered describe the upper left"); printf("\n100x100 corner of the display."); not_finished = 1; while(not_finished){ display_menu(channels, color_transform); get_image_name(file_name); get_parameters(&channel, &il, &ie, &ll, &le, &horizontal, &vertical, &double_display); /******************************************* * * we want to set an offset so the image is * centered on the CRT * ********************************************/ x_offset = 0; y_offset = 0; x_offset = (6-horizontal)*100; x_offset = 20 + x_offset/2; y_offset = (4-vertical)*100; y_offset = 40 + y_offset/2; /********************************************* * * If the color_transform requires histogram * equalization, then calculate the histogram * from the four corners of the image. You * will use this in the display loop below * to equalize the image. * **********************************************/ if(color_transform[0] == 'H'){ printf("\nCalculating histograms"); zero_long_histogram(histogram); printf("\n\t1"); read_image(image, file_name, channel, il, ie, ll, le); calculate_long_histogram(image, histogram); printf("\n\t2"); read_image(image, file_name, channel, il+400, ie, ll+400, le); calculate_long_histogram(image, histogram); printf("\n\t3"); read_image(image, file_name, channel, il, ie+400, ll, le+400); calculate_long_histogram(image, histogram); printf("\n\t4"); read_image(image, file_name, channel, il+400, ie+400, ll+400, le+400); calculate_long_histogram(image, histogram); for(a=0; a<256; a++) printf("\nh[%4d] = %8d", a, histogram[a]); } /* ends if color_transform == H */ /********************************************* * * Find out what the key should be. This * requires looking at the name of the image * that is being displayed. Use a different * key for the three different channels of * the image. * **********************************************/ key = 0; if(file_name[16] == '1') key = 1; if(file_name[16] == '2') key = 2; if(file_name[16] == '3') key = 3; if( (file_name[16] == '.') && (channel == 1)) key = 1; if( (file_name[16] == '.') && (channel == 2)) key = 2; if( (file_name[16] == '.') && (channel == 3)) key = 3; /* set graphics mode */ /******* map_16_shades_of_gray(_VRES16COLOR); blank_out_display(); ********/ my_set_colors(); /*************************************************** * * If a single channel is desired then display a 300x500 * section of one channel. If multiple channels * are desired then display one 100x500 section * of the image three times. * *****************************************************/ if( (channels[0] == 'S') || (channels[0] == 's')){ for(a=0; a Enter choice (0 for no change) "); printf("\nDISPLAY> 1. Channels-- %s", channels); printf("\nDISPLAY> 2. Color Transform-- %s", color_transform); printf("\nDISPLAY> _\b"); get_integer(&r); if(r == 0){ not_finished = 0; } if(r == 1){ printf("\nDISPLAY> Enter the new channel mode "); printf("\nDISPLAY> (S) Single channel (M) Multiple channel"); printf("\nDISPLAY> _\b"); read_string(response); if((response[0] == 'S') || (response[0] == 's')) strcpy(channels, "Single channel"); else strcpy(channels, "Multiple channels"); } /* ends if r == 1 */ if(r == 2){ printf("\nDISPLAY> Enter the new color transform mode "); printf("\nDISPLAY> (S) Straight mode"); printf(" (M) Modified mode"); printf(" (R) Results mode"); printf(" (H) Histogram Equalization"); printf("\nDISPLAY> _\b"); read_string(response); if((response[0] == 'S') || (response[0] == 's')) strcpy(color_transform, "Straight mode"); if((response[0] == 'M') || (response[0] == 'm')) strcpy(color_transform, "Modified mode"); if((response[0] == 'H') || (response[0] == 'h')) strcpy(color_transform, "Histogram Equalization Mode"); if((response[0] == 'R') || (response[0] == 'r')) strcpy(color_transform, "Results Mode"); } /* ends if r == 2 */ } /* ends while not_finished */ } /* ends display_menu */ display_image_portion(image, key, desired_color_transform, x, y, x_offset, y_offset, double_display) char desired_color_transform[]; int key, x_offset, y_offset, double_display; short image[ROWS][COLS]; unsigned int x, y; { unsigned int color, i, j; for(i=0; i ROWS) last_i = ROWS; last_j = le; if(le > COLS) last_j = COLS; file_descriptor = my_open(file_name); origin = 0; /* seek from beginning of file */ offset = (long)(header_size) + ((il-1)*nc + (channel-1))*line_length; position = lseek(file_descriptor, offset, origin); for(i=0; inbih = lcu.l_num; value = 4; long_equate(in_buffer, &lcu, value); params->nbpr = lcu.l_num; value = 8; long_equate(in_buffer, &lcu, value); params->il = lcu.l_num; value = 12; long_equate(in_buffer, &lcu, value); params->ll = lcu.l_num; value = 16; long_equate(in_buffer, &lcu, value); params->ie = lcu.l_num; value = 20; long_equate(in_buffer, &lcu, value); params->le = lcu.l_num; value = 24; long_equate(in_buffer, &lcu, value); params->nc = lcu.l_num; value = 28; long_equate(in_buffer, &lcu, value); params->f321 = lcu.l_num; value = 36; long_equate(in_buffer, &lcu, value); params->y_offset = lcu.l_num; value = 40; for(i=0; i<4; i++) params->desc2[i] = in_buffer[value + i]; value = 44; long_equate(in_buffer, &lcu, value); params->x_offset = lcu.l_num; value = 48; float_equate(in_buffer, &fcu, value); params->y_spot_size = fcu.f_num; value = 52; float_equate(in_buffer, &fcu, value); params->x_spot_size = fcu.f_num; value = 56; for(i=0; i<4; i++){ float_equate(in_buffer, &fcu, (value+i*4)); params->transform[i] = fcu.f_num; } value = 96; for(i=0; i<=256; i++) params->comments[i] = in_buffer[i + value]; value = 32; for(i=0; i<4; i++) params->desc1[i] = in_buffer[value + i]; closed_file = close(file_descriptor); } /* end of read_header */ /***************************************************** * * show_header(name, params) * * This function shows the header input to the * function. * *****************************************************/ show_header(name, params) char name[]; struct header_parameters *params; { int i; char c, line1[64], line2[64], line3[64], line4[64], response[80]; for(i=0; i<64; i++){ line1[i] = params->comments[i]; line2[i] = params->comments[i + 64]; line3[i] = params->comments[i + 128]; line4[i] = params->comments[i + 192]; } line1[63] = '\0'; line2[63] = '\0'; line3[63] = '\0'; line4[63] = '\0'; printf("\nFile name is %s", name); printf("\nnbih=%d",params->nbih); printf("\nnbpr=%d",params->nbpr); printf("\nil=%d",params->il); printf("\nll=%d",params->ll); printf("\nie=%d",params->ie); printf("\nle=%d",params->le); printf("\nnc=%d",params->nc); printf("\n4321=%d",params->f321); printf("\nDescriptor1=%c%c%c%c", params->desc1[0], params->desc1[1], params->desc1[2], params->desc1[3]); printf("\ny offset=%d",params->y_offset); printf("\nDescriptor2=%c%c%c%c", params->desc2[0], params->desc2[1], params->desc2[2], params->desc2[3]); printf("\nx offset=%d",params->x_offset); printf("\ny spot size=%f",params->y_spot_size); printf("\nx spot size=%f",params->x_spot_size); printf("\nThe transform matrix is %f %f %f %f", params->transform[0], params->transform[1], params->transform[2], params->transform[3]); printf("\ncomments"); printf("\n>%s",line1); printf("\n>%s",line2); printf("\n>%s",line3); printf("\n>%s",line4); printf("\nHit RETURN to continue"); read_string(response); } /* end show_header */ /********************************************************* * * file c:\lsu\unions.c * * Functions: This file contains * long_equate * float_equate * store_long_into_buffer * store_float_into_buffer * * Purpose: These functions are used when reading and * writing ELAS image headers. They pack and * unpack floating point numbers and integers * from a buffer of characters. * * External Calls: * none * * Modifications: * July 1986 - ported to IBM-PC * *********************************************************/ long_equate(buffer, lcu, start) char buffer[]; int start; union long_char_union *lcu; { int i; lcu->l_num = 0; for(i=0; i<4; i++){ lcu->l_alpha[3-i] = buffer[start + i]; } /* this is i not 3-i on none 8086 systems */ /* the same is true for the other functions */ /* in this file */ } float_equate(buffer, fcu, start) char buffer[]; int start; union float_char_union *fcu; { int i; for(i=0; i<4; i++) fcu->f_alpha[3-i] = buffer[start + i]; } store_long_into_buffer(buffer, lcu, start) char buffer[]; int start; union long_char_union *lcu; { int i; for(i=0; i<4; i++) buffer[start + i] = lcu->l_alpha[3-i]; } store_float_into_buffer(buffer, fcu, start) char buffer[]; int start; union float_char_union *fcu; { int i; for(i=0; i<4; i++) buffer[start + i] = fcu->f_alpha[3-i]; } /****************************************************** * * file c:\lsu\intcvrt.c * * Functions: This file contains * get_integer * int_convert * * Purpose: These functions convert a string of * characters to their number value. * * Modifications: * Taken from Jamsa's software package * and altered to fit into the computer * vision programming 22 August 1986. * *******************************************************/ #include "d:\tc\numdefs.h" get_integer(n) int *n; { char string[80]; read_string(string); int_convert(string, n); } int_convert (ascii_val, result) char *ascii_val; int *result; { int sign = 1; /* -1 if negative */ *result = 0; /* value returned to the calling routine */ /* read passed blanks */ while (is_blank(*ascii_val)) ascii_val++; /* get next letter */ /* check for sign */ if (*ascii_val == '-' || *ascii_val == '+') sign = (*ascii_val++ == '-') ? -1 : 1; /* find sign */ /* * convert the ASCII representation to the actual * decimal value by subtracting '0' from each character. * * for example, the ASCII '9' is equivalent to 57 in decimal. * by subtracting '0' (or 48 in decimal) we get the desired * value. * * if we have already converted '9' to 9 and the next character * is '3', we must first multiply 9 by 10 and then convert '3' * to decimal and add it to the previous total yielding 93. * */ while (*ascii_val) if (is_digit(*ascii_val)) *result = *result * 10 + to_decimal(*ascii_val++); else return (IO_ERROR); *result = *result * sign; return (NO_ERROR); } color_transform(pixel, key, type_of_transform) char type_of_transform[]; int key; short pixel; { unsigned int color; if( (type_of_transform[0] == 'M') || (type_of_transform[0] == 'm')){ if(key == 1){ if((pixel >= 0) && (pixel < 16)) color = 0; if((pixel >= 16) && (pixel < 32)) color = 1; if((pixel >= 32) && (pixel < 48)) color = 2; if((pixel >= 48) && (pixel < 64)) color = 3; if((pixel >= 64) && (pixel < 80)) color = 4; if((pixel >= 80) && (pixel < 96)) color = 5; if((pixel >= 96) && (pixel < 190)) color = 8; /*if((pixel >= 112) && (pixel < 128)) color = 7; if((pixel >= 128) && (pixel < 144)) color = 8; if((pixel >= 150) && (pixel < 160)) color = 9; if((pixel >= 160) && (pixel < 176)) color = 10; if((pixel >= 176) && (pixel < 192)) color = 11; if((pixel >= 190) && (pixel < 208)) color = 12; if((pixel >= 208) && (pixel < 224)) color = 13; if((pixel >= 224) && (pixel < 240)) color = 14;*/ if((pixel >= 190) && (pixel <= 255)) color = 15; } /* ends if key == 1 */ if(key == 2){ if((pixel >= 0) && (pixel < 16)) color = 0; if((pixel >= 16) && (pixel < 32)) color = 1; if((pixel >= 32) && (pixel < 48)) color = 2; if((pixel >= 48) && (pixel < 64)) color = 3; if((pixel >= 64) && (pixel < 80)) color = 4; if((pixel >= 80) && (pixel < 96)) color = 5; if((pixel >= 96) && (pixel < 190)) color = 6; if((pixel >= 112) && (pixel < 128)) color = 7; if((pixel >= 128) && (pixel < 144)) color = 8; if((pixel >= 150) && (pixel < 160)) color = 9; if((pixel >= 160) && (pixel < 176)) color = 10; if((pixel >= 176) && (pixel < 192)) color = 11; /*if((pixel >= 190) && (pixel < 208)) color = 12; if((pixel >= 208) && (pixel < 224)) color = 13; if((pixel >= 224) && (pixel < 240)) color = 14;*/ if((pixel >= 192) && (pixel <= 255)) color = 15; } /* ends if key == 2 */ if(key == 3){ if((pixel >= 0) && (pixel < 16)) color = 0; if((pixel >= 16) && (pixel < 30)) color = 1; if((pixel >= 30) && (pixel < 55)) color = 2; if((pixel >= 55) && (pixel < 64)) color = 3; if((pixel >= 64) && (pixel < 80)) color = 4; if((pixel >= 80) && (pixel < 96)) color = 5; if((pixel >= 96) && (pixel < 190)) color = 6; if((pixel >= 112) && (pixel < 120)) color = 7; if((pixel >= 120) && (pixel < 140)) color = 8; if((pixel >= 140) && (pixel < 160)) color = 9; if((pixel >= 160) && (pixel < 176)) color = 10; if((pixel >= 176) && (pixel < 192)) color = 11; if((pixel >= 192) && (pixel < 208)) color = 12; if((pixel >= 208) && (pixel < 224)) color = 13; if((pixel >= 224) && (pixel < 240)) color = 14; if((pixel >= 240) && (pixel < 255)) color = 15; } /* ends if key == 3 */ } /* ends if type_of_transform == Modified */ if( (type_of_transform[0] == 'S') || (type_of_transform[0] == 's')) color = pixel/16; if( (type_of_transform[0] == 'R') || (type_of_transform[0] == 'r')){ if(pixel == 0) color = 3; if(pixel == 40) color = 6; if(pixel == 41) color = 9; if(pixel == 69) color = 12; if(pixel == 97) color = 15; } /* ends results mode */ return(color); } /* ends color_transform */ /***************************************************** ******** * * file c:\lsu\mof.c * * Functions: This file contains * my_open * * Purpose: This function opens a file. Borland's * Turbo C opens files a little different from * the standard UNIX C. Instead of using this * different method in a number of various files, * the method is placed in this one file. If the * programs are moved to another system, all changes * will be located in this one place. * * External Calls: * none * * Modifications: * 18 June 1987 - created * ****************************************************** *********/ my_open(file_name) char file_name[]; { int file_descriptor; file_descriptor = open(file_name, O_RDWR | O_CREAT | O_BINARY, S_IWRITE); return(file_descriptor); } /* ends my_open */ /********************************************** * * map_16_shades_of_gray(... * * This function maps 16 shades of gray into * the first 16 color indices. This allows * you to display a true "black and white" * image on a color monitor. * *********************************************/ map_16_shades_of_gray(display_mode) int display_mode; { /* all MSC 6.0 statements */ _setvideomode(display_mode); _remappalette(0, 0x000000L); _remappalette(1, 0x040404L); _remappalette(2, 0x080808L); _remappalette(3, 0x0c0c0cL); _remappalette(4, 0x101010L); _remappalette(5, 0x141414L); _remappalette(6, 0x181818L); _remappalette(7, 0x1c1c1cL); _remappalette(8, 0x202020L); _remappalette(9, 0x242424L); _remappalette(10, 0x282828L); _remappalette(11, 0x2c2c2cL); _remappalette(12, 0x303030L); _remappalette(13, 0x343434L); _remappalette(14, 0x383838L); _remappalette(15, 0x3f3f3fL); } /********************************** * * Modes for the SigmaVGA Legend * (hex) * 10 - 640x350x64? * 12 - 640x480x16 * 29 - 800x600x16 * 30 - 800x600x256 * 38 - 1024x768x256 * ***********************************/ my_set_video_mode() { union REGS regs; regs.h.al = 0x29; /* mode */ regs.h.ah = 0x00; int86(0x10, ®s, ®s); } /* ends my_set_video_mode */ my_set_pixel(x, y, color) unsigned int x, y, color; { union REGS regs; regs.h.ah = 0x0c; regs.x.dx = y; regs.x.cx = x; regs.h.al = color; regs.h.bh = 0; int86(0x10, ®s, ®s); } /* ends my_set_pixel */ lookup(color) int color; { int table[16] = {0, 1, 4, 5, 8, 2, 6, 9, 3, 12, 13, 7, 10, 11, 14, 15}; return(table[color]); } /* ends lookup */ my_set_colors() { _asm{ mov ax,0029h ; 800x600x16 int 10h mov ah,10h mov al,1bh mov bx,0h mov cx,100h int 10h } } /* ends my_set_colors */ /***************************************** * * perform_histogram_equalization(... * ******************************************/ perform_histogram_equalization(image, histogram, new_grays, area) float new_grays, area; short image[ROWS][COLS]; unsigned long histogram[]; { int i, j, k; unsigned long sum, sum_of_h[256]; double constant; sum = 0; for(i=0; i<256; i++){ sum = sum + histogram[i]; sum_of_h[i] = sum; } /* constant = new # of gray levels div by area */ /*constant = new_grays/area;*/ constant = 0.0004; /* 16/40000 = 0.0004 */ for(i=0; i