Печать OpenGL картинки
Модератор: Модераторы
Печать OpenGL картинки
Здравствуйте. Кто-нибудь может привести работающий пример вывода картинки созданной командами OpenGL на принтер. Создание контекста OpenGL на канве принтера печатает чистый лист.
Под вендой на контекст принтера OpenGL рендерить не сможет. По-идее OpenGL может рендерить в софтовом режиме в dib (device intepended bitmap). Иначе - только в окно, этого требуют драйвера (правда как вариант попробовать создать маленькое а возможно и невидимое окно с контекстом, затем приаттачить к нему OpenGL pbuffer или framebuffer, непомню точно, рендерить в них и потом при помощи glreadPixels читать пикселы в битмап, который уже рисовать на принтере - но могут быть траблы с драйверами).
Ок, буду разбираться сам.
Добавлено спустя 4 часа 20 минут 2 секунды:
Вот нашел такой пример: OpenGL выводит картинку на TBitmap, который потом копируется на канву принтера. В Delphi все пашет, а в Lazarus`е черная страница...
Добавлено спустя 4 часа 20 минут 2 секунды:
Вот нашел такой пример: OpenGL выводит картинку на TBitmap, который потом копируется на канву принтера. В Delphi все пашет, а в Lazarus`е черная страница...
Код: Выделить всё
procedure SetDCPixelFormat(DC:THandle;var Palette:HPalette;ToBitmap:Boolean);
var hHeap:THandle;
nColors,I:Integer;
lpPalette:PLogPalette;
byRedMask,byGreenMask,byBlueMask:Byte;
nPixelFormat:Integer;
pfd:TPixelFormatDescriptor;
begin
FillChar(pfd,SizeOf(pfd),0);
with pfd do
begin
nSize:=sizeof(pfd);
nVersion:=1;
if ToBitmap then
dwFlags:=PFD_DRAW_TO_BITMAP or PFD_GENERIC_ACCELERATED or PFD_SUPPORT_OPENGL
else
dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
iPixelType:=PFD_TYPE_RGBA;
cColorBits:=24;
cDepthBits:=32;
iLayerType:=PFD_MAIN_PLANE
end;
nPixelFormat:=ChoosePixelFormat(DC,@pfd);
SetPixelFormat(DC,nPixelFormat,@pfd);
DescribePixelFormat(DC,nPixelFormat,SizeOf(TPixelFormatDescriptor),pfd);
if (pfd.dwFlags and PFD_NEED_PALETTE) <> 0 then
begin
nColors:= 1 shl pfd.cColorBits;
hHeap:=GetProcessHeap;
lpPalette:=HeapAlloc(hHeap,0,SizeOf(TLogPalette)+(nColors*SizeOf(TPaletteEntry)));
lpPalette^.palVersion:=$300;
lpPalette^.palNumEntries:=nColors;
byRedMask:=1 shl pfd.cRedBits-1;
byGreenMask:=1 shl pfd.cGreenBits-1;
byBlueMask:=1 shl pfd.cBlueBits-1;
for I:=0 to nColors-1 do
begin
lpPalette^.palPalEntry[I].peRed:=(((I shr pfd.cRedShift) and byRedMask)*255) div byRedMask;
lpPalette^.palPalEntry[I].peGreen:=(((I shr pfd.cGreenShift) and byGreenMask)*255) div byGreenMask;
lpPalette^.palPalEntry[I].peBlue:=(((I shr pfd.cBlueShift) and byBlueMask)*255) div byBlueMask;
lpPalette^.palPalEntry[I].peFlags:= 0
end;
Palette:=CreatePalette(lpPalette^);
HeapFree(hHeap,0,lpPalette);
if Palette<>0 then
begin
SelectPalette(DC,Palette,False);
RealizePalette(DC)
end
end
end;
procedure TForm1.Button1Click(Sender: TObject);
var Pict:TBitmap;
hrc:HGLRC;
Palette:HPalette;
Obj:GLUQuadricObj;
begin
Pict:=TBitmap.Create;
Palette:=0;
try
Pict.Width:=200;
Pict.Height:=200;
Pict.PixelFormat:=pf24bit;
SetDCPixelFormat(Pict.Canvas.Handle,Palette,True);
hrc:=wglCreateContext(Pict.Canvas.Handle);
wglMakeCurrent(Pict.Canvas.Handle,hrc);
glViewport(0,0,Pict.Width,Pict.Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(30,1,0.5,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
gluLookAt(0,-4.5,3.5,0,0,0,0,0,1);
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModelI(GL_Light_Model_Two_Side,1);
glEnable(GL_COLOR_MATERIAL);
glColor4F(0.7,0.3,0.5,0.9);
Obj:=gluNewQuadric;
gluCylinder(Obj,1.4,0.8,1.2,20,20);
gluDeleteQuadric(Obj);
glFinish;
glFlush;
wglMakeCurrent(0,0);
wglDeleteContext(hrc);
Printer.BeginDoc ;
Printer.Canvas.Draw(10,10,Pict) ;
Printer.EndDoc ;
finally
DeleteObject(Palette);
Pict.Free
end
end;Вот такой вариант работает:
работает медленно, но работает!!!
В принципе в название темы можно добавить "РЕШЕНО"
Код: Выделить всё
procedure TForm1.PrintButtonClick(Sender: TObject);
var
Pict:TBitmap;
Phrc : HGLRC;
Palette : HPalette;
Pixels,P : PGLUByte ; // указатель на область памяти для хранения картинки и счетчик
X,Y : word ;
R,G,B,A : byte ; // цвета
begin
Printer.Copies := 1 ;
Printer.Orientation := poPortrait ; {}
Pict := TBitmap.Create; // создаем битмап
Pict.PixelFormat := pf24bit;
Pict.Width := Printer.PageWidth ; // задаём размеры страницы принтера
Pict.Height := Printer.PageHeight ;
Palette := 0;
try
SetDCPixelFormat(Pict.Canvas.Handle,Palette,True) ; // включаем OpenGL процедура из предыдущего примера
Phrc := wglCreateContext(Pict.Canvas.Handle); // назначаем вывод в битмап
wglMakeCurrent(Pict.Canvas.Handle,Phrc);
GLInit ; // задаем начальные настройки - всё стандартно
glViewport (0,0,Printer.PageWidth,Printer.PageHeight); { define the viewport }
GLCtrlPaint(Pict.Canvas.Handle,Phrc) ; // процедура формирования рисунка - любая
getmem(Pixels,(Printer.PageWidth+1)*(Printer.PageHeight+1)*4) ; // выделяем память под буфер вывода
glReadPixels(0,0,Printer.PageWidth,Printer.PageHeight,GL_RGBA,GL_UNSIGNED_BYTE,Pixels) ; // копируем буфер вывода
P := Pixels ; // устанавливаем счетчик на начало копии буфера
for Y := 0 to Printer.PageHeight do // формируем картинку из буфера в битмап
for X := 0 to Printer.PageWidth-1 do
begin
R := P^ ; inc(P) ; // читаем инфу по цветам ...
G := P^ ; inc(P) ;
B := P^ ; inc(P) ;
A := P^ ; inc(P) ;
Pict.Canvas.Pixels[X,Y] := R+G*$100+B*$10000 ; // и задаем цвет пикселя в битмапе
end;
wglMakeCurrent(fDC,fhrc); // переключаем контекст вывода
wglDeleteContext(Phrc); //
Printer.BeginDoc ; // выводим картинку на принтер
Printer.Canvas.Draw(0,0,Pict) ;
Printer.EndDoc ;
finally
DeleteObject(Palette);
Pict.Free
end ;
end;
работает медленно, но работает!!!
В принципе в название темы можно добавить "РЕШЕНО"
