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





Пожалуйста, пожалуйста, добавьте кучу сахара, патоки, посыпки и туман кукурузного сиропа с высоким содержанием фруктозы сверху и повсюду, объясните Почему, вы не можете просто использовать наложение текстуры для рисования этого изображения.
Отображение текстур - это основная, базовая, повседневная, обычная, разнообразная, стандартная, типичная, ожидаемая и в целом приятная функция OpenGL. Он находится в версии 1.4. Почему бы не использовать это как отправную точку?
@mmr: Для меня это звучит как утечка памяти, вы уверены, что используете это правильно?
нет, я совсем не уверен. Однако мы знаем, что это работает с gldrawpixels. Я бы предпочел, чтобы он работал, даже если он медленный, чем не работал, и мне пришлось бы потратить некоторое время на отслеживание утечек памяти, особенно если они находятся в Tao.GL.
Если я правильно вас понял, то это должно быть похоже на то, что вам нужно, используя 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 - ваше решение приводит к тому, что копирование происходит за пределами видеокарты, поэтому замедляет рисование при перетаскивании мышью, но не фиксирует двойной зажим.
Потому что мы не можем ... мы пытались. Большое количество поддерживаемого графического оборудования явно не позволяет нам делать то, что нам нужно. Мы попробовали, и примерно через пять минут на любой машине повреждение памяти стало настолько серьезным, что нам пришлось перезапустить программу.