Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Printing graphics

Brooks_Van_Horn
New Contributor I
1,199 Views

If I have a window DC (sDC) and a printer DC (pDC), why can't I just draw into pDC the way I would a sDC? Or if I have a DIB, how di I print it? I would really like to know of any experience yoiu've had with this.

Thanks,

Brooks Van Horn

0 Kudos
1 Solution
Paul_Curtis
Valued Contributor I
1,199 Views

Here is a routine which prints a bitmap to an already-initialized printer device context (hdc_printer).  The bitmap in this case is passed as a resourceId already defined via the resource editer, or as a handle to a bitmap generated or acquired by some other means.  This routine is part of a larger module which INCLUDEs IFWIN and IFWINTY.

FUNCTION print_bitmap (hdc_printer, resourceId, hBmap, &
                       xpos, ypos, mult, origin) RESULT (res)
	IMPLICIT NONE
	INTEGER(HANDLE), INTENT(IN)	:: hdc_printer, hBmap
	INTEGER, INTENT(IN)	        :: resourceId, xpos, ypos, origin
	REAL,    INTENT(IN)	        :: mult
	INTEGER(HANDLE)		        :: hdc_screen, hbitmap, hlib
	INTEGER				        :: rval, res
	INTEGER				        :: swide, shigh, pwide, phigh, bwide, bhigh
	TYPE(T_RECT)		        :: rect
    TYPE(T_BITMAPINFO)          :: bmi

	!	NOTE - use of these functions requires that DIBSECTN.LIB be included
	!	in the link build and that DIBSECTN.DLL be present in the runtime path 
	
	!INTERFACE
	!	INTEGER(4) FUNCTION DSLoadDIBSectionFromBMPFile (fname, hbitmap, hpalette)
	!	!DEC$ ATTRIBUTES DLLIMPORT, STDCALL,ALIAS:'_DSLoadDIBSectionFromBMPFile@12':: DSLoadDIBSectionFromBMPFi
    !   !DEC$ ATTRIBUTES REFERENCE :: fname
    !       CHARACTER*(*) fname
	!		INTEGER hbitmap
	!		INTEGER hpalette
	!	END FUNCTION DSLoadDIBSectionFromBMPFile
	!END INTERFACE

	INTERFACE
		INTEGER(4) FUNCTION DSDrawDIBSectionOnDC (hdc, hbitmap, lprect)
		!DEC$ ATTRIBUTES DLLIMPORT, STDCALL,ALIAS:'_DSDrawDIBSectionOnDC@12':: DSDrawDIBSectionOnDC
			INTEGER hdc, hbitmap, lprect
		END FUNCTION DSDrawDIBSectionOnDC
	END INTERFACE

	!	scaling factors, screen to printer
	hdc_screen = GetDC (NULL)
	swide = GetDeviceCaps (hdc_screen,  LOGPIXELSX)
	shigh = GetDeviceCaps (hdc_screen,  LOGPIXELSY)	
	pwide = GetDeviceCaps (hdc_printer, LOGPIXELSX)
	phigh = GetDeviceCaps (hdc_printer, LOGPIXELSY)
    
    !   load bitmap from supplied resource identifier
    IF (hBmap == 0) THEN

	    res = -1	! cannot load library
	    hlib = LoadLibrary ('DIBSECTN.DLL'C)
	    IF (hlib == 0) GO TO 20
	    
        res = -2	! cannot load bitmap
	    hbitmap = LoadImageID (ghInstance, resourceId, IMAGE_BITMAP,  &
	                           0, 0, LR_CREATEDIBSECTION)
	    IF (hbitmap == 0) THEN
	        rval = FreeLibrary (hlib)
	        RETURN
	    END IF
	    
	    res = -3	! bitmap has null extent
	    CALL GetBitmapSize (hbitmap, hdc_screen, bwide, bhigh)
		IF (bwide /= 0 .AND. bhigh /= 0) THEN
			bwide = IFIX(mult*FLOAT(bwide)*FLOAT(pwide)/FLOAT(swide))
			bhigh = IFIX(mult*FLOAT(bhigh)*FLOAT(phigh)/FLOAT(shigh))

			!	displace mapping rectangle wrt local origin
			SELECT CASE (origin)
			
			CASE (top_left)
				rect%left   = xpos
				rect%right  = xpos + bwide
				rect%top    = ypos
				rect%bottom = ypos + bhigh

			CASE (mid_left)
				rect%left   = xpos
				rect%right  = xpos + bwide
				rect%top    = ypos - bhigh/2
				rect%bottom = rect%top + bhigh
			
			CASE (bot_left)
				rect%left   = xpos
				rect%right  = xpos + bwide
				rect%top    = ypos - bhigh
				rect%bottom = ypos

			CASE (top_right)
				rect%left   = xpos - bwide
				rect%right  = xpos
				rect%top    = ypos
				rect%bottom = ypos + bhigh

			CASE (mid_right)
				rect%left   = xpos - bwide
				rect%right  = xpos
				rect%top    = ypos - bhigh/2
				rect%bottom = rect%top + bhigh
			
			CASE (bot_right)
				rect%left   = xpos - bwide
				rect%right  = xpos
				rect%top    = ypos - bhigh
				rect%bottom = ypos
			
			END SELECT

			res = -4	! cannot transfer DIB section to printer
			IF (DSDrawDIBSectionOnDC (hdc_printer, hbitmap, LOC(rect)))	&
				res = rect%bottom - rect%top + 1
			
		    rval = DeleteObject (hbitmap)
	        rval = FreeLibrary (hlib)
	
	    !   use supplied handle to existing bitmap
	    ELSE
	        hbitmap = hBmap
            bmi%bmiHeader%biBitCount = 0
            bmi%bmiHeader%biSize     = SIZEOF(bmi%bmiHeader)
            rval = GetDIBits (hdc_printer, hbitmap, 0, 0, 0, LOC(bmi), DIB_RGB_COLORS)
            IF (rval == 0) THEN
                banner(1) = 'GetDIBits error'
                CALL API_Error (hbitmap)
            END IF
            bwide = bmi%bmiHeader%biWidth
            bhigh = bmi%bmiHeader%biHeight
			!bwide = IFIX(mult*FLOAT(bwide)*FLOAT(pwide)/FLOAT(swide))
			!bhigh = IFIX(mult*FLOAT(bhigh)*FLOAT(phigh)/FLOAT(shigh))

            rval = SetDIBitsToDevice (hdc_printer,  & ! device context
                                      0, 0,         & ! device x,y ULC
                                      bwide, bhigh, & ! source dimensions
				                      0, 0,         & ! source x,y LLC
				                      0, bhigh,     & ! scan line start, count
				                      LOC(hbitmap), & ! DIB bits array
				                      bmi,          & ! bitmapinfo structure                                   
                                      DIB_RGB_COLORS) ! RGB or palette index flag
		
	    END IF
	END IF
