glDrawPixels / glCopyPixels pour obtenir une vue agrandie produisant une image très serrée

StackOverflow https://stackoverflow.com/questions/267275

  •  06-07-2019
  •  | 
  •  

Question

Malgré une question précédente ( posée ici ), notre projet est contraint d'utiliser glDrawPixels, nous devons donc faire du piratage.

L'une des exigences de la fonctionnalité consiste à pouvoir afficher une vue agrandie sur une région cliquée d'une image; alors, en regardant une image, je veux cliquer sur la souris et faire apparaître une fenêtre d’image à 200% à l’endroit où se trouve la souris. Lorsque je déplace mon curseur, la fenêtre doit suivre le curseur.

Le contexte est configuré comme suit:

Le grand livre rouge a un code qui ressemble à ceci:

        Gl.glShadeModel(Gl.GL_FLAT);
        Gl.glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
        Gl.glPixelStorei(Gl.GL_UNPACK_ALIGNMENT, 2);
        Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_LINE);

        Gl.glDisable(Gl.GL_SCISSOR_TEST);
        Gl.glDisable(Gl.GL_ALPHA_TEST);
        Gl.glDisable(Gl.GL_STENCIL_TEST);
        Gl.glDisable(Gl.GL_DEPTH_TEST);
        Gl.glDisable(Gl.GL_BLEND);
        Gl.glDisable(Gl.GL_DITHER);
        Gl.glDisable(Gl.GL_LOGIC_OP);
        Gl.glDisable(Gl.GL_LIGHTING);
        Gl.glDisable(Gl.GL_FOG);
        Gl.glDisable(Gl.GL_TEXTURE_1D);
        Gl.glDisable(Gl.GL_TEXTURE_2D);
        Gl.glPixelTransferi(Gl.GL_MAP_COLOR, Gl.GL_TRUE);
        Gl.glPixelTransferf(Gl.GL_RED_SCALE, 1.0f);
        Gl.glPixelTransferi(Gl.GL_RED_BIAS, 0);
        Gl.glPixelTransferf(Gl.GL_GREEN_SCALE, 1.0f);
        Gl.glPixelTransferi(Gl.GL_GREEN_BIAS, 0);
        Gl.glPixelTransferf(Gl.GL_BLUE_SCALE, 1.0f);
        Gl.glPixelTransferi(Gl.GL_BLUE_BIAS, 0);
        Gl.glPixelTransferi(Gl.GL_ALPHA_SCALE, 1);
        Gl.glPixelTransferi(Gl.GL_ALPHA_BIAS, 0);

Et ensuite, l'appel pour rendre l'image plus petite mais agrandie ressemble à

        int width = (int)((this.Width * 0.2)/2.0);
        Gl.glReadBuffer(Gl.GL_FRONT_AND_BACK);
        Gl.glRasterPos2i(0, 0);
        Gl.glBitmap(0, 0, 0, 0, mStartX - (width*2), mStartY, null);

        Gl.glPixelZoom(2.0f, 2.0f);
        Gl.glCopyPixels(mStartX - width, mStartY, width, width, Gl.GL_COLOR);

où mStartY et mStartX sont les points où le clic s'est produit.

Le problème est que la fenêtre qui s’affiche est en train de brouiller les tables de consultation et de réduire l’image à une image binaire en noir et blanc (c’est-à-dire sans nuance de gris).

Les données sont un tableau court non signé en noir et blanc et sont définies avec le code suivant:

        float step = (65535.0f / (float)(max - min));
        mColorTable = new ushort[65536];
        int i;
        for (i = 0; i < 65536; i++)
        {
            if (i < min)
                mColorTable[i] = 0;
            else if (i > max)
                mColorTable[i] = 65535;
            else
                mColorTable[i] = (ushort)((float)(i - min) * step);
        }       
        .... //some irrelevant code

        Gl.glPixelMapusv(Gl.GL_PIXEL_MAP_R_TO_R, 65536, mColorTable);
        Gl.glPixelMapusv(Gl.GL_PIXEL_MAP_G_TO_G, 65536, mColorTable);
        Gl.glPixelMapusv(Gl.GL_PIXEL_MAP_B_TO_B, 65536, mColorTable);

Maintenant, selon cette documentation , je devrait utiliser GL_PIXEL_MAP_I_TO_I et définir INDEX_SCALE et INDEX_BIAS sur zéro, mais cela ne change pas le résultat, ce qui signifie que l'image est sévèrement bloquée. Et par «sévèrement pincé», je veux dire que ce soit en noir ou en blanc, avec très peu de nuances de gris, mais l'image originale non agrandie ressemble à ce qui était attendu.

