尽管有一个早期的问题(asked here),但我们的项目仅限于使用glDrawPixels,因此我们必须做一些hackery。
其中一项功能要求是能够在图像的单击区域上显示放大的视图;因此,查看图像,我想单击鼠标,并在鼠标所在的位置显示200%的图像窗口。当我拖动光标时,窗口应该跟随光标。
上下文设置如下:
Big Red Book的代码如下:
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);
现在,根据this documentation,我应该使用GL_PIXEL_MAP_I_TO_I并将INDEX_SCALE和INDEX_BIAS设置为零,但这样做不会改变结果,图像被严格限制。并且通过“严格限制”,我的意思是它是黑色或白色,只有很少的灰色阴影,但原始的非放大图像看起来像预期的那样。
那么,我该如何避免放大视图?我应该在光标后面进行第二次控制并使用第一个控件的数据填充吗?这种方法似乎需要将数组副本放在图形卡之外并进入C#,这几乎可以定义为较慢,因此使控件无响应。
哦,如果重要的话,我正在使用C#和Tao框架。
答案 0 :(得分:2)
这是答案。问题是LUT被应用了两次,因此在调用副本之前,请调用:
Gl.glPixelTransferi(Gl.GL_MAP_COLOR, Gl.GL_FALSE);
然后,完成后,请致电:
Gl.glPixelTransferi(Gl.GL_MAP_COLOR, Gl.GL_TRUE);
这样,我所描述的'极端钳位'就被删除了。
@ thing2k--你的解决方案导致副本发生在显卡外部,因此在鼠标拖动时减慢绘图速度,但不能修复双重限制。
答案 1 :(得分:0)
请相当满意地加上糖,糖蜜,洒水和高果糖玉米糖浆的雾气,并解释为什么你不能只使用 texture-mapping < / b>绘制此图像。
纹理映射是工厂的核心,基本,日常运行,花园种类,标准,典型,预期,以及OpenGL的一般优秀功能。它是1.4版本。为什么不把它作为起点?
答案 2 :(得分:0)
如果我理解正确,那么使用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;
}
希望这有帮助。