Document.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. using Resources;
  2. using SmartCoalApplication.Base;
  3. using SmartCoalApplication.Base.Enum;
  4. using System;
  5. using System.Collections.Specialized;
  6. using System.ComponentModel;
  7. using System.Drawing;
  8. using System.Drawing.Drawing2D;
  9. using System.Drawing.Imaging;
  10. using System.Windows.Forms;
  11. namespace SmartCoalApplication.Core
  12. {
  13. [Serializable]
  14. public sealed class Document : IDisposable
  15. {
  16. public Surface surface;
  17. private NameValueCollection userMetaData;
  18. private int width;
  19. private int height;
  20. private Threading.ThreadPool threadPool = new Threading.ThreadPool();
  21. private Vector<Rectangle> updateRegion;
  22. private bool dirty;
  23. [NonSerialized]
  24. private Metadata metadata = null;
  25. public Metadata Metadata
  26. {
  27. get
  28. {
  29. if (metadata == null)
  30. {
  31. metadata = new Metadata(userMetaData);
  32. }
  33. return metadata;
  34. }
  35. }
  36. public MeasurementUnit DpuUnit
  37. {
  38. get
  39. {
  40. return DefaultDpuUnit;
  41. /*PropertyItem[] pis = this.Metadata.GetExifValues(ExifTagID.ResolutionUnit);
  42. if (pis.Length == 0)
  43. {
  44. this.DpuUnit = DefaultDpuUnit;
  45. return DefaultDpuUnit;
  46. }
  47. else
  48. {
  49. try
  50. {
  51. ushort unit = Exif.DecodeShortValue(pis[0]);
  52. // Guard against bad data in the EXIF store
  53. switch ((MeasurementUnit)unit)
  54. {
  55. case MeasurementUnit.Pixel:
  56. case MeasurementUnit.Inch:
  57. case MeasurementUnit.Centimeter:
  58. case MeasurementUnit.Millimeter:
  59. case MeasurementUnit.Micron:
  60. case MeasurementUnit.Nano:
  61. return (MeasurementUnit)unit;
  62. default:
  63. this.Metadata.RemoveExifValues(ExifTagID.ResolutionUnit);
  64. return this.DpuUnit;
  65. }
  66. }
  67. catch (Exception)
  68. {
  69. this.Metadata.RemoveExifValues(ExifTagID.ResolutionUnit);
  70. return this.DpuUnit;
  71. }
  72. }*/
  73. }
  74. set
  75. {
  76. /*PropertyItem pi = Exif.CreateShort(ExifTagID.ResolutionUnit, (ushort)value);
  77. this.Metadata.ReplaceExifValues(ExifTagID.ResolutionUnit, new PropertyItem[1] { pi });
  78. if (value == MeasurementUnit.Pixel)
  79. {
  80. this.DpuX = 1.0;
  81. this.DpuY = 1.0;
  82. }
  83. Dirty = true;*/
  84. }
  85. }
  86. public static MeasurementUnit DefaultDpuUnit
  87. {
  88. get
  89. {
  90. return MeasurementUnit.Inch;
  91. }
  92. }
  93. public static double defaultDpi = 96;
  94. public static double DefaultDpi
  95. {
  96. get
  97. {
  98. return defaultDpi;
  99. }
  100. }
  101. /// <summary>
  102. /// 1英寸 = 2.54厘米
  103. /// </summary>
  104. public static double CmPerInch = 2.54;
  105. /// <summary>
  106. /// 默认值 = dpi / 单位
  107. /// </summary>
  108. public double defaultDpcm;
  109. public const double MinimumDpu = 0.01;
  110. public const double MaximumDpu = 32767.0;
  111. public static double GetDefaultDpu(MeasurementUnit units)
  112. {
  113. double dpu;
  114. switch (units)
  115. {
  116. case MeasurementUnit.Inch:
  117. dpu = defaultDpi;
  118. break;
  119. case MeasurementUnit.Centimeter:
  120. dpu = defaultDpi / CmPerInch;
  121. break;
  122. case MeasurementUnit.Millimeter:
  123. dpu = defaultDpi / CmPerInch / 10;
  124. break;
  125. case MeasurementUnit.Micron:
  126. dpu = defaultDpi / CmPerInch / 10000;
  127. break;
  128. case MeasurementUnit.Nano:
  129. dpu = defaultDpi / CmPerInch / 10000000;
  130. break;
  131. case MeasurementUnit.Pixel:
  132. dpu = 1.0;
  133. break;
  134. default:
  135. throw new InvalidEnumArgumentException("DpuUnit", (int)units, typeof(MeasurementUnit));
  136. }
  137. return dpu;
  138. }
  139. public double DpuX
  140. {
  141. get
  142. {
  143. return this.DpuX;
  144. /*PropertyItem[] pis = this.Metadata.GetExifValues(ExifTagID.XResolution);
  145. if (pis.Length == 0)
  146. {
  147. double defaultDpu = GetDefaultDpu(this.DpuUnit);
  148. this.DpuX = defaultDpu;
  149. return defaultDpu;
  150. }
  151. else
  152. {
  153. try
  154. {
  155. uint numerator;
  156. uint denominator;
  157. Exif.DecodeRationalValue(pis[0], out numerator, out denominator);
  158. if (denominator == 0)
  159. {
  160. throw new DivideByZeroException(); // will be caught by the below catch{}
  161. }
  162. else
  163. {
  164. return Math.Min(MaximumDpu, Math.Max(MinimumDpu, (double)numerator / (double)denominator));
  165. }
  166. }
  167. catch
  168. {
  169. this.Metadata.RemoveExifValues(ExifTagID.XResolution);
  170. return this.DpuX; // recursive call;
  171. }
  172. }*/
  173. }
  174. set
  175. {
  176. if (value <= 0.0)
  177. {
  178. throw new ArgumentOutOfRangeException("value", value, "must be > 0.0");
  179. }
  180. if (this.DpuUnit == MeasurementUnit.Pixel && value != 1.0)
  181. {
  182. throw new ArgumentOutOfRangeException("value", value, "if DpuUnit == Pixel, then value must equal 1.0");
  183. }
  184. Dirty = true;
  185. }
  186. }
  187. public double DpuY
  188. {
  189. get
  190. {
  191. return this.DpuY;
  192. /*PropertyItem[] pis = this.Metadata.GetExifValues(ExifTagID.YResolution);
  193. if (pis.Length == 0)
  194. {
  195. // If there's no DpuY setting, default to the DpuX setting
  196. double dpu = this.DpuX;
  197. this.DpuY = dpu;
  198. return dpu;
  199. }
  200. else
  201. {
  202. try
  203. {
  204. uint numerator;
  205. uint denominator;
  206. Exif.DecodeRationalValue(pis[0], out numerator, out denominator);
  207. if (denominator == 0)
  208. {
  209. throw new DivideByZeroException();
  210. }
  211. else
  212. {
  213. return Math.Min(MaximumDpu, Math.Max(MinimumDpu, (double)numerator / (double)denominator));
  214. }
  215. }
  216. catch
  217. {
  218. return this.DpuY;
  219. }
  220. }*/
  221. }
  222. set
  223. {
  224. if (value <= 0.0)
  225. {
  226. throw new ArgumentOutOfRangeException("value", value, "must be > 0.0");
  227. }
  228. if (this.DpuUnit == MeasurementUnit.Pixel && value != 1.0)
  229. {
  230. throw new ArgumentOutOfRangeException("value", value, "if DpuUnit == Pixel, then value must equal 1.0");
  231. }
  232. Dirty = true;
  233. }
  234. }
  235. /// <summary>
  236. /// 像素换算到物理长度
  237. /// </summary>
  238. /// <param name="pixel"></param>
  239. /// <param name="resultUnit"></param>
  240. /// <returns></returns>
  241. public double PixelToPhysicalX(double pixel, MeasurementUnit resultUnit)
  242. {
  243. double result;
  244. if (resultUnit == MeasurementUnit.Pixel)
  245. {
  246. result = pixel;
  247. }
  248. else
  249. {
  250. MeasurementUnit dpuUnit = this.DpuUnit;
  251. if (resultUnit == dpuUnit)
  252. {
  253. result = pixel / this.DpuX;
  254. }
  255. else if (dpuUnit == MeasurementUnit.Pixel)
  256. {
  257. double defaultDpuX = GetDefaultDpu(dpuUnit);
  258. result = pixel / defaultDpuX;
  259. }
  260. else if (dpuUnit == MeasurementUnit.Centimeter && resultUnit == MeasurementUnit.Inch)
  261. {
  262. result = pixel / this.DpuX; // (CmPerInch * this.DpuX);
  263. }
  264. else if (dpuUnit == MeasurementUnit.Inch && resultUnit == MeasurementUnit.Millimeter)
  265. {
  266. double defaultDpuY = GetDefaultDpu(MeasurementUnit.Millimeter);
  267. result = pixel / defaultDpuY;
  268. }
  269. else if (dpuUnit == MeasurementUnit.Inch && resultUnit == MeasurementUnit.Micron)
  270. {
  271. double defaultDpuY = GetDefaultDpu(MeasurementUnit.Micron);
  272. result = pixel / defaultDpuY;
  273. }
  274. else if (dpuUnit == MeasurementUnit.Inch && resultUnit == MeasurementUnit.Nano)
  275. {
  276. double defaultDpuY = GetDefaultDpu(MeasurementUnit.Nano);
  277. result = pixel / defaultDpuY;
  278. }
  279. else
  280. {
  281. result = pixel / this.DpuX; //(pixel * CmPerInch) / this.DpuX;
  282. }
  283. }
  284. return result;
  285. }
  286. /// <summary>
  287. /// 像素换算到物理长度
  288. /// </summary>
  289. /// <param name="pixel"></param>
  290. /// <param name="resultUnit"></param>
  291. /// <returns></returns>
  292. public double PixelToPhysicalY(double pixel, MeasurementUnit resultUnit)
  293. {
  294. double result;
  295. if (resultUnit == MeasurementUnit.Pixel)
  296. {
  297. result = pixel;
  298. }
  299. else
  300. {
  301. MeasurementUnit dpuUnit = this.DpuUnit;
  302. if (resultUnit == dpuUnit)
  303. {
  304. double defaultDpuY = GetDefaultDpu(dpuUnit);
  305. result = pixel / defaultDpuY;
  306. //result = pixel / this.DpuY;
  307. }
  308. else if (dpuUnit == MeasurementUnit.Pixel)
  309. {
  310. double defaultDpuY = GetDefaultDpu(dpuUnit);
  311. result = pixel / defaultDpuY;
  312. }
  313. else if (dpuUnit == MeasurementUnit.Inch && resultUnit == MeasurementUnit.Centimeter)
  314. {
  315. double defaultDpuY = GetDefaultDpu(MeasurementUnit.Centimeter);
  316. result = pixel / defaultDpuY; // pixel / (CmPerInch * this.DpuY);
  317. }
  318. else if (dpuUnit == MeasurementUnit.Inch && resultUnit == MeasurementUnit.Millimeter)
  319. {
  320. double defaultDpuY = GetDefaultDpu(MeasurementUnit.Millimeter);
  321. result = pixel / defaultDpuY;
  322. }
  323. else if (dpuUnit == MeasurementUnit.Inch && resultUnit == MeasurementUnit.Micron)
  324. {
  325. double defaultDpuY = GetDefaultDpu(MeasurementUnit.Micron);
  326. result = pixel / defaultDpuY;
  327. }
  328. else if (dpuUnit == MeasurementUnit.Inch && resultUnit == MeasurementUnit.Nano)
  329. {
  330. double defaultDpuY = GetDefaultDpu(MeasurementUnit.Nano);
  331. result = pixel / defaultDpuY;
  332. }
  333. else
  334. {
  335. result = pixel / this.DpuX;//(pixel * CmPerInch) / this.DpuY;
  336. }
  337. }
  338. return result;
  339. }
  340. private static string GetUnitsAbbreviation(MeasurementUnit units)
  341. {
  342. string result;
  343. switch (units)
  344. {
  345. case MeasurementUnit.Pixel:
  346. result = string.Empty;
  347. break;
  348. case MeasurementUnit.Inch:
  349. result = PdnResources.GetString("MeasurementUnit.Inch.Abbreviation");
  350. break;
  351. case MeasurementUnit.Centimeter:
  352. result = PdnResources.GetString("MeasurementUnit.Centimeter.Abbreviation");
  353. break;
  354. case MeasurementUnit.Millimeter:
  355. result = PdnResources.GetString("MeasurementUnit.Centimeter.Abbreviation");
  356. break;
  357. case MeasurementUnit.Micron:
  358. result = PdnResources.GetString("MeasurementUnit.Centimeter.Abbreviation");
  359. break;
  360. case MeasurementUnit.Nano:
  361. result = PdnResources.GetString("MeasurementUnit.Centimeter.Abbreviation");
  362. break;
  363. default:
  364. throw new InvalidEnumArgumentException("MeasurementUnit was invalid");
  365. }
  366. return result;
  367. }
  368. public void CoordinatesToStrings(MeasurementUnit units, int x, int y, out string xString, out string yString, out string unitsString)
  369. {
  370. unitsString = GetUnitsAbbreviation(units);
  371. if (units == MeasurementUnit.Pixel)
  372. {
  373. xString = x.ToString();
  374. yString = y.ToString();
  375. }
  376. else
  377. {
  378. double physicalX = PixelToPhysicalX(x, units);
  379. xString = physicalX.ToString("F2");
  380. double physicalY = PixelToPhysicalY(y, units);
  381. yString = physicalY.ToString("F2");
  382. }
  383. }
  384. [field: NonSerialized]
  385. public event EventHandler DirtyChanged;
  386. private void OnDirtyChanged()
  387. {
  388. if (DirtyChanged != null)
  389. {
  390. DirtyChanged(this, EventArgs.Empty);
  391. }
  392. }
  393. public bool Dirty
  394. {
  395. get
  396. {
  397. if (this.disposed)
  398. {
  399. throw new ObjectDisposedException("Document");
  400. }
  401. return this.dirty;
  402. }
  403. set
  404. {
  405. if (this.disposed)
  406. {
  407. throw new ObjectDisposedException("Document");
  408. }
  409. if (this.dirty != value)
  410. {
  411. this.dirty = value;
  412. OnDirtyChanged();
  413. }
  414. }
  415. }
  416. public int Width
  417. {
  418. get
  419. {
  420. return width;
  421. }
  422. }
  423. public int Height
  424. {
  425. get
  426. {
  427. return height;
  428. }
  429. }
  430. public Size Size
  431. {
  432. get
  433. {
  434. return new Size(Width, Height);
  435. }
  436. }
  437. public Document(int width, int height)
  438. {
  439. this.width = width;
  440. this.height = height;
  441. this.Dirty = true;
  442. this.updateRegion = new Vector<Rectangle>();
  443. Invalidate();
  444. }
  445. [field: NonSerialized]
  446. public event InvalidateEventHandler Invalidated;
  447. private void OnInvalidated(InvalidateEventArgs e)
  448. {
  449. if (Invalidated != null)
  450. {
  451. Invalidated(this, e);
  452. }
  453. }
  454. public void Invalidate()
  455. {
  456. Dirty = true;
  457. Rectangle rect = new Rectangle(0, 0, Width, Height);
  458. updateRegion.Clear();
  459. updateRegion.Add(rect);
  460. OnInvalidated(new InvalidateEventArgs(rect));
  461. }
  462. /// <summary>
  463. /// Creates a document that consists of one BitmapLayer.
  464. /// </summary>
  465. /// <param name="image">The Image to make a copy of that will be the first layer ("Background") in the document.</param>
  466. public static Document FromImage(Image image)
  467. {
  468. if (image == null)
  469. {
  470. throw new ArgumentNullException("image");
  471. }
  472. Document document = new Document(image.Width, image.Height);
  473. Surface surface = new Surface(new Size(image.Width, image.Height));
  474. surface.Clear(ColorBgra.FromBgra(0, 0, 0, 0));
  475. surface.PixelFormat = image.PixelFormat;
  476. //BitmapLayer layer = Layer.CreateBackgroundLayer(image.Width, image.Height);
  477. //layer.Surface.Clear(ColorBgra.FromBgra(0, 0, 0, 0));
  478. //layer.Surface.PixelFormat = image.PixelFormat;
  479. Bitmap asBitmap = image as Bitmap;
  480. // Copy pixels
  481. if (asBitmap != null && asBitmap.PixelFormat == PixelFormat.Format32bppArgb)
  482. {
  483. unsafe
  484. {
  485. BitmapData bData = asBitmap.LockBits(new Rectangle(0, 0, asBitmap.Width, asBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
  486. try
  487. {
  488. for (int y = 0; y < bData.Height; ++y)
  489. {
  490. uint* srcPtr = (uint*)((byte*)bData.Scan0.ToPointer() + (y * bData.Stride));
  491. ColorBgra* dstPtr = surface.GetRowAddress(y);
  492. for (int x = 0; x < bData.Width; ++x)
  493. {
  494. dstPtr->Bgra = *srcPtr;
  495. ++srcPtr;
  496. ++dstPtr;
  497. }
  498. }
  499. }
  500. finally
  501. {
  502. asBitmap.UnlockBits(bData);
  503. bData = null;
  504. }
  505. }
  506. }
  507. else if (asBitmap != null && asBitmap.PixelFormat == PixelFormat.Format24bppRgb)
  508. {
  509. unsafe
  510. {
  511. BitmapData bData = asBitmap.LockBits(new Rectangle(0, 0, asBitmap.Width, asBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
  512. try
  513. {
  514. for (int y = 0; y < bData.Height; ++y)
  515. {
  516. byte* srcPtr = (byte*)bData.Scan0.ToPointer() + (y * bData.Stride);
  517. ColorBgra* dstPtr = surface.GetRowAddress(y);
  518. for (int x = 0; x < bData.Width; ++x)
  519. {
  520. byte b = *srcPtr;
  521. byte g = *(srcPtr + 1);
  522. byte r = *(srcPtr + 2);
  523. byte a = 255;
  524. *dstPtr = ColorBgra.FromBgra(b, g, r, a);
  525. srcPtr += 3;
  526. ++dstPtr;
  527. }
  528. }
  529. }
  530. finally
  531. {
  532. asBitmap.UnlockBits(bData);
  533. bData = null;
  534. }
  535. }
  536. }
  537. else
  538. {
  539. using (RenderArgs args = new RenderArgs(surface))
  540. {
  541. args.Graphics.CompositingMode = CompositingMode.SourceCopy;
  542. args.Graphics.SmoothingMode = SmoothingMode.None;
  543. args.Graphics.DrawImage(image, args.Bounds, args.Bounds, GraphicsUnit.Pixel);
  544. }
  545. }
  546. // Transfer metadata
  547. // Sometimes GDI+ does not honor the resolution tags that we
  548. // put in manually via the EXIF properties.
  549. document.DpuUnit = MeasurementUnit.Inch;
  550. document.DpuX = image.HorizontalResolution;
  551. document.DpuY = image.VerticalResolution;
  552. PropertyItem[] pis;
  553. try
  554. {
  555. pis = image.PropertyItems;
  556. }
  557. catch (Exception ex)
  558. {
  559. //Tracing.Ping("Exception while retreiving image's PropertyItems: " + ex.ToString());
  560. pis = null;
  561. }
  562. //if (pis != null)
  563. //{
  564. // for (int i = 0; i < pis.Length; ++i)
  565. // {
  566. // document.Metadata.AddExifValues(new PropertyItem[] { pis[i] });
  567. // }
  568. //}
  569. //document.Layers.Add(layer);
  570. document.surface = surface;
  571. document.Invalidate();
  572. return document;
  573. }
  574. public static Document FromMat(OpenCvSharp.Mat mat)
  575. {
  576. if (mat == null)
  577. {
  578. throw new ArgumentNullException("image");
  579. }
  580. Image image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
  581. Bitmap asBitmap = image as Bitmap;
  582. Document document = new Document(mat.Width, mat.Height);
  583. Surface surface = new Surface(new Size(mat.Width, mat.Height));
  584. surface.Clear(ColorBgra.FromBgra(0, 0, 0, 0));
  585. // Copy pixels
  586. if (asBitmap != null && asBitmap.PixelFormat == PixelFormat.Format32bppArgb)
  587. {
  588. unsafe
  589. {
  590. BitmapData bData = asBitmap.LockBits(new Rectangle(0, 0, asBitmap.Width, asBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
  591. try
  592. {
  593. for (int y = 0; y < bData.Height; ++y)
  594. {
  595. uint* srcPtr = (uint*)((byte*)bData.Scan0.ToPointer() + (y * bData.Stride));
  596. ColorBgra* dstPtr = surface.GetRowAddress(y);
  597. for (int x = 0; x < bData.Width; ++x)
  598. {
  599. dstPtr->Bgra = *srcPtr;
  600. ++srcPtr;
  601. ++dstPtr;
  602. }
  603. }
  604. }
  605. finally
  606. {
  607. asBitmap.UnlockBits(bData);
  608. bData = null;
  609. }
  610. }
  611. }
  612. else if (asBitmap != null && asBitmap.PixelFormat == PixelFormat.Format24bppRgb)
  613. {
  614. unsafe
  615. {
  616. BitmapData bData = asBitmap.LockBits(new Rectangle(0, 0, asBitmap.Width, asBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
  617. try
  618. {
  619. for (int y = 0; y < bData.Height; ++y)
  620. {
  621. byte* srcPtr = (byte*)bData.Scan0.ToPointer() + (y * bData.Stride);
  622. ColorBgra* dstPtr = surface.GetRowAddress(y);
  623. for (int x = 0; x < bData.Width; ++x)
  624. {
  625. byte b = *srcPtr;
  626. byte g = *(srcPtr + 1);
  627. byte r = *(srcPtr + 2);
  628. byte a = 255;
  629. *dstPtr = ColorBgra.FromBgra(b, g, r, a);
  630. srcPtr += 3;
  631. ++dstPtr;
  632. }
  633. }
  634. }
  635. finally
  636. {
  637. asBitmap.UnlockBits(bData);
  638. bData = null;
  639. }
  640. }
  641. }
  642. else
  643. {
  644. using (RenderArgs args = new RenderArgs(surface))
  645. {
  646. args.Graphics.CompositingMode = CompositingMode.SourceCopy;
  647. args.Graphics.SmoothingMode = SmoothingMode.None;
  648. args.Graphics.DrawImage(image, args.Bounds, args.Bounds, GraphicsUnit.Pixel);
  649. }
  650. }
  651. document.DpuUnit = MeasurementUnit.Inch;
  652. document.DpuX = image.HorizontalResolution;
  653. document.DpuY = image.VerticalResolution;
  654. document.surface = surface;
  655. document.Invalidate();
  656. return document;
  657. }
  658. ~Document()
  659. {
  660. Dispose(false);
  661. }
  662. public void Dispose()
  663. {
  664. Dispose(true);
  665. GC.SuppressFinalize(this);
  666. }
  667. private bool disposed = false;
  668. private void Dispose(bool disposing)
  669. {
  670. if (!disposed)
  671. {
  672. if (disposing)
  673. {
  674. /*foreach (Layer layer in layers)
  675. {
  676. layer.Dispose();
  677. }*/
  678. }
  679. disposed = true;
  680. }
  681. }
  682. public void Render(RenderArgs args, bool clearBackground)
  683. {
  684. Render(args, args.Surface.Bounds, clearBackground);
  685. }
  686. /// <summary>
  687. /// Renders a requested region of the document. Will clear the background of the input
  688. /// before rendering if requested.
  689. /// </summary>
  690. /// <param name="args">Contains information used to control where rendering occurs.</param>
  691. /// <param name="roi">The rectangular region to render.</param>
  692. /// <param name="clearBackground">If true, 'args' will be cleared to zero before rendering.</param>
  693. public void Render(RenderArgs args, Rectangle roi, bool clearBackground)
  694. {
  695. /*int startIndex;
  696. if (clearBackground)
  697. {
  698. BitmapLayer layer0;
  699. layer0 = this.layers[0] as BitmapLayer;
  700. // Special case: if the first layer is a visible BitmapLayer with full opacity using
  701. // the default blend op, we can just copy the pixels straight over
  702. if (layer0 != null &&
  703. layer0.Visible &&
  704. layer0.Opacity == 255 &&
  705. layer0.BlendOp.GetType() == UserBlendOps.GetDefaultBlendOp())
  706. {
  707. args.Surface.CopySurface(layer0.Surface);
  708. startIndex = 1;
  709. }
  710. else
  711. {
  712. ClearBackground(args.Surface, roi);
  713. startIndex = 0;
  714. }
  715. }
  716. else
  717. {
  718. startIndex = 0;
  719. }
  720. for (int i = startIndex; i < this.layers.Count; ++i)
  721. {
  722. Layer layer = (Layer)this.layers[i];
  723. if (layer.Visible)
  724. {
  725. layer.Render(args, roi);
  726. }
  727. }*/
  728. }
  729. public void Render(RenderArgs args, Rectangle[] roi, int startIndex, int length, bool clearBackground)
  730. {
  731. /*int startLayerIndex;
  732. if (clearBackground)
  733. {
  734. BitmapLayer layer0;
  735. layer0 = this.layers[0] as BitmapLayer;
  736. // Special case: if the first layer is a visible BitmapLayer with full opacity using
  737. // the default blend op, we can just copy the pixels straight over
  738. if (layer0 != null &&
  739. layer0.Visible &&
  740. layer0.Opacity == 255 &&
  741. layer0.BlendOp.GetType() == UserBlendOps.GetDefaultBlendOp())
  742. {
  743. args.Surface.CopySurface(layer0.Surface, roi, startIndex, length);
  744. startLayerIndex = 1;
  745. }
  746. else
  747. {
  748. ClearBackground(args.Surface, roi, startIndex, length);
  749. startLayerIndex = 0;
  750. }
  751. }
  752. else
  753. {
  754. startLayerIndex = 0;
  755. }
  756. for (int i = startLayerIndex; i < this.layers.Count; ++i)
  757. {
  758. Layer layer = (Layer)this.layers[i];
  759. if (layer.Visible)
  760. {
  761. layer.RenderUnchecked(args, roi, startIndex, length);
  762. }
  763. }*/
  764. }
  765. public static double DotsPerCmToDotsPerInch(double dpcm)
  766. {
  767. return dpcm * CmPerInch;
  768. }
  769. }
  770. }