Printing Bitmap

Printing Bitmap

I am using VF6.5, windows application. I display an image on the screen using OpenGL. Now I want to print it to a printer. When I use the following code the image prints out black. One of my problems is not understanding the structure of BITMAPINFO. I am not sure how to make the array of RGBQUAD structures, bmiColors(1) that specify the red, green, and blue intensities. There may be other things wrong with the code. I would appreciate any help that I can get.

Myron

subroutine PrintDIBbitmap(hdcbitmap) !hdcbitmap is the handle to the bitmap on the screen
use xftgdi
use VarGlob
use dfopngl

use comdlg32, only: PrintDlg, CommDlgExtendedError, T_PRINTDLG, PD_ALLPAGES, PD_RETURNDC, &
PD_NOPAGENUMS, PD_RETURNDEFAULT, PD_NOSELECTION
use gdi32, only: DeleteDC, StartDoc, StartPage, EndDoc, EndPage, TextOut, &
GetDeviceCaps, GetTextExtentPoint32, GetTextExtentExPoint, &
CreateFont, SelectObject, DeleteObject, ResetDC, SetBkMode,&
DM_ORIENTATION, DM_DUPLEX, DM_IN_BUFFER, DM_OUT_BUFFER, &
PHYSICALOFFSETX, PHYSICALOFFSETY, HORZRES, VERTRES, &
LOGPIXELSX, LOGPIXELSY, T_DOCINFO, T_SIZE, T_DEVMODE, &
DMORIENT_PORTRAIT, DMORIENT_LANDSCAPE, TRANSPARENT, &
FW_NORMAL, ANSI_CHARSET, OUT_DEFAULT_PRECIS, &
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, &
DEFAULT_PITCH, FF_DONTCARE, PRINTER_ACCESS_USE, T_PRINTER_DEFAULTS
use kernel32, only: GetLastError, MulDiv, GlobalLock, GlobalUnlock, GlobalFree, &
GetProfileString
use user32, only: GetForegroundWindow
use winspool, only: OpenPrinter, ClosePrinter, DocumentProperties
use dfwinty, only: NULL, TRUE, FALSE, MAX_PATH, ERROR_NO_ERROR
use dfwina

implicit none

integer(4) nRet,bitmap
type(T_PRINTDLG) :: PRINTDLG_Struct
type(T_DOCINFO) :: DOCINFO_Struct
type(T_SIZE) :: SIZE_Struct
type(T_DEVMODE) :: DEVMODE_Struct
type(T_PRINTER_DEFAULTS) :: PrtrDef

type(T_BITMAPFILEHEADER) bmfh
type(T_BITMAPINFOHEADER) bmih
type(T_BITMAPINFO) bmi
type(T_BITMAP) bm
type (T_RGBQUAD) bmiColors(1) !not sure how to get this array of RGBQUAD values

type(T_RECT) rect

integer hFont,hOldFont, hPrinter, hOldDC
integer PrinterXoffset,PrinterYoffset,page_width,page_height,pixels_per_inch_x,pixels_per_inch_y
integer line_height, current_x, current_y, initial_x, initial_y
integer max_y, line_width, font_height
pointer (p_DEVMODE, DEVMODE_Struct)

! Declare default values and local variables for optional arguments
logical(4), parameter :: DDefault_Printer = .TRUE. ! Use default printer?
logical(4) :: WDefault_Printer
real(4), parameter :: Dline_spacing = 1.0 ! Multiplier by line height of line spacing
real(4) :: WLine_Spacing ! Local variable
real(4), parameter :: Dhoriz_margin = 0.5 ! Left and right margins in inches
real(4) :: WHoriz_margin
real(4), parameter :: Dvert_margin = 0.5 ! Top and bottom margins in inches
real(4) :: WVert_Margin
integer(4), parameter :: DTab_stop = 4 ! Tab column width
integer(4) :: WTab_stop
integer(4), parameter :: DPoint_Size = 0 ! Point size (0=Default)
integer(4) :: WPoint_Size

integer anull,bnull
character*33, parameter :: Dfont = "Courier New"C ! Font
character*33 :: Wfont
logical(4), parameter :: DFortran_CC = .FALSE. ! Fortran carriage control?
logical(4) :
: WFortran_CC