20	rval = ReleaseDC (NULL, hdc_screen)

END FUNCTION print_bitmap

 

View solution in original post

0 Kudos
6 Replies
Paul_Curtis
Valued Contributor I
1,200 Views

Here is a routine which prints a bitmap to an already-initialized printer device context (hdc_printer).  The bitmap in this case is passed as a resourceId already defined via the resource editer, or as a handle to a bitmap generated or acquired by some other means.  This routine is part of a larger module which INCLUDEs IFWIN and IFWINTY.

FUNCTION print_bitmap (hdc_printer, resourceId, hBmap, &
                       xpos, ypos, mult, origin) RESULT (res)
	IMPLICIT NONE
	INTEGER(HANDLE), INTENT(IN)	:: hdc_printer, hBmap
	INTEGER, INTENT(IN)	        :: resourceId, xpos, ypos, origin
	REAL,    INTENT(IN)	        :: mult
	INTEGER(HANDLE)		        :: hdc_screen, hbitmap, hlib
	INTEGER				        :: rval, res
	INTEGER				        :: swide, shigh, pwide, phigh, bwide, bhigh
	TYPE(T_RECT)		        :: rect
    TYPE(T_BITMAPINFO)          :: bmi

	!	NOTE - use of these functions requires that DIBSECTN.LIB be included
	!	in the link build and that DIBSECTN.DLL be present in the runtime path 
	
	!INTERFACE
	!	INTEGER(4) FUNCTION DSLoadDIBSectionFromBMPFile (fname, hbitmap, hpalette)
	!	!DEC$ ATTRIBUTES DLLIMPORT, STDCALL,ALIAS:'_DSLoadDIBSectionFromBMPFile@12':: DSLoadDIBSectionFromBMPFi
    !   !DEC$ ATTRIBUTES REFERENCE :: fname
    !       CHARACTER*(*) fname
	!		INTEGER hbitmap
	!		INTEGER hpalette
	!	END FUNCTION DSLoadDIBSectionFromBMPFile
	!END INTERFACE

	INTERFACE
		INTEGER(4) FUNCTION DSDrawDIBSectionOnDC (hdc, hbitmap, lprect)
		!DEC$ ATTRIBUTES DLLIMPORT, STDCALL,ALIAS:'_DSDrawDIBSectionOnDC@12':: DSDrawDIBSectionOnDC
			INTEGER hdc, hbitmap, lprect
		END FUNCTION DSDrawDIBSectionOnDC
	END INTERFACE

	!	scaling factors, screen to printer
	hdc_screen = GetDC (NULL)
	swide = GetDeviceCaps (hdc_screen,  LOGPIXELSX)
	shigh = GetDeviceCaps (hdc_screen,  LOGPIXELSY)	
	pwide = GetDeviceCaps (hdc_printer, LOGPIXELSX)
	phigh = GetDeviceCaps (hdc_printer, LOGPIXELSY)
    
    !   load bitmap from supplied resource identifier
    IF (hBmap == 0) THEN

	    res = -1	! cannot load library
	    hlib = LoadLibrary ('DIBSECTN.DLL'C)
	    IF (hlib == 0) GO TO 20
	    
        res = -2	! cannot load bitmap
	    hbitmap = LoadImageID (ghInstance, resourceId, IMAGE_BITMAP,  &
	                           0, 0, LR_CREATEDIBSECTION)
	    IF (hbitmap == 0) THEN
	        rval = FreeLibrary (hlib)
	        RETURN
	    END IF
	    
	    res = -3	! bitmap has null extent
	    CALL GetBitmapSize (hbitmap, hdc_screen, bwide, bhigh)
		IF (bwide /= 0 .AND. bhigh /= 0) THEN
			bwide = IFIX(mult*FLOAT(bwide)*FLOAT(pwide)/FLOAT(swide))
			bhigh = IFIX(mult*FLOAT(bhigh)*FLOAT(phigh)/FLOAT(shigh))

			!	displace mapping rectangle wrt local origin
			SELECT CASE (origin)
			
			CASE (top_left)
				rect%left   = xpos
				rect%right  = xpos + bwide
				rect%top    = ypos
				rect%bottom = ypos + bhigh

			CASE (mid_left)
				rect%left   = xpos
				rect%right  = xpos + bwide
				rect%top    = ypos - bhigh/2
				rect%bottom = rect%top + bhigh
			
			CASE (bot_left)
				rect%left   = xpos
				rect%right  = xpos + bwide
				rect%top    = ypos - bhigh
				rect%bottom = ypos

			CASE (top_right)
				rect%left   = xpos - bwide
				rect%right  = xpos
				rect%top    = ypos
				rect%bottom = ypos + bhigh

			CASE (mid_right)
				rect%left   = xpos - bwide
				rect%right  = xpos
				rect%top    = ypos - bhigh/2
				rect%bottom = rect%top + bhigh
			
			CASE (bot_right)
				rect%left   = xpos - bwide
				rect%right  = xpos
				rect%top    = ypos - bhigh
				rect%bottom = ypos
			
			END SELECT

			res = -4	! cannot transfer DIB section to printer
			IF (DSDrawDIBSectionOnDC (hdc_printer, hbitmap, LOC(rect)))	&
				res = rect%bottom - rect%top + 1
			
		    rval = DeleteObject (hbitmap)
	        rval = FreeLibrary (hlib)
	
	    !   use supplied handle to existing bitmap
	    ELSE
	        hbitmap = hBmap
            bmi%bmiHeader%biBitCount = 0
            bmi%bmiHeader%biSize     = SIZEOF(bmi%bmiHeader)
            rval = GetDIBits (hdc_printer, hbitmap, 0, 0, 0, LOC(bmi), DIB_RGB_COLORS)
            IF (rval == 0) THEN
                banner(1) = 'GetDIBits error'
                CALL API_Error (hbitmap)
            END IF
            bwide = bmi%bmiHeader%biWidth
            bhigh = bmi%bmiHeader%biHeight
			!bwide = IFIX(mult*FLOAT(bwide)*FLOAT(pwide)/FLOAT(swide))
			!bhigh = IFIX(mult*FLOAT(bhigh)*FLOAT(phigh)/FLOAT(shigh))

            rval = SetDIBitsToDevice (hdc_printer,  & ! device context
                                      0, 0,         & ! device x,y ULC
                                      bwide, bhigh, & ! source dimensions
				                      0, 0,         & ! source x,y LLC
				                      0, bhigh,     & ! scan line start, count
				                      LOC(hbitmap), & ! DIB bits array
				                      bmi,          & ! bitmapinfo structure                                   
                                      DIB_RGB_COLORS) ! RGB or palette index flag
		
	    END IF
	END IF
