PageRenderTime 43ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Data/BmpFileType.cs

https://bitbucket.org/tuldok89/openpdn
C# | 192 lines | 149 code | 30 blank | 13 comment | 4 complexity | ce5338f125f58ef85e0ef2e23a467315 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using PaintDotNet.Base;
  10. using PaintDotNet.Base.PropertySystem;
  11. using PaintDotNet.IndirectUI;
  12. using System.Collections.Generic;
  13. using System.ComponentModel;
  14. using System.Drawing;
  15. using System.Drawing.Imaging;
  16. using System.IO;
  17. namespace PaintDotNet
  18. {
  19. public sealed class BmpFileType
  20. : InternalFileType
  21. {
  22. public BmpFileType()
  23. : base("BMP", FileTypeFlags.SupportsLoading | FileTypeFlags.SupportsSaving, new[] { ".bmp" })
  24. {
  25. }
  26. public enum PropertyNames
  27. {
  28. BitDepth = 0,
  29. DitherLevel = 1
  30. }
  31. public enum BmpBitDepthUIChoices
  32. {
  33. AutoDetect = 0,
  34. Bpp24 = 1,
  35. Bpp8 = 2
  36. }
  37. public override PropertyCollection OnCreateSavePropertyCollection()
  38. {
  39. var props = new List<Property>
  40. {
  41. StaticListChoiceProperty.CreateForEnum(PropertyNames.BitDepth,
  42. BmpBitDepthUIChoices.AutoDetect, false),
  43. new Int32Property(PropertyNames.DitherLevel, 7, 0, 8)
  44. };
  45. var rules = new List<PropertyCollectionRule>
  46. {
  47. new ReadOnlyBoundToValueRule<object, StaticListChoiceProperty>(
  48. PropertyNames.DitherLevel, PropertyNames.BitDepth, BmpBitDepthUIChoices.Bpp8, true)
  49. };
  50. var pc = new PropertyCollection(props, rules);
  51. return pc;
  52. }
  53. public override ControlInfo OnCreateSaveConfigUI(PropertyCollection props)
  54. {
  55. ControlInfo configUI = CreateDefaultSaveConfigUI(props);
  56. configUI.SetPropertyControlValue(
  57. PropertyNames.BitDepth,
  58. ControlInfoPropertyNames.DisplayName,
  59. PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.DisplayName"));
  60. PropertyControlInfo bitDepthPCI = configUI.FindControlForPropertyName(PropertyNames.BitDepth);
  61. bitDepthPCI.SetValueDisplayName(BmpBitDepthUIChoices.AutoDetect, PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.AutoDetect.DisplayName"));
  62. bitDepthPCI.SetValueDisplayName(BmpBitDepthUIChoices.Bpp24, PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.Bpp24.DisplayName"));
  63. bitDepthPCI.SetValueDisplayName(BmpBitDepthUIChoices.Bpp8, PdnResources.GetString("BmpFileType.ConfigUI.BitDepth.Bpp8.DisplayName"));
  64. configUI.SetPropertyControlType(PropertyNames.BitDepth, PropertyControlType.RadioButton);
  65. configUI.SetPropertyControlValue(
  66. PropertyNames.DitherLevel,
  67. ControlInfoPropertyNames.DisplayName,
  68. PdnResources.GetString("BmpFileType.ConfigUI.DitherLevel.DisplayName"));
  69. return configUI;
  70. }
  71. protected override Document OnLoad(Stream input)
  72. {
  73. // This allows us to open images that were created in Explorer using New -> Bitmap Image
  74. // which actually just creates a 0-byte file
  75. if (input.Length == 0)
  76. {
  77. var newDoc = new Document(800, 600);
  78. Layer layer = Layer.CreateBackgroundLayer(newDoc.Width, newDoc.Height);
  79. newDoc.Layers.Add(layer);
  80. return newDoc;
  81. }
  82. using (Image image = PdnResources.LoadImage(input))
  83. {
  84. Document document = Document.FromImage(image);
  85. return document;
  86. }
  87. }
  88. internal override int GetDitherLevelFromToken(PropertyBasedSaveConfigToken token)
  89. {
  90. int ditherLevel = token.GetProperty<Int32Property>(PropertyNames.DitherLevel).Value;
  91. return ditherLevel;
  92. }
  93. internal override int GetThresholdFromToken(PropertyBasedSaveConfigToken token)
  94. {
  95. return 0;
  96. }
  97. internal override Set<SavableBitDepths> CreateAllowedBitDepthListFromToken(PropertyBasedSaveConfigToken token)
  98. {
  99. var bitDepth = (BmpBitDepthUIChoices)token.GetProperty<StaticListChoiceProperty>(PropertyNames.BitDepth).Value;
  100. var bitDepths = new Set<SavableBitDepths>();
  101. switch (bitDepth)
  102. {
  103. case BmpBitDepthUIChoices.AutoDetect:
  104. bitDepths.Add(SavableBitDepths.Rgb24);
  105. bitDepths.Add(SavableBitDepths.Rgb8);
  106. break;
  107. case BmpBitDepthUIChoices.Bpp24:
  108. bitDepths.Add(SavableBitDepths.Rgb24);
  109. break;
  110. case BmpBitDepthUIChoices.Bpp8:
  111. bitDepths.Add(SavableBitDepths.Rgb8);
  112. break;
  113. default:
  114. throw new InvalidEnumArgumentException("bitDepth", (int)bitDepth, typeof(BmpBitDepthUIChoices));
  115. }
  116. return bitDepths;
  117. }
  118. internal override void FinalSave(
  119. Document input,
  120. Stream output,
  121. Surface scratchSurface,
  122. int ditherLevel,
  123. SavableBitDepths bitDepth,
  124. PropertyBasedSaveConfigToken token,
  125. ProgressEventHandler progressCallback)
  126. {
  127. // finally, do the save.
  128. switch (bitDepth)
  129. {
  130. case SavableBitDepths.Rgb24:
  131. {
  132. // In order to save memory, we 'squish' the 32-bit bitmap down to 24-bit in-place
  133. // instead of allocating a new bitmap and copying it over.
  134. SquishSurfaceTo24Bpp(scratchSurface);
  135. ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Bmp);
  136. var parms = new EncoderParameters(1);
  137. var parm = new EncoderParameter(Encoder.ColorDepth, 24);
  138. parms.Param[0] = parm;
  139. using (Bitmap bitmap = CreateAliased24BppBitmap(scratchSurface))
  140. {
  141. GdiPlusFileType.LoadProperties(bitmap, input);
  142. bitmap.Save(output, icf, parms);
  143. }
  144. }
  145. break;
  146. case SavableBitDepths.Rgb8:
  147. using (Bitmap quantized = Quantize(scratchSurface, ditherLevel, 256, false, progressCallback))
  148. {
  149. ImageCodecInfo icf = GdiPlusFileType.GetImageCodecInfo(ImageFormat.Bmp);
  150. var parms = new EncoderParameters(1);
  151. var parm = new EncoderParameter(Encoder.ColorDepth, 8);
  152. parms.Param[0] = parm;
  153. GdiPlusFileType.LoadProperties(quantized, input);
  154. quantized.Save(output, icf, parms);
  155. }
  156. break;
  157. default:
  158. throw new InvalidEnumArgumentException("bitDepth", (int)bitDepth, typeof(SavableBitDepths));
  159. }
  160. }
  161. }
  162. }