character*516 line
character*1024 buffer
character*128 DefaultPrinterName
character*15 document_name
integer(4) line_len,substr_pos,substr_width,nLen
integer(4) column, i,j,ret
logical(4) top_of_page,Opened
character*10 formatted,sequential
integer(4) IOS
character*3 PrintingTextDocument
integer(4) vp(4),width,height,NumPixelPerInchXdir,NumPixelPerInchYdir,bmsize,rdim,rdimdw,rdimbm
integer(4) hbmComp,hbmold,hdcComp,retint,PaperWidthPixels,PaperHeightRasterLines,MaxWidth,MaxHeight
integer(4) retcod,last_error,ScreenDC,ScreenWidthPixels,ScreenHeightRasterLines
integer(4) hDCPrintDLG,busy,oldcursor,hdcbitmap
integer(1), allocatable :: bmbits(:,:),bmrow(:)
integer iw,IOrient
real(8) ScaleFactorX,ScaleFactorY
integer(4) ScaleFactorColumn,ScaleFactorRow,ppix,ppiy,brush
character DiLine*20
integer(4) ih,jw,kw,pixelrgb,xleft,ytop,BitmapWidthPixels,BitmapHeightRasterLines,PrinterWidthPixels,PrinterHeightRasterLines
integer(4) NumPixelPerInchXdirBitmap,NumPixelPerInchYdirBitmap,NumPixelPerInchXdirPrinter,NumPixelPerInchYdirPrinter
integer(4) xsize,ysize,xoffset,yoffset,rgbval,Numbercolors
IOrient=2 !landscape
IOrient=1 !portrait

PRINTDLG_Struct%lStructSize = SIZEOF(PRINTDLG_Struct)
PRINTDLG_Struct%hwndOwner = GetForegroundWindow()
PRINTDLG_Struct%hDevMode = NULL
PRINTDLG_Struct%hDevNames = NULL
PRINTDLG_Struct%hDc = NULL
PRINTDLG_Struct%Flags = PD_ALLPAGES .OR. PD_RETURNDC .OR. PD_NOPAGENUMS &
.OR. PD_NOSELECTION

PRINTDLG_Struct%nFromPage = 1
PRINTDLG_Struct%nToPage = 1
PRINTDLG_Struct%nMinPage = 1
PRINTDLG_Struct%nMaxPage = 1
PRINTDLG_Struct%nCopies = 1
PRINTDLG_Struct%hInstance = NULL
PRINTDLG_Struct%lCustData = NULL
PRINTDLG_Struct%lpfnPrintHook = NULL
PRINTDLG_Struct%lpfnSetupHook = NULL
PRINTDLG_Struct%lpPrintTemplateName = NULL
PRINTDLG_Struct%lpSetupTemplateName = NULL
PRINTDLG_Struct%hPrintTemplate = NULL
PRINTDLG_Struct%hSetupTemplate = NULL

! Bring up the Print dialog box and allow user to select printer
Last_Error = PrintDlg (PRINTDLG_Struct)

hDCPrintDLG=PRINTDLG_Struct%hDc

if((IOrient.eq.1).or.(IOrient.eq.2))then
P_DEVMODE=GlobalLock(PRINTDLG_Struct%hDevMode )
DEVMODE_Struct%dmOrientation=2
if(IOrient.eq.2)DEVMODE_Struct%dmOrientation=1
Last_Error=ResetDC(PRINTDLG_Struct%hDevMode,DEVMODE_Struct)
Last_Error=GlobalUnlock(PRINTDLG_Struct%hDevMode)
endif

!screenwidth and screenheight are width and height of screen in pixels

width=.99*screenwidth
height=.95*screenheight
bmsize = width*height*3
rdim = width*3 !bitmap file always saved as 24 bit bitmap
rdimdw = rdim !row dimension ending on a dword boundary
if (MOD(rdimdw,4) .ne. 0) rdimdw = rdimdw+4-MOD(rdimdw,4)
!-- Get pixel information
BitmapWidthPixels=GetDeviceCaps(hDCbitmap,HORZRES)
BitmapHeightRasterLines=GetDeviceCaps(hDCbitmap,VERTRES)
PrinterWidthPixels=GetDeviceCaps(hDCPrintDLG,HORZRES)
PrinterHeightRasterLines=GetDeviceCaps(hDCPrintDLG,VERTRES)
NumPixelPerInchXdirBitMap = GetDeviceCaps(hDCbitmap,LOGPIXELSX) !no of pixels/inch, x-dir
NumPixelPerInchYdirBitMap = GetDeviceCaps(hDCbitmap,LOGPIXELSY) !no of pixels/inch, y-dir
NumPixelPerInchXdirPrinter = GetDeviceCaps(hDCPrintDLG,LOGPIXELSX) !no of pixels/inch, x-dir
NumPixelPerInchYdirPrinter = GetD
eviceCaps(hDCPrintDLG,LOGPIXELSY) !no of pixels/inch, y-dir
Numbercolors=GetDeviceCaps(hDCPrintDLG,NUMCOLORS)