20	rval = ReleaseDC (NULL, hdc_screen)

END FUNCTION print_bitmap

 

0 Kudos
Brooks_Van_Horn
New Contributor I
1,199 Views

Thanks Paul, but where do I acquire this DIBSECTN.LIB and DIBSECTN.DLL. They are not on my Win 10 x64 system.

Thanks, Brooka

0 Kudos
Brooks_Van_Horn
New Contributor I
1,199 Views

Also, what happens if there is no resource id. My problem is that I want to capture a part of my screen and print it.I can create a dib with the bm inside itt but then what. I have the code as follows:

     iret = StartDoc(hdcPrn, INFO)
     iret = StartPage(hdcPrn)

    ...... what do i do here????

     iret = EndPage(hDCPrn)
     iret = EndDoc(hDCprn)
     bret = DeleteDC(hDCprn)
     bret = ReleaseDC(ghWndMain, phDC)

 

0 Kudos
andrew_4619
Honored Contributor III
1,199 Views

reading Paul's code, if you have the bitmap structures populated and a dc for the print device then it seems to me that you just need to call "SetDIBitsToDevice"

0 Kudos
dboggs
New Contributor I
1,199 Views

If you were using Quickwin this would all be very easily accomplished in just a few (less than 10?) lines of code. That is, if you can settle for capturing the screen to a bmp file (which I usually convert to a tif or gif file) for later printing. But I don't think you are, so I will reserve the specifics for those who are interested.

Also: are you looking for publication quality in your graphics, or is it OK if the "printed" image as only the very crude resolution of a monitor's screen?

An interesting and undocumented note: The "screen" in a Quickwin window is actually a virtual screen, as it can be made any size at all and needn't fit within a window or even the entire monitor. In this way the resolution of the captured graphics can be made extremely high. I usually make my captured graphics 600 dpi, but there is no problem making them 1200 or 2400 dpi or really anything you want. And I don't understand why, but the publishers I work with prefer high-resolution bitmap graphics files instead of scalable vector files.

0 Kudos
Brooks_Van_Horn
New Contributor I
1,199 Views
0 Kudos
Reply