Table of Contents

Sending image files to the printer

by Richard Russell, May 2006, updated November 2010 and January 2012

BBC BASIC for Windows provides the *DISPLAY command to display an image contained in a Windows Bitmap (.BMP) file on the screen, but there is no equivalent command for sending the file to the printer. You can of course first display it on the screen and then transfer it to the printer using *HARDCOPY, but the quality of the resulting printout is then limited by the resolution of the screen.

BMP images


The program below allows you to send a BMP file to the printer. Although in this example nothing else is printed, you can if you wish output text or other images to the same page before finally printing it.

        bmp$ = "C:\Windows\Web\Wallpaper\Bliss.bmp"
        VDU 2,1,32
        PROCprintbmp(bmp$, 1, 1, 6, 4.5)
        VDU 1,12,3
        END
 
        DEF PROCprintbmp(bmp$, X, Y, W, H)
        LOCAL A%, L%, sx%, sy%
        A% = OPENIN(bmp$)
        IF A% = 0 ERROR 100, "Couldn't open file "+bmp$
        L% = EXT#A% : CLOSE#A%
        SYS "GlobalAlloc", 0, L% TO A%
        OSCLI "LOAD """+bmp$+""" "+STR$~A%+"+"+STR$~L%
        SYS "GetDeviceCaps", @prthdc%, 88 TO sx%
        SYS "GetDeviceCaps", @prthdc%, 90 TO sy%
        SYS "SetStretchBltMode", @prthdc%, 4
        SYS "StretchDIBits", @prthdc%, X*sx%, Y*sy%, W*sx%, H*sy%, 0, 0, \
        \                    A%!18, A%!22, A%+A%!10, A%+14, 0, &CC0020
        SYS "GlobalFree", A%
        ENDPROC

The four numeric parameters to “PROCprintbmp” are the position (horizontal, vertical) and size (width, height) respectively of the image on the paper, in inches, measured from the top left-hand corner.

GIF or JPEG images


If you want to print a GIF or JPEG file you can use the code below:

        pic$ = "C:\Windows\Web\Wallpaper\Azul.jpg"
        VDU 2,1,32
        PROCprintgifjpeg(pic$, 1, 1, 6, 4.5)
        VDU 1,12,3
        END
 
        DEF PROCprintgifjpeg(pic$, X, Y, W, H)
        LOCAL ole%, iid%, pic%, gpp%, hmw%, hmh%
        DIM iid% LOCAL 15, pic% LOCAL 513
 
        SYS "LoadLibrary", "OLEAUT32.DLL" TO ole%
        SYS "GetProcAddress", ole%, "OleLoadPicturePath" TO `OleLoadPicturePath`
 
        SYS "MultiByteToWideChar", 0, 0, pic$, -1, pic%, 256
 
        iid%!0  = &7BF80980
        iid%!4  = &101ABF32
        iid%!8  = &AA00BB8B
        iid%!12 = &AB0C3000
 
        SYS `OleLoadPicturePath`, pic%, 0, 0, 0, iid%, ^gpp%
        IF gpp% = 0 ERROR 100, "Couldn't open file "+pic$
 
        SYS !(!gpp%+24), gpp%, ^hmw%
        SYS !(!gpp%+28), gpp%, ^hmh%
 
        SYS "GetDeviceCaps", @prthdc%, 88 TO sx%
        SYS "GetDeviceCaps", @prthdc%, 90 TO sy%
        SYS !(!gpp%+32), gpp%, @prthdc%, X*sx%, Y*sy%, W*sx%, H*sy%, \
        \                0, hmh%, hmw%, -hmh%, 0
 
        SYS !(!gpp%+8), gpp%
        ENDPROC

The parameters for “PROCprintgifjpeg” are as described for “PROCprintbmp” above. Note that it is important to include the drive letter in the file specification.

“PROCprintgifjpeg” will in fact print BMP files as well, but “PROCprintbmp” is simpler if that's all you need to do.

PNG or TIFF images


If you want to print a PNG or TIFF file you can use the code below:

        pic$ = "C:\WINDOWS\ServicePackFiles\i386\news.png"
        VDU 2,1,32
        PROCprintpngtiff(pic$, 1, 1, 6, 4.5)
        VDU 1,12,3
        END
 
        DEF PROCprintpngtiff(pic$, X, Y, W, H)
        LOCAL tSI{}, bmi{}, pic%, gdip%, image%, ix%, iy%, gfx%, lGDIP%
        DIM pic% LOCAL 513
 
        SYS "MultiByteToWideChar", 0, 0, pic$, -1, pic%, 256
 
        SYS "LoadLibrary", "GDIPLUS.DLL" TO gdip%
        IF gdip% = 0 ERROR 100, "Couldn't load GDIPLUS.DLL"
        SYS "GetProcAddress", gdip%, "GdiplusStartup" TO `GdiplusStartup`
        SYS "GetProcAddress", gdip%, "GdipLoadImageFromFile" TO `GdipLoadImageFromFile`
        SYS "GetProcAddress", gdip%, "GdipDrawImageRectRectI" TO `GdipDrawImageRectRectI`
        SYS "GetProcAddress", gdip%, "GdipGetImageHeight" TO `GdipGetImageHeight`
        SYS "GetProcAddress", gdip%, "GdipGetImageWidth" TO `GdipGetImageWidth`
        SYS "GetProcAddress", gdip%, "GdipCreateFromHDC" TO `GdipCreateFromHDC`
        SYS "GetProcAddress", gdip%, "GdipSetSmoothingMode" TO `GdipSetSmoothingMode`
        SYS "GetProcAddress", gdip%, "GdipDeleteGraphics" TO `GdipDeleteGraphics`
        SYS "GetProcAddress", gdip%, "GdipDisposeImage" TO `GdipDisposeImage`
        SYS "GetProcAddress", gdip%, "GdiplusShutdown" TO `GdiplusShutdown`
 
        DIM tSI{GdiplusVersion%, DebugEventCallback%, \
        \       SuppressBackgroundThread%, SuppressExternalCodecs%}
        DIM bmi{biSize%, biWidth%, biHeight%, biPlanes{l&,h&}, biBitCount{l&,h&}, \
        \       biCompression%, biSizeImage%, biXPelsPerMeter%, biYPelsPerMeter%, \
        \       biClrUsed%, biClrImportant%}
        tSI.GdiplusVersion% = 1
 
        SYS `GdiplusStartup`, ^lGDIP%, tSI{}, 0
        SYS `GdipLoadImageFromFile`, pic%, ^image%
        IF image% = 0 THEN
          SYS `GdiplusShutdown`, lGDIP%
          SYS "FreeLibrary", gdip%
          ERROR 90, "Couldn't load " + pic$
        ENDIF
 
        SYS `GdipGetImageWidth`, image%, ^ix%
        SYS `GdipGetImageHeight`, image%, ^iy%
 
        SYS `GdipCreateFromHDC`, @prthdc%, ^gfx%
        IF gfx%=0 ERROR 90, "GdipCreateFromHDC failed"
        SYS `GdipSetSmoothingMode`, gfx%, 2
 
        SYS `GdipDrawImageRectRectI`, gfx%, image%, X*100, Y*100, W*100, H*100, \
        \                                           0, 0, ix%, iy%, 2, 0, 0, 0
 
        SYS `GdipDeleteGraphics`, gfx%
        SYS `GdipDisposeImage`, image%
        SYS `GdiplusShutdown`, lGDIP%
        SYS "FreeLibrary", gdip%
        ENDPROC

The parameters for “PROCprintpngtiff” are as described for “PROCprintbmp” above.

“PROCprintpngtiff” will in fact print BMP, GIF and JPEG files as well, and may give better quality results. However it relies on the presence of the GDI Plus library so will work only on Windows XP (or later) or if you have specifically installed GDIPLUS.DLL on the target computer. Microsoft permits you to redistribute this file so you can include it with your program if necessary.