📄 editor.c
字号:
/*===========================================================================*
*
* YACME
* Yet Another ColorMap Editor
*
* Patrick BOUCHAUD - 1993
* SGI Switzerland
*
* Converted to OpenGL using GLUT
*
*===========================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include "mallocbis.h"
/* For portability... */
#undef fsqrt
#define fsqrt(_a) sqrt(_a)
#define SUP(a,b) ( ((a)>(b)) ? (a) : (b) )
#define INF(a,b) ( ((a)<(b)) ? (a) : (b) )
#define ABS(a) ( ((a)<0) ? -(a) : (a) )
#define POINT 1
#define CURVE 2
#define LEFT_TAN 3
#define RIGHT_TAN 4
#define MANUAL 1
#define CONTINUOUS 2
#define CONSTANT 1
#define LINEAR 2
#define POLYNOMIAL 3
#define TabCmpnt(c,n) TabCmpnt[(n)*4+(c)]
#define MAXNDX (dimlut-1)
#define WINHEIGHT 381
#define WINWIDTH 318
#define LUTRATIO ((float)MAXNDX/255.)
#define LEFT LUTRATIO*(-5.)
#define RIGHT LUTRATIO*(260.)
#define BOTTOM LUTRATIO*(-5.)
#define TOP LUTRATIO*(315.)
#define TANLEN LUTRATIO*(25.)
typedef float Matrix[4][4];
typedef struct {
float x0, y0,
x1, y1;
} Tangente;
typedef struct UserPointStruct {
float x, y;
Tangente tg;
int mode;
float polynome[4];
struct UserPointStruct *next, *last;
} UserPoint;
void ResetCMap(void);
void ApplyCMap(void);
void YACME_makeMenu(void);
extern void invertmat(float from[4][4], float to[4][4]);
static UserPoint *FreePointList = NULL;
#define newPoint( point ) newItem( point, FreePointList, UserPoint )
#define freePoint( point ) freeItem( point, FreePointList )
typedef struct {
int type,
cmpnt,
ndx;
UserPoint *upoint;
} PickObject;
struct {
int leftdown, middledown, rightdown;
} mouse;
void YACME_pick( int mx, int my, PickObject *obj );
void YACME_update( int cmpnt, UserPoint *upoint );
int YACME_get( unsigned long *table );
void DeletePoint( int cmpnt, UserPoint *upoint );
int MovePoint( int, int );
int MoveTangente( int, int, int );
int InsertPoint( PickObject *obj );
void GetPolynome( int mode,
float a0, float b0, float t0,
float a1, float b1, float t1,
float coeff[4] );
void OrthoTransform( int mx, int my, float *x, float *y );
float Polynome4( float x, float *polynome );
static int DrawCurve[4] = { 1, 1, 1, 1, },
modifiedCurve[4] = { 1, 1, 1, 1 },
YACME_refresh = MANUAL,
curCmpnt = 0, curType = 0,
Mousex, Mousey;
static float *TabCmpnt;
static int YACME_switch_menu = 0,
YACME_mode_menu, YACME_edit_menu;
static int YACME_win = 0, W, H , update = 0;
static UserPoint *userPoint[4], *userPointSvg[4], *curPoint = NULL;
static void Redraw( void );
static void Reshape( int, int );
static void Mouse( int, int, int, int );
static void Motion( int, int );
static void Key( unsigned char, int, int );
static void Special( int, int, int );
static void YACME_menuFunc( int );
typedef void (*CallBack)(void);
static CallBack newmapCB, applyCB;
static int dimlut;
/*---------------------------------------------------------------------------*
* YACME_init
*---------------------------------------------------------------------------*/
void
YACME_init(
int x, int y, int w, int h,
int dim, float **list,
CallBack newmapFunc, CallBack applyFunc)
{
int i, j;
UserPoint *userpoint;
if (YACME_win) return;
dimlut = dim;
newmapCB = newmapFunc;
applyCB = applyFunc;
if (*list==NULL)
{
*list = TabCmpnt = (float *) malloc( 4*dimlut*sizeof(float) );
for (i=0; i<4; i++)
{
newPoint( userPoint[i] );
userpoint = userPoint[i];
userpoint->mode = POLYNOMIAL;
userpoint->x = 0.;
userpoint->y = 0.;
userpoint->last = NULL;
userpoint->tg.x0 = 0.;
userpoint->tg.y0 = 0.;
userpoint->tg.x1 = TANLEN;
userpoint->tg.y1 = 0.;
newPoint( userpoint->next );
userpoint = userpoint->next;
userpoint->mode = POLYNOMIAL;
userpoint->x = (float)MAXNDX;
userpoint->y = (float)MAXNDX;
userpoint->last = userPoint[i];
userpoint->next = NULL;
userpoint->tg.x0 = (float)(MAXNDX-TANLEN);
userpoint->tg.y0 = (float)MAXNDX;
userpoint->tg.x1 = (float)MAXNDX;
userpoint->tg.y1 = (float)MAXNDX;
}
}
else
{
UserPoint *upoint[4], *lastupoint[4]={0,0,0,0};
TabCmpnt = *list;
for (i=0; i<dim; i++)
{
for (j=0; j<4; j++)
{
if (i==0)
{
newPoint( userPoint[j] );
upoint[j] = userPoint[j];
}
else
{
newPoint( upoint[j]->next );
upoint[j] = upoint[j]->next;
}
upoint[j]->next = NULL;
upoint[j]->last = lastupoint[j];
upoint[j]->mode = LINEAR;
upoint[j]->x = (float)i;
upoint[j]->y = (float)MAXNDX*TabCmpnt(j,i);
if (i==0)
{
upoint[j]->tg.x0 = 0.;
upoint[j]->tg.y0 = 0.;
upoint[j]->tg.x1 = TANLEN;
upoint[j]->tg.y1 = 0.;
}
else
{
float slope = upoint[j]->y - upoint[j]->last->y,
dx = TANLEN/fsqrt(slope*slope + 1),
dy = slope*dx;
upoint[j]->tg.x0 = upoint[j]->x - dx;
upoint[j]->tg.y0 = upoint[j]->y - dy;
upoint[j]->tg.x1 = upoint[j]->x + dx;
upoint[j]->tg.y1 = upoint[j]->y + dy;
}
lastupoint[j] = upoint[j];
}
}
}
/*
TabComponents update
--------------------
*/
for (i=0; i<4; i++)
{
for (userpoint=userPoint[i]; userpoint!=NULL; userpoint=userpoint->next)
YACME_update( i, userpoint );
}
ApplyCMap();
if (!YACME_win)
{
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
glutInitWindowPosition( x, y );
glutInitWindowSize( w, h );
YACME_win = glutCreateWindow( "LUT editor" );
glutDisplayFunc( Redraw );
glutReshapeFunc( Reshape );
glutMouseFunc( Mouse );
glutMotionFunc( Motion );
glutPassiveMotionFunc( Motion );
glutSpecialFunc( Special );
glutKeyboardFunc( Key );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( LEFT, RIGHT, BOTTOM, TOP, -1., 1. );
glClearColor( 0.66, 0.66, 0.66, 1. );
glClear( GL_COLOR_BUFFER_BIT );
glShadeModel( GL_FLAT );
glutSwapBuffers();
YACME_makeMenu();
}
}
/*---------------------------------------------------------------------------*
* Key
*---------------------------------------------------------------------------*/
/* ARGSUSED1 */
static void
Key( unsigned char key, int x, int y )
{
UserPoint *previousPoint;
switch (key)
{
case 27: /* Escape */
exit(0);
break;
case 127: /* BackSpace */
case 8: /* Delete */
if (!curPoint) return;
previousPoint = (curPoint->last ? curPoint->last : userPoint[curCmpnt]);
DeletePoint( curCmpnt, curPoint );
modifiedCurve[curCmpnt] = 1;
update = 1;
curPoint = previousPoint;
break;
}
glutPostRedisplay();
}
/*---------------------------------------------------------------------------*
* Special
*---------------------------------------------------------------------------*/
/* ARGSUSED1 */
static void
Special( int key, int xx, int yy )
{
int x, y, minx, maxx;
float dx, dy;
if (curPoint == NULL ) return;
if (curPoint->next == NULL) return;
if (curPoint->last == NULL) return;
x = (int)curPoint->x;
y = (int)curPoint->y;
minx = (int)curPoint->last->x; minx++;
maxx = (int)curPoint->next->x; maxx--;
switch (key)
{
case GLUT_KEY_LEFT:
if (x > minx) x--;
break;
case GLUT_KEY_RIGHT:
if (x < maxx) x++;
break;
case GLUT_KEY_UP:
if (y < MAXNDX) y++;
break;
case GLUT_KEY_DOWN:
if (y > 0) y--;
break;
}
dx = (float)x - curPoint->x;
curPoint->x += dx;
curPoint->tg.x0 += dx;
curPoint->tg.x1 += dx;
dy = (float)y - curPoint->y;
curPoint->y = y;
curPoint->tg.y0 += dy;
curPoint->tg.y1 += dy;
update = 1;
glutPostRedisplay();
}
/*---------------------------------------------------------------------------*
* Reshape
*---------------------------------------------------------------------------*/
static void
Reshape( int w, int h )
{
glViewport( 0, 0, w, h );
W = w;
H = h;
glutPostRedisplay();
}
/*---------------------------------------------------------------------------*
* Mouse
*---------------------------------------------------------------------------*/
static void
Mouse( int button, int state, int x, int y )
{
PickObject object;
y = H-y;
switch (button)
{
case GLUT_RIGHT_BUTTON:
mouse.rightdown = (state==GLUT_DOWN);
break;
case GLUT_MIDDLE_BUTTON:
mouse.middledown = (state==GLUT_DOWN);
break;
case GLUT_LEFT_BUTTON:
mouse.leftdown = (state==GLUT_DOWN);
if (mouse.leftdown)
{
YACME_pick( x, y, &object );
curType = object.type;
switch ( object.type )
{
case CURVE:
if ((curType = InsertPoint( &object ) != 0))
{
curPoint = object.upoint;
curCmpnt = object.cmpnt;
}
else curPoint = NULL;
break;
case POINT:
case LEFT_TAN:
case RIGHT_TAN:
curPoint = object.upoint;
curCmpnt = object.cmpnt;
break;
default:
curPoint = NULL;
}
break;
}
}
glutPostRedisplay();
}
/*---------------------------------------------------------------------------*
* Motion
*---------------------------------------------------------------------------*/
static void
Motion( int x, int y )
{
Mousex = x;
Mousey = H-y;
if (mouse.leftdown)
{
switch (curType)
{
case POINT:
update = MovePoint( Mousex, Mousey );
break;
case LEFT_TAN:
update = MoveTangente( -1, Mousex, Mousey );
break;
case RIGHT_TAN:
update = MoveTangente( 1, Mousex, Mousey );
break;
}
}
glutPostRedisplay();
}
/*---------------------------------------------------------------------------*
* YACME_makeMenu
*---------------------------------------------------------------------------*/
#define CONTINUOUS_ITEM 5
#define MANUAL_ITEM 4
#define APPLY_ITEM 3
#define RESET_ITEM 2
#define CLOSE_ITEM 1
#define RED_ITEM 10
#define GREEN_ITEM 11
#define BLUE_ITEM 12
#define ALPHA_ITEM 13
#define CONSTANT_ITEM 22
#define LINEAR_ITEM 21
#define POLYNOM_ITEM 20
#define EDIT_RED_ITEM 30
#define EDIT_GREEN_ITEM 31
#define EDIT_BLUE_ITEM 32
#define EDIT_ALPHA_ITEM 33
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -