GlDrawPixels / glCopyPixels, чтобы получить увеличенное изображение с сильно зажатым изображением

Несмотря на более ранний вопрос (спросил здесь), наш проект ограничен использованием 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# и фреймворк Tao, если это важно.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
2 871
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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

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

mmr 06.11.2008 19:10

@mmr: Для меня это звучит как утечка памяти, вы уверены, что используете это правильно?

thing2k 07.11.2008 19:48

нет, я совсем не уверен. Однако мы знаем, что это работает с gldrawpixels. Я бы предпочел, чтобы он работал, даже если он медленный, чем не работал, и мне пришлось бы потратить некоторое время на отслеживание утечек памяти, особенно если они находятся в Tao.GL.

mmr 08.11.2008 04:53

Если я правильно вас понял, то это должно быть похоже на то, что вам нужно, используя 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;
}

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

Ответ принят как подходящий

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

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

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

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

Таким образом, исчезнет описанный мною «крайний зажим».

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

Другие вопросы по теме