ImageExport.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.IO;
  6. using System.Runtime.InteropServices;
  7. using FastReport.Utils;
  8. namespace FastReport.Export.Image
  9. {
  10. /// <summary>
  11. /// Specifies the image export format.
  12. /// </summary>
  13. public enum ImageExportFormat
  14. {
  15. /// <summary>
  16. /// Specifies the .bmp format.
  17. /// </summary>
  18. Bmp,
  19. /// <summary>
  20. /// Specifies the .png format.
  21. /// </summary>
  22. Png,
  23. /// <summary>
  24. /// Specifies the .jpg format.
  25. /// </summary>
  26. Jpeg,
  27. /// <summary>
  28. /// Specifies the .gif format.
  29. /// </summary>
  30. Gif,
  31. /// <summary>
  32. /// Specifies the .tif format.
  33. /// </summary>
  34. Tiff,
  35. /// <summary>
  36. /// Specifies the .emf format.
  37. /// </summary>
  38. Metafile
  39. }
  40. /// <summary>
  41. /// Represents the image export filter.
  42. /// </summary>
  43. public partial class ImageExport : ExportBase
  44. {
  45. private ImageExportFormat imageFormat;
  46. private bool separateFiles;
  47. private int resolutionX;
  48. private int resolutionY;
  49. private int jpegQuality;
  50. private bool multiFrameTiff;
  51. private bool monochromeTiff;
  52. private EncoderValue monochromeTiffCompression;
  53. private System.Drawing.Image masterTiffImage;
  54. private System.Drawing.Image bigImage;
  55. private Graphics bigGraphics;
  56. private float curOriginY;
  57. private bool firstPage;
  58. private int paddingNonSeparatePages;
  59. private int pageNumber;
  60. private System.Drawing.Image image;
  61. private Graphics g;
  62. private int height;
  63. private int width;
  64. private int widthK;
  65. private string fileSuffix;
  66. private float zoomX;
  67. private float zoomY;
  68. private System.Drawing.Drawing2D.GraphicsState state;
  69. private string imageExtensionFormat;
  70. private string documentTitle;
  71. private bool saveStreams;
  72. const float DIVIDER = 0.75f;
  73. const float PAGE_DIVIDER = 2.8346400000000003f; // mm to point
  74. #region Properties
  75. /// <summary>
  76. /// Gets or sets the image format.
  77. /// </summary>
  78. public ImageExportFormat ImageFormat
  79. {
  80. get { return imageFormat; }
  81. set { imageFormat = value; }
  82. }
  83. /// <summary>
  84. /// Gets or sets a value that determines whether to generate separate image file
  85. /// for each exported page.
  86. /// </summary>
  87. /// <remarks>
  88. /// If this property is set to <b>false</b>, the export filter will produce one big image
  89. /// containing all exported pages. Be careful using this property with a big report
  90. /// because it may produce out of memory error.
  91. /// And also when using Memory Stream and the value is true, an exception will be thrown.
  92. /// </remarks>
  93. public bool SeparateFiles
  94. {
  95. get { return separateFiles; }
  96. set { separateFiles = value; }
  97. }
  98. /// <summary>
  99. /// Gets or sets image resolution, in dpi.
  100. /// </summary>
  101. /// <remarks>
  102. /// By default this property is set to 96 dpi. Use bigger values (300-600 dpi)
  103. /// if you going to print the exported images.
  104. /// </remarks>
  105. public int Resolution
  106. {
  107. get { return resolutionX; }
  108. set
  109. {
  110. resolutionX = value;
  111. resolutionY = value;
  112. }
  113. }
  114. /// <summary>
  115. /// Gets or sets horizontal image resolution, in dpi.
  116. /// </summary>
  117. /// <remarks>
  118. /// Separate horizontal and vertical resolution is used when exporting to TIFF. In other
  119. /// cases, use the <see cref="Resolution"/> property instead.
  120. /// </remarks>
  121. public int ResolutionX
  122. {
  123. get { return resolutionX; }
  124. set { resolutionX = value; }
  125. }
  126. /// <summary>
  127. /// Gets or sets vertical image resolution, in dpi.
  128. /// </summary>
  129. /// <remarks>
  130. /// Separate horizontal and vertical resolution is used when exporting to TIFF. In other
  131. /// cases, use the <see cref="Resolution"/> property instead.
  132. /// </remarks>
  133. public int ResolutionY
  134. {
  135. get { return resolutionY; }
  136. set { resolutionY = value; }
  137. }
  138. /// <summary>
  139. /// Gets or sets the jpg image quality.
  140. /// </summary>
  141. /// <remarks>
  142. /// This property is used if <see cref="ImageFormat"/> is set to <b>Jpeg</b>. By default
  143. /// it is set to 100. Use lesser value to decrease the jpg file size.
  144. /// </remarks>
  145. public int JpegQuality
  146. {
  147. get { return jpegQuality; }
  148. set { jpegQuality = value; }
  149. }
  150. /// <summary>
  151. /// Gets or sets the value determines whether to produce multi-frame tiff file.
  152. /// </summary>
  153. public bool MultiFrameTiff
  154. {
  155. get { return multiFrameTiff; }
  156. set { multiFrameTiff = value; }
  157. }
  158. /// <summary>
  159. /// Gets or sets a value that determines whether the Tiff export must produce monochrome image.
  160. /// </summary>
  161. /// <remarks>
  162. /// Monochrome tiff image is compressed using the compression method specified in the
  163. /// <see cref="MonochromeTiffCompression"/> property.
  164. /// </remarks>
  165. public bool MonochromeTiff
  166. {
  167. get { return monochromeTiff; }
  168. set { monochromeTiff = value; }
  169. }
  170. /// <summary>
  171. /// Gets or sets the compression method for a monochrome TIFF image.
  172. /// </summary>
  173. /// <remarks>
  174. /// This property is used only when exporting to TIFF image, and the <see cref="MonochromeTiff"/> property
  175. /// is set to <b>true</b>.
  176. /// <para/>The valid values for this property are: <b>EncoderValue.CompressionNone</b>,
  177. /// <b>EncoderValue.CompressionLZW</b>, <b>EncoderValue.CompressionRle</b>,
  178. /// <b>EncoderValue.CompressionCCITT3</b>, <b>EncoderValue.CompressionCCITT4</b>.
  179. /// The default compression method is CCITT4.
  180. /// </remarks>
  181. public EncoderValue MonochromeTiffCompression
  182. {
  183. get { return monochromeTiffCompression; }
  184. set { monochromeTiffCompression = value; }
  185. }
  186. /// <summary>
  187. /// Sets padding in non separate pages
  188. /// </summary>
  189. public int PaddingNonSeparatePages
  190. {
  191. get { return paddingNonSeparatePages; }
  192. set { paddingNonSeparatePages = value; }
  193. }
  194. private bool IsMultiFrameTiff
  195. {
  196. get { return ImageFormat == ImageExportFormat.Tiff && MultiFrameTiff; }
  197. }
  198. /// <summary>
  199. /// Enable or disable saving streams in GeneratedStreams collection.
  200. /// </summary>
  201. public bool SaveStreams
  202. {
  203. get { return saveStreams; }
  204. set { saveStreams = value; }
  205. }
  206. #endregion
  207. #region Private Methods
  208. private System.Drawing.Image CreateImage(int width, int height, string suffix)
  209. {
  210. widthK = width;
  211. if (ImageFormat == ImageExportFormat.Metafile)
  212. return CreateMetafile(suffix);
  213. return new Bitmap(width, height);
  214. }
  215. private void GeneratedUpdate(string filename, Stream stream)
  216. {
  217. int i = GeneratedFiles.IndexOf(filename);
  218. if (i == -1)
  219. {
  220. GeneratedFiles.Add(filename);
  221. GeneratedStreams.Add(stream);
  222. }
  223. else
  224. {
  225. GeneratedStreams[i] = stream;
  226. }
  227. }
  228. private System.Drawing.Image CreateMetafile(string suffix)
  229. {
  230. string extension = Path.GetExtension(FileName);
  231. string targetFileName = Path.ChangeExtension(FileName, suffix + extension);
  232. System.Drawing.Image image;
  233. using (Bitmap bmp = new Bitmap(1, 1))
  234. using (Graphics g = Graphics.FromImage(bmp))
  235. {
  236. IntPtr hdc = g.GetHdc();
  237. if (suffix == "")
  238. image = new Metafile(Stream, hdc);
  239. else
  240. {
  241. image = new Metafile(targetFileName, hdc);
  242. if (!GeneratedFiles.Contains(targetFileName))
  243. GeneratedFiles.Add(targetFileName);
  244. }
  245. g.ReleaseHdc(hdc);
  246. }
  247. return image;
  248. }
  249. private Bitmap ConvertToBitonal(Bitmap original)
  250. {
  251. Bitmap source = null;
  252. // If original bitmap is not already in 32 BPP, ARGB format, then convert
  253. if (original.PixelFormat != PixelFormat.Format32bppArgb)
  254. {
  255. source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
  256. source.SetResolution(original.HorizontalResolution, original.VerticalResolution);
  257. using (Graphics g = Graphics.FromImage(source))
  258. {
  259. g.DrawImageUnscaled(original, 0, 0);
  260. }
  261. }
  262. else
  263. {
  264. source = original;
  265. }
  266. // Lock source bitmap in memory
  267. BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
  268. // Copy image data to binary array
  269. int imageSize = sourceData.Stride * sourceData.Height;
  270. byte[] sourceBuffer = new byte[imageSize];
  271. Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
  272. // Unlock source bitmap
  273. source.UnlockBits(sourceData);
  274. // Create destination bitmap
  275. Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);
  276. // Lock destination bitmap in memory
  277. BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
  278. // Create destination buffer
  279. imageSize = destinationData.Stride * destinationData.Height;
  280. byte[] destinationBuffer = new byte[imageSize];
  281. int sourceIndex = 0;
  282. int destinationIndex = 0;
  283. int pixelTotal = 0;
  284. byte destinationValue = 0;
  285. int pixelValue = 128;
  286. int height = source.Height;
  287. int width = source.Width;
  288. int threshold = 500;
  289. // Iterate lines
  290. for (int y = 0; y < height; y++)
  291. {
  292. sourceIndex = y * sourceData.Stride;
  293. destinationIndex = y * destinationData.Stride;
  294. destinationValue = 0;
  295. pixelValue = 128;
  296. // Iterate pixels
  297. for (int x = 0; x < width; x++)
  298. {
  299. // Compute pixel brightness (i.e. total of Red, Green, and Blue values)
  300. pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3];
  301. if (pixelTotal > threshold)
  302. {
  303. destinationValue += (byte)pixelValue;
  304. }
  305. if (pixelValue == 1)
  306. {
  307. destinationBuffer[destinationIndex] = destinationValue;
  308. destinationIndex++;
  309. destinationValue = 0;
  310. pixelValue = 128;
  311. }
  312. else
  313. {
  314. pixelValue >>= 1;
  315. }
  316. sourceIndex += 4;
  317. }
  318. if (pixelValue != 128)
  319. {
  320. destinationBuffer[destinationIndex] = destinationValue;
  321. }
  322. }
  323. // Copy binary image data to destination bitmap
  324. Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
  325. // Unlock destination bitmap
  326. destination.UnlockBits(destinationData);
  327. // Dispose of source if not originally supplied bitmap
  328. if (source != original)
  329. {
  330. source.Dispose();
  331. }
  332. // Return
  333. destination.SetResolution(ResolutionX, ResolutionY);
  334. return destination;
  335. }
  336. private void SaveImage(System.Drawing.Image image, string suffix)
  337. {
  338. // store the resolution in output file.
  339. // Call this method after actual draw because it may affect drawing the text
  340. if (image is Bitmap)
  341. (image as Bitmap).SetResolution(ResolutionX, ResolutionY);
  342. if (IsMultiFrameTiff)
  343. {
  344. // select the image encoder
  345. ImageCodecInfo info = ExportUtils.GetCodec("image/tiff");
  346. EncoderParameters ep = new EncoderParameters(2);
  347. ep.Param[0] = new EncoderParameter(Encoder.Compression, MonochromeTiff ?
  348. (long)MonochromeTiffCompression : (long)EncoderValue.CompressionLZW);
  349. if (image == masterTiffImage)
  350. {
  351. // save the master bitmap
  352. if (MonochromeTiff)
  353. masterTiffImage = ConvertToBitonal(image as Bitmap);
  354. ep.Param[1] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
  355. masterTiffImage.Save(Stream, info, ep);
  356. }
  357. else
  358. {
  359. // save the frame
  360. if (MonochromeTiff)
  361. {
  362. System.Drawing.Image oldImage = image;
  363. image = ConvertToBitonal(image as Bitmap);
  364. oldImage.Dispose();
  365. }
  366. ep.Param[1] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
  367. masterTiffImage.SaveAdd(image, ep);
  368. }
  369. }
  370. else if (ImageFormat != ImageExportFormat.Metafile)
  371. {
  372. Stream stream;
  373. string targetFileName;
  374. if (saveStreams)
  375. {
  376. targetFileName = Path.ChangeExtension(documentTitle + suffix, imageExtensionFormat);
  377. stream = new MemoryStream();
  378. }
  379. else
  380. {
  381. string extension = Path.GetExtension(FileName);
  382. targetFileName = Path.ChangeExtension(FileName, suffix + extension);
  383. // empty suffix means that we should use the Stream that was created in the ExportBase
  384. stream = suffix == "" ? Stream : new FileStream(targetFileName, FileMode.Create);
  385. if (suffix != "")
  386. {
  387. GeneratedFiles.Add(targetFileName);
  388. }
  389. }
  390. if (ImageFormat == ImageExportFormat.Jpeg)
  391. {
  392. ExportUtils.SaveJpeg(image, stream, JpegQuality);
  393. }
  394. else if (ImageFormat == ImageExportFormat.Tiff && MonochromeTiff)
  395. {
  396. // handle monochrome tiff separately
  397. ImageCodecInfo info = ExportUtils.GetCodec("image/tiff");
  398. EncoderParameters ep = new EncoderParameters();
  399. ep.Param[0] = new EncoderParameter(Encoder.Compression, (long)MonochromeTiffCompression);
  400. using (Bitmap bwImage = ConvertToBitonal(image as Bitmap))
  401. {
  402. bwImage.Save(stream, info, ep);
  403. }
  404. }
  405. else
  406. {
  407. ImageFormat format = System.Drawing.Imaging.ImageFormat.Bmp;
  408. switch (ImageFormat)
  409. {
  410. case ImageExportFormat.Gif:
  411. format = System.Drawing.Imaging.ImageFormat.Gif;
  412. break;
  413. case ImageExportFormat.Png:
  414. format = System.Drawing.Imaging.ImageFormat.Png;
  415. break;
  416. case ImageExportFormat.Tiff:
  417. format = System.Drawing.Imaging.ImageFormat.Tiff;
  418. break;
  419. }
  420. image.Save(stream, format);
  421. }
  422. if (saveStreams)
  423. GeneratedUpdate(targetFileName, stream);
  424. else if (suffix != "")
  425. stream.Dispose();
  426. }
  427. if (image != masterTiffImage)
  428. image.Dispose();
  429. }
  430. #endregion
  431. #region Protected Methods
  432. /// <inheritdoc/>
  433. protected override string GetFileFilter()
  434. {
  435. string filter = ImageFormat.ToString();
  436. return Res.Get("FileFilters," + filter + "File");
  437. }
  438. /// <inheritdoc/>
  439. protected override void Start()
  440. {
  441. base.Start();
  442. //init
  443. SeparateFiles = Stream is MemoryStream ? false : SeparateFiles;
  444. GeneratedStreams = new List<Stream>();
  445. pageNumber = 0;
  446. height = 0;
  447. width = 0;
  448. image = null;
  449. g = null;
  450. zoomX = 1;
  451. zoomY = 1;
  452. state = null;
  453. curOriginY = 0;
  454. firstPage = true;
  455. if (saveStreams)
  456. {
  457. imageExtensionFormat = ImageFormat.ToString();
  458. separateFiles = true;
  459. documentTitle = (!String.IsNullOrEmpty(Report.ReportInfo.Name) ?
  460. Report.ReportInfo.Name : "");
  461. }
  462. if (!SeparateFiles && !IsMultiFrameTiff)
  463. {
  464. // create one big image. To do this, calculate max width and sum of pages height
  465. float w = 0;
  466. float h = 0;
  467. foreach (int pageNo in Pages)
  468. {
  469. SizeF size = Report.PreparedPages.GetPageSize(pageNo);
  470. if (size.Width > w)
  471. w = size.Width;
  472. h += size.Height + paddingNonSeparatePages * 2;
  473. }
  474. w += paddingNonSeparatePages * 2;
  475. bigImage = CreateImage((int)(w * ResolutionX / 96f), (int)(h * ResolutionY / 96f), "");
  476. bigGraphics = Graphics.FromImage(bigImage);
  477. bigGraphics.Clear(Color.Transparent);
  478. }
  479. pageNumber = 0;
  480. }
  481. /// <inheritdoc/>
  482. protected override void ExportPageBegin(ReportPage page)
  483. {
  484. base.ExportPageBegin(page);
  485. zoomX = ResolutionX / 96f;
  486. zoomY = ResolutionY / 96f;
  487. width = (int)(ExportUtils.GetPageWidth(page) * Units.Millimeters * zoomX);
  488. height = (int)(ExportUtils.GetPageHeight(page) * Units.Millimeters * zoomY);
  489. int suffixDigits = Pages[Pages.Length - 1].ToString().Length;
  490. fileSuffix = firstPage ? "" : (pageNumber + 1).ToString("".PadLeft(suffixDigits, '0'));
  491. if (SeparateFiles || IsMultiFrameTiff)
  492. {
  493. image = CreateImage(width, height, fileSuffix);
  494. if (IsMultiFrameTiff && masterTiffImage == null)
  495. masterTiffImage = image;
  496. }
  497. else
  498. image = bigImage;
  499. if (bigGraphics != null)
  500. g = bigGraphics;
  501. else
  502. g = Graphics.FromImage(image);
  503. state = g.Save();
  504. g.FillRegion(Brushes.Transparent, new Region(new RectangleF(0, curOriginY, width, height)));
  505. if (bigImage != null && curOriginY + height * 2 > bigImage.Height)
  506. page.Fill.Draw(new FRPaintEventArgs(g, 1, 1, Report.GraphicCache), new RectangleF(0, curOriginY, widthK, bigImage.Height - curOriginY));
  507. else
  508. page.Fill.Draw(new FRPaintEventArgs(g, 1, 1, Report.GraphicCache), new RectangleF(0, curOriginY, widthK, height + paddingNonSeparatePages * 2));
  509. if (image == bigImage)
  510. {
  511. if (ImageFormat != ImageExportFormat.Metafile)
  512. g.TranslateTransform(image.Width / 2 - width / 2 + page.LeftMargin * Units.Millimeters * zoomX,
  513. curOriginY + paddingNonSeparatePages + page.TopMargin * Units.Millimeters * zoomY);
  514. else
  515. g.TranslateTransform(widthK / 2 - width / 2 + page.LeftMargin * Units.Millimeters * zoomX,
  516. curOriginY + paddingNonSeparatePages + page.TopMargin * Units.Millimeters * zoomY);
  517. }
  518. else
  519. g.TranslateTransform(page.LeftMargin * Units.Millimeters * zoomX, page.TopMargin * Units.Millimeters * zoomY);
  520. g.ScaleTransform(1, zoomY / zoomX);
  521. // export bottom watermark
  522. if (page.Watermark.Enabled && !page.Watermark.ShowImageOnTop)
  523. AddImageWatermark(page);
  524. if (page.Watermark.Enabled && !page.Watermark.ShowTextOnTop)
  525. AddTextWatermark(page);
  526. // page borders
  527. if (page.Border.Lines != BorderLines.None)
  528. {
  529. using (TextObject pageBorder = new TextObject())
  530. {
  531. pageBorder.Border = page.Border;
  532. pageBorder.Left = 0;
  533. pageBorder.Top = 0;
  534. pageBorder.Width = (ExportUtils.GetPageWidth(page) - page.LeftMargin - page.RightMargin) * PAGE_DIVIDER / DIVIDER;
  535. pageBorder.Height = (ExportUtils.GetPageHeight(page) - page.TopMargin - page.BottomMargin) * PAGE_DIVIDER / DIVIDER;
  536. ExportObj(pageBorder);
  537. }
  538. }
  539. }
  540. /// <inheritdoc/>
  541. protected override void ExportBand(BandBase band)
  542. {
  543. base.ExportBand(band);
  544. ExportObj(band);
  545. foreach (Base c in band.ForEachAllConvectedObjects(this))
  546. {
  547. if (!(c is Table.TableColumn || c is Table.TableCell || c is Table.TableRow))
  548. ExportObj(c);
  549. }
  550. }
  551. private void ExportObj(Base obj)
  552. {
  553. if (obj is ReportComponentBase && (obj as ReportComponentBase).Exportable)
  554. (obj as ReportComponentBase).Draw(new FRPaintEventArgs(g, zoomX, zoomX, Report.GraphicCache));
  555. }
  556. /// <inheritdoc/>
  557. protected override void ExportPageEnd(ReportPage page)
  558. {
  559. // export top watermark
  560. if (page.Watermark.Enabled && page.Watermark.ShowImageOnTop)
  561. AddImageWatermark(page);
  562. if (page.Watermark.Enabled && page.Watermark.ShowTextOnTop)
  563. AddTextWatermark(page);
  564. g.Restore(state);
  565. if (g != bigGraphics)
  566. g.Dispose();
  567. if (SeparateFiles || IsMultiFrameTiff)
  568. SaveImage(image, fileSuffix);
  569. else
  570. curOriginY += height + paddingNonSeparatePages * 2;
  571. firstPage = false;
  572. pageNumber++;
  573. }
  574. private void AddImageWatermark(ReportPage page)
  575. {
  576. page.Watermark.DrawImage(new FRPaintEventArgs(g, zoomX, zoomX, Report.GraphicCache),
  577. new RectangleF(-page.LeftMargin * Units.Millimeters, -page.TopMargin * Units.Millimeters, width / zoomX, height / zoomY),
  578. page.Report, false);
  579. }
  580. private void AddTextWatermark(ReportPage page)
  581. {
  582. if (string.IsNullOrEmpty(page.Watermark.Text))
  583. return;
  584. page.Watermark.DrawText(new FRPaintEventArgs(g, zoomX, zoomX, Report.GraphicCache),
  585. new RectangleF(-page.LeftMargin * Units.Millimeters, -page.TopMargin * Units.Millimeters, width / zoomX, height / zoomY),
  586. page.Report, false);
  587. }
  588. /// <inheritdoc/>
  589. protected override void Finish()
  590. {
  591. if (IsMultiFrameTiff)
  592. {
  593. // close the file.
  594. EncoderParameters ep = new EncoderParameters(1);
  595. ep.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.Flush);
  596. masterTiffImage.SaveAdd(ep);
  597. }
  598. else if (!SeparateFiles)
  599. {
  600. bigGraphics.Dispose();
  601. bigGraphics = null;
  602. SaveImage(bigImage, "");
  603. }
  604. if (masterTiffImage != null)
  605. {
  606. masterTiffImage.Dispose();
  607. masterTiffImage = null;
  608. }
  609. }
  610. #endregion
  611. #region Public Methods
  612. /// <inheritdoc/>
  613. public override void Serialize(FRWriter writer)
  614. {
  615. base.Serialize(writer);
  616. writer.WriteValue("ImageFormat", ImageFormat);
  617. writer.WriteBool("SeparateFiles", SeparateFiles);
  618. writer.WriteInt("ResolutionX", ResolutionX);
  619. writer.WriteInt("ResolutionY", ResolutionY);
  620. writer.WriteInt("JpegQuality", JpegQuality);
  621. writer.WriteBool("MultiFrameTiff", MultiFrameTiff);
  622. writer.WriteBool("MonochromeTiff", MonochromeTiff);
  623. }
  624. #endregion
  625. /// <summary>
  626. /// Initializes a new instance of the <see cref="ImageExport"/> class.
  627. /// </summary>
  628. public ImageExport()
  629. {
  630. paddingNonSeparatePages = 0;
  631. fileSuffix = String.Empty;
  632. HasMultipleFiles = true;
  633. imageFormat = ImageExportFormat.Jpeg;
  634. separateFiles = true;
  635. Resolution = 96;
  636. jpegQuality = 100;
  637. monochromeTiffCompression = EncoderValue.CompressionCCITT4;
  638. saveStreams = false;
  639. }
  640. }
  641. }