如何实现打印时,根据纸张大小来自动缩放图片

在打印图片时,经常会碰到一种情况: 图片的大小会超过纸张的大小; 此时,我们需要对图片进行缩放,来适应纸张的大小.

那么如何来实现呢?方法有二,

1) 根据打印机和打印纸张的设置, 直接转换图片的分辨率(Resolution).

   

 1  ' m_metafile是Metafile的一个实例 
 2 
 3  Using  bmp  As   New  Bitmap(m_metafile)
 4                       ' if image is large that printable area, scale it to fix page size
 5                       If  bmp.Width  >  settings.PrintableArea.Width  OrElse  bmp.Height  >  settings.PrintableArea.Height  Then
 6                           Dim  wRatio  As   Single
 7                           Dim  hRatio  As   Single
 8 
 9                          hRatio  =  bmp.Height  /  settings.PrintableArea.Height
10                          wRatio  =  bmp.Width  /  settings.PrintableArea.Width
11 
12                           If  wRatio  >  hRatio  Then
13                              bmp.SetResolution(hRatio  *   100 , hRatio  *   100 )
14                           Else
15                              bmp.SetResolution(wRatio  *   100 , wRatio  *   100 )
16                           End   If
17                       End   If
18                       ' draw image
19                      g.DrawImage(bmp,  0 0 )
20                   End   Using


注意:使用此方法的一个弊端是会降低图片分辨率,从而导致打印出来的图片有闪烁(dithering).因此它不适用有打印分辨率高的场合;例如在打印条形码(barcode)时,低分辨率有可能会造成无法被机器识别.


2) 使用Public Sub EnumerateMetafile(ByVal metafile As System.Drawing.Imaging.Metafile, ByVal destRect As System.Drawing.Rectangle, ByVal callback As System.Drawing.Graphics.EnumerateMetafileProc)

 1  ' m_metafile为Metafile的一个实例;
 2  ' g是Graphics的一个实例
 3  Dim  width  As   Integer   =  m_metafile.Width
 4               Dim  height  As   Integer   =  m_metafile.Height
 5 
 6              m_delegate  =   New  Graphics.EnumerateMetafileProc( AddressOf  MetafileCallback)
 7 
 8               ' -- YOU MUST PASS THE SIZE TO EnumerateMetafile, OTHERWIZE, THE PAGE IS NOT AUTO SCALED.
 9              g.EnumerateMetafile(m_metafile,  New  Rectangle( 0 0 , width, height), m_delegate)
10 
11               '  Clean up 
12              m_delegate  =   Nothing


注意:此方法没有1)中的闪烁问题,实现也比较简单,推荐使用.

 

完整的一个打印示例如下:

