GdiPlusFileType.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using PaintDotNet.SystemLayer;
  2. using System;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.IO;
  6. namespace PaintDotNet
  7. {
  8. /// <summary>
  9. /// Implements FileType for generic GDI+ codecs.
  10. /// </summary>
  11. /// <remarks>
  12. /// GDI+ file types do not support custom headers.
  13. /// </remarks>
  14. public class GdiPlusFileType : FileType
  15. {
  16. private ImageFormat imageFormat;
  17. public ImageFormat ImageFormat
  18. {
  19. get
  20. {
  21. return this.imageFormat;
  22. }
  23. }
  24. protected override void OnSave(Document input, Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback)
  25. {
  26. GdiPlusFileType.Save(input, output, scratchSurface, this.ImageFormat, callback);
  27. }
  28. public static void Save(Document input, Stream output, Surface scratchSurface, ImageFormat format, ProgressEventHandler callback)
  29. {
  30. // flatten the document
  31. scratchSurface.Clear(ColorBgra.FromBgra(0, 0, 0, 0));
  32. using (RenderArgs ra = new RenderArgs(scratchSurface))
  33. {
  34. input.Render(ra, true);
  35. }
  36. using (Bitmap bitmap = scratchSurface.CreateAliasedBitmap())
  37. {
  38. LoadProperties(bitmap, input);
  39. bitmap.Save(output, format);
  40. }
  41. }
  42. public static void LoadProperties(Image dstImage, Document srcDoc)
  43. {
  44. Bitmap asBitmap = dstImage as Bitmap;
  45. if (asBitmap != null)
  46. {
  47. // Sometimes GDI+ does not honor the resolution tags that we
  48. // put in manually via the EXIF properties.
  49. float dpiX;
  50. float dpiY;
  51. switch (srcDoc.DpuUnit)
  52. {
  53. case MeasurementUnit.Centimeter:
  54. dpiX = (float)Document.DotsPerCmToDotsPerInch(srcDoc.DpuX);
  55. dpiY = (float)Document.DotsPerCmToDotsPerInch(srcDoc.DpuY);
  56. break;
  57. case MeasurementUnit.Inch:
  58. dpiX = (float)srcDoc.DpuX;
  59. dpiY = (float)srcDoc.DpuY;
  60. break;
  61. default:
  62. case MeasurementUnit.Pixel:
  63. dpiX = 1.0f;
  64. dpiY = 1.0f;
  65. break;
  66. }
  67. try
  68. {
  69. asBitmap.SetResolution(dpiX, dpiY);
  70. }
  71. catch (Exception)
  72. {
  73. // Ignore error
  74. }
  75. }
  76. Metadata metaData = srcDoc.Metadata;
  77. foreach (string key in metaData.GetKeys(Metadata.ExifSectionName))
  78. {
  79. string blob = metaData.GetValue(Metadata.ExifSectionName, key);
  80. PropertyItem pi = PdnGraphics.DeserializePropertyItem(blob);
  81. try
  82. {
  83. dstImage.SetPropertyItem(pi);
  84. }
  85. catch (ArgumentException)
  86. {
  87. // Ignore error: the image does not support property items
  88. }
  89. }
  90. }
  91. public override Document OnLoad(Stream input)
  92. {
  93. using (Image image = PdnResources.LoadImage(input))
  94. {
  95. Document document = Document.FromImage(image);
  96. return document;
  97. }
  98. }
  99. public static ImageCodecInfo GetImageCodecInfo(ImageFormat format)
  100. {
  101. ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
  102. foreach (ImageCodecInfo icf in encoders)
  103. {
  104. if (icf.FormatID == format.Guid)
  105. {
  106. return icf;
  107. }
  108. }
  109. return null;
  110. }
  111. public GdiPlusFileType(string name, ImageFormat imageFormat, bool supportsLayers, string[] extensions)
  112. : this(name, imageFormat, supportsLayers, extensions, false)
  113. {
  114. }
  115. public GdiPlusFileType(string name, ImageFormat imageFormat, bool supportsLayers, string[] extensions, bool savesWithProgress)
  116. : base(name,
  117. (supportsLayers ? FileTypeFlags.SupportsLayers : 0) |
  118. FileTypeFlags.SupportsLoading |
  119. FileTypeFlags.SupportsSaving |
  120. (savesWithProgress ? FileTypeFlags.SavesWithProgress : 0),
  121. extensions)
  122. {
  123. this.imageFormat = imageFormat;
  124. }
  125. }
  126. }