glDrawPixels / glCopyPixels, чтобы получить увеличенное изображение с сильно сжатым изображением - PullRequest
0 голосов
/ 06 ноября 2008

Несмотря на более ранний вопрос ( заданный здесь ), наш проект ограничен использованием glDrawPixels, поэтому мы должны сделать некоторую хакерскую попытку.

Одним из требований к функциональности является возможность отображения увеличенного изображения в выбранной области изображения; поэтому, глядя на изображение, я хочу щелкнуть мышью, и у меня появится окно с 200% изображением, где находится мышь. Когда я перетаскиваю курсор, окно должно следовать за курсором.

Контекст настроен так:

Большая Красная Книга имеет код, который выглядит следующим образом:

        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);

И тогда призыв сделать уменьшенное, но увеличенное изображение выглядит как

        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);

где mStartY и mStartX - точки, где произошел щелчок.

Проблема в том, что открывающееся окно действительно искажает таблицы поиска и действительно сжимает изображение до по существу черно-белого двоичного изображения (то есть без оттенков серого).

Данные представляют собой черно-белый короткий массив без знака и задаются с помощью этого кода:

        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);

Теперь, согласно этой документации , я должен использовать GL_PIXEL_MAP_I_TO_I и установить INDEX_SCALE и INDEX_BIAS в ноль, но это не изменит результат, что изображение будет сильно зажато. Под «сильно зажатыми» я имею в виду черный или белый, с очень небольшим количеством оттенков серого, но исходное не увеличенное изображение выглядит так, как и ожидалось.

Итак, как мне избежать захвата увеличенного изображения? Должен ли я создать второй элемент управления, следующий за курсором и заполненный данными из первого элемента управления? Этот подход выглядит так, как если бы он брал копии массива вне графической карты и в C #, что почти по определению было бы медленнее, и поэтому управление не отвечало бы.

О, я использую C # и платформу Дао, если это имеет значение.

Ответы [ 3 ]

2 голосов
/ 14 ноября 2008

Вот ответ. Проблема в том, что LUT применяется дважды, поэтому перед вызовом копии вызовите:

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

Затем, когда закончите, позвоните:

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

Таким образом, «крайний зажим», который я описывал, удаляется.

@ thing2k-- ваше решение приводит к тому, что копирование происходит за пределами графической карты, поэтому замедляет рисование при перетаскивании мышью, но не устраняет двойной зажим.

0 голосов
/ 08 ноября 2008

Если я правильно вас понимаю, это должно быть близко к тому, что вы используете, используя glReadPixels и glDrawPixels.

Извините, это C ++, а не C #, но функция OpenGL должна быть такой же.

// 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;
}

Надеюсь, это поможет.

0 голосов
/ 06 ноября 2008

Пожалуйста, довольно пожалуйста с большим количеством сахара, патоки, брызг и тумана кукурузного сиропа с высоким содержанием фруктозы сверху и со всех сторон, объясните почему вы не можете просто использовать текстурное наложение Чтобы нарисовать этот образ.

Отображение текстур - это базовая, базовая, повседневная работа мельницы, разнообразия садов, стандартная, типичная, ожидаемая и просто приятная особенность OpenGL. Это в версии 1.4. Почему бы не использовать его в качестве отправной точки?

...