home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************/
- /* Copyright (C) 1989, California Institute of Technology */
- /* U. S. Government Sponsorship under NASA Contract */
- /* NAS7-918 is acknowledged. */
- /*************************************************************/
-
- /*** IMDISP module IMAGUTIL.C
-
- Special Purpose Device Independant Display Routines
-
- Contains high level display routines such as interactive palette
- adjustment, histogram display, and image profile drawing.
- ***/
-
- /* Changed 10/6/87 to read cursor keys without numlock - mdm */
-
- /* * * * INCLUDE files * * * */
-
- #include <conio.h>
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "imdef.h"
- #include "imdisp.h"
- #include "dispio.h"
- #include "disputil.h"
-
- /* * * * External functions * * * */
-
- /* * * * Function declarations * * * */
-
- int DiddlePalette (int );
- int DisplayHistogram (long *,int ,int ,int );
- int Stretch (int ,int );
- int Profile (void);
- void DoNegative(void);
- void ShowPalette( int);
- void ErasePalette( int);
-
- /* * * * Global Variables * * * */
-
-
-
- int DiddlePalette( int numdiddle)
-
- /*** DiddlePalette performs interactive adjustment of the color
- palette. A wedge of numdiddle DN values, from 0 to the maximum,
- is displayed at the bottom of the screen, and the palette is
- changed to have only numdiddle distinct shades. Then a loop
- for user input is entered. The active color is the one in the
- wedge with the small black box inside it.
-
- The following is a list of commands:
- Character Action
- 7 (HOME) move to first color in wedge
- 4 (6) move to next lower (higher) color in wedge
- ^4 (^6) move 8 steps lower (higher) in wedge
- r (R) decrease (increase) amount of red one notch
- g (G) decrease (increase) amount of green one notch
- b (B) decrease (increase) amount of blue one notch
- S scroll palette right
- s scroll palette left
- 2 (8) decrease (increase) amount of all colors one notch
- 1 (END) move to last color in wedge
- x (X) invert color wedge
- . exit from palette diddle mode
-
- The wedge is erased after the user exits.
-
- Parameter Type Description
- numdiddle int number of colors in the wedge and resulting palette
-
- ***/
-
- {
- int line, samp, i, box, DN, numbox, DNperbox, shade, numcol;
- int boxnl, boxns, linepos, samppos, marksize, len;
- int colornum;
- unsigned char ch; /* mdm 10/6/87 */
- unsigned char PaletteLine[MAXDISPNS];
- unsigned char hold, holdr, holdg, holdb;
- struct Color coltab[256];
- char dispstr[60];
-
- /* Set up some constants */
- numbox = min (numDN, numdiddle);
- DNperbox = numDN / numbox;
- boxns = dispns / numbox;
- boxnl = dispnl / 10;
- marksize = 8;
- linepos = dispnl - (boxnl / 2) - (marksize / 2);
-
- /* Draw the palette on the bottom of the screen */
- ShowPalette( numdiddle );
-
- /* Reduce the number of colors in the palette to numbox */
- ReadPalette (coltab);
- for (box = 0; box < numbox; box++)
- {
- DN = box*DNperbox;
- for (i = DN; i < DN+DNperbox; i++)
- { coltab[i].r = coltab[DN].r;
- coltab[i].g = coltab[DN].g;
- coltab[i].b = coltab[DN].b;
- }
- }
- WritePalette (coltab);
-
- box = numbox / 2;
- samppos = box*boxns - (boxns / 2) - (marksize / 2);
- DrawBox (linepos, samppos, marksize, marksize, 0);
- shade = /*max(*/ 256 / numshades /*, 16)*/;
-
- /* Interactively adjust the palette */
- do {
- /* Save EGA settings in colornun: (red) (grn) (blue) */
- if (DisplayDevice == EGA350 || DisplayDevice == EGA480
- || DisplayDevice == VGA480)
- {
- colornum = (int)(coltab[DN].r/64);
- colornum = (colornum << 2) | (0x03 & (int)(coltab[DN].g/64));
- colornum = (colornum << 2) | (0x03 & (int)(coltab[DN].b/64));
- }
-
- if ((ch = getch()) == 0) /* mdm 10/9/87 */
- ch = 0x80 | getch();
-
- DN = (box-1)*DNperbox;
- DrawBox (linepos, samppos, marksize, marksize, DN);
-
- switch (ch)
- {
- case 'r' :
- coltab[DN].r = coltab[DN].r - shade;
- if (coltab[DN].r < 0) coltab[DN].r = 255;
- break;
- case 'R' :
- coltab[DN].r = (coltab[DN].r + shade)%256;
- /*min (coltab[DN].r + shade,255);*/
- break;
- case 'g' :
- coltab[DN].g = coltab[DN].g - shade;
- if (coltab[DN].g < 0) coltab[DN].g = 255;
- break;
- case 'G' :
- coltab[DN].g = (coltab[DN].g + shade)%256;
- /*min (coltab[DN].g + shade,255);*/
- break;
- case 'b' :
- coltab[DN].b = max (coltab[DN].b - shade,0);
- if (coltab[DN].b < 0) coltab[DN].b = 255;
- break;
- case 'B' :
- coltab[DN].b = (coltab[DN].b + shade)%256;
- /*min (coltab[DN].b + shade,255);*/
- break;
- case 'X' : /* xchange color table values */
- case 'x' :
- for (i = 1; i <= numbox/2; i++)
- { hold = coltab[numbox-i].r;
- coltab[numbox-i].r = coltab[i-1].r;
- coltab[i-1].r = hold;
-
- hold = coltab[numbox-i].g;
- coltab[numbox-i].g = coltab[i-1].g;
- coltab[i-1].g = hold;
-
- hold = coltab[numbox-i].b;
- coltab[numbox-i].b = coltab[i-1].b;
- coltab[i-1].b = hold;
- }
- break;
- case 'S' : /* shift color table one right */
- holdr = coltab[numbox-1].r;
- holdg = coltab[numbox-1].g;
- holdb = coltab[numbox-1].b;
- for (i = numbox-1; i > 0; i--)
- {
- coltab[i].r = coltab[i-1].r;
- coltab[i].g = coltab[i-1].g;
- coltab[i].b = coltab[i-1].b;
- }
- coltab[0].r = holdr;
- coltab[0].g = holdg;
- coltab[0].b = holdb;
- break;
- case 's' : /* shift color table one left */
- holdr = coltab[0].r;
- holdg = coltab[0].g;
- holdb = coltab[0].b;
- for (i = 1; i < numbox ; i++)
- {
- coltab[i-1].r = coltab[i].r;
- coltab[i-1].g = coltab[i].g;
- coltab[i-1].b = coltab[i].b;
- }
- coltab[numbox-1].r = holdr;
- coltab[numbox-1].g = holdg;
- coltab[numbox-1].b = holdb;
- break;
- case DOWN_ARROW:
- case '2' :
- if ( (DisplayDevice == EGA350 || DisplayDevice == EGA480)
- && numshades == 4)
- {
- --colornum;
- coltab[DN].b = 64 * (colornum & 0x03);
- coltab[DN].g = 64 * ((colornum >> 2) & 0x03);
- coltab[DN].r = 64 * ((colornum >> 4) & 0x03);
- }
- else
- {
- coltab[DN].r = coltab[DN].r - shade;
- coltab[DN].g = coltab[DN].g - shade;
- coltab[DN].b = coltab[DN].b - shade;
- }
- break;
- case UP_ARROW:
- case '8' :
- if ( (DisplayDevice == EGA350 || DisplayDevice == EGA480)
- && numshades == 4)
- {
- ++colornum;
- coltab[DN].b = 64 * (colornum & 0x03);
- coltab[DN].g = 64 * ((colornum >> 2) & 0x03);
- coltab[DN].r = 64 * ((colornum >> 4) & 0x03);
- } else {
- /*
- coltab[DN].r = min (coltab[DN].r + shade,255);
- coltab[DN].g = min (coltab[DN].g + shade,255);
- coltab[DN].b = min (coltab[DN].b + shade,255);
- */
- coltab[DN].r = (coltab[DN].r + shade) % 256;
- coltab[DN].g = (coltab[DN].g + shade) % 256;
- coltab[DN].b = (coltab[DN].b + shade) % 256;
- }
- break;
- case RIGHT_ARROW:
- case '6' :
- box = min (box+1, numbox);
- goto Skip;
- case LEFT_ARROW:
- case '4' :
- box = max (box-1, 1);
- goto Skip;
- case CONTROL_RIGHT_ARROW:
- box = min (box+(numDN>>3), numbox);
- goto Skip;
- case CONTROL_LEFT_ARROW:
- box = max (box-(numDN>>3), 1);
- goto Skip;
- case HOME:
- case '7' :
- box = 1;
- goto Skip;
- case END:
- case '1' :
- box = numbox;
- goto Skip;
- }
- for (i = DN; i < DN+DNperbox; i++)
- { coltab[i].r = coltab[DN].r;
- coltab[i].g = coltab[DN].g;
- coltab[i].b = coltab[DN].b;
- }
- WritePalette (coltab);
-
- Skip:
- samppos = box*boxns - (boxns / 2) - (marksize / 2);
- DrawBox (linepos, samppos, marksize, marksize, 0);
- DN = (box-1)*DNperbox;
- sprintf( dispstr, "color = %2d red = %3d green = %3d blue = %3d",
- DN, coltab[DN].r, coltab[DN].g, coltab[DN].b);
-
- LengthText( dispstr, TextHeight, &len);
- EraseText( TextLine, 1, TextHeight, len, 0);
-
- DrawText( dispstr, TextLine, 1, TextHeight, 0, numDN-1);
-
- if (ch == RETURN || ch == ESCAPE) ch = '.';
- }
- while (ch != '.');
-
-
- /* Erase the palette on the screen */
- ErasePalette( numdiddle );
-
- }
-
-
- int DisplayHistogram (long int * histbuf, int numbins, int minDN, int maxDN)
-
- /*** DisplayHistogram diplays the passed histogram on the screen.
- The third highest bin in the histogram is used to scale the
- plot. The axes of the plot are labeled and annotated. The
- number in each bin is indicated by the length of the line
- drawn vertically from the axis.
-
- Parameter Type Description
- histbuf long int array the array of count values for each bin
- numbins int the number of bins in the histogram
- minDN int the minimum DN value in the histogram
- maxDN int the maximum DN value in the histogram
-
- ***/
-
- {
- int top, bottom, left, right, height, pixperbin, width;
- int i, DN, j, length, tic, tic_height=5;
- int num_Xtics=16, num_Ytics=10, num_Xlabels=8, num_Ylabels=5;
- long count, MaxCount;
- char dispstring[16];
-
-
- top = dispnl / 10;
- bottom = dispnl - top;
- left = dispns / 10;
- right = dispns - (dispns / 100);
- height = bottom - top;
- pixperbin = (right - left) / numbins;
- width = (numbins+1)*pixperbin;
- right = left + width - 1; /* reset right edge */
-
-
- MaxCount = max3arr( histbuf, numbins);
-
- /* Draw the x axis (DN value) */
- /* DrawLine (bottom, left, bottom, right, numDN-1); */
- FrameBox( top, left, bottom, right, numDN-1, FALSE);
- tic = (numbins / 16) * pixperbin;
- tic_height = dispnl / 100;
- /* Put in the tic marks */
- for (i = 0; i <= num_Xtics; i++)
- {
- j = left + pixperbin + i*tic;
- DrawLine (bottom, j, bottom+tic_height, j, numDN-1);
- }
- /* Put in the labels */
- for (i = 0; i <= num_Xlabels; i++)
- {
- DN = i*0.125*((float)maxDN-minDN+1) + (float)minDN + 0.5;
- if (DN < 0) DN--;
- sprintf (dispstring, "%3d", DN);
- j = left + (((numbins*i) / 8) + 1)*pixperbin - 15;
- DrawText (dispstring, bottom+20, j, SmallChars, 0, numDN-1);
- }
- /* And write out the X-axis title */
- DrawText ("DN value", bottom+40, left+(width / 2) - 75, TextHeight, 0, numDN-1);
-
-
- /* Draw the y axis (Counts) */
- /* DrawLine (bottom, left, top, left, numDN-1); */
- for (i = 0; i <= num_Ytics; i++)
- {
- j = bottom - height*i/num_Ytics;
- DrawLine (j, left, j, left-tic_height, numDN-1);
- }
- DrawText ("0", bottom-5, left-20, SmallChars, 0, numDN-1);
- sprintf (dispstring, "%5ld", MaxCount);
- DrawText (dispstring, bottom-height+5, left-60, SmallChars, 0, numDN-1);
- DrawText ("Counts", bottom-(height / 2)+50, left-20, TextHeight, 90, numDN-1);
-
-
-
- /* Draw the histogram lines */
- j = left;
- for (i = 0; i < numbins; i++)
- {
- j += pixperbin;
- if (histbuf[i] > MaxCount)
- length = height;
- else
- length = height*((float)histbuf[i]/(float)MaxCount) + 0.5;
-
- if (Color_Hist)
- DrawLine (bottom, j, bottom-length, j, i); /* color histo */
- else
- DrawLine (bottom, j, bottom-length, j, numDN-1);
- }
-
- }
-
- int Stretch (int DNlow, int DNhigh)
-
- /*** Stretch applies a linear gray scale ramp to the palette
- starting with 0 at Dnlow and proceeding to 255 at DNhigh.
-
- Parameter Type Description
- DNlow int the starting DN value of the linear ramp
- DNhigh int the ending DN value of the linear ramp
-
- ***/
- /* int DNlow, DNhigh; */
- {
- struct Color CT[256];
- float slope;
- int i, shade;
-
-
- if (DNhigh > numDN-1) DNhigh = numDN-1;
- if (DNhigh < 0) DNhigh = numDN-1;
- if (DNlow < 0) DNlow = 0;
- if (DNlow > numDN-1) DNlow = 0;
- slope = 256/ (float)(DNhigh - DNlow + 1);
- for (i = 0; i < numDN; i++)
- {
- shade = slope*(i-DNlow) + 0.5;
- if (shade < 0) shade = 0;
- if (shade > 255) shade = 255;
- CT[i].r = shade;
- CT[i].g = shade;
- CT[i].b = shade;
- }
- WritePalette (CT);
- }
-
- int Profile( void )
-
- /*** Profile plots a profile of the pixel values between two points
- on the screen. Cursor mode is used to select the two endpoints.
- A line is drawn between the endpoints and a plot of DN value
- versus distance along the line is made.
- ***/
- {
- int line1, samp1, line2, samp2;
- int line, samp, distance, delline, delsamp;
- int bottom, left, height, width, top, right;
- int DN, minDN, maxDN;
- int i, j, numpoints;
- float t, scalefact;
- char dispstring[64];
- int DNvalues[MAXDISPNL+MAXDISPNS];
- int Pixels[MAXDISPNL+MAXDISPNS];
- unsigned char SavePatch[CURSORSIZE][CURSORSIZE];
-
-
- MoveCursor (&line1, &samp1);
- PlaceCursor (line1, samp1, numDN-1); CursorOn = 0;
- for (i = 0; i < CURSORSIZE; i++)
- for (j = 0; j < CURSORSIZE; j++)
- SavePatch[i][j] = CursorPatch[i][j];
- MoveCursor (&line2, &samp2);
- for (i = 0; i < CURSORSIZE; i++)
- for (j = 0; j < CURSORSIZE; j++)
- CursorPatch[i][j] = SavePatch[i][j];
- CursorOn = 1; CursorLine = line1; CursorSample = samp1;
- RemoveCursor();
- if (line1==line2 && samp1==samp2) return;
- delline = line2 - line1; delsamp = samp2 - samp1;
- distance = sqrt( (float)
- ( (long)delline*delline + (long)delsamp*delsamp ) ) + 0.5;
-
-
- bottom = dispnl - 45; left = 60;
- height = dispnl/3; width = dispns - 150;
- top = bottom - height; right = left + width;
-
- minDN = 255; maxDN = 0;
- numpoints = distance;
- if (numpoints > width / 2) numpoints = width / 2;
- for (i = 0; i <= numpoints; i++)
- {
- t = (float)i/numpoints;
- line = line1 + (int)(delline*t+0.5);
- samp = samp1 + (int)(delsamp*t+0.5);
- ReadPixel (line, samp, &DN);
- if (DN < minDN) minDN = DN;
- if (DN > maxDN) maxDN = DN;
- DNvalues[i] = DN;
- Pixels[i] = (int)(width*t+0.5) + left;
- }
-
- if (minDN == maxDN) scalefact = 0;
- else scalefact = (float)height/(maxDN - minDN);
- for (i = 0; i<= numpoints; i++)
- DNvalues[i] = bottom - (int)( scalefact*(DNvalues[i] - minDN) + 0.5);
-
-
- DrawLine (line1, samp1, line2, samp2, numDN-1);
-
- /* Draw the x axis (Pixels) */
- DrawLine (bottom, left, bottom, right, numDN-1);
- DrawLine (bottom, right, bottom-5, right, numDN-1);
- DrawText ("0", bottom+20, left, SmallChars, 0, numDN-1);
- sprintf (dispstring, "%4d", distance);
- DrawText (dispstring, bottom+20, right-30, SmallChars, 0, numDN-1);
- DrawText ("Pixels", bottom+25, left+(width/2) - 70, TextHeight, 0, numDN-1);
-
-
- /* Draw the y axis (DN value) */
- DrawLine (bottom, left, top, left, numDN-1);
- DrawLine (top, left, top, left+5, numDN-1);
- sprintf (dispstring, "%3d", minDN);
- DrawText (dispstring, bottom-5, left-40, SmallChars, 0, numDN-1);
- sprintf (dispstring, "%3d", maxDN);
- DrawText (dispstring, top+5, left-40, SmallChars, 0, numDN-1);
- DrawText ("DN Value", bottom-(height / 2)+50, left-30, TextHeight, 90, numDN-1);
-
-
- for (i = 0; i < numpoints; i++)
- DrawLine (DNvalues[i], Pixels[i], DNvalues[i+1], Pixels[i+1], numDN-1);
-
- }
-
- void DoNegative(void)
- {
- int i;
- unsigned char hold;
- struct Color coltab[256];
-
- ReadPalette(coltab);
-
- for (i = 1; i <= numDN/2; i++)
- { hold = coltab[numDN-i].r;
- coltab[numDN-i].r = coltab[i-1].r;
- coltab[i-1].r = hold;
-
- hold = coltab[numDN-i].g;
- coltab[numDN-i].g = coltab[i-1].g;
- coltab[i-1].g = hold;
-
- hold = coltab[numDN-i].b;
- coltab[numDN-i].b = coltab[i-1].b;
- coltab[i-1].b = hold;
- }
-
- WritePalette(coltab);
- }
-
-
- void ShowPalette( int numdiddle)
- {
- int samp, box, line, i;
- int numbox, DNperbox, boxns, boxnl;
- unsigned char PaletteLine[MAXDISPNS];
-
- /* Set up some constants */
- numbox = min (numDN, numdiddle);
- DNperbox = numDN / numbox;
- boxns = dispns / numbox;
- boxnl = dispnl / 10;
- samp = 0;
-
- for (box = 0; box < numbox; box++)
- for (i = 0; i < boxns; i++)
- PaletteLine[samp++] = box*DNperbox;
-
- for (line = dispnl-boxnl; line <= dispnl; line++)
- DisplayLine (PaletteLine, line, 1, numbox*boxns);
- }
-
-
- void ErasePalette( int numdiddle)
- {
- int samp, box, line, i;
- int numbox, DNperbox, boxns, boxnl;
- unsigned char PaletteLine[MAXDISPNS];
-
- /* Set up some constants */
- numbox = min (numDN, numdiddle);
- DNperbox = numDN / numbox;
- boxns = dispns / numbox;
- boxnl = dispnl / 10;
- samp = 0;
-
- for (box = 0; box < numbox; box++)
- for (i = 0; i < boxns; i++)
- PaletteLine[samp++] = 0;
-
- for (line = dispnl-boxnl; line <= dispnl; line++)
- DisplayLine (PaletteLine, line, 1, numbox*boxns);
- }
-