Alors, comment puis-je éviter le blocage de la vue agrandie? Devrais-je faire un deuxième contrôle qui suit le curseur et est rempli avec les données du premier contrôle? Cette approche semble impliquer que les copies de matrice soient prises en dehors de la carte graphique et en C #, ce qui, presque par définition, serait plus lent et rendrait donc le contrôle inactif.

Oh, j'utilise C # et le framework Tao, si cela compte.

Était-ce utile?

La solution

Voici la réponse. Le problème est que la table de correspondance est appliquée deux fois. Par conséquent, avant d'appeler la copie, appelez:

Gl.glPixelTransferi(Gl.GL_MAP_COLOR, Gl.GL_FALSE);

Puis, une fois terminé, appelez:

Gl.glPixelTransferi(Gl.GL_MAP_COLOR, Gl.GL_TRUE);

Ainsi, le "serrage extrême" que je décrivais est supprimé.

@ thing2k-- votre solution entraîne la copie en dehors de la carte graphique, donc ralentit le dessin lors du glissement de la souris, mais ne résout pas le double blocage.

Autres conseils

S'il-vous-plaît, jolie, s'il-vous-plaît, avec beaucoup de sucre, de mélasse, de pépites et un brouillard de sirop de maïs à haute teneur en fructose, expliquez pourquoi vous ne pouvez pas simplement utiliser la texture / b> pour dessiner cette image.

Le mappage de texture est une fonctionnalité essentielle, fondamentale, quotidienne, courante, variée de jardin, standard, typique, attendue et tout simplement agréable d’OpenGL. C'est dans la version 1.4. Pourquoi ne pas l'utiliser comme point de départ?

Si je vous ai bien compris, vous devriez utiliser les fonctions glReadPixels et glDrawPixels.

Désolé, c'est C ++ et non C #, mais la fonction OpenGL devrait rester identique.

// main.cpp
// glut Text

#ifdef __WIN32__
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
#endif
#include <GL/glut.h>
#include <cstdio>

int WIDTH = 800;
int HEIGHT = 600;
int MouseButton, MouseY = 0, MouseX = 0;
const int size = 80;
char *image, rect[size*size*3];
int imagewidth, imageheight;

bool Init()
{
    int offset;
    FILE* file = fopen("image.bmp", "rb");
    if (file == NULL)
        return false;
    fseek(file, 10, SEEK_SET);
    fread(&offset, sizeof(int), 1, file);
    fseek(file, 18, SEEK_SET);
    fread(&imagewidth, sizeof(int), 1, file);
    fread(&imageheight, sizeof(int), 1, file);
    fseek(file, offset, SEEK_SET);
    image = new char[imagewidth*imageheight*3];
    if (image == NULL)
        return false;
    fread(image, 1, imagewidth*imageheight*3, file);
    fclose(file);
    return true;
}

void Reshape(int width, int height)
{
    WIDTH = width;
    HEIGHT = height;
    glViewport(0 , 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width, 0, height);
}

void Display()
{
    int size2 = size/2;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRasterPos2i(0,0);
    glPixelZoom(1.f, 1.f);
    glDrawPixels(imagewidth, imageheight, 0x80E0/*GL_RGB*/, GL_UNSIGNED_BYTE, image);
    glReadPixels(MouseX-size2, MouseY-size2, size, size, GL_RGB, GL_UNSIGNED_BYTE, rect);
    glPixelZoom(2.f, 2.f);
    glRasterPos2i(MouseX-size, MouseY-size);
    glDrawPixels(size, size, GL_RGB, GL_UNSIGNED_BYTE, rect);
    glFlush();
    glutSwapBuffers();
}

void Mouse(int button, int state, int x, int y)
{
    if (state == GLUT_DOWN)
        MouseButton &= (1<<button);
    else
        MouseButton &= ~(1<<button);
}

void MouseMove(int x, int y)
{
    MouseX = x;
    MouseY = HEIGHT - y;
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    if (Init() == false)
        return 1;
    glutInitWindowSize(WIDTH, HEIGHT);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutCreateWindow("glut_Text");
    glClearColor(0.25, 0.25, 0.25, 1.0);
    glutReshapeFunc(Reshape);
    glutDisplayFunc(Display);
    glutIdleFunc(Display);
    glutMouseFunc(Mouse);
    glutMotionFunc(MouseMove);
    glutPassiveMotionFunc(MouseMove);

    glutMainLoop();
    return 0;
}

J'espère que cela vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top