home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GRIPS 2: Government Rast…rocessing Software & Data
/
GRIPS_2.cdr
/
dos
/
imdisp
/
source
/
imagutil.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-20
|
20KB
|
574 lines
/*************************************************************/
/* 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);
}