A: 

Please, pretty please with loads of sugar, molasses, sprinkles and a mist of high-fructose corn syrup on top and all over, explain why you cannot just use texture-mapping to draw this imagery.

Texture-mapping is a core, basic, everyday, run of the mill, garden-variety, standard, typical, expected, and just generally nice feature of OpenGL. It is in version 1.4. Why not use it as a starting point?

unwind
Because we can't-- we tried. The wide variety of graphics hardware we have to support apparently doesn't allow for the things we need to do. We tried, and after about five minutes on any machine, memory corruption got so bad, we have to restart the program.
mmr
@mmr: That sounds like a memory leak to me, are you sure you are using it correctly?
thing2k
nope, I'm not sure at all. We know it works with the gldrawpixels, though. I'd rather it work, even if it's slow, than it not work, and have to spend a while tracking down memory leaks, especially if they're in Tao.GL.
mmr
A: 

If I understand you correctly then this should be close to what you after, using glReadPixels and glDrawPixels.

Sorry it's C++ not C# but the OpenGL function should still be the same.

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

Hope this helps.

thing2k
+2  A: 

Here's the answer. The problem is that the LUT is being applied twice, so before calling the copy, call:

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

Then, once done, call:

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

That way, the 'extreme clamping' I was describing is removed.

@thing2k-- your solution causes the copy to happen outside the graphics card, so slows down the drawing on mouse drag, but doesn't fix the double clamp.

mmr