!-- Create compatible DC and get bitmap
hdcComp = CreateCompatibleDC(hDCbitmap)
hbmComp = CreateCompatibleBitmap(hDCbitmap,Width,Height)
hbmold = SelectObject(hdcComp,hbmComp)
retint = BitBlt(hdcComp,0,0,width,height,hdcbitmap,0,0,SRCCOPY)
retint = GetObject(hbmComp,24,LOC(bm))

if (bm%bmBitsPixel .eq. 24) then
rdimbm = rdim !row dimension ending on a word boundary
if (MOD(rdimbm,2) .ne. 0) rdimbm = rdimbm+1
else if (bm%bmBitsPixel .eq. 32) then
rdimbm = width*4
else
retint = MessageBox(NULL,'Display properties not supported, bitmap not saved'C, &
'Under Display Properties, set Color Palette to True Color'C,MB_OK+MB_ICONEXCLAMATION)
retcod = 0
go to 900
end if
allocate(bmbits(rdimbm,height))
retint = GetBitmapBits(hbmComp,rdimbm*height,LOC(bmbits))

!-- Create bitmap file header
bmfh%bfType = 'BM'
bmfh%bfSize = SIZEOF(bmfh)+SIZEOF(bmih)+rdimdw*height
bmfh%bfReserved1 = 0
bmfh%bfReserved2 = 0
bmfh%bfOffBits = SIZEOF(bmfh)+SIZEOF(bmih)

!-- Create bitmap info header
bmih%biSize = SIZEOF(bmih)
bmih%biWidth = width
bmih%biHeight = height
bmih%biPlanes = bm%bmPlanes
bmih%biBitCount = MIN(24,bm%bmBitsPixel)
bmih%biCompression = BI_RGB
bmih%biSizeImage = rdimdw*height
bmih%biXPelsPerMeter = NINT(NumPixelPerInchXdirBitmap/0.0254) !(1 inch = 0.0254 m)
bmih%biYPelsPerMeter = NINT(NumPixelPerInchYdirBitmap/0.0254) !(1 inch = 0.0254 m)
bmih%biClrUsed = 0
bmih%biClrImportant = 0

bmi%bmiHeader%biSize = SIZEOF(bmih)
bmi%bmiHeader%biWidth = width
bmi%bmiHeader%biHeight = height
bmi%bmiHeader%biPlanes = bm%bmPlanes
bmi%bmiHeader%biBitCount = MIN(24,bm%bmBitsPixel)
bmi%bmiHeader%biCompression = BI_RGB
bmi%bmiHeader%biSizeImage = rdimdw*height
bmi%bmiHeader%biXPelsPerMeter = NINT(NumPixelPerInchXdirBitmap/0.0254) !(1 inch = 0.0254 m)
bmi%bmiHeader%biYPelsPerMeter = NINT(NumPixelPerInchYdirBitmap/0.0254) !(1 inch = 0.0254 m)
bmi%bmiHeader%biClrUsed = 0
bmi%bmiHeader%biClrImportant = 0

DiLine='MyronBitmap'
IW=LEN_TRIM(DiLine)+1
DiLine(IW:IW)=CHAR(0)
DOCINFO_Struct%cbSize = SIZEOF(DOCINFO_Struct)
DOCINFO_Struct%lpszDocName =LOC(DiLine)
DOCINFO_Struct%lpszOutput = NULL
DOCINFO_Struct%lpszDatatype = NULL
DOCINFO_Struct%fwType = 0

! I know the following is wrong. I am not sure how to specify bmi%bmiColors
do ih=height,1,-1
do iw=1,width
rgbval=getpixel(hdcComp,iw,ih)
bmi%bmiColors(1)%rgbBlue=ibits(rgbval,3,2)
bmi%bmiColors(1)%rgbGreen=ibits(rgbval,5,2)
bmi%bmiColors(1)%rgbRed=ibits(rgbval,7,2)
bmi%bmiColors(1)%rgbReserved=0
end do
enddo