代码
  1  Imports  System
  2  Imports  System.IO
  3  Imports  System.Web.Services.Protocols
  4  Imports  System.Data
  5  Imports  System.Xml
  6  Imports  System.Drawing
  7  Imports  System.Drawing.Imaging
  8  Imports  System.Drawing.Printing
  9  Imports  System.Runtime.InteropServices
 10  Imports  System.Collections.Generic
 11 
 12 
 13  Public   Class  AutoScalePrint
 14 
 15       Private  m_renderedReport  As   Byte ()()
 16       Private  m_delegate  As  Graphics.EnumerateMetafileProc  =   Nothing
 17       Private  m_currentPageStream  As  MemoryStream
 18       Private  m_metafile  As  Metafile  =   Nothing
 19       Private  m_numberOfPages  As   Integer
 20       Private  m_currentPrintingPage  As   Integer
 21       Private  m_lastPrintingPage  As   Integer
 22       Private  m_PrintSettings  As  RTSystems.Framework.Printing.IPrintSetting
 23       Private  m_ReportProxy  As  Framework.Reporting.IReportProxy
 24       Private  ctlJob  As   New  PrintQueueController
 25 
 26       Private   Sub  pd_PrintPage( ByVal  sender  As   Object ByVal  ev  As  PrintPageEventArgs)
 27          ev.HasMorePages  =   False
 28           If  m_currentPrintingPage  <=  m_lastPrintingPage  AndAlso  MoveToPage(m_currentPrintingPage)  Then
 29               '  Draw the page 
 30              DrawPage(ev.Graphics, ev.PageSettings)
 31               '  If the next page is less than or equal to the last page, 
 32               '  print another page. 
 33               If  System.Threading.Interlocked.Increment(m_currentPrintingPage)  <=  m_lastPrintingPage  Then
 34                  ev.HasMorePages  =   True
 35               End   If
 36           End   If
 37       End Sub
 38 
 39       '  Method to draw the current emf memory stream 
 40       Private   Sub  DrawPage( ByVal  g  As  Graphics,  ByRef  settings  As  PageSettings)
 41           If  m_currentPageStream  Is   Nothing   OrElse   0   =  m_currentPageStream.Length  OrElse  m_metafile  Is   Nothing   Then
 42               Exit Sub
 43           End   If
 44           SyncLock   Me
 45               Dim  width  As   Integer   =  m_metafile.Width
 46               Dim  height  As   Integer   =  m_metafile.Height
 47 
 48              m_delegate  =   New  Graphics.EnumerateMetafileProc( AddressOf  MetafileCallback)
 49 
 50               ' -- YOU MUST PASS THE SIZE TO EnumerateMetafile, OTHERWIZE, THE PAGE IS NOT AUTO SCALED.
 51              g.EnumerateMetafile(m_metafile,  New  Rectangle( 0 0 , width, height), m_delegate)
 52 
 53               '  Clean up 
 54              m_delegate  =   Nothing
 55 
 56           End   SyncLock
 57       End Sub
 58 
 59       Private   Function  MoveToPage( ByVal  page  As  Int32)  As   Boolean
 60           '  Check to make sure that the current page exists in 
 61           '  the array list 
 62           If   Me .RenderedPage(m_currentPrintingPage  -   1 Is   Nothing   Then
 63               Return   False
 64           End   If
 65           '  Set current page stream equal to the rendered page 
 66          m_currentPageStream  =   New  MemoryStream( Me .RenderedReport(m_currentPrintingPage  -   1 ))
 67           '  Set its postion to start. 
 68          m_currentPageStream.Position  =   0
 69           '  Initialize the metafile 
 70           If  m_metafile  IsNot   Nothing   Then
 71              m_metafile.Dispose()
 72              m_metafile  =   Nothing
 73           End   If
 74           '  Load the metafile image for this page 
 75          m_metafile  =   New  Metafile( DirectCast (m_currentPageStream, Stream))
 76           Return   True
 77       End Function
 78 
 79       Private   Function  MetafileCallback( ByVal  recordType  As  EmfPlusRecordType,  ByVal  flags  As   Integer ByVal  dataSize  As   Integer ByVal  data  As  IntPtr,  ByVal  callbackData  As  PlayRecordCallback)  As   Boolean
 80           Dim  dataArray  As   Byte ()  =   Nothing
 81           '  Dance around unmanaged code. 
 82           If  data  <>  IntPtr.Zero  Then
 83               '  Copy the unmanaged record to a managed byte buffer 
 84               '  that can be used by PlayRecord. 
 85              dataArray  =   New   Byte (dataSize  -   1 ) {}
 86              Marshal.Copy(data, dataArray,  0 , dataSize)
 87           End   If
 88           '  play the record. 
 89          m_metafile.PlayRecord(recordType, flags, dataSize, dataArray)
 90 
 91           Return   True
 92       End Function
 93 
 94       Public   Property  RenderedPage()  As   Byte ()()
 95           Get
 96               Return  m_renderedReport
 97           End   Get
 98           Set ( ByVal  value  As   Byte ()())
 99              m_renderedReport  =  value
100           End   Set
101       End Property
102 
103       Public   Sub   Print ()  Implements  Framework.Printing.IPrintProxy.Print
104           ' set data to RenderedPage  in Byte()() format
105 
106          m_numberOfPages  =   Me .RenderedPage.Length
107 
108           If  m_numberOfPages  <   1   Then
109               Return
110           End   If
111 
112           Dim  pd  As   New  PrintDocument()
113           Dim  printerSettings  As   New  PrinterSettings()
114 
115          printerSettings.MaximumPage  =  m_numberOfPages
116          printerSettings.MinimumPage  =   1
117          printerSettings.PrintRange  =  PrintRange.SomePages
118          printerSettings.FromPage  =   1
119          printerSettings.ToPage  =  m_numberOfPages
120          printerSettings.PrinterName  =  job.Printer.PrinterName
121 
122          m_currentPrintingPage  =   1
123          m_lastPrintingPage  =  m_numberOfPages
124          pd.PrinterSettings  =  printerSettings
125 
126           AddHandler  pd.PrintPage,  AddressOf   Me .pd_PrintPage
127 
128           Try
129              pd.Print()
130           Finally
131              pd.Dispose()
132           End   Try
133       End Sub
134  End Class
135 


 

 

 

 

你可能感兴趣的:(图片)