/* rotim-cor.c - Edouard.Thiel@lim.univ-mrs.fr - 13/02/2002 Compilation : cc bsutil.c rotim-cor.c -o rotim-cor \ `~/helium/helium-cfg --cflags --libs` -lm Usage : rotim-cor [image-in.pgm] [image-out.pgm] */ #include #include "bsutil.h" #include /* Variables globales */ He_node *princ, *panel, *text_load, *text_save, *b_quit, *tog_rot, *text_larg, *text_haut, *text_angle, *text_zoom, *text_x1, *text_y1, *text_x2, *text_y2, *fen1_frame = NULL, *fen1_canvas, *fen2_frame = NULL, *fen2_canvas; BsMap *gbm1 = NULL, *gbm2 = NULL; XImage *fen1_xi = NULL, *fen2_xi = NULL; int c_gris, c_rouge, c_vert, c_bleu, c_jaune, c_cyan, c_magenta; /*--------------------------- A F F I C H A G E ------------------------------*/ void init_couleurs () { c_gris = HeAllocRgb (150, 150, 150, he_white); c_rouge = HeAllocRgb (255, 0, 0, he_black); c_vert = HeAllocRgb (0, 255, 0, he_black); c_bleu = HeAllocRgb (0, 0, 255, he_black); c_jaune = HeAllocRgb (255, 255, 0, he_black); c_cyan = HeAllocRgb (0, 255, 255, he_black); c_magenta = HeAllocRgb (255, 0, 255, he_black); } /* * Dessins de base */ void couleur (int coul) { XSetForeground (he_display, he_gc, coul); } void dessin_point (Window win, int x, int y) { XDrawPoint (he_display, win, he_gc, x, y); } void dessin_ligne (Window win, int x1, int y1, int x2, int y2) { XDrawLine (he_display, win, he_gc, x1, y1, x2, y2); } void dessin_fleche (Window win, int x1, int y1, int x2, int y2) { int dx = x1-x2, dy=y1-y2, x, y; double l, a, e = 25*M_PI/180, d = 10; if (dx == 0 && dy == 0) return; l = sqrt(dx*dx+dy*dy); a = acos(dx/l); if (dy < 0) a = -a; dessin_ligne (win, x1, y1, x2, y2); x = x2+d*cos(a+e)+0.5; y = y2+d*sin(a+e)+0.5; dessin_ligne (win, x, y, x2, y2); x = x2+d*cos(a-e)+0.5; y = y2+d*sin(a-e)+0.5; dessin_ligne (win, x, y, x2, y2); } void dessin_cercle (Window win, int x, int y, int r) { XDrawArc (he_display, win, he_gc, x-r, y-r, 2*r, 2*r, 0, 360*64); } void dessin_croix (Window win, int x, int y, int r) { dessin_ligne (win, x, y-r, x, y+r); dessin_ligne (win, x+r, y, x-r, y); } void dessin_rond (Window win, int x, int y) { int d = 3; dessin_cercle (win, x, y, d); } /*-------------------------- A L G O R I T H M E S --------------------------*/ void rotation_simple (BsMap *bm1, BsMap *bm2, int xc1, int yc1, int xc2, int yc2, double angle_degre, double zoom, int coul_fond) { int x1, y1, x2, y2; double a = -angle_degre * M_PI/180, c = cos(a) * zoom, s = sin(a) * zoom; InitWholeBsMap (bm2, coul_fond); for (y1 = 0; y1 < bm1->ysiz; y1++) for (x1 = 0; x1 < bm1->xsiz; x1++) { x2 = xc2 + (x1-xc1)*c - (y1-yc1)*s; y2 = yc2 + (x1-xc1)*s + (y1-yc1)*c; if (x2 >= 0 && y2 >= 0 && x2 < bm2->xsiz && y2 < bm2->ysiz) bm2->tab[y2][x2] = bm1->tab[y1][x1]; } } void rotation_inverse (BsMap *bm1, BsMap *bm2, int xc1, int yc1, int xc2, int yc2, double angle_degre, double zoom, int coul_fond) { int x1, y1, x2, y2; double a = angle_degre * M_PI/180, c = cos(a) / zoom, s = sin(a) / zoom; InitWholeBsMap (bm2, coul_fond); for (y2 = 0; y2 < bm2->ysiz; y2++) for (x2 = 0; x2 < bm2->xsiz; x2++) { x1 = xc1 + (x2-xc2)*c - (y2-yc2)*s; y1 = yc1 + (x2-xc2)*s + (y2-yc2)*c; if (x1 >= 0 && y1 >= 0 && x1 < bm1->xsiz && y1 < bm1->ysiz) bm2->tab[y2][x2] = bm1->tab[y1][x1]; } } void rotation_bilin_inverse (BsMap *bm1, BsMap *bm2, int xc1, int yc1, int xc2, int yc2, double angle_degre, double zoom, int coul_fond) { int x2, y2, xa, ya, xb, yb; double x1, y1, a = angle_degre * M_PI/180, c = cos(a) / zoom, s = sin(a) / zoom; InitWholeBsMap (bm2, coul_fond); for (y2 = 0; y2 < bm2->ysiz; y2++) for (x2 = 0; x2 < bm2->xsiz; x2++) { x1 = xc1 + (x2-xc2)*c - (y2-yc2)*s; y1 = yc1 + (x2-xc2)*s + (y2-yc2)*c; /* Attention, (int) -2.5 = -2 et non -3 */ if (x1 >= 0) { xa = x1; xb = xa+1; } else { xa = x1-1; xb = xa; } if (y1 >= 0) { ya = y1; yb = ya+1; } else { ya = y1-1; yb = ya; } if (xa >= 0 && ya >= 0 && xb < bm1->xsiz && yb < bm1->ysiz) bm2->tab[y2][x2] = bm1->tab[ya][xa] * (xb-x1) * (yb-y1) + bm1->tab[ya][xb] * (x1-xa) * (yb-y1) + bm1->tab[yb][xa] * (xb-x1) * (y1-ya) + bm1->tab[yb][xb] * (x1-xa) * (y1-ya) ; } } /*---------------------------- I N T E R F A C E ----------------------------*/ void fen1_repaint_proc (He_node *hn, Window win) { int xc1 = atoi(HeGetTextValue(text_x1)), yc1 = atoi(HeGetTextValue(text_y1)); if (fen1_xi == NULL) return; PaintXImage (fen1_xi, win); couleur (c_rouge); dessin_croix (win, xc1, yc1, 15); } void fen1_event_proc (He_node *hn, He_event *hev) { char bla[32]; void appliquer_proc (He_node *hn); if (gbm1 == NULL) return; switch (hev->type) { case ButtonPress : case MotionNotify : if (hev->sb == 1) /* Coordonnées x,y */ { sprintf (bla, "%d", hev->sy); HeSetTextValue (text_y1, bla); sprintf (bla, "%d", hev->sx); HeSetTextValue (text_x1, bla); HePostRepaint (fen1_canvas); } break; case ButtonRelease : appliquer_proc (NULL); break; } } void afficher_fen1 () { if (gbm1 == NULL) return; if (fen1_frame == NULL) { fen1_frame = HeCreateFrame (); fen1_canvas = HeCreateCanvas (fen1_frame); } HeSetShow (fen1_frame, TRUE); HeSetFrameLabel (fen1_frame, "Image 1 : original"); HeSetTip (fen1_canvas, "Bouton 1 : x1,y1"); HeSetCanvasRepaintProc (fen1_canvas, fen1_repaint_proc); HeSetCanvasEventProc (fen1_canvas, fen1_event_proc); HeSetX (fen1_canvas, 0); HeSetWidth (fen1_canvas, gbm1->xsiz); HeSetHeight (fen1_canvas, gbm1->ysiz); HeFit (fen1_frame); if (fen1_xi != NULL) FreeXImage (fen1_xi); fen1_xi = NewXImageFromBsMap (gbm1, LUT_GREY); HePostRepaint(fen1_canvas); } void fen2_repaint_proc (He_node *hn, Window win) { int xc2 = atoi(HeGetTextValue(text_x2)), yc2 = atoi(HeGetTextValue(text_y2)); double a = -atof(HeGetTextValue(text_angle))*M_PI/180, d = atoi(HeGetTextValue(text_larg))/5, z = atof(HeGetTextValue(text_zoom)); if (fen2_xi == NULL) return; PaintXImage (fen2_xi, win); couleur (c_rouge); dessin_rond (win, xc2, yc2); dessin_fleche (win, xc2, yc2, xc2+d, yc2); dessin_fleche (win, xc2, yc2, xc2+cos(a)*d*z, yc2+sin(a)*d*z); } void fen2_event_proc (He_node *hn, He_event *hev) { char bla[32]; void appliquer_proc (He_node *hn); if (gbm2 == NULL) return; switch (hev->type) { case ButtonPress : case MotionNotify : if (hev->sb == 1) /* Coordonnées x,y */ { sprintf (bla, "%d", hev->sy); HeSetTextValue (text_y2, bla); sprintf (bla, "%d", hev->sx); HeSetTextValue (text_x2, bla); HePostRepaint (fen2_canvas); } else if (hev->sb == 2) /* Angle */ { static int old_x, old_y; char bla[80]; int angle; if (hev->type == MotionNotify) { angle = ( atoi(HeGetTextValue(text_angle)) - (hev->sx - old_x + hev->sy - old_y) ) % 360; if (angle < 0) angle = 360 - angle; sprintf(bla, "%d", angle); HeSetTextValue(text_angle, bla); HePostRepaint (fen2_canvas); } old_x = hev->sx; old_y = hev->sy; } else if (hev->sb == 3) /* Zoom */ { static int old_x, old_y; char bla[80]; double zoom; if (hev->type == MotionNotify) { zoom = (atof(HeGetTextValue(text_zoom)) - (hev->sx - old_x + hev->sy - old_y)/50. ); sprintf(bla, "%.2f", zoom); HeSetTextValue(text_zoom, bla); HePostRepaint (fen2_canvas); } old_x = hev->sx; old_y = hev->sy; } break; case ButtonRelease : appliquer_proc (NULL); break; } } void fen2_resize_proc (He_node *hn, int width, int height) { char bla[32]; void appliquer_proc (He_node *hn); /* printf ("fen2_resize_proc %d %d\n", width, height); */ HeExpand (fen2_canvas, NULL, HE_BOTTOM_RIGHT); sprintf (bla, "%d", HeGetWidth(fen2_canvas)); HeSetTextValue (text_larg, bla); sprintf (bla, "%d", HeGetHeight(fen2_canvas)); HeSetTextValue (text_haut, bla); appliquer_proc (NULL); } void afficher_fen2 () { if (gbm2 == NULL) return; if (fen2_frame == NULL) { fen2_frame = HeCreateFrame (); fen2_canvas = HeCreateCanvas (fen2_frame); HeSetFrameResizeProc (fen2_frame, fen2_resize_proc); } HeSetShow (fen2_frame, TRUE); HeSetFrameLabel (fen2_frame, "Image 2 : résultat"); HeSetTip (fen2_canvas, "Bouton 1 : x2,y2\n" "Bouton 2 : angle\n" "Bouton 3 : zoom"); HeSetCanvasRepaintProc (fen2_canvas, fen2_repaint_proc); HeSetCanvasEventProc (fen2_canvas, fen2_event_proc); HeSetX (fen2_canvas, 0); HeSetWidth (fen2_canvas, gbm2->xsiz); HeSetHeight (fen2_canvas, gbm2->ysiz); HeFit (fen2_frame); if (fen2_xi != NULL) FreeXImage (fen2_xi); fen2_xi = NewXImageFromBsMap (gbm2, LUT_GREY); HePostRepaint(fen2_canvas); } void quit_proc (He_node *hn) { HeQuit(0); } void appliquer_proc (He_node *hn) { He_node *tmp = HeGetToggleLighted (tog_rot); char *choix = HeGetToggleLabel (tmp); int larg = atoi(HeGetTextValue(text_larg)), haut = atoi(HeGetTextValue(text_haut)), xc1 = atoi(HeGetTextValue(text_x1)), yc1 = atoi(HeGetTextValue(text_y1)), xc2 = atoi(HeGetTextValue(text_x2)), yc2 = atoi(HeGetTextValue(text_y2)); double angle = atof(HeGetTextValue(text_angle)), zoom = atof(HeGetTextValue(text_zoom)); if (gbm1 == NULL || gbm2 == NULL) return; if (zoom == 0) zoom = 1; if (larg != gbm2->xsiz || haut != gbm2->ysiz) { FreeBsMap(gbm2); gbm2 = NewBsMap (haut, larg, 0); if (gbm2 == NULL) return; } if (strcmp (choix, "Simple") == 0) rotation_simple (gbm1, gbm2, xc1, yc1, xc2, yc2, angle, zoom, 127); else if (strcmp (choix, "Inverse") == 0) rotation_inverse (gbm1, gbm2, xc1, yc1, xc2, yc2, angle, zoom, 127); else if (strcmp (choix, "Bilinéaire inverse") == 0) rotation_bilin_inverse (gbm1, gbm2, xc1, yc1, xc2, yc2, angle, zoom, 127); afficher_fen2 (); } void rot_proc (He_node *hn) { if (HeGetToggleValue(hn)) appliquer_proc (NULL); } void text_proc (He_node *hn) { appliquer_proc (NULL); } void text1_proc (He_node *hn) { HePostRepaint (fen1_canvas); appliquer_proc (NULL); } void orig_larghaut_proc (He_node *hn) { char bla[32]; if (gbm1 == NULL) return; sprintf (bla, "%d", gbm1->ysiz); HeSetTextValue (text_haut, bla); sprintf (bla, "%d", gbm1->xsiz); HeSetTextValue (text_larg, bla); text_proc (NULL); } void centre1_proc (He_node *hn) { char bla[32]; if (gbm1 == NULL) return; sprintf (bla, "%d", gbm1->ysiz/2); HeSetTextValue (text_y1, bla); sprintf (bla, "%d", gbm1->xsiz/2); HeSetTextValue (text_x1, bla); if (hn != NULL) HePostRepaint (fen1_canvas); appliquer_proc (NULL); } void centre2_proc (He_node *hn) { char bla[32]; if (gbm2 == NULL) return; sprintf (bla, "%d", gbm2->ysiz/2); HeSetTextValue (text_y2, bla); sprintf (bla, "%d", gbm2->xsiz/2); HeSetTextValue (text_x2, bla); appliquer_proc (NULL); } void load_proc (He_node *hn) { char *nom = HeGetTextValue (text_load); FreeBsMap(gbm1); gbm1 = NULL; FreeBsMap(gbm2); gbm2 = NULL; gbm1 = ReadBsMapFromPGM (nom, 0); if (gbm1 == NULL) { HeSimpleDialog ( HE_DIALOG_BELL, HE_DIALOG_TITLE, "Attention", HE_DIALOG_MESSAGE, "Erreur de lecture du fichier", HE_DIALOG_QUOTED, nom, HE_DIALOG_BUTTOK, "Ok", 0); return; } gbm2 = CopyBsMap (gbm1); orig_larghaut_proc (NULL); centre1_proc (NULL); centre2_proc (NULL); afficher_fen1 (); appliquer_proc (NULL); } void save_proc (He_node *hn) { char *nom = HeGetTextValue (text_save); if (gbm2 == NULL) { HeSimpleDialog ( HE_DIALOG_BELL, HE_DIALOG_TITLE, "Attention", HE_DIALOG_MESSAGE, "Image vide, rien à enregistrer", HE_DIALOG_BUTTOK, "Ok", 0); return; } if (WriteBsMapInPGM (nom, gbm2) < 0) { HeSimpleDialog ( HE_DIALOG_BELL, HE_DIALOG_TITLE, "Attention", HE_DIALOG_MESSAGE, "Erreur d'écriture du fichier", HE_DIALOG_QUOTED, nom, HE_DIALOG_BUTTOK, "Ok", 0); } } He_node *create_textP (He_node *panel, char *nom, He_notify_proc proc, char *val) { He_node *tmp1, *tmp2; tmp1 = HeCreateMessageP (panel, nom, TRUE); tmp2 = HeCreateText (panel); HeSetTextVisibleLen (tmp2, 8); HeSetTextValue (tmp2, val); HeSetTextNotifyProc (tmp2, proc); HeSetClientData (tmp2, tmp1); return tmp2; } /*---------------------------- P R I N C I P A L ----------------------------*/ int main (int argc, char **argv) { int code_sortie; HeInit (&argc, &argv); init_couleurs (); princ = HeCreateFrame(); HeSetFrameLabel (princ, "Rotations d'images"); panel = HeCreatePanel (princ); text_load = HeCreateText (panel); HeSetTextVisibleLen (text_load, 40); HeSetTextCompletion (text_load, TRUE); HeSetTextNotifyProc (text_load, load_proc); HeCreateButtonP (panel, "Charger", load_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); text_save = HeCreateText (panel); HeSetTextVisibleLen (text_save, 40); HeSetTextCompletion (text_save, TRUE); HeSetTextNotifyProc (text_save, save_proc); HeCreateButtonP (panel, "Sauver ", save_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); text_larg = create_textP (panel, " Larg", text_proc, NULL); text_haut = create_textP (panel, "Haut", text_proc, NULL); HeCreateButtonP (panel, "Original", orig_larghaut_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); text_angle = create_textP (panel, "Angle", text_proc, "10"); text_zoom = create_textP (panel, "Zoom", text_proc, "1"); HeSetPanelLayout (panel, HE_LINE_FEED); text_x1 = create_textP (panel, " x1", text1_proc, NULL); text_y1 = create_textP (panel, " y1", text1_proc, NULL); HeCreateButtonP (panel, "Centre", centre1_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); text_x2 = create_textP (panel, " x2", text_proc, NULL); text_y2 = create_textP (panel, " y2", text_proc, NULL); HeCreateButtonP (panel, "Centre", centre2_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); tog_rot = HeCreateToggleRadioP (panel, "Simple", rot_proc, NULL); HeCreateToggleRadioP (panel, "Inverse", rot_proc, tog_rot); HeCreateToggleRadioP (panel, "Bilinéaire inverse", rot_proc, tog_rot); HeSetPanelLayout (panel, HE_LINE_FEED); HeCreateButtonP (panel, "Appliquer", appliquer_proc, NULL); b_quit = HeCreateButtonP (panel, "Quitter", quit_proc, NULL); HeSetPanelLayout (panel, HE_LINE_FEED); HeFit(panel); HeFit(princ); HeJustify (b_quit, NULL, HE_RIGHT); if (argc > 1) { HeSetTextValue (text_load, argv[1]); load_proc(text_load); } HeSetTextValue (text_save, argc > 2 ? argv[2] : "tmp1.pgm"); code_sortie = HeMainLoop (princ); FreeBsMap(gbm1); gbm1 = NULL; FreeBsMap(gbm2); gbm2 = NULL; FreeXImage (fen1_xi); fen1_xi = NULL; FreeXImage (fen2_xi); fen2_xi = NULL; return code_sortie; }