Last_Error=SetMapMode(hDCPrintDLG,MM_TEXT)

Last_Error = StartDoc (hDCPrintDLG,DOCINFO_Struct)
Last_Error = StartPage (hDCPrintDLG)
rect%top=0
rect%left=0
rect%right=GetDeviceCaps(hDCPrintDLG,HORZRES)
rect%bottom=GetDeviceCaps(hDCPrintDLG,VERTRES)

hbmComp = CreateCompatibleDC(hDCPrintDLG)
bitmap=CreateDIBSection(hDCPrintDLG,bmi,DIB_RGB_COLORS,LOC(bmbits),Null,Null)

Last_Error=SelectObject(hbmComp,bitmap)

! scale and center on page
xsize=rect%right
ysize=xsize*bmi%bmiHeader%biHeight/bmi%bmiHeader%biWidth
if(ysize.gt.rect%bottom)then
ysize=rect%bottom
xsize=ysize*bmi%bmiHeader%biWidth/bmi%bmiHeader%biHeight
endif
xoffset=(rect%right-xsize)/2
yoffset=(rect%bottom-ysize)/2

Last_Error = StretchBlt(hDCPrintDLG,Xoffset,Yoffset,xsize,ysize,hbmComp,&
0,0,bmi%bmiHeader%biWidth,bmi%bmiHeader%biHeight,SRCCOPY)
Last_Error=ENDPAGE(hDCPrintDLG)
Last_Error=ENDDOC(hDCPrintDLG)
Last_Error=DeleteDC(hDCPrintDLG)
Last_Error=DeleteDC(hdcComp)
Last_Error=DeleteObject(hbmComp)
900 continue
endsubroutine PrintDIBbitmap

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Can't say why this looong code doesn't work -- only that it's unnecessarily complicated. It should be as simple as:

hDCPrintDLG=PRINTDLG_Struct%hDc
!Calculate offsets & scaling here
Last_Error = StretchBlt(hDCPrintDLG,Xoffset,Yoffset,xsize,ysize,hdcbitmap,&
0,0,someWidth,someHeight,SRCCOPY)

Jugoslav

Jugoslav
www.xeffort.com

Jugoslav

Thank you for your help. My code started off as simple as you suggested but it didn't work. I found a couple help documents, "Printing a Document", "Using Bitmaps", and "Device-Inpendent Bitmaps". I also had a C program from OpenGL SuperBible. According to "Printing a Document" you need to initialize the members of a DOCINFO structure so that you can use the StartDoc and StartPage function. For the print dialog you need to initialize members of the Print Dialog structure. I thought that it was necessary to make a device independent bitmap. I found myself trying to initialize a bunch of structures about the bitmap. My code kept getting bigger and bigger.
I am not sure why it doesn't work with the couple of lines of code that you suggest. I think the printer needs more information than what it gets from the bitmap handle that you give it in the StretchBlt command. If you are interested I can send you the C code that prints a bitmap. The only reason I am not using the C code is because when I went to Windows 2000 it quit working (memory error). Since all of my programs are Fortran I wanted a subroutine that prints bitmaps in Fortran.

Myron

Umm, "didn't work" is a broad term -- if a paper came out of the printer it has been set up correctly; if it produced garbage or blank paper, that's another kind of problem.

However...
I think the printer needs more information than what it gets from the bitmap handle that you give it in the StretchBlt command
Are you mixing DC handles and bitmap handles or was it a typo? DCs and bitmaps are not the same. StretchBlt expects a DC handle; I assumed hdcBitmap was one, but rereading your code it seems I was wrong ("hdc" prefix confused me). To "convert" a bitmap to a DC you do need to create a DC first and select the bitmap onto it:

hdcBuffer = CreateCompatibleDC(NULL)
iSt = SelectObject(hdcBuffer, hBitmap)
iSt = Last_Error = StretchBlt(hDCPrintDLG,Xoffset,Yoffset,xsize,ysize,hdcBuffer,&
0,0,bmi%bmiHeader%biWidth,bmi%bmiHeader%biHeight,SRCCOPY)

If it still fails, feel free to contact me privately.

Jugoslav

Jugoslav
www.xeffort.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today