mirror of
https://github.com/eddyem/eddys_snippets.git
synced 2025-12-06 02:35:12 +03:00
Almost ready image view OpenGL module
This commit is contained in:
parent
bf7a247678
commit
4e5d015e53
60
Bresenham_circle.c
Normal file
60
Bresenham_circle.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char *drawCircle(int R, int geom){
|
||||||
|
if(R > 200 || R < 1) return NULL;
|
||||||
|
int S, i, Y = 2 * R + 2;
|
||||||
|
if(geom)
|
||||||
|
S = Y * (R + 1);
|
||||||
|
else
|
||||||
|
S = Y * (Y - 1);
|
||||||
|
char *buf = malloc(S+1);
|
||||||
|
if(!buf) return NULL;
|
||||||
|
memset(buf, ' ', S);
|
||||||
|
buf[S] = 0;
|
||||||
|
for(i = Y-1; i < S; i+=Y) buf[i] = '\n';
|
||||||
|
inline void DrawPixel(int x, int y){
|
||||||
|
if(geom){
|
||||||
|
if(y%2==0) buf[Y * y/2 + x] = '*';
|
||||||
|
}else{
|
||||||
|
buf[Y * y + x] = '*';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Bresenham's circle algorithm
|
||||||
|
int x = R;
|
||||||
|
int y = 0;
|
||||||
|
int radiusError = 1-x;
|
||||||
|
while(x >= y){
|
||||||
|
DrawPixel(x + R, y + R);
|
||||||
|
DrawPixel(y + R, x + R);
|
||||||
|
DrawPixel(-x + R, y + R);
|
||||||
|
DrawPixel(-y + R, x + R);
|
||||||
|
DrawPixel(-x + R, -y + R);
|
||||||
|
DrawPixel(-y + R, -x + R);
|
||||||
|
DrawPixel(x + R, -y + R);
|
||||||
|
DrawPixel(y + R, -x + R);
|
||||||
|
y++;
|
||||||
|
if (radiusError < 0){
|
||||||
|
radiusError += 2 * y + 1;
|
||||||
|
}else{
|
||||||
|
x--;
|
||||||
|
radiusError += 2 * (y - x) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
int i, R;
|
||||||
|
char *buf;
|
||||||
|
for(i = 1; i < argc; i++){
|
||||||
|
if(!(buf = drawCircle(R = atoi(argv[i]), 1))){
|
||||||
|
printf("Wrong parameter %s\n", argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("\nCircle with R = %d:\n%s\n", R, buf);
|
||||||
|
free(buf); buf = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,189 +0,0 @@
|
|||||||
// bmpview.c
|
|
||||||
//
|
|
||||||
// Copyright 2010 Edward V. Emelianoff <eddy@sao.ru>
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
// MA 02110-1301, USA.
|
|
||||||
//-lglut
|
|
||||||
#include "bmpview.h"
|
|
||||||
#include "macros.h"
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
int totWindows = 0; // total number of opened windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
void *GLloop(){
|
|
||||||
FNAME();
|
|
||||||
glutMainLoop();
|
|
||||||
return NULL;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create window & run main loop
|
|
||||||
*/
|
|
||||||
void createWindow(windowData *win){
|
|
||||||
FNAME();
|
|
||||||
if(!win) return;
|
|
||||||
int w = win->w, h = win->h;
|
|
||||||
/*
|
|
||||||
char *argv[] = {PROJNAME, NULL};
|
|
||||||
int argc = 1;
|
|
||||||
glutInit(&argc, argv);
|
|
||||||
*/
|
|
||||||
glGenTextures(1, &(win->Tex));
|
|
||||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
|
|
||||||
glutInitWindowSize(w, h);
|
|
||||||
win->GL_ID = glutCreateWindow(win->title);
|
|
||||||
DBG("created GL_ID=%d", win->GL_ID);
|
|
||||||
glutIdleFunc(Redraw);
|
|
||||||
glutReshapeFunc(Resize);
|
|
||||||
glutDisplayFunc(RedrawWindow);
|
|
||||||
glutKeyboardFunc(keyPressed);
|
|
||||||
glutSpecialFunc(keySpPressed);
|
|
||||||
glutMouseFunc(mousePressed);
|
|
||||||
glutMotionFunc(mouseMove);
|
|
||||||
win->z = 0.;
|
|
||||||
createMenu(win->ID);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, win->Tex);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
||||||
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, win->rawdata);
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
totWindows++;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
void showid(int id){
|
|
||||||
printf("ID: %d\n", id);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* destroy window with OpenGL or inner identificator "window"
|
|
||||||
* @param window inner or OpenGL id
|
|
||||||
* @param idtype = INNER or OPENGL
|
|
||||||
* @return 1 in case of OK, 0 if fault
|
|
||||||
*/
|
|
||||||
int destroyWindow(int window, winIdType type){
|
|
||||||
windowData *win;
|
|
||||||
int canceled = 1;
|
|
||||||
if(type == OPENGL)
|
|
||||||
win = searchWindow_byGLID(window);
|
|
||||||
else
|
|
||||||
win = searchWindow(window);
|
|
||||||
if(!win) return 0;
|
|
||||||
//forEachWindow(showid);
|
|
||||||
pthread_mutex_lock(&win->mutex);
|
|
||||||
if(!pthread_cancel(win->thread)){ // cancel thread changing data
|
|
||||||
canceled = 0;
|
|
||||||
}
|
|
||||||
pthread_join(win->thread, NULL);
|
|
||||||
glDeleteTextures(1, &win->Tex);
|
|
||||||
glFinish();
|
|
||||||
glutDestroyWindow(win->GL_ID);
|
|
||||||
win->GL_ID = 0; // reset for forEachWindow()
|
|
||||||
pthread_mutex_unlock(&win->mutex);
|
|
||||||
if(!canceled && !pthread_cancel(win->thread)){ // cancel thread changing data
|
|
||||||
WARN(_("can't cancel a thread!"));
|
|
||||||
}
|
|
||||||
pthread_join(win->thread, NULL);
|
|
||||||
if(!removeWindow(win->ID)) WARNX(_("Error removing from list"));
|
|
||||||
totWindows--;
|
|
||||||
//forEachWindow(showid);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color){
|
|
||||||
char *c;
|
|
||||||
int x1=x, W=0;
|
|
||||||
for(c = string; *c; c++){
|
|
||||||
W += glutBitmapWidth(font,*c);// + 1;
|
|
||||||
}
|
|
||||||
x1 -= W/2;
|
|
||||||
glColor3ubv(color);
|
|
||||||
glLoadIdentity();
|
|
||||||
glTranslatef(0.,0., -150);
|
|
||||||
//glTranslatef(x,y, -4000.);
|
|
||||||
for (c = string; *c != '\0'; c++){
|
|
||||||
glColor3ubv(color);
|
|
||||||
glRasterPos2f(x1,y);
|
|
||||||
glutBitmapCharacter(font, *c);
|
|
||||||
//glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
|
|
||||||
x1 = x1 + glutBitmapWidth(font,*c);// + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void redisplay(int GL_ID){
|
|
||||||
glutSetWindow(GL_ID);
|
|
||||||
glutPostRedisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Redraw(){
|
|
||||||
forEachWindow(redisplay);
|
|
||||||
usleep(10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RedrawWindow(){
|
|
||||||
int window;
|
|
||||||
window = glutGetWindow();
|
|
||||||
windowData *win = searchWindow_byGLID(window);
|
|
||||||
if(!win) return;
|
|
||||||
if(pthread_mutex_trylock(&win->mutex) != 0) return;
|
|
||||||
/* Clear the windwindowDataow to black */
|
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
glLoadIdentity();
|
|
||||||
glTranslatef(-win->w/2.,-win->h/2., win->z);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, win->Tex);
|
|
||||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, win->w, win->h, GL_RGB, GL_UNSIGNED_BYTE, win->rawdata);
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glTexCoord2f(0., 1.); glVertex3f(0., 0., 0.);
|
|
||||||
glTexCoord2f(0., 0.); glVertex3f(0., win->h, 0.);
|
|
||||||
glTexCoord2f(1., 0.); glVertex3f(win->w, win->h, 0.);
|
|
||||||
glTexCoord2f(1., 1.); glVertex3f(win->w, 0., 0.);
|
|
||||||
glEnd();
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
glFinish();
|
|
||||||
glutSwapBuffers();
|
|
||||||
pthread_mutex_unlock(&win->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Resize(int width, int height){
|
|
||||||
FNAME();
|
|
||||||
int window = glutGetWindow();
|
|
||||||
windowData *win = searchWindow_byGLID(window);
|
|
||||||
if(!win) return;
|
|
||||||
int GRAB_WIDTH = win->w, GRAB_HEIGHT = win->h;
|
|
||||||
float _U_ tmp, wd = (float) width/GRAB_WIDTH, ht = (float)height/GRAB_HEIGHT;
|
|
||||||
tmp = (wd + ht) / 2.;
|
|
||||||
width = (int)(tmp * GRAB_WIDTH); height = (int)(tmp * GRAB_HEIGHT);
|
|
||||||
glutReshapeWindow(width, height);
|
|
||||||
glViewport(0, 0, width, height);
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
GLfloat W = (GLfloat)GRAB_WIDTH; GLfloat H = (GLfloat)GRAB_HEIGHT;
|
|
||||||
//glOrtho(-W,W, -H,H, -1., 1.);
|
|
||||||
gluPerspective(90., W/H, 0., 100.0);
|
|
||||||
gluLookAt(0., 0., H/2., 0., 0., 0., 0., 1., 0.);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -19,7 +19,7 @@
|
|||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "bmpview.h"
|
#include "imageview.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
/*
|
/*
|
||||||
* æÕÎËÃÉÉ ÄÌÑ ÒÁÂÏÔÙ Ó OpenGL'ÎÙÍÉ ÓÏÂÙÔÉÑÍÉ
|
* æÕÎËÃÉÉ ÄÌÑ ÒÁÂÏÔÙ Ó OpenGL'ÎÙÍÉ ÓÏÂÙÔÉÑÍÉ
|
||||||
@ -35,21 +35,29 @@ void keyPressed(unsigned char key, //
|
|||||||
//DBG("Key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", mod, key, x,y);
|
//DBG("Key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", mod, key, x,y);
|
||||||
if((mod == GLUT_ACTIVE_CTRL) && (key == 'q' || key == 17)) exit(0); // ctrl + q
|
if((mod == GLUT_ACTIVE_CTRL) && (key == 'q' || key == 17)) exit(0); // ctrl + q
|
||||||
switch(key){
|
switch(key){
|
||||||
|
case '1': // return zoom to 1 & image to 0
|
||||||
|
win->zoom = 1;
|
||||||
|
win->x = 0; win->y = 0;
|
||||||
|
break;
|
||||||
// case 'i': more_info = !more_info;
|
// case 'i': more_info = !more_info;
|
||||||
// break;
|
// break;
|
||||||
case 27: destroyWindow(window, OPENGL);
|
case 27: destroyWindow(window, OPENGL);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
printf("z = %f\n", win->z);
|
printf("zoom = %f\n", win->zoom);
|
||||||
break;
|
break;
|
||||||
// case 'm': createWindow(&mainWindow);
|
// case 'm': createWindow(&mainWindow);
|
||||||
// break;
|
// break;
|
||||||
// case 'w': createWindow(&WaveWindow);
|
// case 'w': createWindow(&WaveWindow);
|
||||||
// break;
|
// break;
|
||||||
case 'Z': win->z += 1.0;
|
case 'Z':
|
||||||
break;
|
win->zoom *= 1.1;
|
||||||
case 'z': win->z -= 1.0;
|
calc_win_props(win, NULL, NULL);
|
||||||
break;
|
break;
|
||||||
|
case 'z':
|
||||||
|
win->zoom /= 1.1;
|
||||||
|
calc_win_props(win, NULL, NULL);
|
||||||
|
break;
|
||||||
// case 'h': createWindow(&SubWindow);
|
// case 'h': createWindow(&SubWindow);
|
||||||
// break;
|
// break;
|
||||||
}
|
}
|
||||||
@ -60,10 +68,28 @@ void keySpPressed(_U_ int key, _U_ int x, _U_ int y){
|
|||||||
DBG("Sp. key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", glutGetModifiers(), key, x,y);
|
DBG("Sp. key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", glutGetModifiers(), key, x,y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mousePressed(int _U_ key, int _U_ state, _U_ int x, _U_ int y){
|
int oldx, oldy; // coordinates when mouse was pressed
|
||||||
// GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON
|
int movingwin = 0; // ==1 when user moves image by middle button
|
||||||
DBG("Mouse button %s. point=(%d, %d); mod=%d, button=%d\n",
|
void mousePressed(_U_ int key, _U_ int state, _U_ int x, _U_ int y){
|
||||||
(state == GLUT_DOWN)? "pressed":"released", x, y, glutGetModifiers(), key);
|
// key: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON
|
||||||
|
// state: GLUT_UP, GLUT_DOWN
|
||||||
|
int window = glutGetWindow();
|
||||||
|
windowData *win = searchWindow_byGLID(window);
|
||||||
|
if(!win) return;
|
||||||
|
if(state == GLUT_DOWN){
|
||||||
|
oldx = x; oldy = y;
|
||||||
|
float X,Y;
|
||||||
|
conv_mouse_to_image_coords(x,y,&X,&Y,win);
|
||||||
|
DBG("press in (%d, %d) == (%f, %f) on image", x,y,X,Y);
|
||||||
|
if(key == GLUT_MIDDLE_BUTTON) movingwin = 1;
|
||||||
|
if(key == 3){ // wheel UP
|
||||||
|
}else if(key == 4){ // wheel DOWN
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
movingwin = 0;
|
||||||
|
}
|
||||||
|
/* DBG("Mouse button %s. point=(%d, %d); mod=%d, button=%d\n",
|
||||||
|
(state == GLUT_DOWN)? "pressed":"released", x, y, glutGetModifiers(), key);*/
|
||||||
|
|
||||||
/* int window = glutGetWindow();
|
/* int window = glutGetWindow();
|
||||||
if(window == WaveWindow){ // ÝÅÌËÎÕÌÉ × ÏËÎÅ Ó ×ÅÊ×ÌÅÔÏÍ
|
if(window == WaveWindow){ // ÝÅÌËÎÕÌÉ × ÏËÎÅ Ó ×ÅÊ×ÌÅÔÏÍ
|
||||||
@ -76,9 +102,36 @@ void mousePressed(int _U_ key, int _U_ state, _U_ int x, _U_ int y){
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
/* this doesn't work
|
||||||
|
void mouseWheel(int button, int dir, int x, int y){
|
||||||
|
int window = glutGetWindow();
|
||||||
|
windowData *win = searchWindow_byGLID(window);
|
||||||
|
if(!win) return;
|
||||||
|
DBG("Mouse wheel, dir: %d. point=(%d, %d); mod=%d, button=%d\n",
|
||||||
|
dir, x, y, glutGetModifiers(), button);
|
||||||
|
}
|
||||||
|
*/
|
||||||
void mouseMove(_U_ int x, _U_ int y){
|
void mouseMove(_U_ int x, _U_ int y){
|
||||||
DBG("Mouse moved to (%d, %d)\n", x, y);
|
int window = glutGetWindow();
|
||||||
|
windowData *win = searchWindow_byGLID(window);
|
||||||
|
if(!win) return;
|
||||||
|
//DBG("Mouse moved to (%d, %d)\n", x, y);
|
||||||
|
if(movingwin){
|
||||||
|
float X, Y, nx, ny, w2, h2;
|
||||||
|
float a = win->Daspect;
|
||||||
|
X = (x - oldx) * a; Y = (y - oldy) * a;
|
||||||
|
nx = win->x + X;
|
||||||
|
ny = win->y - Y;
|
||||||
|
w2 = win->image->w / 2. * win->zoom;
|
||||||
|
h2 = win->image->h / 2. * win->zoom;
|
||||||
|
if(nx < w2 && nx > -w2)
|
||||||
|
win->x = nx;
|
||||||
|
if(ny < h2 && ny > -h2)
|
||||||
|
win->y = ny;
|
||||||
|
oldx = x;
|
||||||
|
oldy = y;
|
||||||
|
calc_win_props(win, NULL, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <GL/glut.h>
|
#include <GL/glut.h>
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
|
||||||
extern float Z; // ËÏÏÒÄÉÎÁÔÁ Z (zoom)
|
extern float Z; // ËÏÏÒÄÉÎÁÔÁ Z (zoom)
|
||||||
|
|
||||||
@ -36,6 +37,6 @@ void mousePressed(int key, int state, int x, int y);
|
|||||||
void mouseMove(int x, int y);
|
void mouseMove(int x, int y);
|
||||||
void createMenu(int window);
|
void createMenu(int window);
|
||||||
void menuEvents(int opt);
|
void menuEvents(int opt);
|
||||||
|
//void mouseWheel(int button, int dir, int x, int y);
|
||||||
|
|
||||||
#endif // __EVENTS_H__
|
#endif // __EVENTS_H__
|
||||||
|
|||||||
398
image_view_module/imageview.c
Normal file
398
image_view_module/imageview.c
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
// bmpview.c
|
||||||
|
//
|
||||||
|
// Copyright 2010 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
// MA 02110-1301, USA.
|
||||||
|
//-lglut
|
||||||
|
#include "imageview.h"
|
||||||
|
#include "macros.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <X11/Xlib.h> // XInitThreads();
|
||||||
|
|
||||||
|
int totWindows = 0; // total number of opened windows
|
||||||
|
|
||||||
|
pthread_t GLUTthread; // main GLUT thread
|
||||||
|
pthread_mutex_t winini_mutex = PTHREAD_MUTEX_INITIALIZER; // mutex for windows initialization
|
||||||
|
volatile int wannacreate = 0; // flag: ==1 if someone wants to create window
|
||||||
|
windowData *wininiptr = NULL;
|
||||||
|
|
||||||
|
int initialized = 0; // ==1 if GLUT is initialized; ==0 after clear_GL_context
|
||||||
|
|
||||||
|
void createWindow(windowData *win);
|
||||||
|
void RedrawWindow();
|
||||||
|
void Resize(int width, int height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculate window properties on creating & resizing
|
||||||
|
*/
|
||||||
|
void calc_win_props(windowData *win, GLfloat *Wortho, GLfloat *Hortho){
|
||||||
|
if(!win || ! win->image) return;
|
||||||
|
double a, A, w, h, W, H;
|
||||||
|
double Zoom = win->zoom;
|
||||||
|
w = (double)win->image->w / 2.;
|
||||||
|
h = (double)win->image->h / 2.;
|
||||||
|
W = (double)win->w;
|
||||||
|
H = (double)win->h;
|
||||||
|
A = W / H;
|
||||||
|
a = w / h;
|
||||||
|
if(A > a){ // now W & H are parameters for glOrtho
|
||||||
|
win->Daspect = h / H * 2.;
|
||||||
|
W = h * A; H = h;
|
||||||
|
}else{
|
||||||
|
win->Daspect = w / W * 2.;
|
||||||
|
H = w / A; W = w;
|
||||||
|
}
|
||||||
|
if(Wortho) *Wortho = W;
|
||||||
|
if(Hortho) *Hortho = H;
|
||||||
|
// calculate coordinates of center
|
||||||
|
win->x0 = W/Zoom - w + win->x / Zoom;
|
||||||
|
win->y0 = H / Zoom + h - win->y / Zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create window & run main loop
|
||||||
|
*/
|
||||||
|
void createWindow(windowData *win){
|
||||||
|
FNAME();
|
||||||
|
if(!initialized) return;
|
||||||
|
if(!win) return;
|
||||||
|
int w = win->w, h = win->h;
|
||||||
|
DBG("create window with title %s", win->title);
|
||||||
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
|
||||||
|
glutInitWindowSize(w, h);
|
||||||
|
win->GL_ID = glutCreateWindow(win->title);
|
||||||
|
DBG("created GL_ID=%d", win->GL_ID);
|
||||||
|
glutReshapeFunc(Resize);
|
||||||
|
glutDisplayFunc(RedrawWindow);
|
||||||
|
glutKeyboardFunc(keyPressed);
|
||||||
|
glutSpecialFunc(keySpPressed);
|
||||||
|
//glutMouseWheelFunc(mouseWheel);
|
||||||
|
glutMouseFunc(mousePressed);
|
||||||
|
glutMotionFunc(mouseMove);
|
||||||
|
//glutIdleFunc(glutPostRedisplay);
|
||||||
|
glutIdleFunc(NULL);
|
||||||
|
DBG("init textures");
|
||||||
|
glGenTextures(1, &(win->Tex));
|
||||||
|
calc_win_props(win, NULL, NULL);
|
||||||
|
win->zoom = 1. / win->Daspect;
|
||||||
|
// createMenu(win->ID);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, win->Tex);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
|
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, win->image->w, win->image->h, 0,
|
||||||
|
GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
totWindows++;
|
||||||
|
DBG("OK, total opened windows: %d", totWindows);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int killwindow(int GL_ID){
|
||||||
|
DBG("try to kill win GL_ID=%d", GL_ID);
|
||||||
|
windowData *win;
|
||||||
|
int canceled = 1;
|
||||||
|
win = searchWindow_byGLID(GL_ID);
|
||||||
|
if(!win) return 0;
|
||||||
|
if(!pthread_cancel(win->thread)){ // cancel thread changing data
|
||||||
|
canceled = 0;
|
||||||
|
}
|
||||||
|
// pthread_join(win->thread, NULL);
|
||||||
|
glDeleteTextures(1, &win->Tex);
|
||||||
|
glFinish();
|
||||||
|
glutDestroyWindow(win->GL_ID);
|
||||||
|
win->GL_ID = 0; // reset for forEachWindow()
|
||||||
|
pthread_mutex_unlock(&win->mutex);
|
||||||
|
if(!canceled && !pthread_cancel(win->thread)){ // cancel thread changing data
|
||||||
|
WARN(_("can't cancel a thread!"));
|
||||||
|
}
|
||||||
|
pthread_join(win->thread, NULL);
|
||||||
|
if(!removeWindow(win->ID)) WARNX(_("Error removing from list"));
|
||||||
|
totWindows--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destroy window with OpenGL or inner identificator "window"
|
||||||
|
* @param window inner or OpenGL id
|
||||||
|
* @param idtype = INNER or OPENGL
|
||||||
|
* @return 1 in case of OK, 0 if fault
|
||||||
|
*/
|
||||||
|
int destroyWindow(int window, winIdType type){
|
||||||
|
if(!initialized) return 0;
|
||||||
|
int r = 0;
|
||||||
|
pthread_mutex_lock(&winini_mutex);
|
||||||
|
if(type == INNER){
|
||||||
|
windowData *win = searchWindow(window);
|
||||||
|
if(win) r = killwindow(win->GL_ID);
|
||||||
|
}else
|
||||||
|
r = killwindow(window);
|
||||||
|
pthread_mutex_unlock(&winini_mutex);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color){
|
||||||
|
if(!initialized) return;
|
||||||
|
char *c;
|
||||||
|
int x1=x, W=0;
|
||||||
|
for(c = string; *c; c++){
|
||||||
|
W += glutBitmapWidth(font,*c);// + 1;
|
||||||
|
}
|
||||||
|
x1 -= W/2;
|
||||||
|
glColor3ubv(color);
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0.,0., -150);
|
||||||
|
//glTranslatef(x,y, -4000.);
|
||||||
|
for (c = string; *c != '\0'; c++){
|
||||||
|
glColor3ubv(color);
|
||||||
|
glRasterPos2f(x1,y);
|
||||||
|
glutBitmapCharacter(font, *c);
|
||||||
|
//glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
|
||||||
|
x1 = x1 + glutBitmapWidth(font,*c);// + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void redisplay(int GL_ID){
|
||||||
|
if(!initialized) return;
|
||||||
|
glutSetWindow(GL_ID);
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(redraw)
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
|
||||||
|
GL_LUMINANCE, GL_FLOAT, ptro); // s/image->data/tex/
|
||||||
|
else
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, w, h,
|
||||||
|
0, GL_LUMINANCE, GL_FLOAT, ptro);
|
||||||
|
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||||
|
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
||||||
|
*/
|
||||||
|
|
||||||
|
void RedrawWindow(){
|
||||||
|
if(!initialized) return;
|
||||||
|
int window;
|
||||||
|
window = glutGetWindow();
|
||||||
|
windowData *win = searchWindow_byGLID(window);
|
||||||
|
if(!win) return;
|
||||||
|
if(pthread_mutex_trylock(&win->mutex) != 0) return;
|
||||||
|
int w = win->image->w, h = win->image->h;
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glLoadIdentity();
|
||||||
|
//glTranslatef(win->x-w/2., win->y-h/2., win->z);
|
||||||
|
glTranslatef(win->x, win->y, 0.);
|
||||||
|
glScalef(-win->zoom, -win->zoom, 1.);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, win->Tex);
|
||||||
|
if(win->image->changed){
|
||||||
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata);
|
||||||
|
win->image->changed = 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0., 1.); glVertex3f(0., 0., 0.);
|
||||||
|
glTexCoord2f(0., 0.); glVertex3f(0.,h, 0.);
|
||||||
|
glTexCoord2f(1., 0.); glVertex3f(w, h, 0.);
|
||||||
|
glTexCoord2f(1., 1.); glVertex3f(w, 0., 0.);
|
||||||
|
glEnd();
|
||||||
|
*/
|
||||||
|
w /= 2.; h /= 2.;
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0.0f, 0.0f); glVertex2f(-w, -h );
|
||||||
|
glTexCoord2f(1.0f, 0.0f); glVertex2f( w, -h );
|
||||||
|
glTexCoord2f(1.0f, 1.0f); glVertex2f( w, h );
|
||||||
|
glTexCoord2f(0.0f, 1.0f); glVertex2f(-w, h );
|
||||||
|
glEnd();
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glFinish();
|
||||||
|
glutSwapBuffers();
|
||||||
|
pthread_mutex_unlock(&win->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main freeGLUT loop
|
||||||
|
* waits for global signals to create windows & make other actions
|
||||||
|
*/
|
||||||
|
void *Redraw(_U_ void *arg){
|
||||||
|
while(1){
|
||||||
|
pthread_mutex_lock(&winini_mutex);
|
||||||
|
if(!initialized) return NULL;
|
||||||
|
if(wannacreate){ // someone asks to create window
|
||||||
|
DBG("call for window creating, id: %d", wininiptr->ID);
|
||||||
|
createWindow(wininiptr);
|
||||||
|
DBG("done!");
|
||||||
|
wininiptr = NULL;
|
||||||
|
wannacreate = 0;
|
||||||
|
}
|
||||||
|
forEachWindow(redisplay);
|
||||||
|
pthread_mutex_unlock(&winini_mutex);
|
||||||
|
if(totWindows) glutMainLoopEvent(); // process actions if there are windows
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resize(int width, int height){
|
||||||
|
if(!initialized) return;
|
||||||
|
int window = glutGetWindow();
|
||||||
|
windowData *win = searchWindow_byGLID(window);
|
||||||
|
if(!win) return;
|
||||||
|
/* int GRAB_WIDTH = win->w, GRAB_HEIGHT = win->h;
|
||||||
|
float _U_ tmp, wd = (float) width/GRAB_WIDTH, ht = (float)height/GRAB_HEIGHT;
|
||||||
|
tmp = (wd + ht) / 2.;
|
||||||
|
width = (int)(tmp * GRAB_WIDTH); height = (int)(tmp * GRAB_HEIGHT);*/
|
||||||
|
glutReshapeWindow(width, height);
|
||||||
|
win->w = width;
|
||||||
|
win->h = height;
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
//GLfloat W = (GLfloat)GRAB_WIDTH; GLfloat H = (GLfloat)GRAB_HEIGHT;
|
||||||
|
GLfloat W, H;
|
||||||
|
calc_win_props(win, &W, &H);
|
||||||
|
glOrtho(-W,W, -H,H, -1., 1.);
|
||||||
|
// gluPerspective(90., W/H, 0., 100.0);
|
||||||
|
// gluLookAt(0., 0., H/2., 0., 0., 0., 0., 1., 0.);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create new window, run thread & return pointer to its structure or NULL
|
||||||
|
* asynchroneous call from outside
|
||||||
|
* wait for window creating & return its data
|
||||||
|
* @param title - header (copyed inside this function)
|
||||||
|
* @param w,h - image size
|
||||||
|
* @param rawdata - NULL (then the memory will be allocated here with size w x h)
|
||||||
|
* or allocated outside data
|
||||||
|
*/
|
||||||
|
windowData *createGLwin(char *title, int w, int h, rawimage *rawdata){
|
||||||
|
FNAME();
|
||||||
|
if(!initialized) return NULL;
|
||||||
|
windowData *win = MALLOC(windowData, 1);
|
||||||
|
if(!addWindow(win)){
|
||||||
|
FREE(win);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
rawimage *raw;
|
||||||
|
if(rawdata){
|
||||||
|
raw = rawdata;
|
||||||
|
}else{
|
||||||
|
raw = MALLOC(rawimage, 1);
|
||||||
|
if(raw){
|
||||||
|
raw->rawdata = MALLOC(GLubyte, w*h*3);
|
||||||
|
raw->w = w;
|
||||||
|
raw->h = h;
|
||||||
|
raw->changed = 1;
|
||||||
|
// raw->protected is zero automatically
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!raw || !raw->rawdata){
|
||||||
|
free(raw);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
win->title = strdup(title);
|
||||||
|
win->image = raw;
|
||||||
|
if(pthread_mutex_init(&win->mutex, NULL)){
|
||||||
|
WARN(_("Can't init mutex!"));
|
||||||
|
removeWindow(win->ID);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
win->w = w;
|
||||||
|
win->h = h;
|
||||||
|
while(wannacreate); // wait if there was another creating
|
||||||
|
pthread_mutex_lock(&winini_mutex);
|
||||||
|
wininiptr = win;
|
||||||
|
wannacreate = 1;
|
||||||
|
pthread_mutex_unlock(&winini_mutex);
|
||||||
|
DBG("wait for creatin");
|
||||||
|
while(wannacreate); // wait until window created from main thread
|
||||||
|
DBG("window created");
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init freeGLUT
|
||||||
|
*/
|
||||||
|
void imageview_init(){
|
||||||
|
FNAME();
|
||||||
|
char *v[] = {PROJNAME, NULL};
|
||||||
|
int c = 1;
|
||||||
|
static int glutnotinited = 1;
|
||||||
|
if(initialized){
|
||||||
|
// "Уже инициализировано!"
|
||||||
|
WARNX(_("Already initialized!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(glutnotinited){
|
||||||
|
XInitThreads(); // we need it for threaded windows
|
||||||
|
glutInit(&c, v);
|
||||||
|
glutnotinited = 0;
|
||||||
|
}
|
||||||
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
|
||||||
|
pthread_create(&GLUTthread, NULL, &Redraw, NULL);
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void killwindow_v(int GL_ID){
|
||||||
|
DBG("GL_ID: %d", GL_ID);
|
||||||
|
killwindow(GL_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close all opened windows and terminate main GLUT thread
|
||||||
|
*/
|
||||||
|
void clear_GL_context(){
|
||||||
|
FNAME();
|
||||||
|
if(!initialized) return;
|
||||||
|
pthread_mutex_lock(&winini_mutex);
|
||||||
|
forEachWindow(killwindow_v);
|
||||||
|
pthread_cancel(GLUTthread); // kill main GLUT thread
|
||||||
|
pthread_join(GLUTthread, NULL);
|
||||||
|
initialized = 0;
|
||||||
|
pthread_mutex_unlock(&winini_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coordinates transformation from CS of drawingArea into CS of picture
|
||||||
|
* x,y - pointer coordinates
|
||||||
|
* X,Y - coordinates of appropriate point at picture
|
||||||
|
*/
|
||||||
|
void conv_mouse_to_image_coords(int x, int y,
|
||||||
|
float *X, float *Y,
|
||||||
|
windowData *window){
|
||||||
|
float a = window->Daspect / window->zoom;
|
||||||
|
*X = x * a - window->x0;
|
||||||
|
*Y = window->y0 - y * a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void conv_image_to_mouse_coords(float X, float Y,
|
||||||
|
int *x, int *y,
|
||||||
|
windowData *window){
|
||||||
|
float a = window->zoom / window->Daspect;
|
||||||
|
*x = (X + window->x0) * a;
|
||||||
|
*y = (window->y0 - Y) * a;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* bmpview.h
|
* imageview.h
|
||||||
*
|
*
|
||||||
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
*
|
*
|
||||||
@ -33,11 +33,16 @@ typedef enum{
|
|||||||
OPENGL
|
OPENGL
|
||||||
} winIdType;
|
} winIdType;
|
||||||
|
|
||||||
void createWindow(windowData *win);
|
void imageview_init();
|
||||||
|
windowData *createGLwin(char *title, int w, int h, rawimage *rawdata);
|
||||||
|
//void window_redraw(windowData *win);
|
||||||
int destroyWindow(int window, winIdType type);
|
int destroyWindow(int window, winIdType type);
|
||||||
void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color);
|
void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color);
|
||||||
void Redraw();
|
void clear_GL_context();
|
||||||
void RedrawWindow();
|
|
||||||
void Resize(int width, int height);
|
void calc_win_props(windowData *win, GLfloat *Wortho, GLfloat *Hortho);
|
||||||
|
|
||||||
|
void conv_mouse_to_image_coords(int x, int y, float *X, float *Y, windowData *window);
|
||||||
|
void conv_image_to_mouse_coords(float X, float Y, int *x, int *y, windowData *window);
|
||||||
|
|
||||||
#endif // __BMPVIEW_H__
|
#endif // __BMPVIEW_H__
|
||||||
@ -119,7 +119,7 @@ windowData *searchWindow_byGLID(int GL_ID){
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* free() all data for node of list
|
* free() all data for node of list
|
||||||
* !!! data for raw pixels (rawdata) doesn't removed as it should be used
|
* !!! data for raw pixels (win->image) will be removed only if image->protected == 0
|
||||||
* only for initialisation and free() by user !!!
|
* only for initialisation and free() by user !!!
|
||||||
*/
|
*/
|
||||||
void WinList_freeNode(WinList **node){
|
void WinList_freeNode(WinList **node){
|
||||||
@ -128,7 +128,10 @@ void WinList_freeNode(WinList **node){
|
|||||||
windowData *win = cur->data;
|
windowData *win = cur->data;
|
||||||
if(root == cur) root = next;
|
if(root == cur) root = next;
|
||||||
FREE(win->title);
|
FREE(win->title);
|
||||||
FREE(win->rawdata);
|
if(win->image->protected == 0){
|
||||||
|
FREE(win->image->rawdata);
|
||||||
|
FREE(win->image);
|
||||||
|
}
|
||||||
pthread_mutex_destroy(&win->mutex);
|
pthread_mutex_destroy(&win->mutex);
|
||||||
FREE(*node);
|
FREE(*node);
|
||||||
if(prev)
|
if(prev)
|
||||||
@ -154,7 +157,6 @@ int removeWindow(int winID){
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* remove all nodes in list
|
* remove all nodes in list
|
||||||
* @param root - pointer to root node
|
|
||||||
*/
|
*/
|
||||||
void freeWinList(){
|
void freeWinList(){
|
||||||
WinList *node = root, *next;
|
WinList *node = root, *next;
|
||||||
|
|||||||
@ -29,14 +29,25 @@
|
|||||||
|
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
GLubyte *rawdata; // raw image data
|
||||||
|
int protected; // don't delete this memory with window
|
||||||
|
int w; // size of image
|
||||||
|
int h;
|
||||||
|
int changed; // == 1 if data was changed outside (to redraw)
|
||||||
|
} rawimage;
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
int ID; // identificator
|
int ID; // identificator
|
||||||
char *title; // title of window
|
char *title; // title of window
|
||||||
GLuint Tex; // texture for image inside window
|
GLuint Tex; // texture for image inside window
|
||||||
int GL_ID; // identificator of OpenGL window
|
int GL_ID; // identificator of OpenGL window
|
||||||
GLubyte *rawdata; // raw image data
|
rawimage *image; // raw image data
|
||||||
int w; int h; // image size
|
int w; int h; // window size
|
||||||
float z; // z-coordinate (zoom)
|
float x; float y; // image offset coordinates
|
||||||
|
float x0; float y0;// center of window for coords conversion
|
||||||
|
float zoom; // zoom aspect
|
||||||
|
float Daspect; // aspect ratio between image & window sizes
|
||||||
pthread_t thread; // identificator of thread that changes window data
|
pthread_t thread; // identificator of thread that changes window data
|
||||||
pthread_mutex_t mutex;// mutex for operations with image
|
pthread_mutex_t mutex;// mutex for operations with image
|
||||||
} windowData;
|
} windowData;
|
||||||
|
|||||||
Binary file not shown.
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2015-02-18 18:46+0300\n"
|
"POT-Creation-Date: 2015-02-28 19:36+0300\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -17,41 +17,46 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=koi8-r\n"
|
"Content-Type: text/plain; charset=koi8-r\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:175
|
#: /home/eddy/tmp/image_view_module/macros.c:175
|
||||||
msgid "No filename given!"
|
msgid "No filename given!"
|
||||||
msgstr "îÅ ÕËÁÚÁÎÏ ÉÍÑ ÆÁÊÌÁ!"
|
msgstr ""
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:177
|
#: /home/eddy/tmp/image_view_module/macros.c:177
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Can't open %s for reading"
|
msgid "Can't open %s for reading"
|
||||||
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
|
msgstr ""
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:179
|
#: /home/eddy/tmp/image_view_module/macros.c:179
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Can't stat %s"
|
msgid "Can't stat %s"
|
||||||
msgstr "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ stat ÄÌÑ %s"
|
msgstr ""
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:182
|
#: /home/eddy/tmp/image_view_module/macros.c:182
|
||||||
msgid "Mmap error for input"
|
msgid "Mmap error for input"
|
||||||
msgstr "ïÛÉÂËÁ mmap ÄÌÑ ×ÈÏÄÎÙÈ ÄÁÎÎÙÈ"
|
msgstr ""
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:183
|
#: /home/eddy/tmp/image_view_module/macros.c:183
|
||||||
msgid "Can't close mmap'ed file"
|
msgid "Can't close mmap'ed file"
|
||||||
msgstr "îÅ ÍÏÇÕ ÚÁËÒÙÔØ mmap'ÎÕÔÙÊ ÆÁÊÌ"
|
msgstr ""
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:192
|
#: /home/eddy/tmp/image_view_module/macros.c:192
|
||||||
msgid "Can't munmap"
|
msgid "Can't munmap"
|
||||||
msgstr "îÅ ÍÏÇÕ ×ÙÚÙ×ÁÔØ munmap"
|
msgstr ""
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/main.c:106
|
|
||||||
msgid "Can't init mutex!"
|
|
||||||
msgstr "îÅ ÍÏÇÕ ÉÎÉÃÉÉÒÏ×ÁÔØ ×ÚÁÉÍÎÏÅ ÉÓËÌÀÞÅÎÉÅ!"
|
|
||||||
|
|
||||||
#. cancel thread changing data
|
#. cancel thread changing data
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/bmpview.c:102
|
#: /home/eddy/tmp/image_view_module/imageview.c:124
|
||||||
msgid "can't cancel a thread!"
|
msgid "can't cancel a thread!"
|
||||||
msgstr "îÅ ÍÏÇÕ ÏÔÍÅÎÉÔØ ×ÙÐÏÌÎÅÎÉÅ ÐÏÔÏËÁ!"
|
msgstr ""
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/bmpview.c:105
|
#: /home/eddy/tmp/image_view_module/imageview.c:127
|
||||||
msgid "Error removing from list"
|
msgid "Error removing from list"
|
||||||
msgstr "ïÛÉÂËÁ ÕÄÁÌÅÎÉÑ ÉÚ ÓÐÉÓËÁ"
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/eddy/tmp/image_view_module/imageview.c:318
|
||||||
|
msgid "Can't init mutex!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. "õÖÅ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÎÏ!"
|
||||||
|
#: /home/eddy/tmp/image_view_module/imageview.c:345
|
||||||
|
msgid "Already initialized!"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr "Project-Id-Version: PACKAGE VERSION\n"
|
msgstr "Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2015-02-18 18:46+0300\n"
|
"POT-Creation-Date: 2015-02-28 19:32+0300\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -16,41 +16,50 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n"
|
|||||||
"Content-Type: text/plain; charset=koi8-r\n"
|
"Content-Type: text/plain; charset=koi8-r\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:183
|
#. "õÖÅ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÎÏ!"
|
||||||
|
#: /home/eddy/tmp/image_view_module/imageview.c:345
|
||||||
|
msgid "Already initialized!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/eddy/tmp/image_view_module/macros.c:183
|
||||||
msgid "Can't close mmap'ed file"
|
msgid "Can't close mmap'ed file"
|
||||||
msgstr "îÅ ÍÏÇÕ ÚÁËÒÙÔØ mmap'ÎÕÔÙÊ ÆÁÊÌ"
|
msgstr "îÅ ÍÏÇÕ ÚÁËÒÙÔØ mmap'ÎÕÔÙÊ ÆÁÊÌ"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/main.c:106
|
#: /home/eddy/tmp/image_view_module/imageview.c:318
|
||||||
msgid "Can't init mutex!"
|
msgid "Can't init mutex!"
|
||||||
msgstr "îÅ ÍÏÇÕ ÉÎÉÃÉÉÒÏ×ÁÔØ ×ÚÁÉÍÎÏÅ ÉÓËÌÀÞÅÎÉÅ!"
|
msgstr "îÅ ÍÏÇÕ ÉÎÉÃÉÉÒÏ×ÁÔØ ×ÚÁÉÍÎÏÅ ÉÓËÌÀÞÅÎÉÅ!"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:192
|
#: /home/eddy/tmp/image_view_module/macros.c:192
|
||||||
msgid "Can't munmap"
|
msgid "Can't munmap"
|
||||||
msgstr "îÅ ÍÏÇÕ ×ÙÚÙ×ÁÔØ munmap"
|
msgstr "îÅ ÍÏÇÕ ×ÙÚÙ×ÁÔØ munmap"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:177
|
#: /home/eddy/tmp/image_view_module/macros.c:177
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Can't open %s for reading"
|
msgid "Can't open %s for reading"
|
||||||
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
|
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:179
|
#: /home/eddy/tmp/image_view_module/macros.c:179
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Can't stat %s"
|
msgid "Can't stat %s"
|
||||||
msgstr "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ stat ÄÌÑ %s"
|
msgstr "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ stat ÄÌÑ %s"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/bmpview.c:105
|
#: /home/eddy/tmp/image_view_module/imageview.c:127
|
||||||
msgid "Error removing from list"
|
msgid "Error removing from list"
|
||||||
msgstr "ïÛÉÂËÁ ÕÄÁÌÅÎÉÑ ÉÚ ÓÐÉÓËÁ"
|
msgstr "ïÛÉÂËÁ ÕÄÁÌÅÎÉÑ ÉÚ ÓÐÉÓËÁ"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:182
|
#: /home/eddy/tmp/image_view_module/macros.c:182
|
||||||
msgid "Mmap error for input"
|
msgid "Mmap error for input"
|
||||||
msgstr "ïÛÉÂËÁ mmap ÄÌÑ ×ÈÏÄÎÙÈ ÄÁÎÎÙÈ"
|
msgstr "ïÛÉÂËÁ mmap ÄÌÑ ×ÈÏÄÎÙÈ ÄÁÎÎÙÈ"
|
||||||
|
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/macros.c:175
|
#: /home/eddy/tmp/image_view_module/macros.c:175
|
||||||
msgid "No filename given!"
|
msgid "No filename given!"
|
||||||
msgstr "îÅ ÕËÁÚÁÎÏ ÉÍÑ ÆÁÊÌÁ!"
|
msgstr "îÅ ÕËÁÚÁÎÏ ÉÍÑ ÆÁÊÌÁ!"
|
||||||
|
|
||||||
#. cancel thread changing data
|
#. cancel thread changing data
|
||||||
#: /home/eddy/tmp/wavelets-hough-and-so-on/image_view_module/bmpview.c:102
|
#: /home/eddy/tmp/image_view_module/imageview.c:124
|
||||||
msgid "can't cancel a thread!"
|
msgid "can't cancel a thread!"
|
||||||
msgstr "îÅ ÍÏÇÕ ÏÔÍÅÎÉÔØ ×ÙÐÏÌÎÅÎÉÅ ÐÏÔÏËÁ!"
|
msgstr "îÅ ÍÏÇÕ ÏÔÍÅÎÉÔØ ×ÙÐÏÌÎÅÎÉÅ ÐÏÔÏËÁ!"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~ msgid "Can't init main GLUT mutex!"
|
||||||
|
#~ msgstr "îÅ ÍÏÇÕ ÉÎÉÃÉÉÒÏ×ÁÔØ ×ÚÁÉÍÎÏÅ ÉÓËÌÀÞÅÎÉÅ!"
|
||||||
|
|||||||
@ -18,48 +18,28 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <X11/Xlib.h> // XInitThreads();
|
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "bmpview.h"
|
#include "imageview.h"
|
||||||
|
|
||||||
|
|
||||||
//GLubyte *BitmapBits = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
pthread_mutex_t m_ima = PTHREAD_MUTEX_INITIALIZER, m_wvlt = PTHREAD_MUTEX_INITIALIZER,
|
|
||||||
m_hist = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
*/
|
|
||||||
unsigned int bufsize;
|
|
||||||
|
|
||||||
void help(char *s){
|
|
||||||
fprintf(stderr, "\n\n%s, simple interface for LOMO's webcam \"microscope\"\n", s);
|
|
||||||
fprintf(stderr, "Usage: %s [-h] [-d videodev] [-c channel]\n\n", s);
|
|
||||||
fprintf(stderr,
|
|
||||||
"-h, --help:\tthis help\n"
|
|
||||||
"-d, --device:\tcapture from <videodev>\n"
|
|
||||||
"-c, --channel:\tset channel <channel> (0..3)\n"
|
|
||||||
);
|
|
||||||
fprintf(stderr, "\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void* change_image(void *data){
|
void* change_image(void *data){
|
||||||
FNAME();
|
FNAME();
|
||||||
windowData *win = (windowData*) data;
|
windowData *win = (windowData*) data;
|
||||||
int w = win->w, h = win->h, x,y, id = win->ID;
|
int w = win->image->w, h = win->image->h, x,y, id = win->ID;
|
||||||
GLubyte i;
|
GLubyte i;
|
||||||
DBG("w=%d, h=%d",w,h);
|
DBG("w=%d, h=%d",w,h);
|
||||||
for(i = 1; ;i++){
|
for(i = 1; ;i++){
|
||||||
|
// DBG("search to refresh %d", id);
|
||||||
if(!searchWindow(id)) pthread_exit(NULL);
|
if(!searchWindow(id)) pthread_exit(NULL);
|
||||||
|
// DBG("found, lock mutex");
|
||||||
pthread_mutex_lock(&win->mutex);
|
pthread_mutex_lock(&win->mutex);
|
||||||
GLubyte *raw = win->rawdata;
|
// DBG("refresh");
|
||||||
|
GLubyte *raw = win->image->rawdata;
|
||||||
for(y = 0; y < h; y++){
|
for(y = 0; y < h; y++){
|
||||||
if(y%20 == 19){
|
if(y%20 == 19){
|
||||||
raw += w*3;
|
raw += w*3;
|
||||||
@ -74,79 +54,49 @@ void* change_image(void *data){
|
|||||||
raw += 3;
|
raw += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
win->image->changed = 1;
|
||||||
pthread_mutex_unlock(&win->mutex);
|
pthread_mutex_unlock(&win->mutex);
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
|
//sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void *main_thread(_U_ void *none){
|
||||||
void *GLloop(void *data){
|
// while(1){};
|
||||||
FNAME();
|
rawimage im;
|
||||||
windowData *win = (windowData *)data;
|
windowData *mainwin, *win, *third;
|
||||||
createWindow(win);
|
int w = 640, h = 480;
|
||||||
|
im.protected = 1;
|
||||||
|
im.rawdata = MALLOC(GLubyte, w*h*3);
|
||||||
|
im.w = w; im.h = h;
|
||||||
|
mainwin = createGLwin("Sample window", w, h, &im);
|
||||||
|
DBG("ok");
|
||||||
|
if(!mainwin) ERRX("can't create main");
|
||||||
|
pthread_create(&mainwin->thread, NULL, &change_image, (void*)mainwin);
|
||||||
|
win = createGLwin("Second window", w/2, h/2, NULL);
|
||||||
|
if(!win) ERRX("can't create second");
|
||||||
|
pthread_create(&win->thread, NULL, &change_image, (void*)win);
|
||||||
|
pthread_join(mainwin->thread, NULL);
|
||||||
|
pthread_join(win->thread, NULL);
|
||||||
|
clear_GL_context();
|
||||||
|
WARNX("Two windows closed, create another one");
|
||||||
|
imageview_init(); // init after killing
|
||||||
|
third = createGLwin("third window", w*2, h, &im);
|
||||||
|
if(!third) ERRX("can't create third");
|
||||||
|
pthread_create(&third->thread, NULL, &change_image, (void*)third);
|
||||||
|
pthread_join(third->thread, NULL);
|
||||||
|
DBG("try to clear");
|
||||||
|
clear_GL_context();
|
||||||
|
DBG("cleared");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create new window, run thread & return pointer to its structure or NULL
|
|
||||||
* @param title - header (copyed inside this function)
|
|
||||||
* @param w,h - image size
|
|
||||||
*/
|
|
||||||
windowData *createGLwin(char *title, int w, int h){
|
|
||||||
windowData *win = MALLOC(windowData, 1);
|
|
||||||
if(!addWindow(win)){
|
|
||||||
FREE(win);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
GLubyte *raw = MALLOC(GLubyte, w*h*3);
|
|
||||||
win->title = strdup(title);
|
|
||||||
win->rawdata = raw;
|
|
||||||
if(pthread_mutex_init(&win->mutex, NULL)){
|
|
||||||
WARN(_("Can't init mutex!"));
|
|
||||||
removeWindow(win->ID);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
win->w = w;
|
|
||||||
win->h = h;
|
|
||||||
// pthread_create(&win->glthread, NULL, GLloop, (void*)win);
|
|
||||||
createWindow(win);
|
|
||||||
return win;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
GLubyte *prepareImage(){
|
|
||||||
static GLubyte *imPtr = NULL;
|
|
||||||
//static int bufferSize;
|
|
||||||
//int readlines, linesize;
|
|
||||||
//GLubyte *ptr;
|
|
||||||
if(!imPtr) imPtr = calloc(100, sizeof(GLubyte));
|
|
||||||
return imPtr;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main(_U_ int argc, _U_ char** argv){
|
|
||||||
windowData *mainwin, _U_ *win, _U_ *third;
|
|
||||||
int w = 640, h = 480;
|
|
||||||
|
|
||||||
char *v[] = {PROJNAME, NULL};
|
|
||||||
int c = 1;
|
|
||||||
glutInit(&c, v);
|
|
||||||
|
|
||||||
|
int main(_U_ int argc, _U_ char **argv){
|
||||||
|
pthread_t mainthread;
|
||||||
initial_setup(); // locale & messages
|
initial_setup(); // locale & messages
|
||||||
XInitThreads(); // we need it for threaded windows
|
imageview_init();
|
||||||
//BitmapBits = prepareImage();
|
DBG("init main thread");
|
||||||
mainwin = createGLwin("Sample window", w, h);
|
pthread_create(&mainthread, NULL, &main_thread, NULL);
|
||||||
if(!mainwin) return 1;
|
pthread_join(mainthread, NULL);
|
||||||
pthread_create(&mainwin->thread, NULL, &change_image, (void*)mainwin);
|
|
||||||
win = createGLwin("Second window", w/2, h/2);
|
|
||||||
if(!win) return 1;
|
|
||||||
pthread_create(&win->thread, NULL, &change_image, (void*)win);
|
|
||||||
third = createGLwin("Second window", w/4, h/4);
|
|
||||||
if(!win) return 1;
|
|
||||||
pthread_create(&third->thread, NULL, &change_image, (void*)third);
|
|
||||||
// wait for end
|
|
||||||
glutMainLoop();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
opengl.c
Normal file
44
opengl.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// the simplest opengl example
|
||||||
|
|
||||||
|
#include <GL/glut.h>
|
||||||
|
#include <math.h>
|
||||||
|
// compile:
|
||||||
|
// gcc -Wall -Wextra -Werror -lglut -lGL -lm -std=gnu99 -D_GNU_SOURCE opengl.c -o openglcircle
|
||||||
|
|
||||||
|
#define _U_ __attribute__((__unused__))
|
||||||
|
// exit by ctrl+q or escape
|
||||||
|
void keyPressed(unsigned char key, _U_ int x, _U_ int y){
|
||||||
|
int mod = glutGetModifiers(); // window = glutGetWindow()
|
||||||
|
if(mod == GLUT_ACTIVE_CTRL && key == 'q') exit(0);
|
||||||
|
else if(key == 27) exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawCircle(float cx, float cy, float r, int num_segments){
|
||||||
|
float theta = 2. * M_PI / (float)num_segments;
|
||||||
|
float c, s, t, x = r, y = 0.;
|
||||||
|
sincosf(theta, &s, &c);
|
||||||
|
glBegin(GL_LINE_LOOP);
|
||||||
|
for(int ii = 0; ii < num_segments; ii++){
|
||||||
|
glVertex2f(x + cx, y + cy);
|
||||||
|
t = x;
|
||||||
|
x = c * x - s * y;
|
||||||
|
y = s * t + c * y;
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void display(){
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
DrawCircle(0.,0.,0.5,100);
|
||||||
|
glFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv){
|
||||||
|
glutInit(&argc, argv);
|
||||||
|
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
|
||||||
|
glutInitWindowSize(400, 400);
|
||||||
|
glutCreateWindow("A Simple Circle");
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutKeyboardFunc(keyPressed);
|
||||||
|
glutMainLoop();
|
||||||
|
}
|
||||||
122
sendfile.c
Normal file
122
sendfile.c
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/sendfile.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
./sendfile Titanik.mp4
|
||||||
|
Copied by sendfile, time: 30.1055s
|
||||||
|
Copied by mmap, time: 35.6469s
|
||||||
|
|
||||||
|
du Titanik.mp4
|
||||||
|
2.6GTitanik.mp4
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
double dtime(){
|
||||||
|
double t;
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
t = tv.tv_sec + ((double)tv.tv_usec)/1e6;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
char *data;
|
||||||
|
size_t len;
|
||||||
|
} mmapbuf;
|
||||||
|
|
||||||
|
void My_munmap(mmapbuf **b){
|
||||||
|
if(munmap((*b)->data, (*b)->len))
|
||||||
|
perror("Can't munmap");
|
||||||
|
free(*b);
|
||||||
|
*b = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmapbuf *My_mmap(char *filename){
|
||||||
|
int fd;
|
||||||
|
char *ptr = NULL;
|
||||||
|
size_t Mlen;
|
||||||
|
struct stat statbuf;
|
||||||
|
if((fd = open(filename, O_RDONLY)) < 0){
|
||||||
|
perror("Can't open file for reading");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
if(fstat (fd, &statbuf) < 0){
|
||||||
|
perror("Can't stat file");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
Mlen = statbuf.st_size;
|
||||||
|
if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){
|
||||||
|
perror("Mmap error for input");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
mmapbuf *ret = calloc(sizeof(mmapbuf), 1);
|
||||||
|
if(ret){
|
||||||
|
ret->data = ptr;
|
||||||
|
ret->len = Mlen;
|
||||||
|
}else munmap(ptr, Mlen);
|
||||||
|
ret:
|
||||||
|
if(close(fd)) perror("Can't close mmap'ed file");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
struct stat st;
|
||||||
|
double T0;
|
||||||
|
if(argc != 2){
|
||||||
|
printf("Usage: %s file\n", argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (stat(argv[1], &st) == 0 && S_ISREG(st.st_mode)){
|
||||||
|
off_t off = 0;
|
||||||
|
int fd = open(argv[1], O_RDONLY);
|
||||||
|
int fdo = open("tmpoutput", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
if (fd < 0 || fdo < 0){
|
||||||
|
perror("can't open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
T0 = dtime();
|
||||||
|
posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||||
|
while (off < st.st_size) {
|
||||||
|
ssize_t bytes = sendfile(fdo, fd, &off, st.st_size - off);
|
||||||
|
if (bytes <= 0){
|
||||||
|
perror("can't sendfile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
close(fdo);
|
||||||
|
printf("Copied by sendfile, time: %gs\n", dtime()-T0);
|
||||||
|
T0 = dtime();
|
||||||
|
mmapbuf *map = My_mmap(argv[1]);
|
||||||
|
if(map){
|
||||||
|
fdo = open("tmpoutput", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
if (fd < 0 || fdo < 0){
|
||||||
|
perror("can't open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
size_t written = 0, towrite = map->len;
|
||||||
|
char *ptr = map->data;
|
||||||
|
do{
|
||||||
|
ssize_t wr = write(fdo, ptr, towrite);
|
||||||
|
if(wr <= 0) break;
|
||||||
|
written += wr;
|
||||||
|
towrite -= wr;
|
||||||
|
ptr += wr;
|
||||||
|
}while(towrite);
|
||||||
|
if(written != map->len){
|
||||||
|
printf("err: writed only %zd byted of %zd\n", written, map->len);
|
||||||
|
}
|
||||||
|
close(fdo);
|
||||||
|
My_munmap(&map);
|
||||||
|
printf("Copied by mmap, time: %gs\n", dtime()-T0);
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
perror("Can't stat file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user